add edit profile feature
This commit is contained in:
parent
0bde09ad5c
commit
51064d95e3
131
mobile/src/screens/EditProfileScreen.tsx
Normal file
131
mobile/src/screens/EditProfileScreen.tsx
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { View, Text, TextInput, TouchableOpacity, ScrollView, ActivityIndicator, useColorScheme, KeyboardAvoidingView, Platform, Image } from 'react-native';
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import { useAuthStore } from '../store/useAuthStore';
|
||||||
|
import { getThemeStyles, commonStyles } from '../theme/styles';
|
||||||
|
import { COLORS } from '../theme/colors';
|
||||||
|
import { useProfileManager } from '../hooks/useProfileManager';
|
||||||
|
|
||||||
|
export default function EditProfileScreen() {
|
||||||
|
const { user } = useAuthStore();
|
||||||
|
|
||||||
|
const colorScheme = useColorScheme();
|
||||||
|
const isDark = colorScheme === 'dark';
|
||||||
|
const themeStyles = getThemeStyles(isDark);
|
||||||
|
const themeColors = isDark ? COLORS.DARK : COLORS.LIGHT;
|
||||||
|
|
||||||
|
const {
|
||||||
|
loading,
|
||||||
|
avatar,
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
phone,
|
||||||
|
address,
|
||||||
|
setFirstName,
|
||||||
|
setLastName,
|
||||||
|
setPhone,
|
||||||
|
setAddress,
|
||||||
|
pickImage,
|
||||||
|
handleSave,
|
||||||
|
} = useProfileManager();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<KeyboardAvoidingView
|
||||||
|
style={themeStyles.container}
|
||||||
|
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
|
||||||
|
keyboardVerticalOffset={Platform.OS === 'ios' ? 100 : 0}
|
||||||
|
>
|
||||||
|
<ScrollView contentContainerStyle={{ padding: 20 }}>
|
||||||
|
<Text style={[commonStyles.title, themeStyles.text, { textAlign: 'left', marginBottom: 20 }]}>
|
||||||
|
Edit Profile
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View style={{ alignItems: 'center', marginBottom: 30 }}>
|
||||||
|
<TouchableOpacity onPress={pickImage} style={{ position: 'relative' }}>
|
||||||
|
<View style={{
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
borderRadius: 50,
|
||||||
|
backgroundColor: themeColors.brand,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}>
|
||||||
|
{avatar ? (
|
||||||
|
<Image source={{ uri: avatar }} style={{ width: '100%', height: '100%' }} />
|
||||||
|
) : (
|
||||||
|
<Text style={{ fontSize: 40, fontWeight: 'bold', color: 'white' }}>
|
||||||
|
{user?.user?.first_name?.charAt(0).toUpperCase() || user?.user?.email?.charAt(0).toUpperCase() || 'U'}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
<View style={{
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
right: 0,
|
||||||
|
backgroundColor: themeColors.card,
|
||||||
|
borderRadius: 15,
|
||||||
|
padding: 6,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: isDark ? '#2d3748' : '#e2e8f0',
|
||||||
|
}}>
|
||||||
|
<Ionicons name="camera" size={18} color={themeColors.text} />
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={commonStyles.form}>
|
||||||
|
<Text style={[commonStyles.label, themeStyles.subtitle]}>First Name</Text>
|
||||||
|
<TextInput
|
||||||
|
style={themeStyles.input}
|
||||||
|
value={firstName}
|
||||||
|
onChangeText={setFirstName}
|
||||||
|
placeholder="Enter first name"
|
||||||
|
placeholderTextColor={isDark ? '#a0aec0' : '#a0aec0'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Text style={[commonStyles.label, themeStyles.subtitle]}>Last Name</Text>
|
||||||
|
<TextInput
|
||||||
|
style={themeStyles.input}
|
||||||
|
value={lastName}
|
||||||
|
onChangeText={setLastName}
|
||||||
|
placeholder="Enter last name"
|
||||||
|
placeholderTextColor={isDark ? '#a0aec0' : '#a0aec0'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Text style={[commonStyles.label, themeStyles.subtitle]}>Phone</Text>
|
||||||
|
<TextInput
|
||||||
|
style={themeStyles.input}
|
||||||
|
value={phone}
|
||||||
|
onChangeText={setPhone}
|
||||||
|
placeholder="Enter phone number"
|
||||||
|
keyboardType="phone-pad"
|
||||||
|
placeholderTextColor={isDark ? '#a0aec0' : '#a0aec0'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Text style={[commonStyles.label, themeStyles.subtitle]}>Address</Text>
|
||||||
|
<TextInput
|
||||||
|
style={[themeStyles.input, { height: 100, textAlignVertical: 'top' }]}
|
||||||
|
value={address}
|
||||||
|
onChangeText={setAddress}
|
||||||
|
placeholder="Enter address"
|
||||||
|
multiline
|
||||||
|
placeholderTextColor={isDark ? '#a0aec0' : '#a0aec0'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[themeStyles.button, loading && commonStyles.buttonDisabled, { marginTop: 40 }]}
|
||||||
|
onPress={handleSave}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<ActivityIndicator color="white" />
|
||||||
|
) : (
|
||||||
|
<Text style={themeStyles.buttonText}>Save Changes</Text>
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</KeyboardAvoidingView>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -7,7 +7,13 @@ interface User {
|
|||||||
user: {
|
user: {
|
||||||
id: number;
|
id: number;
|
||||||
email: string;
|
email: string;
|
||||||
// Add other user fields as needed
|
first_name?: string;
|
||||||
|
last_name?: string;
|
||||||
|
phone?: string;
|
||||||
|
address?: string;
|
||||||
|
username?: string;
|
||||||
|
email_verified_at?: string | null;
|
||||||
|
avatar?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,6 +21,7 @@ interface AuthState {
|
|||||||
user: User | null;
|
user: User | null;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
login: (userData: User) => void;
|
login: (userData: User) => void;
|
||||||
|
updateUser: (updates: Partial<User['user']>) => void;
|
||||||
logout: () => void;
|
logout: () => void;
|
||||||
setLoading: (loading: boolean) => void;
|
setLoading: (loading: boolean) => void;
|
||||||
}
|
}
|
||||||
@ -25,6 +32,12 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
user: null,
|
user: null,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
login: (userData) => set({ user: userData }),
|
login: (userData) => set({ user: userData }),
|
||||||
|
updateUser: (updates) =>
|
||||||
|
set((state) => ({
|
||||||
|
user: state.user
|
||||||
|
? { ...state.user, user: { ...state.user.user, ...updates } }
|
||||||
|
: null,
|
||||||
|
})),
|
||||||
logout: () => set({ user: null }),
|
logout: () => set({ user: null }),
|
||||||
setLoading: (loading) => set({ isLoading: loading }),
|
setLoading: (loading) => set({ isLoading: loading }),
|
||||||
}),
|
}),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user