Sergei abcc380984 Sync all changes - profile restructure and scheme updates
- Restructured profile screens location
- Updated beneficiary detail page
- Updated API service
- Updated all scheme files (MainScheme, ENV API, Discussion, AppStore, SysAnal)
- Added PageHeader component

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 16:48:07 -08:00

328 lines
9.9 KiB
TypeScript

import React, { useState } from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
TextInput,
TouchableOpacity,
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 { useAuth } from '@/contexts/AuthContext';
import { PageHeader } from '@/components/PageHeader';
import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
export default function EditProfileScreen() {
const { user } = useAuth();
const [displayName, setDisplayName] = useState(user?.user_name || '');
const [email, setEmail] = useState('');
const [phone, setPhone] = useState('');
const [timezone, setTimezone] = useState('UTC');
const [isSaving, setIsSaving] = useState(false);
const handleSave = async () => {
if (!displayName.trim()) {
Alert.alert('Error', 'Display name is required');
return;
}
setIsSaving(true);
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000));
setIsSaving(false);
Alert.alert(
'Profile Updated',
'Your profile has been updated successfully.',
[{ text: 'OK', onPress: () => router.back() }]
);
};
const handleChangePhoto = () => {
Alert.alert(
'Change Photo',
'Choose an option',
[
{ text: 'Take Photo', onPress: () => Alert.alert('Camera', 'Camera functionality coming soon!') },
{ text: 'Choose from Library', onPress: () => Alert.alert('Library', 'Photo library coming soon!') },
{ text: 'Remove Photo', style: 'destructive', onPress: () => Alert.alert('Removed', 'Photo removed') },
{ text: 'Cancel', style: 'cancel' },
]
);
};
return (
<SafeAreaView style={styles.container} edges={['top', 'bottom']}>
<PageHeader title="Edit Profile" />
<KeyboardAvoidingView
style={styles.keyboardView}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<ScrollView showsVerticalScrollIndicator={false}>
{/* Avatar Section */}
<View style={styles.avatarSection}>
<View style={styles.avatarContainer}>
<Text style={styles.avatarText}>
{displayName?.charAt(0).toUpperCase() || 'U'}
</Text>
</View>
<TouchableOpacity style={styles.changePhotoButton} onPress={handleChangePhoto}>
<Ionicons name="camera" size={16} color={AppColors.white} />
</TouchableOpacity>
<Text style={styles.changePhotoText}>Tap to change photo</Text>
</View>
{/* Form */}
<View style={styles.form}>
<View style={styles.inputGroup}>
<Text style={styles.label}>Display Name *</Text>
<TextInput
style={styles.input}
value={displayName}
onChangeText={setDisplayName}
placeholder="Enter your display name"
placeholderTextColor={AppColors.textMuted}
/>
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>Email Address</Text>
<TextInput
style={styles.input}
value={email}
onChangeText={setEmail}
placeholder="Enter your email"
placeholderTextColor={AppColors.textMuted}
keyboardType="email-address"
autoCapitalize="none"
/>
<Text style={styles.hint}>Used for notifications and account recovery</Text>
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>Phone Number</Text>
<TextInput
style={styles.input}
value={phone}
onChangeText={setPhone}
placeholder="+1 (555) 123-4567"
placeholderTextColor={AppColors.textMuted}
keyboardType="phone-pad"
/>
<Text style={styles.hint}>For emergency contact and SMS alerts</Text>
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>Timezone</Text>
<TouchableOpacity
style={styles.selectInput}
onPress={() => {
Alert.alert(
'Select Timezone',
'Choose your timezone',
[
{ text: 'UTC', onPress: () => setTimezone('UTC') },
{ text: 'America/New_York', onPress: () => setTimezone('America/New_York') },
{ text: 'America/Los_Angeles', onPress: () => setTimezone('America/Los_Angeles') },
{ text: 'Europe/London', onPress: () => setTimezone('Europe/London') },
{ text: 'Cancel', style: 'cancel' },
]
);
}}
>
<Text style={styles.selectText}>{timezone}</Text>
<Ionicons name="chevron-down" size={20} color={AppColors.textMuted} />
</TouchableOpacity>
</View>
{/* Account Info (read-only) */}
<View style={styles.readOnlySection}>
<Text style={styles.readOnlyTitle}>Account Information</Text>
<View style={styles.readOnlyItem}>
<Text style={styles.readOnlyLabel}>User ID</Text>
<Text style={styles.readOnlyValue}>{user?.user_id || 'N/A'}</Text>
</View>
<View style={styles.readOnlyItem}>
<Text style={styles.readOnlyLabel}>Username</Text>
<Text style={styles.readOnlyValue}>{user?.user_name || 'N/A'}</Text>
</View>
<View style={styles.readOnlyItem}>
<Text style={styles.readOnlyLabel}>Role</Text>
<Text style={styles.readOnlyValue}>
{user?.max_role === 2 ? 'Administrator' : 'Caregiver'}
</Text>
</View>
<View style={styles.readOnlyItem}>
<Text style={styles.readOnlyLabel}>Assigned Beneficiaries</Text>
<Text style={styles.readOnlyValue}>
{user?.privileges?.split(',').length || 0}
</Text>
</View>
</View>
</View>
</ScrollView>
{/* Save Button */}
<View style={styles.footer}>
<TouchableOpacity
style={[styles.saveButton, isSaving && styles.saveButtonDisabled]}
onPress={handleSave}
disabled={isSaving}
>
<Text style={styles.saveButtonText}>
{isSaving ? 'Saving...' : 'Save Changes'}
</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: AppColors.surface,
},
keyboardView: {
flex: 1,
},
avatarSection: {
alignItems: 'center',
paddingVertical: Spacing.xl,
backgroundColor: AppColors.background,
},
avatarContainer: {
width: 100,
height: 100,
borderRadius: 50,
backgroundColor: AppColors.primary,
justifyContent: 'center',
alignItems: 'center',
},
avatarText: {
fontSize: 40,
fontWeight: '600',
color: AppColors.white,
},
changePhotoButton: {
position: 'absolute',
bottom: 50,
right: '35%',
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: AppColors.primaryLight,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 2,
borderColor: AppColors.background,
},
changePhotoText: {
marginTop: Spacing.sm,
fontSize: FontSizes.sm,
color: AppColors.primary,
},
form: {
padding: Spacing.lg,
},
inputGroup: {
marginBottom: Spacing.lg,
},
label: {
fontSize: FontSizes.sm,
fontWeight: '600',
color: AppColors.textPrimary,
marginBottom: Spacing.xs,
},
input: {
backgroundColor: AppColors.background,
borderRadius: BorderRadius.md,
paddingHorizontal: Spacing.md,
paddingVertical: Spacing.md,
fontSize: FontSizes.base,
color: AppColors.textPrimary,
borderWidth: 1,
borderColor: AppColors.border,
},
selectInput: {
backgroundColor: AppColors.background,
borderRadius: BorderRadius.md,
paddingHorizontal: Spacing.md,
paddingVertical: Spacing.md,
borderWidth: 1,
borderColor: AppColors.border,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
selectText: {
fontSize: FontSizes.base,
color: AppColors.textPrimary,
},
hint: {
fontSize: FontSizes.xs,
color: AppColors.textMuted,
marginTop: Spacing.xs,
},
readOnlySection: {
marginTop: Spacing.lg,
backgroundColor: AppColors.background,
borderRadius: BorderRadius.lg,
padding: Spacing.md,
},
readOnlyTitle: {
fontSize: FontSizes.sm,
fontWeight: '600',
color: AppColors.textSecondary,
marginBottom: Spacing.md,
},
readOnlyItem: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: Spacing.sm,
borderBottomWidth: 1,
borderBottomColor: AppColors.border,
},
readOnlyLabel: {
fontSize: FontSizes.sm,
color: AppColors.textSecondary,
},
readOnlyValue: {
fontSize: FontSizes.sm,
fontWeight: '500',
color: AppColors.textPrimary,
},
footer: {
padding: Spacing.lg,
backgroundColor: AppColors.background,
borderTopWidth: 1,
borderTopColor: AppColors.border,
},
saveButton: {
backgroundColor: AppColors.primary,
borderRadius: BorderRadius.lg,
paddingVertical: Spacing.md,
alignItems: 'center',
},
saveButtonDisabled: {
opacity: 0.6,
},
saveButtonText: {
fontSize: FontSizes.base,
fontWeight: '600',
color: AppColors.white,
},
});