Changes: - Updated app.json, eas.json configurations - Modified login, chat, profile, dashboard screens - Added profile subpages (about, edit, help, language, notifications, privacy, subscription, support, terms) - Updated BeneficiaryContext - Updated API service and types - Updated discussion questions scheme - Added .history to gitignore 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
476 lines
13 KiB
TypeScript
476 lines
13 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
ScrollView,
|
|
TouchableOpacity,
|
|
TextInput,
|
|
Linking,
|
|
Alert,
|
|
KeyboardAvoidingView,
|
|
Platform,
|
|
} from 'react-native';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
import { router } from 'expo-router';
|
|
import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
|
|
|
|
interface ContactMethodProps {
|
|
icon: keyof typeof Ionicons.glyphMap;
|
|
iconColor: string;
|
|
iconBgColor: string;
|
|
title: string;
|
|
subtitle: string;
|
|
onPress: () => void;
|
|
}
|
|
|
|
function ContactMethod({
|
|
icon,
|
|
iconColor,
|
|
iconBgColor,
|
|
title,
|
|
subtitle,
|
|
onPress,
|
|
}: ContactMethodProps) {
|
|
return (
|
|
<TouchableOpacity style={styles.contactMethod} onPress={onPress}>
|
|
<View style={[styles.contactIcon, { backgroundColor: iconBgColor }]}>
|
|
<Ionicons name={icon} size={24} color={iconColor} />
|
|
</View>
|
|
<View style={styles.contactContent}>
|
|
<Text style={styles.contactTitle}>{title}</Text>
|
|
<Text style={styles.contactSubtitle}>{subtitle}</Text>
|
|
</View>
|
|
<Ionicons name="chevron-forward" size={20} color={AppColors.textMuted} />
|
|
</TouchableOpacity>
|
|
);
|
|
}
|
|
|
|
export default function SupportScreen() {
|
|
const [subject, setSubject] = useState('');
|
|
const [message, setMessage] = useState('');
|
|
const [category, setCategory] = useState('');
|
|
const [isSending, setIsSending] = useState(false);
|
|
|
|
const categories = [
|
|
'Technical Issue',
|
|
'Billing Question',
|
|
'Feature Request',
|
|
'Account Help',
|
|
'Emergency',
|
|
'Other',
|
|
];
|
|
|
|
const handleCall = () => {
|
|
Linking.openURL('tel:+15551234567').catch(() => {
|
|
Alert.alert('Error', 'Unable to make phone call');
|
|
});
|
|
};
|
|
|
|
const handleEmail = () => {
|
|
Linking.openURL('mailto:support@wellnuo.com?subject=Support Request').catch(() => {
|
|
Alert.alert('Error', 'Unable to open email client');
|
|
});
|
|
};
|
|
|
|
const handleChat = () => {
|
|
Alert.alert(
|
|
'Live Chat',
|
|
'Connecting to a support agent...\n\nEstimated wait time: 2 minutes',
|
|
[
|
|
{ text: 'Cancel', style: 'cancel' },
|
|
{ text: 'Start Chat', onPress: () => Alert.alert('Coming Soon', 'Live chat feature coming soon!') },
|
|
]
|
|
);
|
|
};
|
|
|
|
const handleSendTicket = async () => {
|
|
if (!category) {
|
|
Alert.alert('Error', 'Please select a category');
|
|
return;
|
|
}
|
|
if (!subject.trim()) {
|
|
Alert.alert('Error', 'Please enter a subject');
|
|
return;
|
|
}
|
|
if (!message.trim()) {
|
|
Alert.alert('Error', 'Please describe your issue');
|
|
return;
|
|
}
|
|
|
|
setIsSending(true);
|
|
|
|
// Simulate API call
|
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
|
setIsSending(false);
|
|
Alert.alert(
|
|
'Ticket Submitted',
|
|
'Thank you for contacting us!\n\nTicket #WN-2024-12345\n\nWe\'ll respond within 24 hours.',
|
|
[{ text: 'OK', onPress: () => router.back() }]
|
|
);
|
|
};
|
|
|
|
return (
|
|
<SafeAreaView style={styles.container} edges={['bottom']}>
|
|
<KeyboardAvoidingView
|
|
style={styles.keyboardView}
|
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
>
|
|
<ScrollView showsVerticalScrollIndicator={false}>
|
|
{/* Quick Contact */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>Quick Contact</Text>
|
|
<View style={styles.card}>
|
|
<ContactMethod
|
|
icon="call"
|
|
iconColor="#10B981"
|
|
iconBgColor="#D1FAE5"
|
|
title="Call Us"
|
|
subtitle="+1 (555) 123-4567"
|
|
onPress={handleCall}
|
|
/>
|
|
<View style={styles.divider} />
|
|
<ContactMethod
|
|
icon="mail"
|
|
iconColor="#3B82F6"
|
|
iconBgColor="#DBEAFE"
|
|
title="Email Support"
|
|
subtitle="support@wellnuo.com"
|
|
onPress={handleEmail}
|
|
/>
|
|
<View style={styles.divider} />
|
|
<ContactMethod
|
|
icon="chatbubbles"
|
|
iconColor="#8B5CF6"
|
|
iconBgColor="#EDE9FE"
|
|
title="Live Chat"
|
|
subtitle="Available 24/7"
|
|
onPress={handleChat}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Support Hours */}
|
|
<View style={styles.section}>
|
|
<View style={styles.hoursCard}>
|
|
<Ionicons name="time" size={24} color={AppColors.primary} />
|
|
<View style={styles.hoursContent}>
|
|
<Text style={styles.hoursTitle}>Support Hours</Text>
|
|
<Text style={styles.hoursText}>Phone: Mon-Fri 8am-8pm EST</Text>
|
|
<Text style={styles.hoursText}>Email & Chat: 24/7</Text>
|
|
<Text style={styles.hoursText}>Emergency: 24/7</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Submit a Ticket */}
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>Submit a Ticket</Text>
|
|
<View style={styles.formCard}>
|
|
{/* Category */}
|
|
<View style={styles.inputGroup}>
|
|
<Text style={styles.label}>Category *</Text>
|
|
<View style={styles.categoryContainer}>
|
|
{categories.map((cat) => (
|
|
<TouchableOpacity
|
|
key={cat}
|
|
style={[
|
|
styles.categoryChip,
|
|
category === cat && styles.categoryChipSelected,
|
|
]}
|
|
onPress={() => setCategory(cat)}
|
|
>
|
|
<Text
|
|
style={[
|
|
styles.categoryChipText,
|
|
category === cat && styles.categoryChipTextSelected,
|
|
]}
|
|
>
|
|
{cat}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
))}
|
|
</View>
|
|
</View>
|
|
|
|
{/* Subject */}
|
|
<View style={styles.inputGroup}>
|
|
<Text style={styles.label}>Subject *</Text>
|
|
<TextInput
|
|
style={styles.input}
|
|
value={subject}
|
|
onChangeText={setSubject}
|
|
placeholder="Brief description of your issue"
|
|
placeholderTextColor={AppColors.textMuted}
|
|
/>
|
|
</View>
|
|
|
|
{/* Message */}
|
|
<View style={styles.inputGroup}>
|
|
<Text style={styles.label}>Message *</Text>
|
|
<TextInput
|
|
style={[styles.input, styles.textArea]}
|
|
value={message}
|
|
onChangeText={setMessage}
|
|
placeholder="Please describe your issue in detail. Include any error messages or steps to reproduce the problem."
|
|
placeholderTextColor={AppColors.textMuted}
|
|
multiline
|
|
numberOfLines={5}
|
|
textAlignVertical="top"
|
|
/>
|
|
</View>
|
|
|
|
{/* Attachments hint */}
|
|
<View style={styles.attachmentHint}>
|
|
<Ionicons name="attach" size={16} color={AppColors.textMuted} />
|
|
<Text style={styles.attachmentHintText}>
|
|
Need to attach screenshots? Reply to your ticket email.
|
|
</Text>
|
|
</View>
|
|
|
|
{/* Submit Button */}
|
|
<TouchableOpacity
|
|
style={[styles.submitButton, isSending && styles.submitButtonDisabled]}
|
|
onPress={handleSendTicket}
|
|
disabled={isSending}
|
|
>
|
|
<Text style={styles.submitButtonText}>
|
|
{isSending ? 'Sending...' : 'Submit Ticket'}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
|
|
{/* FAQ Link */}
|
|
<View style={styles.section}>
|
|
<TouchableOpacity
|
|
style={styles.faqLink}
|
|
onPress={() => router.push('/profile/help')}
|
|
>
|
|
<View style={styles.faqLinkContent}>
|
|
<Ionicons name="help-circle" size={24} color={AppColors.primary} />
|
|
<View style={styles.faqLinkText}>
|
|
<Text style={styles.faqLinkTitle}>Check our Help Center</Text>
|
|
<Text style={styles.faqLinkSubtitle}>
|
|
Find answers to common questions
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
<Ionicons name="chevron-forward" size={20} color={AppColors.textMuted} />
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
{/* Emergency Notice */}
|
|
<View style={styles.emergencyNotice}>
|
|
<Ionicons name="warning" size={20} color={AppColors.error} />
|
|
<Text style={styles.emergencyText}>
|
|
If you're experiencing a medical emergency, please call 911 or your local
|
|
emergency services immediately.
|
|
</Text>
|
|
</View>
|
|
</ScrollView>
|
|
</KeyboardAvoidingView>
|
|
</SafeAreaView>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: AppColors.surface,
|
|
},
|
|
keyboardView: {
|
|
flex: 1,
|
|
},
|
|
section: {
|
|
marginTop: Spacing.md,
|
|
},
|
|
sectionTitle: {
|
|
fontSize: FontSizes.sm,
|
|
fontWeight: '600',
|
|
color: AppColors.textSecondary,
|
|
paddingHorizontal: Spacing.lg,
|
|
paddingVertical: Spacing.sm,
|
|
textTransform: 'uppercase',
|
|
},
|
|
card: {
|
|
backgroundColor: AppColors.background,
|
|
},
|
|
contactMethod: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingVertical: Spacing.md,
|
|
paddingHorizontal: Spacing.lg,
|
|
},
|
|
contactIcon: {
|
|
width: 48,
|
|
height: 48,
|
|
borderRadius: BorderRadius.md,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
contactContent: {
|
|
flex: 1,
|
|
marginLeft: Spacing.md,
|
|
},
|
|
contactTitle: {
|
|
fontSize: FontSizes.base,
|
|
fontWeight: '500',
|
|
color: AppColors.textPrimary,
|
|
},
|
|
contactSubtitle: {
|
|
fontSize: FontSizes.sm,
|
|
color: AppColors.textSecondary,
|
|
marginTop: 2,
|
|
},
|
|
divider: {
|
|
height: 1,
|
|
backgroundColor: AppColors.border,
|
|
marginLeft: Spacing.lg + 48 + Spacing.md,
|
|
},
|
|
hoursCard: {
|
|
flexDirection: 'row',
|
|
backgroundColor: AppColors.background,
|
|
marginHorizontal: Spacing.lg,
|
|
padding: Spacing.md,
|
|
borderRadius: BorderRadius.lg,
|
|
alignItems: 'flex-start',
|
|
},
|
|
hoursContent: {
|
|
flex: 1,
|
|
marginLeft: Spacing.md,
|
|
},
|
|
hoursTitle: {
|
|
fontSize: FontSizes.base,
|
|
fontWeight: '600',
|
|
color: AppColors.textPrimary,
|
|
marginBottom: Spacing.xs,
|
|
},
|
|
hoursText: {
|
|
fontSize: FontSizes.sm,
|
|
color: AppColors.textSecondary,
|
|
marginTop: 2,
|
|
},
|
|
formCard: {
|
|
backgroundColor: AppColors.background,
|
|
padding: Spacing.lg,
|
|
},
|
|
inputGroup: {
|
|
marginBottom: Spacing.md,
|
|
},
|
|
label: {
|
|
fontSize: FontSizes.sm,
|
|
fontWeight: '600',
|
|
color: AppColors.textPrimary,
|
|
marginBottom: Spacing.xs,
|
|
},
|
|
input: {
|
|
backgroundColor: AppColors.surface,
|
|
borderRadius: BorderRadius.md,
|
|
paddingHorizontal: Spacing.md,
|
|
paddingVertical: Spacing.md,
|
|
fontSize: FontSizes.base,
|
|
color: AppColors.textPrimary,
|
|
borderWidth: 1,
|
|
borderColor: AppColors.border,
|
|
},
|
|
textArea: {
|
|
minHeight: 120,
|
|
paddingTop: Spacing.md,
|
|
},
|
|
categoryContainer: {
|
|
flexDirection: 'row',
|
|
flexWrap: 'wrap',
|
|
marginTop: Spacing.xs,
|
|
},
|
|
categoryChip: {
|
|
paddingHorizontal: Spacing.md,
|
|
paddingVertical: Spacing.xs,
|
|
borderRadius: BorderRadius.full,
|
|
backgroundColor: AppColors.surface,
|
|
marginRight: Spacing.xs,
|
|
marginBottom: Spacing.xs,
|
|
borderWidth: 1,
|
|
borderColor: AppColors.border,
|
|
},
|
|
categoryChipSelected: {
|
|
backgroundColor: AppColors.primary,
|
|
borderColor: AppColors.primary,
|
|
},
|
|
categoryChipText: {
|
|
fontSize: FontSizes.sm,
|
|
color: AppColors.textSecondary,
|
|
},
|
|
categoryChipTextSelected: {
|
|
color: AppColors.white,
|
|
},
|
|
attachmentHint: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
marginBottom: Spacing.lg,
|
|
},
|
|
attachmentHintText: {
|
|
fontSize: FontSizes.xs,
|
|
color: AppColors.textMuted,
|
|
marginLeft: Spacing.xs,
|
|
},
|
|
submitButton: {
|
|
backgroundColor: AppColors.primary,
|
|
borderRadius: BorderRadius.lg,
|
|
paddingVertical: Spacing.md,
|
|
alignItems: 'center',
|
|
},
|
|
submitButtonDisabled: {
|
|
opacity: 0.6,
|
|
},
|
|
submitButtonText: {
|
|
fontSize: FontSizes.base,
|
|
fontWeight: '600',
|
|
color: AppColors.white,
|
|
},
|
|
faqLink: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: AppColors.background,
|
|
marginHorizontal: Spacing.lg,
|
|
padding: Spacing.md,
|
|
borderRadius: BorderRadius.lg,
|
|
},
|
|
faqLinkContent: {
|
|
flex: 1,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
},
|
|
faqLinkText: {
|
|
marginLeft: Spacing.md,
|
|
},
|
|
faqLinkTitle: {
|
|
fontSize: FontSizes.base,
|
|
fontWeight: '500',
|
|
color: AppColors.textPrimary,
|
|
},
|
|
faqLinkSubtitle: {
|
|
fontSize: FontSizes.xs,
|
|
color: AppColors.textMuted,
|
|
marginTop: 2,
|
|
},
|
|
emergencyNotice: {
|
|
flexDirection: 'row',
|
|
alignItems: 'flex-start',
|
|
backgroundColor: '#FEE2E2',
|
|
marginHorizontal: Spacing.lg,
|
|
marginVertical: Spacing.lg,
|
|
padding: Spacing.md,
|
|
borderRadius: BorderRadius.lg,
|
|
},
|
|
emergencyText: {
|
|
flex: 1,
|
|
fontSize: FontSizes.xs,
|
|
color: AppColors.error,
|
|
marginLeft: Spacing.sm,
|
|
lineHeight: 18,
|
|
},
|
|
});
|