Profile credit data maskd
This commit is contained in:
@@ -45,6 +45,8 @@ const EditProfileModal = ({
|
|||||||
|
|
||||||
const [errors, setErrors] = useState({});
|
const [errors, setErrors] = useState({});
|
||||||
const [showPassportPicker, setShowPassportPicker] = useState(false);
|
const [showPassportPicker, setShowPassportPicker] = useState(false);
|
||||||
|
const [showMonthPicker, setShowMonthPicker] = useState(false);
|
||||||
|
const [showYearPicker, setShowYearPicker] = useState(false);
|
||||||
|
|
||||||
const phoneInputRef = useRef(null);
|
const phoneInputRef = useRef(null);
|
||||||
const passwordInputRef = useRef(null);
|
const passwordInputRef = useRef(null);
|
||||||
@@ -88,9 +90,9 @@ const EditProfileModal = ({
|
|||||||
newErrors.card_name = 'Kartyň ady 255 harpdan köp bolmaly däl';
|
newErrors.card_name = 'Kartyň ady 255 harpdan köp bolmaly däl';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Card number validation (optional, must be 16 digits)
|
// Card number validation (optional, must be 16 digits and allow hyphens)
|
||||||
if (formData.card_number && !/^\d{16}$/.test(formData.card_number.trim())) {
|
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';
|
newErrors.card_number = 'Kart belgisi 16 sany sandan durmaly (mysal: 9999-9999-9999-9999)';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Card month validation (optional, 1-12)
|
// Card month validation (optional, 1-12)
|
||||||
@@ -102,8 +104,12 @@ const EditProfileModal = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Card year validation (optional, 4 digits and reasonable year)
|
// Card year validation (optional, 4 digits and reasonable year)
|
||||||
if (formData.card_year && !/^\d{4}$/.test(formData.card_year.trim())) {
|
if (formData.card_year) {
|
||||||
newErrors.card_year = 'Ýyl 4 sany sandan durmaly';
|
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);
|
setErrors(newErrors);
|
||||||
@@ -147,7 +153,8 @@ const EditProfileModal = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (formData.card_number) {
|
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);
|
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 (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
visible={visible}
|
visible={visible}
|
||||||
@@ -340,6 +470,7 @@ const EditProfileModal = ({
|
|||||||
error={errors.passport_id}
|
error={errors.passport_id}
|
||||||
keyboardType="numeric"
|
keyboardType="numeric"
|
||||||
returnKeyType="next"
|
returnKeyType="next"
|
||||||
|
maxLength={6}
|
||||||
onSubmitEditing={() => cardNameInputRef.current?.focus()}
|
onSubmitEditing={() => cardNameInputRef.current?.focus()}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
@@ -362,36 +493,55 @@ const EditProfileModal = ({
|
|||||||
ref={cardNumberInputRef}
|
ref={cardNumberInputRef}
|
||||||
label="Kart belgisi"
|
label="Kart belgisi"
|
||||||
value={formData.card_number}
|
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}
|
error={errors.card_number}
|
||||||
keyboardType="numeric"
|
keyboardType="numeric"
|
||||||
maxLength={16}
|
maxLength={19} // 16 digits + 3 hyphens
|
||||||
returnKeyType="next"
|
returnKeyType="next"
|
||||||
onSubmitEditing={() => cardMonthInputRef.current?.focus()}
|
onSubmitEditing={() => cardMonthInputRef.current?.focus()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input
|
<View style={styles.inputContainer}>
|
||||||
ref={cardMonthInputRef}
|
<Text style={styles.label}>Kart aýy (MM)</Text>
|
||||||
label="Kart aýy (MM)"
|
<TouchableOpacity
|
||||||
value={formData.card_month}
|
style={[styles.pickerButton, errors.card_month && styles.inputError]}
|
||||||
onChangeText={(value) => updateFormData('card_month', value)}
|
onPress={() => setShowMonthPicker(true)}
|
||||||
error={errors.card_month}
|
>
|
||||||
keyboardType="numeric"
|
<Text style={[styles.pickerButtonText, !formData.card_month && styles.placeholderText]}>
|
||||||
maxLength={2}
|
{formData.card_month || 'Saýlaň'}
|
||||||
returnKeyType="next"
|
</Text>
|
||||||
onSubmitEditing={() => cardYearInputRef.current?.focus()}
|
<Ionicons name="chevron-down" size={20} color={COLORS.textSecondary} />
|
||||||
/>
|
</TouchableOpacity>
|
||||||
|
{errors.card_month && (
|
||||||
|
<Text style={styles.errorText}>{errors.card_month}</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
|
||||||
<Input
|
<View style={styles.inputContainer}>
|
||||||
ref={cardYearInputRef}
|
<Text style={styles.label}>Kartyň senesi (YYYY)</Text>
|
||||||
label="Kartyň senesi (YYYY)"
|
<TouchableOpacity
|
||||||
value={formData.card_year}
|
style={[styles.pickerButton, errors.card_year && styles.inputError]}
|
||||||
onChangeText={(value) => updateFormData('card_year', value)}
|
onPress={() => setShowYearPicker(true)}
|
||||||
error={errors.card_year}
|
>
|
||||||
keyboardType="numeric"
|
<Text style={[styles.pickerButtonText, !formData.card_year && styles.placeholderText]}>
|
||||||
maxLength={4}
|
{formData.card_year || 'Saýlaň'}
|
||||||
returnKeyType="done"
|
</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>
|
||||||
|
|
||||||
<View style={styles.note}>
|
<View style={styles.note}>
|
||||||
@@ -422,6 +572,8 @@ const EditProfileModal = ({
|
|||||||
</KeyboardAvoidingView>
|
</KeyboardAvoidingView>
|
||||||
|
|
||||||
{renderPassportSeriesPicker()}
|
{renderPassportSeriesPicker()}
|
||||||
|
{renderMonthPicker()}
|
||||||
|
{renderYearPicker()}
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user