Profile credit data maskd
This commit is contained in:
@@ -45,6 +45,8 @@ const EditProfileModal = ({
|
||||
|
||||
const [errors, setErrors] = useState({});
|
||||
const [showPassportPicker, setShowPassportPicker] = useState(false);
|
||||
const [showMonthPicker, setShowMonthPicker] = useState(false);
|
||||
const [showYearPicker, setShowYearPicker] = useState(false);
|
||||
|
||||
const phoneInputRef = useRef(null);
|
||||
const passwordInputRef = useRef(null);
|
||||
@@ -88,9 +90,9 @@ const EditProfileModal = ({
|
||||
newErrors.card_name = 'Kartyň ady 255 harpdan köp bolmaly däl';
|
||||
}
|
||||
|
||||
// Card number validation (optional, must be 16 digits)
|
||||
if (formData.card_number && !/^\d{16}$/.test(formData.card_number.trim())) {
|
||||
newErrors.card_number = 'Kart belgisi 16 sany sandan durmaly';
|
||||
// Card number validation (optional, must be 16 digits and allow hyphens)
|
||||
if (formData.card_number && !/^[0-9]{4}-?[0-9]{4}-?[0-9]{4}-?[0-9]{4}$/.test(formData.card_number.trim())) {
|
||||
newErrors.card_number = 'Kart belgisi 16 sany sandan durmaly (mysal: 9999-9999-9999-9999)';
|
||||
}
|
||||
|
||||
// Card month validation (optional, 1-12)
|
||||
@@ -102,8 +104,12 @@ const EditProfileModal = ({
|
||||
}
|
||||
|
||||
// Card year validation (optional, 4 digits and reasonable year)
|
||||
if (formData.card_year && !/^\d{4}$/.test(formData.card_year.trim())) {
|
||||
newErrors.card_year = 'Ýyl 4 sany sandan durmaly';
|
||||
if (formData.card_year) {
|
||||
const year = parseInt(formData.card_year.trim(), 10);
|
||||
const currentYear = new Date().getFullYear();
|
||||
if (!/^[0-9]{4}$/.test(formData.card_year.trim()) || year < currentYear - 10 || year > currentYear + 10) {
|
||||
newErrors.card_year = `Ýyl ${currentYear - 10}-den ${currentYear + 10}-e çenli bolmaly`;
|
||||
}
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
@@ -147,7 +153,8 @@ const EditProfileModal = ({
|
||||
}
|
||||
|
||||
if (formData.card_number) {
|
||||
updateData.card_number = formData.card_number.trim();
|
||||
// Remove all non-digit characters before sending
|
||||
updateData.card_number = formData.card_number.replace(/[^\d]/g, '');
|
||||
}
|
||||
|
||||
onSave(updateData);
|
||||
@@ -245,6 +252,129 @@ const EditProfileModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
const renderMonthPicker = () => {
|
||||
if (!showMonthPicker) return null;
|
||||
|
||||
const months = Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, '0'));
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={showMonthPicker}
|
||||
transparent={true}
|
||||
animationType="slide"
|
||||
onRequestClose={() => setShowMonthPicker(false)}
|
||||
>
|
||||
<TouchableWithoutFeedback onPress={() => setShowMonthPicker(false)}>
|
||||
<View style={styles.modalOverlay}>
|
||||
<View style={styles.pickerContainer}>
|
||||
<View style={styles.pickerHeader}>
|
||||
<Text style={styles.pickerTitle}>Kart aýy</Text>
|
||||
<TouchableOpacity onPress={() => setShowMonthPicker(false)}>
|
||||
<Text style={styles.pickerDoneText}>Boldy</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<ScrollView style={styles.pickerList}>
|
||||
<TouchableOpacity
|
||||
style={styles.pickerItem}
|
||||
onPress={() => {
|
||||
updateFormData('card_month', '');
|
||||
setShowMonthPicker(false);
|
||||
}}
|
||||
>
|
||||
<Text style={[styles.pickerItemText, styles.placeholderText]}>
|
||||
Saýlaň
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
{months.map((month) => (
|
||||
<TouchableOpacity
|
||||
key={month}
|
||||
style={[
|
||||
styles.pickerItem,
|
||||
formData.card_month === month && styles.selectedPickerItem
|
||||
]}
|
||||
onPress={() => {
|
||||
updateFormData('card_month', month);
|
||||
setShowMonthPicker(false);
|
||||
}}
|
||||
>
|
||||
<Text style={[
|
||||
styles.pickerItemText,
|
||||
formData.card_month === month && styles.selectedPickerItemText
|
||||
]}>
|
||||
{month}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const renderYearPicker = () => {
|
||||
if (!showYearPicker) return null;
|
||||
|
||||
const currentYear = new Date().getFullYear();
|
||||
const years = Array.from({ length: 75 }, (_, i) => String(currentYear - 10 + i)); // +/- 10 years
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={showYearPicker}
|
||||
transparent={true}
|
||||
animationType="slide"
|
||||
onRequestClose={() => setShowYearPicker(false)}
|
||||
>
|
||||
<TouchableWithoutFeedback onPress={() => setShowYearPicker(false)}>
|
||||
<View style={styles.modalOverlay}>
|
||||
<View style={styles.pickerContainer}>
|
||||
<View style={styles.pickerHeader}>
|
||||
<Text style={styles.pickerTitle}>Kartyň senesi</Text>
|
||||
<TouchableOpacity onPress={() => setShowYearPicker(false)}>
|
||||
<Text style={styles.pickerDoneText}>Boldy</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<ScrollView style={styles.pickerList}>
|
||||
<TouchableOpacity
|
||||
style={styles.pickerItem}
|
||||
onPress={() => {
|
||||
updateFormData('card_year', '');
|
||||
setShowYearPicker(false);
|
||||
}}
|
||||
>
|
||||
<Text style={[styles.pickerItemText, styles.placeholderText]}>
|
||||
Saýlaň
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
{years.map((year) => (
|
||||
<TouchableOpacity
|
||||
key={year}
|
||||
style={[
|
||||
styles.pickerItem,
|
||||
formData.card_year === year && styles.selectedPickerItem
|
||||
]}
|
||||
onPress={() => {
|
||||
updateFormData('card_year', year);
|
||||
setShowYearPicker(false);
|
||||
}}
|
||||
>
|
||||
<Text style={[
|
||||
styles.pickerItemText,
|
||||
formData.card_year === year && styles.selectedPickerItemText
|
||||
]}>
|
||||
{year}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
@@ -340,6 +470,7 @@ const EditProfileModal = ({
|
||||
error={errors.passport_id}
|
||||
keyboardType="numeric"
|
||||
returnKeyType="next"
|
||||
maxLength={6}
|
||||
onSubmitEditing={() => cardNameInputRef.current?.focus()}
|
||||
/>
|
||||
</View>
|
||||
@@ -362,36 +493,55 @@ const EditProfileModal = ({
|
||||
ref={cardNumberInputRef}
|
||||
label="Kart belgisi"
|
||||
value={formData.card_number}
|
||||
onChangeText={(value) => updateFormData('card_number', value)}
|
||||
onChangeText={(value) => {
|
||||
const unmaskedValue = value.replace(/[^\d]/g, ''); // Remove non-digits
|
||||
let maskedValue = '';
|
||||
for (let i = 0; i < unmaskedValue.length; i++) {
|
||||
if (i > 0 && i % 4 === 0) {
|
||||
maskedValue += '-';
|
||||
}
|
||||
maskedValue += unmaskedValue[i];
|
||||
}
|
||||
updateFormData('card_number', maskedValue);
|
||||
}}
|
||||
error={errors.card_number}
|
||||
keyboardType="numeric"
|
||||
maxLength={16}
|
||||
maxLength={19} // 16 digits + 3 hyphens
|
||||
returnKeyType="next"
|
||||
onSubmitEditing={() => cardMonthInputRef.current?.focus()}
|
||||
/>
|
||||
|
||||
<Input
|
||||
ref={cardMonthInputRef}
|
||||
label="Kart aýy (MM)"
|
||||
value={formData.card_month}
|
||||
onChangeText={(value) => updateFormData('card_month', value)}
|
||||
error={errors.card_month}
|
||||
keyboardType="numeric"
|
||||
maxLength={2}
|
||||
returnKeyType="next"
|
||||
onSubmitEditing={() => cardYearInputRef.current?.focus()}
|
||||
/>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.label}>Kart aýy (MM)</Text>
|
||||
<TouchableOpacity
|
||||
style={[styles.pickerButton, errors.card_month && styles.inputError]}
|
||||
onPress={() => setShowMonthPicker(true)}
|
||||
>
|
||||
<Text style={[styles.pickerButtonText, !formData.card_month && styles.placeholderText]}>
|
||||
{formData.card_month || 'Saýlaň'}
|
||||
</Text>
|
||||
<Ionicons name="chevron-down" size={20} color={COLORS.textSecondary} />
|
||||
</TouchableOpacity>
|
||||
{errors.card_month && (
|
||||
<Text style={styles.errorText}>{errors.card_month}</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Input
|
||||
ref={cardYearInputRef}
|
||||
label="Kartyň senesi (YYYY)"
|
||||
value={formData.card_year}
|
||||
onChangeText={(value) => updateFormData('card_year', value)}
|
||||
error={errors.card_year}
|
||||
keyboardType="numeric"
|
||||
maxLength={4}
|
||||
returnKeyType="done"
|
||||
/>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.label}>Kartyň senesi (YYYY)</Text>
|
||||
<TouchableOpacity
|
||||
style={[styles.pickerButton, errors.card_year && styles.inputError]}
|
||||
onPress={() => setShowYearPicker(true)}
|
||||
>
|
||||
<Text style={[styles.pickerButtonText, !formData.card_year && styles.placeholderText]}>
|
||||
{formData.card_year || 'Saýlaň'}
|
||||
</Text>
|
||||
<Ionicons name="chevron-down" size={20} color={COLORS.textSecondary} />
|
||||
</TouchableOpacity>
|
||||
{errors.card_year && (
|
||||
<Text style={styles.errorText}>{errors.card_year}</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.note}>
|
||||
@@ -422,6 +572,8 @@ const EditProfileModal = ({
|
||||
</KeyboardAvoidingView>
|
||||
|
||||
{renderPassportSeriesPicker()}
|
||||
{renderMonthPicker()}
|
||||
{renderYearPicker()}
|
||||
</SafeAreaView>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user