import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, ScrollView, TextInput, TouchableOpacity, Alert, KeyboardAvoidingView, Platform, Image, } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { SafeAreaView } from 'react-native-safe-area-context'; import { router } from 'expo-router'; import * as SecureStore from 'expo-secure-store'; import * as ImagePicker from 'expo-image-picker'; import { useAuth } from '@/contexts/AuthContext'; import { PageHeader } from '@/components/PageHeader'; import { AppColors, BorderRadius, FontSizes, Spacing, FontWeights, Shadows, } from '@/constants/theme'; export default function EditProfileScreen() { const { user, updateUser } = useAuth(); const [displayName, setDisplayName] = useState(user?.user_name || ''); const [phone, setPhone] = useState(''); const [isSaving, setIsSaving] = useState(false); const [avatarUri, setAvatarUri] = useState(null); // Load saved data from SecureStore useEffect(() => { const loadData = async () => { try { const [savedAvatar, savedPhone, savedName] = await Promise.all([ SecureStore.getItemAsync('userAvatar'), SecureStore.getItemAsync('userPhone'), SecureStore.getItemAsync('userName'), ]); if (savedAvatar) setAvatarUri(savedAvatar); if (savedPhone) setPhone(savedPhone); if (savedName) setDisplayName(savedName); } catch (err) { console.error('Failed to load profile data:', err); } }; loadData(); }, []); const handleSave = async () => { if (!displayName.trim()) { Alert.alert('Error', 'Display name is required'); return; } setIsSaving(true); try { // Save to SecureStore await Promise.all([ SecureStore.setItemAsync('userName', displayName.trim()), phone ? SecureStore.setItemAsync('userPhone', phone) : Promise.resolve(), ]); // Update user in AuthContext if (updateUser) { updateUser({ user_name: displayName.trim() }); } Alert.alert( 'Profile Updated', 'Your profile has been updated successfully.', [{ text: 'OK', onPress: () => router.back() }] ); } catch (error) { console.error('Failed to save profile:', error); Alert.alert('Error', 'Failed to save profile. Please try again.'); } setIsSaving(false); }; const handleChangePhoto = async () => { const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (status !== 'granted') { Alert.alert('Permission needed', 'Please allow access to your photo library to change avatar.'); return; } const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: true, aspect: [1, 1], quality: 0.5, }); if (!result.canceled && result.assets[0]) { const uri = result.assets[0].uri; setAvatarUri(uri); await SecureStore.setItemAsync('userAvatar', uri); } }; const userInitial = displayName?.charAt(0).toUpperCase() || 'U'; return ( {/* Avatar Section */} {avatarUri ? ( ) : ( {userInitial} )} Tap to change photo {/* Form */} Display Name * Email Address {user?.email || 'Not set'} Email cannot be changed Phone Number For emergency contact and SMS alerts {/* Save Button */} {isSaving ? ( Saving... ) : ( <> Save Changes )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: AppColors.background, }, keyboardView: { flex: 1, }, avatarSection: { alignItems: 'center', paddingVertical: Spacing.xl, backgroundColor: AppColors.surface, marginBottom: Spacing.md, }, avatarWrapper: { position: 'relative', }, avatarContainer: { width: 100, height: 100, borderRadius: 50, backgroundColor: AppColors.primary, justifyContent: 'center', alignItems: 'center', }, avatarImage: { width: 100, height: 100, borderRadius: 50, }, avatarText: { fontSize: 40, fontWeight: FontWeights.bold, color: AppColors.white, }, changePhotoButton: { position: 'absolute', bottom: 0, right: 0, width: 32, height: 32, borderRadius: 16, backgroundColor: AppColors.primary, justifyContent: 'center', alignItems: 'center', borderWidth: 3, borderColor: AppColors.surface, }, changePhotoText: { marginTop: Spacing.sm, fontSize: FontSizes.sm, color: AppColors.textMuted, }, form: { padding: Spacing.lg, }, inputGroup: { marginBottom: Spacing.lg, }, label: { fontSize: FontSizes.sm, fontWeight: FontWeights.medium, color: AppColors.textSecondary, marginBottom: Spacing.xs, marginLeft: Spacing.xs, }, inputContainer: { flexDirection: 'row', alignItems: 'center', backgroundColor: AppColors.surface, borderRadius: BorderRadius.lg, paddingHorizontal: Spacing.md, paddingVertical: Spacing.md, borderWidth: 1.5, borderColor: AppColors.borderLight, gap: Spacing.sm, ...Shadows.xs, }, input: { flex: 1, fontSize: FontSizes.base, color: AppColors.textPrimary, }, disabledInput: { backgroundColor: AppColors.surfaceSecondary, borderColor: AppColors.border, }, disabledText: { flex: 1, fontSize: FontSizes.base, color: AppColors.textSecondary, }, lockBadge: { width: 24, height: 24, borderRadius: 12, backgroundColor: AppColors.border, justifyContent: 'center', alignItems: 'center', }, hint: { fontSize: FontSizes.xs, color: AppColors.textMuted, marginTop: Spacing.xs, marginLeft: Spacing.xs, }, footer: { padding: Spacing.lg, backgroundColor: AppColors.surface, borderTopWidth: 1, borderTopColor: AppColors.border, }, saveButton: { flexDirection: 'row', backgroundColor: AppColors.primary, borderRadius: BorderRadius.lg, paddingVertical: Spacing.md, alignItems: 'center', justifyContent: 'center', gap: Spacing.xs, ...Shadows.primary, }, saveButtonDisabled: { opacity: 0.6, }, saveButtonText: { fontSize: FontSizes.base, fontWeight: FontWeights.semibold, color: AppColors.white, }, });