208 lines
8.8 KiB
TypeScript
208 lines
8.8 KiB
TypeScript
import React, { useState, useEffect, useMemo } from 'react';
|
|
import { View, Text, StyleSheet, TouchableOpacity, TextInput, ScrollView, Platform } from 'react-native';
|
|
import { Feather } from '@expo/vector-icons';
|
|
import { useAppTheme } from '../../context/ThemeContext';
|
|
import { useToast } from '../../context/ToastContext';
|
|
import { useAppConfig } from '../../context/ConfigContext';
|
|
import { AppScreen } from '../../components/AppScreen';
|
|
import { AISectionHeader, AISkeleton, AIPressable } from '../../components/UI';
|
|
import { useTranslation } from '../../context/LanguageContext';
|
|
import { MOCK_FAQS } from '../../constants/mocks';
|
|
import { PALETTE } from '../../constants/theme';
|
|
import * as Haptics from 'expo-haptics';
|
|
|
|
const getTopics = (t: any) => [
|
|
{ id: '1', name: t.web || 'Web', icon: 'book-open' },
|
|
{ id: '2', name: t.account || 'Account', icon: 'user' },
|
|
{ id: '3', name: t.billing || 'Billing', icon: 'credit-card' },
|
|
{ id: '4', name: t.system || 'System', icon: 'cpu' },
|
|
];
|
|
|
|
// Mock data moved to constants/mocks.ts
|
|
|
|
export default function HelpScreen() {
|
|
const { colors, isDark } = useAppTheme();
|
|
const { showToast } = useToast();
|
|
const { config } = useAppConfig();
|
|
const { t } = useTranslation();
|
|
|
|
const topics = useMemo(() => {
|
|
if (config?.support_social?.help_topics_json && Array.isArray(config.support_social.help_topics_json)) {
|
|
return config.support_social.help_topics_json;
|
|
}
|
|
return getTopics(t);
|
|
}, [config?.support_social?.help_topics_json, t]);
|
|
|
|
const faqs = useMemo(() => {
|
|
if (config?.support_social?.faq_json && Array.isArray(config.support_social.faq_json)) {
|
|
return config.support_social.faq_json.map((f, i) => ({ id: String(i+1), ...f }));
|
|
}
|
|
return MOCK_FAQS;
|
|
}, [config?.support_social?.faq_json]);
|
|
|
|
const [loading, setLoading] = useState(true);
|
|
const [search, setSearch] = useState('');
|
|
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => setLoading(false), 1500);
|
|
return () => clearTimeout(timer);
|
|
}, []);
|
|
|
|
const handleContactSupport = (type: 'whatsapp' | 'email') => {
|
|
const contact = type === 'whatsapp' ? config?.support_social?.support_whatsapp : config?.support_social?.support_email;
|
|
if (contact) {
|
|
const url = type === 'whatsapp' ? `https://wa.me/${contact}` : `mailto:${contact}`;
|
|
require('react-native').Linking.openURL(url).catch(() => {
|
|
showToast(`Failed to open ${type}`, 'error');
|
|
});
|
|
} else {
|
|
showToast('Support contact not available', 'info');
|
|
}
|
|
};
|
|
|
|
const cardBg = colors.surface;
|
|
const border = colors.border;
|
|
const subText = colors.textSecondary;
|
|
|
|
const renderTopic = (topic: any) => {
|
|
return (
|
|
<AIPressable
|
|
key={topic.id}
|
|
onPress={() => showToast(`Opening ${topic.name} topics`, 'info')}
|
|
style={styles.topicWrapper}
|
|
containerStyle={{ flex: 1 }}
|
|
>
|
|
<View style={[styles.topicCard, { backgroundColor: cardBg, borderColor: border }]}>
|
|
<Feather name={topic.icon as any} size={24} color={isDark ? colors.primary : colors.secondary} />
|
|
<Text style={[styles.topicName, { color: colors.text }]} numberOfLines={1}>{topic.name}</Text>
|
|
</View>
|
|
</AIPressable>
|
|
);
|
|
};
|
|
|
|
const renderSkeleton = () => (
|
|
<View style={{ paddingHorizontal: 24, paddingTop: 56 }}>
|
|
<AISkeleton width={220} height={32} style={{ marginBottom: 12 }} />
|
|
<AISkeleton width={160} height={14} style={{ marginBottom: 32 }} />
|
|
<AISkeleton width="100%" height={56} radius={14} style={{ marginBottom: 32 }} />
|
|
<View style={{ flexDirection: 'row', gap: 12 }}>
|
|
{[1, 2, 3, 4].map(i => <AISkeleton key={i} width="22%" height={90} radius={20} />)}
|
|
</View>
|
|
</View>
|
|
);
|
|
|
|
if (loading) return <AppScreen scrollable={false}>{renderSkeleton()}</AppScreen>;
|
|
|
|
return (
|
|
<AppScreen>
|
|
<View>
|
|
{/* Header */}
|
|
<View style={styles.header}>
|
|
<Text style={[styles.title, { color: colors.text }]}>{t.supportCenter || 'Support Center'}</Text>
|
|
<Text style={[styles.subtitle, { color: subText }]}>
|
|
{t.helpSubtitle || 'Find answers'}
|
|
</Text>
|
|
</View>
|
|
|
|
{/* Search */}
|
|
<View style={styles.searchSection}>
|
|
<View style={[styles.searchBox, { backgroundColor: cardBg, borderColor: border }]}>
|
|
<Feather name="search" size={18} color={colors.textPlaceholder} />
|
|
<TextInput
|
|
placeholder={t.searchDoc || "Search documentation..."}
|
|
placeholderTextColor={isDark ? '#444' : '#BBBBBB'}
|
|
style={[styles.searchInput, { color: colors.text }]}
|
|
value={search}
|
|
onChangeText={setSearch}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Topics Grid: 2 Columns FULL */}
|
|
<AISectionHeader title={t.browseTopics || "Browse Topics"} />
|
|
<View style={styles.topicGrid}>
|
|
<View style={styles.topicRow}>
|
|
{renderTopic(topics[0])}
|
|
{renderTopic(topics[1])}
|
|
</View>
|
|
<View style={styles.topicRow}>
|
|
{renderTopic(topics[2])}
|
|
{renderTopic(topics[3])}
|
|
</View>
|
|
</View>
|
|
|
|
{/* FAQs */}
|
|
<AISectionHeader title={t.faqTitle || "Frequently Asked Questions (FAQ)"} />
|
|
<View style={styles.faqList}>
|
|
{faqs.map((faq: any) => (
|
|
<AIPressable key={faq.id} style={[styles.faqCard, { backgroundColor: cardBg, borderColor: border }]}>
|
|
<View style={styles.faqRow}>
|
|
<View style={styles.faqIconBox}>
|
|
<Feather name="help-circle" size={18} color={colors.primary} />
|
|
</View>
|
|
<View style={{ flex: 1 }}>
|
|
<Text style={[styles.question, { color: colors.text }]}>{faq.q}</Text>
|
|
<Text style={[styles.answer, { color: subText }]}>{faq.a}</Text>
|
|
</View>
|
|
<Feather name="chevron-right" size={16} color={subText} />
|
|
</View>
|
|
</AIPressable>
|
|
))}
|
|
</View>
|
|
|
|
{/* Contact Footer */}
|
|
<View style={styles.footerRow}>
|
|
<AIPressable style={styles.supportBtn} onPress={() => handleContactSupport('whatsapp')}>
|
|
<View style={[styles.contactCard, { backgroundColor: '#1A1A1A' }]}>
|
|
<View style={[styles.contactIcon, { backgroundColor: '#25D36620' }]}>
|
|
<Feather name="message-circle" size={20} color="#25D366" />
|
|
</View>
|
|
<Text style={styles.contactLabel}>{t.whatsapp || 'WhatsApp'}</Text>
|
|
</View>
|
|
</AIPressable>
|
|
|
|
<AIPressable style={styles.supportBtn} onPress={() => handleContactSupport('email')}>
|
|
<View style={[styles.contactCard, { backgroundColor: '#1A1A1A' }]}>
|
|
<View style={[styles.contactIcon, { backgroundColor: colors.primary + '20' }]}>
|
|
<Feather name="mail" size={20} color={colors.primary} />
|
|
</View>
|
|
<Text style={styles.contactLabel}>{t.emailSupport || 'Email Support'}</Text>
|
|
</View>
|
|
</AIPressable>
|
|
</View>
|
|
|
|
<View style={{ height: 110 }} />
|
|
</View>
|
|
</AppScreen>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
header: { paddingHorizontal: 24, paddingTop: 20, marginBottom: 20 },
|
|
title: { fontSize: 32, fontFamily: 'Outfit_800ExtraBold', letterSpacing: -0.5 },
|
|
subtitle: { fontSize: 13, fontFamily: 'Outfit_400Regular', marginTop: 4 },
|
|
|
|
searchSection: { paddingHorizontal: 24, marginBottom: 28 },
|
|
searchBox: { flexDirection: 'row', alignItems: 'center', height: 56, borderRadius: 16, borderWidth: 1, paddingHorizontal: 16, gap: 12 },
|
|
searchInput: { flex: 1, fontSize: 15, fontFamily: 'Outfit_500Medium' },
|
|
|
|
topicGrid: { paddingHorizontal: 24, gap: 12, marginBottom: 24 },
|
|
topicRow: { flexDirection: 'row', gap: 12 },
|
|
topicWrapper: { flex: 1 },
|
|
topicCard: { height: 100, borderRadius: 20, borderWidth: 1, alignItems: 'center', justifyContent: 'center', gap: 10 },
|
|
topicName: { fontSize: 13, fontFamily: 'Outfit_700Bold' },
|
|
|
|
faqList: { paddingHorizontal: 24, gap: 12 },
|
|
faqCard: { borderRadius: 24, borderWidth: 1, padding: 16 },
|
|
faqRow: { flexDirection: 'row', alignItems: 'center', gap: 14 },
|
|
faqIconBox: { width: 36, height: 36, borderRadius: 10, backgroundColor: '#C6F13520', alignItems: 'center', justifyContent: 'center' },
|
|
question: { fontSize: 14, fontFamily: 'Outfit_700Bold', marginBottom: 2 },
|
|
answer: { fontSize: 12, fontFamily: 'Outfit_400Regular', lineHeight: 18 },
|
|
|
|
footerRow: { flexDirection: 'row', paddingHorizontal: 24, gap: 12, marginTop: 32 },
|
|
supportBtn: { flex: 1 },
|
|
contactCard: { height: 120, borderRadius: 24, alignItems: 'center', justifyContent: 'center', gap: 12 },
|
|
contactIcon: { width: 44, height: 44, borderRadius: 14, alignItems: 'center', justifyContent: 'center' },
|
|
contactLabel: { color: '#FFFFFF', fontSize: 13, fontFamily: 'Outfit_700Bold' },
|
|
});
|