profile update works
This commit is contained in:
470
src/components/EditProfileModal.js
Normal file
470
src/components/EditProfileModal.js
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
Modal,
|
||||||
|
StyleSheet,
|
||||||
|
SafeAreaView,
|
||||||
|
TouchableOpacity,
|
||||||
|
Alert,
|
||||||
|
ActivityIndicator,
|
||||||
|
ScrollView,
|
||||||
|
TouchableWithoutFeedback,
|
||||||
|
Keyboard,
|
||||||
|
} from 'react-native';
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import Input from './Input';
|
||||||
|
import Button from './Button';
|
||||||
|
import { COLORS } from '../constants/colors';
|
||||||
|
|
||||||
|
const PASSPORT_SERIES = [
|
||||||
|
'I-AS', 'I-MR', 'II-MR', 'I-AH', 'II-AH',
|
||||||
|
'I-LB', 'II-LB', 'I-BN', 'II-BN', 'I-DZ', 'II-DZ'
|
||||||
|
];
|
||||||
|
|
||||||
|
const EditProfileModal = ({
|
||||||
|
visible,
|
||||||
|
onClose,
|
||||||
|
onSave,
|
||||||
|
initialData = {},
|
||||||
|
isLoading = false
|
||||||
|
}) => {
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
name: initialData.name || '',
|
||||||
|
phone: initialData.phone ? initialData.phone.toString() : '',
|
||||||
|
password: '',
|
||||||
|
passport_serie: initialData.passport_serie || '',
|
||||||
|
passport_id: initialData.passport_id ? initialData.passport_id.toString() : '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const [errors, setErrors] = useState({});
|
||||||
|
const [showPassportPicker, setShowPassportPicker] = useState(false);
|
||||||
|
|
||||||
|
const phoneInputRef = useRef(null);
|
||||||
|
const passwordInputRef = useRef(null);
|
||||||
|
const passportIdInputRef = useRef(null);
|
||||||
|
|
||||||
|
const validateForm = () => {
|
||||||
|
const newErrors = {};
|
||||||
|
|
||||||
|
// Name validation (required, max 255 characters)
|
||||||
|
if (!formData.name.trim()) {
|
||||||
|
newErrors.name = 'At gerek';
|
||||||
|
} else if (formData.name.length > 255) {
|
||||||
|
newErrors.name = 'At 255 harpdan köp bolmaly däl';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phone validation (required, should be number)
|
||||||
|
if (!formData.phone.trim()) {
|
||||||
|
newErrors.phone = 'Telefon belgisi gerek';
|
||||||
|
} else if (!/^\d+$/.test(formData.phone)) {
|
||||||
|
newErrors.phone = 'Telefon belgisi diňe sanlardan durmalı';
|
||||||
|
} else if (formData.phone.length < 8) {
|
||||||
|
newErrors.phone = 'Telefon belgisi azyndan 8 san bolmaly';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password validation (optional, but if provided should be strong)
|
||||||
|
if (formData.password && formData.password.length < 6) {
|
||||||
|
newErrors.password = 'Parol azyndan 6 harp bolmaly';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passport ID validation (optional, but if provided should be number)
|
||||||
|
if (formData.passport_id && !/^\d+$/.test(formData.passport_id)) {
|
||||||
|
newErrors.passport_id = 'Passport ID diňe sanlardan durmalı';
|
||||||
|
}
|
||||||
|
|
||||||
|
setErrors(newErrors);
|
||||||
|
return Object.keys(newErrors).length === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
if (!validateForm()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare data for API call
|
||||||
|
const updateData = {
|
||||||
|
name: formData.name.trim(),
|
||||||
|
phone: parseInt(formData.phone),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only include optional fields if they're provided
|
||||||
|
if (formData.password) {
|
||||||
|
updateData.password = formData.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formData.passport_serie) {
|
||||||
|
updateData.passport_serie = formData.passport_serie;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formData.passport_id) {
|
||||||
|
updateData.passport_id = parseInt(formData.passport_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSave(updateData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
// Reset form data and errors
|
||||||
|
setFormData({
|
||||||
|
name: initialData.name || '',
|
||||||
|
phone: initialData.phone ? initialData.phone.toString() : '',
|
||||||
|
password: '',
|
||||||
|
passport_serie: initialData.passport_serie || '',
|
||||||
|
passport_id: initialData.passport_id ? initialData.passport_id.toString() : '',
|
||||||
|
});
|
||||||
|
setErrors({});
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateFormData = (field, value) => {
|
||||||
|
setFormData(prev => ({
|
||||||
|
...prev,
|
||||||
|
[field]: value
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Clear error for this field if it exists
|
||||||
|
if (errors[field]) {
|
||||||
|
setErrors(prev => ({
|
||||||
|
...prev,
|
||||||
|
[field]: null
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPassportSeriesPicker = () => {
|
||||||
|
if (!showPassportPicker) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
visible={showPassportPicker}
|
||||||
|
transparent={true}
|
||||||
|
animationType="slide"
|
||||||
|
onRequestClose={() => setShowPassportPicker(false)}
|
||||||
|
>
|
||||||
|
<TouchableWithoutFeedback onPress={() => setShowPassportPicker(false)}>
|
||||||
|
<View style={styles.modalOverlay}>
|
||||||
|
<View style={styles.pickerContainer}>
|
||||||
|
<View style={styles.pickerHeader}>
|
||||||
|
<Text style={styles.pickerTitle}>Passport seriýasy</Text>
|
||||||
|
<TouchableOpacity onPress={() => setShowPassportPicker(false)}>
|
||||||
|
<Text style={styles.pickerDoneText}>Boldy</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
<ScrollView style={styles.pickerList}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.pickerItem}
|
||||||
|
onPress={() => {
|
||||||
|
updateFormData('passport_serie', '');
|
||||||
|
setShowPassportPicker(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={[styles.pickerItemText, styles.placeholderText]}>
|
||||||
|
Saýlaň
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
{PASSPORT_SERIES.map((series) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={series}
|
||||||
|
style={[
|
||||||
|
styles.pickerItem,
|
||||||
|
formData.passport_serie === series && styles.selectedPickerItem
|
||||||
|
]}
|
||||||
|
onPress={() => {
|
||||||
|
updateFormData('passport_serie', series);
|
||||||
|
setShowPassportPicker(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={[
|
||||||
|
styles.pickerItemText,
|
||||||
|
formData.passport_serie === series && styles.selectedPickerItemText
|
||||||
|
]}>
|
||||||
|
{series}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</TouchableWithoutFeedback>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
visible={visible}
|
||||||
|
animationType="slide"
|
||||||
|
presentationStyle="pageSheet"
|
||||||
|
onRequestClose={handleClose}
|
||||||
|
>
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
||||||
|
<View style={styles.content}>
|
||||||
|
{/* Header */}
|
||||||
|
<View style={styles.header}>
|
||||||
|
<TouchableOpacity onPress={handleClose} style={styles.closeButton}>
|
||||||
|
<Ionicons name="close" size={24} color={COLORS.text} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text style={styles.title}>Şahsy maglumatlar</Text>
|
||||||
|
<View style={styles.placeholder} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Form */}
|
||||||
|
<ScrollView style={styles.form} showsVerticalScrollIndicator={false}>
|
||||||
|
<View style={styles.formSection}>
|
||||||
|
<Text style={styles.sectionTitle}>Esasy maglumatlar</Text>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label="Ady *"
|
||||||
|
value={formData.name}
|
||||||
|
onChangeText={(value) => updateFormData('name', value)}
|
||||||
|
error={errors.name}
|
||||||
|
maxLength={255}
|
||||||
|
returnKeyType="next"
|
||||||
|
onSubmitEditing={() => phoneInputRef.current?.focus()}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
ref={phoneInputRef}
|
||||||
|
label="Telefon belgisi *"
|
||||||
|
value={formData.phone}
|
||||||
|
onChangeText={(value) => updateFormData('phone', value)}
|
||||||
|
error={errors.phone}
|
||||||
|
keyboardType="numeric"
|
||||||
|
maxLength={8}
|
||||||
|
returnKeyType="next"
|
||||||
|
onSubmitEditing={() => passwordInputRef.current?.focus()}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
ref={passwordInputRef}
|
||||||
|
label="Täze parol"
|
||||||
|
value={formData.password}
|
||||||
|
onChangeText={(value) => updateFormData('password', value)}
|
||||||
|
error={errors.password}
|
||||||
|
secureTextEntry
|
||||||
|
placeholder="Parol üýtgetmezlik üçin boş goýuň"
|
||||||
|
returnKeyType="next"
|
||||||
|
onSubmitEditing={() => passportIdInputRef.current?.focus()}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.formSection}>
|
||||||
|
<Text style={styles.sectionTitle}>Passport maglumatlary</Text>
|
||||||
|
|
||||||
|
<View style={styles.inputContainer}>
|
||||||
|
<Text style={styles.label}>Passport seriýasy</Text>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.pickerButton, errors.passport_serie && styles.inputError]}
|
||||||
|
onPress={() => setShowPassportPicker(true)}
|
||||||
|
>
|
||||||
|
<Text style={[styles.pickerButtonText, !formData.passport_serie && styles.placeholderText]}>
|
||||||
|
{formData.passport_serie || 'Saýlaň'}
|
||||||
|
</Text>
|
||||||
|
<Ionicons name="chevron-down" size={20} color={COLORS.textSecondary} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
{errors.passport_serie && (
|
||||||
|
<Text style={styles.errorText}>{errors.passport_serie}</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
ref={passportIdInputRef}
|
||||||
|
label="Passport ID"
|
||||||
|
value={formData.passport_id}
|
||||||
|
onChangeText={(value) => updateFormData('passport_id', value)}
|
||||||
|
error={errors.passport_id}
|
||||||
|
keyboardType="numeric"
|
||||||
|
returnKeyType="done"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.note}>
|
||||||
|
<Ionicons name="information-circle" size={16} color={COLORS.textSecondary} />
|
||||||
|
<Text style={styles.noteText}>
|
||||||
|
* belgisi bolan meýdanlar hökmany doldurulmaly
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
{/* Save Button */}
|
||||||
|
<View style={styles.footer}>
|
||||||
|
<Button
|
||||||
|
title="Ýatda sakla"
|
||||||
|
onPress={handleSave}
|
||||||
|
disabled={isLoading}
|
||||||
|
style={styles.saveButton}
|
||||||
|
/>
|
||||||
|
{isLoading && (
|
||||||
|
<ActivityIndicator
|
||||||
|
size="small"
|
||||||
|
color={COLORS.primary}
|
||||||
|
style={styles.loader}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</TouchableWithoutFeedback>
|
||||||
|
|
||||||
|
{renderPassportSeriesPicker()}
|
||||||
|
</SafeAreaView>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: COLORS.background,
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
paddingVertical: 16,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: COLORS.border,
|
||||||
|
},
|
||||||
|
closeButton: {
|
||||||
|
padding: 4,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: COLORS.text,
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
width: 32,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
flex: 1,
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
},
|
||||||
|
formSection: {
|
||||||
|
marginTop: 24,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: COLORS.text,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
inputContainer: {
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '500',
|
||||||
|
color: COLORS.text,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
pickerButton: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 12,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: COLORS.border,
|
||||||
|
borderRadius: 8,
|
||||||
|
backgroundColor: COLORS.surface,
|
||||||
|
},
|
||||||
|
pickerButtonText: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: COLORS.text,
|
||||||
|
},
|
||||||
|
placeholderText: {
|
||||||
|
color: COLORS.textSecondary,
|
||||||
|
},
|
||||||
|
inputError: {
|
||||||
|
borderColor: COLORS.error,
|
||||||
|
},
|
||||||
|
errorText: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: COLORS.error,
|
||||||
|
marginTop: 4,
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: 16,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 12,
|
||||||
|
backgroundColor: COLORS.surface,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
noteText: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: COLORS.textSecondary,
|
||||||
|
marginLeft: 8,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
padding: 20,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
saveButton: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
loader: {
|
||||||
|
marginLeft: 12,
|
||||||
|
},
|
||||||
|
modalOverlay: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
|
pickerContainer: {
|
||||||
|
backgroundColor: COLORS.surface,
|
||||||
|
borderTopLeftRadius: 12,
|
||||||
|
borderTopRightRadius: 12,
|
||||||
|
maxHeight: 400,
|
||||||
|
},
|
||||||
|
pickerHeader: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
paddingVertical: 16,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: COLORS.border,
|
||||||
|
},
|
||||||
|
pickerTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: COLORS.text,
|
||||||
|
},
|
||||||
|
pickerDoneText: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: COLORS.primary,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
pickerList: {
|
||||||
|
maxHeight: 300,
|
||||||
|
},
|
||||||
|
pickerItem: {
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
paddingVertical: 16,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: COLORS.border,
|
||||||
|
},
|
||||||
|
selectedPickerItem: {
|
||||||
|
backgroundColor: COLORS.primary + '10',
|
||||||
|
},
|
||||||
|
pickerItemText: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: COLORS.text,
|
||||||
|
},
|
||||||
|
selectedPickerItemText: {
|
||||||
|
color: COLORS.primary,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default EditProfileModal;
|
||||||
@@ -35,4 +35,8 @@ export const COLORS = {
|
|||||||
textSecondary: '#6b7280',
|
textSecondary: '#6b7280',
|
||||||
textDisabled: '#9ca3af',
|
textDisabled: '#9ca3af',
|
||||||
textOnPrimary: '#ffffff',
|
textOnPrimary: '#ffffff',
|
||||||
|
text: '#111827',
|
||||||
|
|
||||||
|
// Additional semantic color
|
||||||
|
border: '#e5e7eb', // Same as gray.200
|
||||||
};
|
};
|
||||||
@@ -14,6 +14,7 @@ import { StatusBar } from 'expo-status-bar';
|
|||||||
import { Ionicons } from '@expo/vector-icons';
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
import { useAuth } from '../../contexts/AuthContext';
|
import { useAuth } from '../../contexts/AuthContext';
|
||||||
import apiService from '../../services/apiService';
|
import apiService from '../../services/apiService';
|
||||||
|
import EditProfileModal from '../../components/EditProfileModal';
|
||||||
import { COLORS } from '../../constants/colors';
|
import { COLORS } from '../../constants/colors';
|
||||||
|
|
||||||
const ProfileScreen = () => {
|
const ProfileScreen = () => {
|
||||||
@@ -21,6 +22,8 @@ const ProfileScreen = () => {
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
const [profileData, setProfileData] = useState(null);
|
const [profileData, setProfileData] = useState(null);
|
||||||
|
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
||||||
|
const [isUpdatingProfile, setIsUpdatingProfile] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadProfileData();
|
loadProfileData();
|
||||||
@@ -108,8 +111,35 @@ const ProfileScreen = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEditPersonalInfo = () => {
|
const handleEditPersonalInfo = () => {
|
||||||
// Navigate to edit personal info screen
|
setIsEditModalVisible(true);
|
||||||
Alert.alert('Şahsy maglumatlar', 'Şahsy maglumatlar sahypasy açylýar...');
|
};
|
||||||
|
|
||||||
|
const handleSaveProfile = async (updatedData) => {
|
||||||
|
try {
|
||||||
|
setIsUpdatingProfile(true);
|
||||||
|
const result = await apiService.updateProfile(updatedData);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
// Update local profile data optimistically
|
||||||
|
setProfileData(prev => ({
|
||||||
|
...prev,
|
||||||
|
...updatedData,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Optionally refresh profile from server
|
||||||
|
await loadProfileData();
|
||||||
|
|
||||||
|
Alert.alert('Success', result.message);
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
} else {
|
||||||
|
Alert.alert('Error', result.error || 'Could not update profile');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating profile:', error);
|
||||||
|
Alert.alert('Error', error.message || 'Could not update profile');
|
||||||
|
} finally {
|
||||||
|
setIsUpdatingProfile(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEditContactInfo = () => {
|
const handleEditContactInfo = () => {
|
||||||
@@ -295,6 +325,15 @@ const ProfileScreen = () => {
|
|||||||
|
|
||||||
<View style={styles.bottomSpacing} />
|
<View style={styles.bottomSpacing} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
{/* Edit Profile Modal */}
|
||||||
|
<EditProfileModal
|
||||||
|
visible={isEditModalVisible}
|
||||||
|
onClose={() => setIsEditModalVisible(false)}
|
||||||
|
onSave={handleSaveProfile}
|
||||||
|
initialData={profileData || user}
|
||||||
|
isLoading={isUpdatingProfile}
|
||||||
|
/>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,11 +7,35 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateProfile(data) {
|
async updateProfile(data) {
|
||||||
return authService.updateProfile(data);
|
try {
|
||||||
|
const response = await authService.updateProfile(data);
|
||||||
|
// Server returns { message: "Successfully updated profile" }
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: response.message || 'Profile updated successfully',
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async changePassword(currentPassword, newPassword) {
|
async changePassword(currentPassword, newPassword) {
|
||||||
return authService.changePassword(currentPassword, newPassword);
|
try {
|
||||||
|
const response = await authService.changePassword(currentPassword, newPassword);
|
||||||
|
// Assume server returns { message: "Successfully changed password" }
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: response.message || 'Password changed successfully',
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteAccount() {
|
async deleteAccount() {
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateProfile(data) {
|
async updateProfile(data) {
|
||||||
return this.makeRequest('/profile', data, true, 'PUT');
|
return this.makeRequest('/profile', data, true, 'POST');
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTransactions(page = 1, limit = 20) {
|
async getTransactions(page = 1, limit = 20) {
|
||||||
|
|||||||
Reference in New Issue
Block a user