Profile credit data maskd

This commit is contained in:
2025-07-10 23:45:29 +05:00
parent 8f16f14796
commit 50d299fb24

View File

@@ -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>
);