UNPKG

@oxyhq/services

Version:

OxyHQ Expo/React Native SDK — UI components, screens, and native features

194 lines (189 loc) 7.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _vectorIcons = require("@expo/vector-icons"); var _index = require("../../components/index.js"); var _useI18n = require("../../hooks/useI18n.js"); var _useThemeStyles = require("../../hooks/useThemeStyles.js"); var _themeUtils = require("../../utils/themeUtils.js"); var _useColorScheme = require("../../hooks/useColorScheme.js"); var _theme = require("../../constants/theme.js"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } 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 } = (0, _useI18n.useI18n)(); const [expanded, setExpanded] = (0, _react.useState)(null); const [search, setSearch] = (0, _react.useState)(''); // Memoize theme-related calculations to prevent unnecessary recalculations const normalizedTheme = (0, _themeUtils.normalizeTheme)(theme); const baseThemeStyles = (0, _useThemeStyles.useThemeStyles)(normalizedTheme); const colorScheme = (0, _useColorScheme.useColorScheme)(); const normalizedColorScheme = (0, _themeUtils.normalizeColorScheme)(colorScheme); const colors = _theme.Colors[normalizedColorScheme]; const themeStyles = (0, _react.useMemo)(() => ({ ...baseThemeStyles, primaryColor: '#d169e5', inputBg: baseThemeStyles.isDarkTheme ? '#23232b' : '#f2f2f7', inputBorder: baseThemeStyles.borderColor }), [baseThemeStyles]); // Memoize filtered FAQs to prevent filtering on every render const faqs = (0, _react.useMemo)(() => FAQ_KEYS.map(key => ({ id: key, q: t(`karma.faq.items.${key}.q`) || '', a: t(`karma.faq.items.${key}.a`) || '' })), [t]); const filteredFaqs = (0, _react.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 = (0, _react.useCallback)(id => { _reactNative.LayoutAnimation.configureNext(_reactNative.LayoutAnimation.Presets.easeInEaseOut); setExpanded(prev => prev === id ? null : id); }, []); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.container, { backgroundColor: themeStyles.backgroundColor }], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_index.Header, { title: t('karma.faq.title') || 'Karma FAQ', subtitle: t('karma.faq.subtitle') || 'Frequently asked questions about karma', subtitleVariant: "muted", onBack: goBack, elevation: "subtle" }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, { contentContainerStyle: styles.contentContainer, showsVerticalScrollIndicator: false, children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.searchContainer, { backgroundColor: colors.card }], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, { name: "search", size: 22, color: colors.icon }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, { style: [styles.searchInput, { color: themeStyles.textColor }], placeholder: t('karma.faq.search') || 'Search FAQ...', placeholderTextColor: themeStyles.isDarkTheme ? '#BBBBBB' : '#888888', value: search, onChangeText: setSearch, returnKeyType: "search" })] }), filteredFaqs.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [styles.noResults, { color: colors.secondaryText }], children: t('karma.faq.noResults', { query: search }) || `No FAQ items found matching "${search}"` }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.groupedSectionContainer, children: filteredFaqs.map((faq, idx) => { const isExpanded = expanded === faq.id; const isFirst = idx === 0; const isLast = idx === filteredFaqs.length - 1; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.faqItemWrapper, { marginBottom: idx < filteredFaqs.length - 1 ? 4 : 0 }], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_index.GroupedItem, { title: faq.q, onPress: () => handleToggle(faq.id), isFirst: isFirst, isLast: isLast && !isExpanded, showChevron: false, customContent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, { name: isExpanded ? 'chevron-up' : 'chevron-down', size: 20, color: colors.icon }) }), isExpanded && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: [styles.answerContainer, { backgroundColor: colors.card }, isLast && styles.lastAnswerContainer], children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [styles.answer, { color: themeStyles.textColor }], children: faq.a }) })] }, faq.id); }) })] })] }); }; const styles = _reactNative.StyleSheet.create({ container: { flex: 1 }, contentContainer: { paddingHorizontal: 24, paddingTop: 20, paddingBottom: 40 }, searchContainer: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 14, paddingVertical: 10, marginBottom: 12, borderRadius: 999, gap: 10 }, searchInput: { flex: 1, fontSize: 16, lineHeight: 20 }, groupedSectionContainer: { width: '100%' }, faqItemWrapper: { width: '100%' }, answerContainer: { paddingHorizontal: 10, paddingTop: 4, paddingBottom: 12 }, lastAnswerContainer: { borderBottomLeftRadius: 18, borderBottomRightRadius: 18 }, answer: { fontSize: 14, lineHeight: 20 }, noResults: { fontSize: 16, marginTop: 32, textAlign: 'center' } }); var _default = exports.default = /*#__PURE__*/_react.default.memo(KarmaFAQScreen); //# sourceMappingURL=KarmaFAQScreen.js.map