- Voice tab: simplified interface, voice picker improvements - Subscription: Stripe integration, purchase flow updates - Beneficiaries: dashboard, sharing, improved management - Profile: drawer, edit, help, privacy sections - Theme: expanded constants, new colors - New components: MockDashboard, ProfileDrawer, Toast - Backend: Stripe routes additions - Auth: activate, add-loved-one, purchase screens
318 lines
10 KiB
TypeScript
318 lines
10 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
ScrollView,
|
|
TouchableOpacity,
|
|
TextInput,
|
|
Linking,
|
|
} from 'react-native';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
import { AppColors, BorderRadius, FontSizes, Spacing, FontWeights } from '@/constants/theme';
|
|
import { PageHeader } from '@/components/PageHeader';
|
|
|
|
interface FAQItemProps {
|
|
question: string;
|
|
answer: string;
|
|
isExpanded: boolean;
|
|
onToggle: () => void;
|
|
}
|
|
|
|
function FAQItem({ question, answer, isExpanded, onToggle }: FAQItemProps) {
|
|
return (
|
|
<TouchableOpacity style={styles.faqItem} onPress={onToggle} activeOpacity={0.7}>
|
|
<View style={styles.faqHeader}>
|
|
<Text style={styles.faqQuestion}>{question}</Text>
|
|
<Ionicons
|
|
name={isExpanded ? 'chevron-up' : 'chevron-down'}
|
|
size={20}
|
|
color={AppColors.textMuted}
|
|
/>
|
|
</View>
|
|
{isExpanded && (
|
|
<Text style={styles.faqAnswer}>{answer}</Text>
|
|
)}
|
|
</TouchableOpacity>
|
|
);
|
|
}
|
|
|
|
export default function HelpScreen() {
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
const [expandedFAQ, setExpandedFAQ] = useState<number | null>(null);
|
|
|
|
const faqs = [
|
|
{
|
|
question: 'How do I add a new beneficiary?',
|
|
answer: 'Tap the "+" button on the Home screen or go to Add Loved One. Enter their name, activate your WellNuo kit with the 6-digit code, and follow the setup instructions.',
|
|
},
|
|
{
|
|
question: 'What does the wellness score mean?',
|
|
answer: 'The wellness score (0-100%) reflects the overall health pattern of your beneficiary based on daily activities, sleep patterns, movement data, and sensor readings. A score above 70% indicates healthy patterns, 40-70% suggests some concerns, and below 40% may require attention.',
|
|
},
|
|
{
|
|
question: 'How often is the data updated?',
|
|
answer: 'Sensor data is collected in real-time and synced every few minutes. Dashboard summaries are calculated daily. Emergency alerts are instant and will notify you immediately.',
|
|
},
|
|
{
|
|
question: 'What triggers an emergency alert?',
|
|
answer: 'Emergency alerts are triggered by: falls detected by motion sensors, prolonged inactivity exceeding normal patterns, SOS button press by the beneficiary, and abnormal environmental readings.',
|
|
},
|
|
{
|
|
question: 'Can I share access with family members?',
|
|
answer: 'Yes! Multiple family members can monitor the same beneficiary. Each caregiver will have their own account and can set their own notification preferences.',
|
|
},
|
|
{
|
|
question: 'How do I change notification settings?',
|
|
answer: 'Go to Profile > Settings to customize your alert preferences. You can enable or disable push notifications and email alerts.',
|
|
},
|
|
{
|
|
question: 'Is my data secure?',
|
|
answer: 'Yes. WellNuo uses encryption for all data transmission. Your data is stored securely, and we never share personal information with third parties.',
|
|
},
|
|
{
|
|
question: 'What devices are in the Starter Kit?',
|
|
answer: 'The WellNuo Starter Kit includes: motion sensor (PIR), door/window sensor, temperature & humidity sensor, and the WellNuo Hub that connects everything.',
|
|
},
|
|
{
|
|
question: 'How do I activate my kit?',
|
|
answer: 'After purchase, you\'ll receive a 6-digit activation code. Go to Add Loved One, enter the code, and the app will guide you through connecting each sensor.',
|
|
},
|
|
{
|
|
question: 'What if a sensor goes offline?',
|
|
answer: 'Check that the sensor has battery power and is within range of the WellNuo Hub. You can see sensor status on the beneficiary detail page. If issues persist, contact support.',
|
|
},
|
|
];
|
|
|
|
const filteredFAQs = faqs.filter(
|
|
faq =>
|
|
faq.question.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
faq.answer.toLowerCase().includes(searchQuery.toLowerCase())
|
|
);
|
|
|
|
return (
|
|
<SafeAreaView style={styles.container} edges={['top', 'bottom']}>
|
|
<PageHeader title="Help Center" />
|
|
<ScrollView showsVerticalScrollIndicator={false}>
|
|
{/* Search */}
|
|
<View style={styles.searchSection}>
|
|
<View style={styles.searchContainer}>
|
|
<Ionicons name="search" size={20} color={AppColors.textMuted} />
|
|
<TextInput
|
|
style={styles.searchInput}
|
|
placeholder="Search FAQ..."
|
|
placeholderTextColor={AppColors.textMuted}
|
|
value={searchQuery}
|
|
onChangeText={setSearchQuery}
|
|
/>
|
|
{searchQuery.length > 0 && (
|
|
<TouchableOpacity onPress={() => setSearchQuery('')}>
|
|
<Ionicons name="close-circle" size={20} color={AppColors.textMuted} />
|
|
</TouchableOpacity>
|
|
)}
|
|
</View>
|
|
</View>
|
|
|
|
{/* FAQs */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>Frequently Asked Questions</Text>
|
|
<View style={styles.faqContainer}>
|
|
{filteredFAQs.length > 0 ? (
|
|
filteredFAQs.map((faq, index) => (
|
|
<View key={index}>
|
|
<FAQItem
|
|
question={faq.question}
|
|
answer={faq.answer}
|
|
isExpanded={expandedFAQ === index}
|
|
onToggle={() => setExpandedFAQ(expandedFAQ === index ? null : index)}
|
|
/>
|
|
{index < filteredFAQs.length - 1 && <View style={styles.faqDivider} />}
|
|
</View>
|
|
))
|
|
) : (
|
|
<View style={styles.noResults}>
|
|
<Ionicons name="search-outline" size={48} color={AppColors.textMuted} />
|
|
<Text style={styles.noResultsText}>No results found</Text>
|
|
<Text style={styles.noResultsHint}>Try different keywords</Text>
|
|
</View>
|
|
)}
|
|
</View>
|
|
</View>
|
|
|
|
{/* Contact Support */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>Contact Support</Text>
|
|
<View style={styles.contactCard}>
|
|
<View style={styles.contactItem}>
|
|
<View style={styles.contactIcon}>
|
|
<Ionicons name="mail" size={22} color={AppColors.primary} />
|
|
</View>
|
|
<View style={styles.contactInfo}>
|
|
<Text style={styles.contactLabel}>Email</Text>
|
|
<TouchableOpacity onPress={() => Linking.openURL('mailto:support@wellnuo.com')}>
|
|
<Text style={styles.contactValue}>support@wellnuo.com</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
|
|
<View style={styles.contactDivider} />
|
|
|
|
<View style={styles.contactItem}>
|
|
<View style={styles.contactIcon}>
|
|
<Ionicons name="call" size={22} color={AppColors.primary} />
|
|
</View>
|
|
<View style={styles.contactInfo}>
|
|
<Text style={styles.contactLabel}>Phone</Text>
|
|
<TouchableOpacity onPress={() => Linking.openURL('tel:+18005551234')}>
|
|
<Text style={styles.contactValue}>1-800-555-1234</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
|
|
<View style={styles.contactDivider} />
|
|
|
|
<View style={styles.contactItem}>
|
|
<View style={styles.contactIcon}>
|
|
<Ionicons name="time" size={22} color={AppColors.primary} />
|
|
</View>
|
|
<View style={styles.contactInfo}>
|
|
<Text style={styles.contactLabel}>Hours</Text>
|
|
<Text style={styles.contactHours}>Mon - Fri: 9am - 6pm EST</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Spacer for bottom */}
|
|
<View style={{ height: Spacing.xl }} />
|
|
</ScrollView>
|
|
</SafeAreaView>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: AppColors.background,
|
|
},
|
|
searchSection: {
|
|
padding: Spacing.lg,
|
|
},
|
|
searchContainer: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: AppColors.surface,
|
|
borderRadius: BorderRadius.lg,
|
|
paddingHorizontal: Spacing.md,
|
|
paddingVertical: Spacing.sm,
|
|
},
|
|
searchInput: {
|
|
flex: 1,
|
|
marginLeft: Spacing.sm,
|
|
fontSize: FontSizes.base,
|
|
color: AppColors.textPrimary,
|
|
},
|
|
section: {
|
|
marginTop: Spacing.sm,
|
|
},
|
|
sectionTitle: {
|
|
fontSize: FontSizes.xs,
|
|
fontWeight: FontWeights.semibold,
|
|
color: AppColors.textMuted,
|
|
paddingHorizontal: Spacing.lg,
|
|
paddingVertical: Spacing.sm,
|
|
textTransform: 'uppercase',
|
|
letterSpacing: 0.5,
|
|
},
|
|
faqContainer: {
|
|
backgroundColor: AppColors.surface,
|
|
marginHorizontal: Spacing.lg,
|
|
borderRadius: BorderRadius.xl,
|
|
},
|
|
faqItem: {
|
|
paddingVertical: Spacing.md,
|
|
paddingHorizontal: Spacing.lg,
|
|
},
|
|
faqHeader: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
},
|
|
faqQuestion: {
|
|
flex: 1,
|
|
fontSize: FontSizes.base,
|
|
fontWeight: FontWeights.medium,
|
|
color: AppColors.textPrimary,
|
|
marginRight: Spacing.sm,
|
|
},
|
|
faqAnswer: {
|
|
fontSize: FontSizes.sm,
|
|
color: AppColors.textSecondary,
|
|
marginTop: Spacing.sm,
|
|
lineHeight: 20,
|
|
},
|
|
faqDivider: {
|
|
height: 1,
|
|
backgroundColor: AppColors.borderLight,
|
|
marginHorizontal: Spacing.lg,
|
|
},
|
|
noResults: {
|
|
alignItems: 'center',
|
|
paddingVertical: Spacing.xl,
|
|
},
|
|
noResultsText: {
|
|
fontSize: FontSizes.base,
|
|
fontWeight: FontWeights.medium,
|
|
color: AppColors.textPrimary,
|
|
marginTop: Spacing.md,
|
|
},
|
|
noResultsHint: {
|
|
fontSize: FontSizes.sm,
|
|
color: AppColors.textMuted,
|
|
marginTop: Spacing.xs,
|
|
},
|
|
contactCard: {
|
|
backgroundColor: AppColors.surface,
|
|
marginHorizontal: Spacing.lg,
|
|
borderRadius: BorderRadius.xl,
|
|
padding: Spacing.md,
|
|
},
|
|
contactItem: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingVertical: Spacing.sm,
|
|
},
|
|
contactIcon: {
|
|
width: 44,
|
|
height: 44,
|
|
borderRadius: BorderRadius.lg,
|
|
backgroundColor: AppColors.primarySubtle,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
marginRight: Spacing.md,
|
|
},
|
|
contactInfo: {
|
|
flex: 1,
|
|
},
|
|
contactLabel: {
|
|
fontSize: FontSizes.xs,
|
|
color: AppColors.textMuted,
|
|
marginBottom: 2,
|
|
},
|
|
contactValue: {
|
|
fontSize: FontSizes.base,
|
|
fontWeight: FontWeights.medium,
|
|
color: AppColors.primary,
|
|
},
|
|
contactHours: {
|
|
fontSize: FontSizes.base,
|
|
color: AppColors.textPrimary,
|
|
},
|
|
contactDivider: {
|
|
height: 1,
|
|
backgroundColor: AppColors.borderLight,
|
|
marginLeft: 56,
|
|
},
|
|
});
|