UNPKG

@oxyhq/services

Version:

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

315 lines (311 loc) 11.3 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 _sonner = require("../../lib/sonner"); var _index = require("../components/index.js"); var _useI18n = require("../hooks/useI18n.js"); var _useThemeStyles = require("../hooks/useThemeStyles.js"); var _OxyContext = require("../context/OxyContext.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 FAQScreen = ({ onClose, theme, goBack }) => { const { oxyServices } = (0, _OxyContext.useOxy)(); const { t } = (0, _useI18n.useI18n)(); const themeStyles = (0, _useThemeStyles.useThemeStyles)(theme || 'light'); const [faqs, setFaqs] = (0, _react.useState)([]); const [isLoading, setIsLoading] = (0, _react.useState)(true); const [searchQuery, setSearchQuery] = (0, _react.useState)(''); const [expandedIds, setExpandedIds] = (0, _react.useState)(new Set()); const [selectedCategory, setSelectedCategory] = (0, _react.useState)(null); // Load FAQs from API (0, _react.useEffect)(() => { const loadFAQs = async () => { try { setIsLoading(true); const data = await oxyServices.getFAQs(); setFaqs(data); } catch (error) { _sonner.toast.error(t('faq.loadError') || 'Failed to load FAQs'); } finally { setIsLoading(false); } }; loadFAQs(); }, [oxyServices, t]); // Get unique categories const categories = (0, _react.useMemo)(() => { const cats = [...new Set(faqs.map(f => f.category))]; return cats.sort(); }, [faqs]); // Filter FAQs based on search and category const filteredFaqs = (0, _react.useMemo)(() => { let result = faqs; if (selectedCategory) { result = result.filter(f => f.category === selectedCategory); } if (searchQuery.trim()) { const query = searchQuery.toLowerCase(); result = result.filter(f => f.question.toLowerCase().includes(query) || f.answer.toLowerCase().includes(query)); } return result; }, [faqs, searchQuery, selectedCategory]); const toggleExpanded = (0, _react.useCallback)(id => { setExpandedIds(prev => { const next = new Set(prev); if (next.has(id)) { next.delete(id); } else { next.add(id); } return next; }); }, []); const styles = (0, _react.useMemo)(() => createStyles(themeStyles), [themeStyles]); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.container, { backgroundColor: themeStyles.backgroundColor }], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_index.Header, { title: t('faq.title') || 'FAQ', onBack: goBack || onClose, variant: "minimal", elevation: "subtle" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.searchContainer, children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.searchInputWrapper, { backgroundColor: themeStyles.secondaryBackgroundColor, borderColor: themeStyles.borderColor }], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, { name: "search", size: 20, color: themeStyles.mutedTextColor, style: styles.searchIcon }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, { style: [styles.searchInput, { color: themeStyles.textColor }], placeholder: t('faq.searchPlaceholder') || 'Search FAQs...', placeholderTextColor: themeStyles.mutedTextColor, value: searchQuery, onChangeText: setSearchQuery, accessibilityLabel: "Search FAQs" }), searchQuery.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { onPress: () => setSearchQuery(''), accessibilityRole: "button", accessibilityLabel: "Clear search", children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, { name: "close-circle", size: 20, color: themeStyles.mutedTextColor }) })] }) }), categories.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles.categoriesContainer, contentContainerStyle: styles.categoriesContent, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: [styles.categoryChip, !selectedCategory && styles.categoryChipActive, { backgroundColor: !selectedCategory ? themeStyles.primaryColor : themeStyles.secondaryBackgroundColor }], onPress: () => setSelectedCategory(null), accessibilityRole: "button", accessibilityLabel: "Show all categories", accessibilityState: { selected: !selectedCategory }, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [styles.categoryChipText, { color: !selectedCategory ? '#FFFFFF' : themeStyles.textColor }], children: t('faq.allCategories') || 'All' }) }), categories.map(cat => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: [styles.categoryChip, selectedCategory === cat && styles.categoryChipActive, { backgroundColor: selectedCategory === cat ? themeStyles.primaryColor : themeStyles.secondaryBackgroundColor }], onPress: () => setSelectedCategory(cat), accessibilityRole: "button", accessibilityLabel: `Filter by ${cat}`, accessibilityState: { selected: selectedCategory === cat }, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [styles.categoryChipText, { color: selectedCategory === cat ? '#FFFFFF' : themeStyles.textColor }], children: cat }) }, cat))] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, { style: styles.content, showsVerticalScrollIndicator: false, children: isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.LoadingState, { message: t('faq.loading') || 'Loading FAQs...', color: themeStyles.textColor }) : filteredFaqs.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.EmptyState, { message: searchQuery ? t('faq.noResults') || 'No FAQs match your search' : t('faq.empty') || 'No FAQs available', textColor: themeStyles.textColor }) : filteredFaqs.map((faq, index) => { const isExpanded = expandedIds.has(faq.id); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.faqItem, { backgroundColor: themeStyles.secondaryBackgroundColor, borderColor: themeStyles.borderColor }, index === 0 && styles.faqItemFirst], children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, { style: styles.faqQuestion, onPress: () => toggleExpanded(faq.id), accessibilityRole: "button", accessibilityLabel: faq.question, accessibilityHint: isExpanded ? 'Collapse answer' : 'Expand answer', accessibilityState: { expanded: isExpanded }, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [styles.faqQuestionText, { color: themeStyles.textColor }], children: faq.question }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, { name: isExpanded ? 'chevron-up' : 'chevron-down', size: 20, color: themeStyles.mutedTextColor })] }), isExpanded && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.faqAnswer, { borderTopColor: themeStyles.borderColor }], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [styles.faqAnswerText, { color: themeStyles.mutedTextColor }], children: faq.answer }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.faqCategory, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, { name: "pricetag-outline", size: 14, color: themeStyles.primaryColor }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [styles.faqCategoryText, { color: themeStyles.primaryColor }], children: faq.category })] })] })] }, faq.id); }) })] }); }; const createStyles = themeStyles => _reactNative.StyleSheet.create({ container: { flex: 1 }, searchContainer: { paddingHorizontal: 16, paddingVertical: 12 }, searchInputWrapper: { flexDirection: 'row', alignItems: 'center', borderRadius: 12, borderWidth: 1, paddingHorizontal: 12, height: 44 }, searchIcon: { marginRight: 8 }, searchInput: { flex: 1, fontSize: 16, ..._reactNative.Platform.select({ web: { outlineStyle: 'none' } }) }, categoriesContainer: { maxHeight: 50 }, categoriesContent: { paddingHorizontal: 16, gap: 8 }, categoryChip: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20, marginRight: 8 }, categoryChipActive: {}, categoryChipText: { fontSize: 14, fontWeight: '500' }, content: { flex: 1, padding: 16 }, faqItem: { borderRadius: 12, borderWidth: 1, marginBottom: 12, overflow: 'hidden' }, faqItemFirst: { marginTop: 0 }, faqQuestion: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: 16 }, faqQuestionText: { flex: 1, fontSize: 16, fontWeight: '600', marginRight: 12 }, faqAnswer: { padding: 16, paddingTop: 12, borderTopWidth: 1 }, faqAnswerText: { fontSize: 14, lineHeight: 22 }, faqCategory: { flexDirection: 'row', alignItems: 'center', marginTop: 12 }, faqCategoryText: { fontSize: 12, marginLeft: 6, fontWeight: '500' } }); var _default = exports.default = FAQScreen; //# sourceMappingURL=FAQScreen.js.map