@oxyhq/services
Version:
Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀
202 lines (197 loc) • 6.08 kB
JavaScript
"use strict";
import React, { useState, useMemo, useCallback } from 'react';
import { View, Text, StyleSheet, ScrollView, Platform, TouchableOpacity, TextInput, LayoutAnimation } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { Header } from '../../components';
import { useI18n } from '../../hooks/useI18n';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const FAQ_KEYS = ['what', 'earn', 'lose', 'use', 'transfer', 'support'];
/**
* KarmaFAQScreen - Optimized for performance
*
* Performance optimizations implemented:
* - useMemo for theme calculations (only recalculates when theme changes)
* - useMemo for filtered FAQs (only recalculates when search changes)
* - useCallback for event handlers to prevent unnecessary re-renders
* - React.memo wrapper to prevent re-renders when props haven't changed
*/
const KarmaFAQScreen = ({
goBack,
theme
}) => {
const {
t
} = useI18n();
const [expanded, setExpanded] = useState(0);
const [search, setSearch] = useState('');
// Memoize theme-related calculations to prevent unnecessary recalculations
const themeStyles = useMemo(() => {
const isDarkTheme = theme === 'dark';
return {
isDarkTheme,
backgroundColor: isDarkTheme ? '#121212' : '#FFFFFF',
textColor: isDarkTheme ? '#FFFFFF' : '#000000',
cardColor: isDarkTheme ? '#23232b' : '#f7f7fa',
primaryColor: '#d169e5',
inputBg: isDarkTheme ? '#23232b' : '#f2f2f7',
inputBorder: isDarkTheme ? '#444' : '#e0e0e0'
};
}, [theme]);
// Memoize filtered FAQs to prevent filtering on every render
const faqs = useMemo(() => FAQ_KEYS.map(key => ({
q: t(`karma.faq.items.${key}.q`) || '',
a: t(`karma.faq.items.${key}.a`) || ''
})), [t]);
const filteredFaqs = useMemo(() => {
if (!search.trim()) return faqs;
const searchLower = search.toLowerCase();
return faqs.filter(faq => faq.q.toLowerCase().includes(searchLower) || faq.a.toLowerCase().includes(searchLower));
}, [search, faqs]);
// Memoize toggle handler to prevent recreation on every render
const handleToggle = useCallback(idx => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setExpanded(prev => prev === idx ? null : idx);
}, []);
return /*#__PURE__*/_jsxs(View, {
style: [styles.container, {
backgroundColor: themeStyles.backgroundColor
}],
children: [/*#__PURE__*/_jsx(Header, {
title: t('karma.faq.title') || 'Karma FAQ',
subtitle: t('karma.faq.subtitle') || 'Frequently asked questions about karma',
subtitleVariant: "muted",
theme: theme,
onBack: goBack,
elevation: "subtle"
}), /*#__PURE__*/_jsxs(View, {
style: [styles.searchBar, {
backgroundColor: themeStyles.inputBg,
borderColor: themeStyles.inputBorder
}],
children: [/*#__PURE__*/_jsx(Ionicons, {
name: "search-outline",
size: 20,
color: themeStyles.primaryColor,
style: {
marginRight: 8
}
}), /*#__PURE__*/_jsx(TextInput, {
style: [styles.searchInput, {
color: themeStyles.textColor
}],
placeholder: t('karma.faq.search') || 'Search FAQ...',
placeholderTextColor: themeStyles.isDarkTheme ? '#aaa' : '#888',
value: search,
onChangeText: setSearch,
returnKeyType: "search"
})]
}), /*#__PURE__*/_jsx(ScrollView, {
contentContainerStyle: styles.contentContainer,
children: filteredFaqs.length === 0 ? /*#__PURE__*/_jsx(Text, {
style: [styles.noResults, {
color: themeStyles.textColor
}],
children: t('karma.faq.noResults', {
query: search
}) || `No FAQ items found matching "${search}"`
}) : filteredFaqs.map((faq, idx) => /*#__PURE__*/_jsxs(TouchableOpacity, {
style: [styles.card, {
backgroundColor: themeStyles.cardColor
}],
onPress: () => handleToggle(idx),
activeOpacity: 0.7,
children: [/*#__PURE__*/_jsxs(View, {
style: styles.questionRow,
children: [/*#__PURE__*/_jsx(Text, {
style: [styles.question, {
color: themeStyles.textColor
}],
children: faq.q
}), /*#__PURE__*/_jsx(Ionicons, {
name: expanded === idx ? 'chevron-up' : 'chevron-down',
size: 20,
color: themeStyles.primaryColor
})]
}), expanded === idx && /*#__PURE__*/_jsx(Text, {
style: [styles.answer, {
color: themeStyles.textColor
}],
children: faq.a
})]
}, idx))
})]
});
};
const styles = StyleSheet.create({
container: {
flex: 1
},
title: {
fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
fontSize: 38,
margin: 24,
marginBottom: 12,
textAlign: 'center'
},
searchBar: {
flexDirection: 'row',
alignItems: 'center',
borderRadius: 16,
borderWidth: 1,
marginHorizontal: 24,
marginBottom: 12,
paddingHorizontal: 12,
height: 44
},
searchInput: {
flex: 1,
fontSize: 16,
height: 44
},
contentContainer: {
padding: 24,
paddingTop: 20,
paddingBottom: 40
},
card: {
borderRadius: 18,
padding: 20,
marginBottom: 18,
shadowOpacity: 0.08,
shadowOffset: {
width: 0,
height: 2
},
shadowRadius: 8,
elevation: 2
},
questionRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 8
},
question: {
fontSize: 17,
fontWeight: 'bold',
flex: 1
},
answer: {
fontSize: 16,
lineHeight: 22,
marginTop: 8
},
paragraph: {
fontSize: 16,
marginBottom: 12
},
noResults: {
fontSize: 16,
marginTop: 32,
textAlign: 'center',
opacity: 0.7
}
});
export default /*#__PURE__*/React.memo(KarmaFAQScreen);
//# sourceMappingURL=KarmaFAQScreen.js.map