diff --git a/frontend/src/screens/ChangePasswordScreen.tsx b/frontend/src/screens/ChangePasswordScreen.tsx
new file mode 100644
index 00000000..c728e478
--- /dev/null
+++ b/frontend/src/screens/ChangePasswordScreen.tsx
@@ -0,0 +1,264 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ TextInput,
+ ScrollView,
+ Alert,
+ ActivityIndicator,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { useAuth } from '../contexts/AuthContext';
+
+export default function ChangePasswordScreen({ navigation }: any) {
+ const insets = useSafeAreaInsets();
+ const { user } = useAuth();
+ const [loading, setLoading] = useState(false);
+ const [currentPassword, setCurrentPassword] = useState('');
+ const [newPassword, setNewPassword] = useState('');
+ const [confirmPassword, setConfirmPassword] = useState('');
+ const [showCurrent, setShowCurrent] = useState(false);
+ const [showNew, setShowNew] = useState(false);
+ const [showConfirm, setShowConfirm] = useState(false);
+
+ const handleChangePassword = async () => {
+ if (!currentPassword || !newPassword || !confirmPassword) {
+ Alert.alert('Error', 'Please fill in all fields');
+ return;
+ }
+
+ if (newPassword !== confirmPassword) {
+ Alert.alert('Error', 'New passwords do not match');
+ return;
+ }
+
+ if (newPassword.length < 8) {
+ Alert.alert('Error', 'Password must be at least 8 characters');
+ return;
+ }
+
+ setLoading(true);
+ try {
+ const backendUrl = process.env.EXPO_PUBLIC_BACKEND_URL || 'http://localhost:8001';
+ const response = await fetch(`${backendUrl}/api/auth/change-password`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ user_id: user?.user_id,
+ current_password: currentPassword,
+ new_password: newPassword,
+ }),
+ });
+
+ if (response.ok) {
+ Alert.alert('Success', 'Password changed successfully!', [
+ { text: 'OK', onPress: () => navigation.goBack() },
+ ]);
+ } else {
+ Alert.alert('Error', 'Failed to change password');
+ }
+ } catch (error) {
+ Alert.alert('Error', 'Network error occurred');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+ navigation.goBack()} style={styles.backButton}>
+
+
+ Change Password
+
+
+
+
+
+
+
+ Password must be at least 8 characters long
+
+
+
+
+ Current Password
+
+
+ setShowCurrent(!showCurrent)}
+ style={styles.eyeButton}
+ >
+
+
+
+
+
+
+ New Password
+
+
+ setShowNew(!showNew)}
+ style={styles.eyeButton}
+ >
+
+
+
+
+
+
+ Confirm New Password
+
+
+ setShowConfirm(!showConfirm)}
+ style={styles.eyeButton}
+ >
+
+
+
+
+
+
+ {loading ? (
+
+ ) : (
+ Change Password
+ )}
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#F8F9FA',
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingHorizontal: 16,
+ paddingVertical: 16,
+ backgroundColor: '#FFF',
+ borderBottomWidth: 1,
+ borderBottomColor: '#E5E7EB',
+ },
+ backButton: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: '#F3F4F6',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ headerTitle: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: '#1F2937',
+ },
+ scrollContent: {
+ padding: 16,
+ paddingBottom: 80,
+ },
+ infoBox: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#DBEAFE',
+ padding: 12,
+ borderRadius: 8,
+ marginBottom: 24,
+ },
+ infoText: {
+ fontSize: 14,
+ color: '#1E40AF',
+ marginLeft: 8,
+ flex: 1,
+ },
+ section: {
+ marginBottom: 20,
+ },
+ label: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: '#374151',
+ marginBottom: 8,
+ },
+ passwordContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#FFF',
+ borderRadius: 12,
+ borderWidth: 1,
+ borderColor: '#E5E7EB',
+ },
+ passwordInput: {
+ flex: 1,
+ padding: 16,
+ fontSize: 16,
+ },
+ eyeButton: {
+ padding: 12,
+ },
+ saveButton: {
+ backgroundColor: '#EE2A35',
+ padding: 16,
+ borderRadius: 12,
+ alignItems: 'center',
+ marginTop: 24,
+ },
+ saveButtonDisabled: {
+ opacity: 0.6,
+ },
+ saveButtonText: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: '#FFF',
+ },
+});
\ No newline at end of file
diff --git a/frontend/src/screens/EditProfileScreen.tsx b/frontend/src/screens/EditProfileScreen.tsx
new file mode 100644
index 00000000..4db5445c
--- /dev/null
+++ b/frontend/src/screens/EditProfileScreen.tsx
@@ -0,0 +1,224 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ TextInput,
+ ScrollView,
+ Alert,
+ ActivityIndicator,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { useAuth } from '../contexts/AuthContext';
+import { API_ENDPOINTS } from '../config/api';
+
+export default function EditProfileScreen({ navigation }: any) {
+ const insets = useSafeAreaInsets();
+ const { user } = useAuth();
+ const [loading, setLoading] = useState(false);
+ const [email, setEmail] = useState('');
+ const [firstName, setFirstName] = useState('');
+ const [lastName, setLastName] = useState('');
+ const [phone, setPhone] = useState('');
+ const [walletAddress, setWalletAddress] = useState('');
+
+ useEffect(() => {
+ loadUserData();
+ }, []);
+
+ const loadUserData = async () => {
+ try {
+ const response = await fetch(`${API_ENDPOINTS.AUTH_USER(user?.user_id || '')}`);
+ if (response.ok) {
+ const data = await response.json();
+ setEmail(data.email || '');
+ setFirstName(data.first_name || '');
+ setLastName(data.last_name || '');
+ setPhone(data.phone || '');
+ setWalletAddress(data.wallet_address || '');
+ }
+ } catch (error) {
+ console.error('Error loading user data:', error);
+ }
+ };
+
+ const handleSave = async () => {
+ setLoading(true);
+ try {
+ const backendUrl = process.env.EXPO_PUBLIC_BACKEND_URL || 'http://localhost:8001';
+ const response = await fetch(`${backendUrl}/api/auth/profile`, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ user_id: user?.user_id,
+ email,
+ first_name: firstName,
+ last_name: lastName,
+ phone,
+ wallet_address: walletAddress,
+ }),
+ });
+
+ if (response.ok) {
+ Alert.alert('Success', 'Profile updated successfully!');
+ navigation.goBack();
+ } else {
+ Alert.alert('Error', 'Failed to update profile');
+ }
+ } catch (error) {
+ Alert.alert('Error', 'Network error occurred');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+ navigation.goBack()} style={styles.backButton}>
+
+
+ Edit Profile
+
+
+
+
+
+ First Name
+
+
+
+
+ Last Name
+
+
+
+
+ Email
+
+
+
+
+ Phone Number
+
+
+
+
+ Wallet Address
+
+
+
+
+ {loading ? (
+
+ ) : (
+ Save Changes
+ )}
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#F8F9FA',
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingHorizontal: 16,
+ paddingVertical: 16,
+ backgroundColor: '#FFF',
+ borderBottomWidth: 1,
+ borderBottomColor: '#E5E7EB',
+ },
+ backButton: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: '#F3F4F6',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ headerTitle: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: '#1F2937',
+ },
+ scrollContent: {
+ padding: 16,
+ paddingBottom: 80,
+ },
+ section: {
+ marginBottom: 20,
+ },
+ label: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: '#374151',
+ marginBottom: 8,
+ },
+ input: {
+ backgroundColor: '#FFF',
+ padding: 16,
+ borderRadius: 12,
+ fontSize: 16,
+ borderWidth: 1,
+ borderColor: '#E5E7EB',
+ },
+ saveButton: {
+ backgroundColor: '#EE2A35',
+ padding: 16,
+ borderRadius: 12,
+ alignItems: 'center',
+ marginTop: 24,
+ },
+ saveButtonDisabled: {
+ opacity: 0.6,
+ },
+ saveButtonText: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: '#FFF',
+ },
+});
\ No newline at end of file