WellNuo/app/(auth)/add-loved-one.tsx

307 lines
8.3 KiB
TypeScript

import React, { useState, useCallback } from 'react';
import {
View,
Text,
StyleSheet,
KeyboardAvoidingView,
Platform,
ScrollView,
TouchableOpacity,
} from 'react-native';
import { router, useLocalSearchParams } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { ErrorMessage } from '@/components/ui/ErrorMessage';
import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
import { api } from '@/services/api';
export default function AddLovedOneScreen() {
const params = useLocalSearchParams<{ email: string; partnerCode: string }>();
const email = params.email || '';
const partnerCode = params.partnerCode || '';
const [lovedOneName, setLovedOneName] = useState('');
const [relationship, setRelationship] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const relationships = [
{ id: 'parent', label: 'Parent', icon: 'people' },
{ id: 'grandparent', label: 'Grandparent', icon: 'heart' },
{ id: 'spouse', label: 'Spouse', icon: 'heart-circle' },
{ id: 'other', label: 'Other', icon: 'person' },
];
const handleContinue = useCallback(async () => {
setError(null);
const trimmedName = lovedOneName.trim();
if (!trimmedName) {
setError('Please enter the name of your loved one');
return;
}
if (!relationship) {
setError('Please select your relationship');
return;
}
setIsLoading(true);
try {
// TODO: Save loved one data to backend
// For now, just navigate to the purchase/subscription screen
router.replace({
pathname: '/(auth)/purchase',
params: {
lovedOneName: trimmedName,
relationship,
partnerCode,
},
});
} catch (err) {
setError(err instanceof Error ? err.message : 'Something went wrong');
} finally {
setIsLoading(false);
}
}, [lovedOneName, relationship, partnerCode]);
const handleSkip = async () => {
// Mark onboarding as completed so we don't redirect back here
await api.setOnboardingCompleted(true);
// Skip and go to main app without adding loved one
router.replace('/(tabs)');
};
return (
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<ScrollView
contentContainerStyle={styles.scrollContent}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
{/* Skip Button */}
<View style={styles.headerRow}>
<View style={{ width: 44 }} />
<TouchableOpacity style={styles.skipButton} onPress={handleSkip}>
<Text style={styles.skipText}>Skip for now</Text>
</TouchableOpacity>
</View>
{/* Icon */}
<View style={styles.iconContainer}>
<View style={styles.iconCircle}>
<Ionicons name="heart" size={48} color={AppColors.primary} />
</View>
</View>
{/* Header */}
<View style={styles.header}>
<Text style={styles.title}>Add a Loved One</Text>
<Text style={styles.subtitle}>
Tell us about the person you want to care for
</Text>
</View>
{/* Error Message */}
{error && (
<ErrorMessage
message={error}
onDismiss={() => setError(null)}
/>
)}
{/* Form */}
<View style={styles.form}>
<Input
label="Their Name"
placeholder="e.g., Mom, Grandma Julia"
leftIcon="person-outline"
value={lovedOneName}
onChangeText={(text) => {
setLovedOneName(text);
setError(null);
}}
autoCapitalize="words"
autoCorrect={false}
editable={!isLoading}
returnKeyType="done"
/>
{/* Relationship Selection */}
<View style={styles.relationshipSection}>
<Text style={styles.relationshipLabel}>Relationship</Text>
<View style={styles.relationshipGrid}>
{relationships.map((rel) => (
<TouchableOpacity
key={rel.id}
style={[
styles.relationshipCard,
relationship === rel.id && styles.relationshipCardSelected,
]}
onPress={() => {
setRelationship(rel.id);
setError(null);
}}
disabled={isLoading}
>
<Ionicons
name={rel.icon as keyof typeof Ionicons.glyphMap}
size={24}
color={relationship === rel.id ? AppColors.primary : AppColors.textSecondary}
/>
<Text
style={[
styles.relationshipText,
relationship === rel.id && styles.relationshipTextSelected,
]}
>
{rel.label}
</Text>
</TouchableOpacity>
))}
</View>
</View>
</View>
{/* Continue Button */}
<View style={styles.buttonContainer}>
<Button
title="Continue"
onPress={handleContinue}
loading={isLoading}
fullWidth
size="lg"
/>
</View>
{/* Info */}
<View style={styles.infoContainer}>
<Text style={styles.infoText}>
You'll be able to add more loved ones later and invite family members to help care for them
</Text>
</View>
</ScrollView>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: AppColors.background,
},
scrollContent: {
flexGrow: 1,
paddingHorizontal: Spacing.lg,
paddingTop: Spacing.xl,
paddingBottom: Spacing.xl,
},
headerRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: Spacing.xl,
},
skipButton: {
paddingVertical: Spacing.sm,
paddingHorizontal: Spacing.md,
},
skipText: {
fontSize: FontSizes.base,
color: AppColors.textSecondary,
fontWeight: '500',
},
iconContainer: {
alignItems: 'center',
marginBottom: Spacing.xl,
},
iconCircle: {
width: 100,
height: 100,
borderRadius: 50,
backgroundColor: `${AppColors.primary}15`,
justifyContent: 'center',
alignItems: 'center',
},
header: {
alignItems: 'center',
marginBottom: Spacing.xl,
},
title: {
fontSize: FontSizes['2xl'],
fontWeight: '700',
color: AppColors.textPrimary,
marginBottom: Spacing.md,
textAlign: 'center',
},
subtitle: {
fontSize: FontSizes.base,
color: AppColors.textSecondary,
textAlign: 'center',
},
form: {
gap: Spacing.lg,
},
relationshipSection: {
gap: Spacing.sm,
},
relationshipLabel: {
fontSize: FontSizes.sm,
fontWeight: '600',
color: AppColors.textPrimary,
marginBottom: Spacing.xs,
},
relationshipGrid: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: Spacing.sm,
},
relationshipCard: {
flex: 1,
minWidth: '45%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
gap: Spacing.sm,
paddingVertical: Spacing.md,
paddingHorizontal: Spacing.md,
borderRadius: BorderRadius.md,
borderWidth: 2,
borderColor: AppColors.border,
backgroundColor: AppColors.surface,
},
relationshipCardSelected: {
borderColor: AppColors.primary,
backgroundColor: `${AppColors.primary}10`,
},
relationshipText: {
fontSize: FontSizes.base,
color: AppColors.textSecondary,
fontWeight: '500',
},
relationshipTextSelected: {
color: AppColors.primary,
},
buttonContainer: {
marginTop: Spacing.xl,
},
infoContainer: {
alignItems: 'center',
marginTop: Spacing.lg,
paddingHorizontal: Spacing.md,
},
infoText: {
fontSize: FontSizes.sm,
color: AppColors.textMuted,
textAlign: 'center',
lineHeight: 20,
},
});