bug fixes

This commit is contained in:
2025-07-08 23:58:08 +05:00
parent 89a1c0d9f2
commit 7ce0b92f92
7 changed files with 94 additions and 26 deletions

Binary file not shown.

View File

@@ -49,8 +49,8 @@ const VerificationScreen = ({ navigation }) => {
}; };
if (Platform.OS === 'android') { if (Platform.OS === 'android') {
BackHandler.addEventListener('hardwareBackPress', onBackPress); const sub = BackHandler.addEventListener('hardwareBackPress', onBackPress);
return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress); return () => sub.remove();
} }
}, [handleGoBack]) }, [handleGoBack])
); );

View File

@@ -20,6 +20,12 @@ const yearOptions = Array.from({ length: 60 }).map((_, i) => {
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 PASSPORT_SERIES = ['I-AS','I-MR','II-MR','I-AH','II-AH','I-LB','II-LB','I-BN','II-BN','I-DZ','II-DZ'];
// Helper to format card number with spaces
const formatCardNumber = (value) => {
const digits = String(value).replace(/[^0-9]/g, '').slice(0, 16);
return (digits.match(/.{1,4}/g) || []).join(' ');
};
const CreateCardBalanceOrderScreen = () => { const CreateCardBalanceOrderScreen = () => {
const navigation = useNavigation(); const navigation = useNavigation();
const [cardNumber, setCardNumber] = useState(''); const [cardNumber, setCardNumber] = useState('');
@@ -42,7 +48,11 @@ const CreateCardBalanceOrderScreen = () => {
useEffect(() => { useEffect(() => {
if (user) { if (user) {
if (user.passport_serie) setPassportSerie(user.passport_serie); if (user.passport_serie) setPassportSerie(user.passport_serie);
if (user.passport_id) setPassportId(String(user.passport_id)); if (user.passport_id) setPassportId(String(user.passport_id));e
if (user.card_number) setCardNumber(formatCardNumber(user.card_number));
if (user.card_month) setCardMonth(String(user.card_month).padStart(2, '0'));
if (user.card_year) setCardYear(String(user.card_year));
} }
}, [user]); }, [user]);

View File

@@ -21,6 +21,12 @@ const yearOptions = Array.from({ length: 60 }).map((_, i) => {
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 PASSPORT_SERIES = ['I-AS','I-MR','II-MR','I-AH','II-AH','I-LB','II-LB','I-BN','II-BN','I-DZ','II-DZ'];
// Helper to format card number 9999 9999 9999 9999
const formatCardNumber = (value) => {
const digits = value.replace(/[^0-9]/g, '').slice(0, 16);
return (digits.match(/.{1,4}/g) || []).join(' ');
};
const CreateCardTransactionOrderScreen = () => { const CreateCardTransactionOrderScreen = () => {
const navigation = useNavigation(); const navigation = useNavigation();
const [cardNumber, setCardNumber] = useState(''); const [cardNumber, setCardNumber] = useState('');
@@ -35,16 +41,25 @@ const CreateCardTransactionOrderScreen = () => {
if (user) { if (user) {
if (user.passport_serie) setPassportSerie(user.passport_serie); if (user.passport_serie) setPassportSerie(user.passport_serie);
if (user.passport_id) setPassportId(String(user.passport_id)); if (user.passport_id) setPassportId(String(user.passport_id));
if (user.card_number) setCardNumber(formatCardNumber(String(user.card_number)));
if (user.card_month) setCardMonth(String(user.card_month).padStart(2,'0'));
if (user.card_year) setCardYear(String(user.card_year));
} }
}, [user]); }, [user]);
const handleCardNumberChange = (val) => {
setCardNumber(formatCardNumber(val));
};
const handleSubmit = async () => { const handleSubmit = async () => {
if (!cardNumber.trim() || !cardMonth || !cardYear || !passportSerie || !passportId.trim()) { if (!cardNumber.trim() || !cardMonth || !cardYear || !passportSerie || !passportId.trim()) {
Alert.alert('Error', 'All fields are required'); Alert.alert('Error', 'All fields are required');
return; return;
} }
setLoading(true); setLoading(true);
const res = await apiService.createCardTransactionOrder(cardNumber.trim(), cardMonth, cardYear, passportSerie, passportId.trim()); const rawCard = cardNumber.replace(/\s+/g, '').trim();
const res = await apiService.createCardTransactionOrder(rawCard, cardMonth, cardYear, passportSerie, passportId.trim());
setLoading(false); setLoading(false);
if (res.success) { if (res.success) {
Alert.alert('Success', res.message || 'Order created successfully', [ Alert.alert('Success', res.message || 'Order created successfully', [
@@ -85,10 +100,11 @@ const CreateCardTransactionOrderScreen = () => {
label="*Kart belgisi" label="*Kart belgisi"
placeholder="9934..." placeholder="9934..."
value={cardNumber} value={cardNumber}
onChangeText={setCardNumber} onChangeText={handleCardNumberChange}
keyboardType="numeric" keyboardType="numeric"
autoCapitalize="none" autoCapitalize="none"
autoCorrect={false} autoCorrect={false}
maxLength={19}
/> />
<SelectInput <SelectInput

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, SafeAreaView } from 'react-native';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
@@ -6,19 +6,33 @@ import apiService from '../../services/apiService';
import { COLORS } from '../../constants/colors'; import { COLORS } from '../../constants/colors';
import Input from '../../components/Input'; import Input from '../../components/Input';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import SelectInput from '../../components/SelectInput';
import { useAuth } from '../../contexts/AuthContext';
const CreateLoanRemainingOrderScreen = () => { const CreateLoanRemainingOrderScreen = () => {
const navigation = useNavigation(); const navigation = useNavigation();
const [accountNumber, setAccountNumber] = useState(''); const [accountNumber, setAccountNumber] = useState('');
const [passportSerie, setPassportSerie] = useState('');
const [passportId, setPassportId] = useState('');
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const { user } = useAuth();
useEffect(() => {
if (user) {
if (user.passport_serie) setPassportSerie(user.passport_serie);
if (user.passport_id) setPassportId(String(user.passport_id));
}
}, [user]);
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 handleSubmit = async () => { const handleSubmit = async () => {
if (accountNumber.trim().length === 0) { if (accountNumber.trim().length === 0 || !passportSerie || passportId.trim().length === 0) {
Alert.alert('Error', 'Account number is required'); Alert.alert('Error', 'All fields are required');
return; return;
} }
setLoading(true); setLoading(true);
const res = await apiService.createLoanRemainingOrder(accountNumber.trim()); const res = await apiService.createLoanRemainingOrder(accountNumber.trim(), passportSerie, passportId.trim());
setLoading(false); setLoading(false);
if (res.success) { if (res.success) {
Alert.alert('Success', res.message || 'Order created successfully', [ Alert.alert('Success', res.message || 'Order created successfully', [
@@ -40,6 +54,22 @@ const CreateLoanRemainingOrderScreen = () => {
<Text style={styles.title}>Täze sargyt</Text> <Text style={styles.title}>Täze sargyt</Text>
<SelectInput
label="*Passport seriýasy"
value={passportSerie}
onValueChange={setPassportSerie}
options={PASSPORT_SERIES.map((v) => ({ label: v, value: v }))}
placeholder="Saýla"
/>
<Input
label="*Passport belgisi"
placeholder="123456"
value={passportId}
onChangeText={setPassportId}
keyboardType="numeric"
/>
<Input <Input
label="Karz hasaby" label="Karz hasaby"
placeholder="1420..." placeholder="1420..."

View File

@@ -106,9 +106,9 @@ class ApiService {
} }
} }
async createLoanRemainingOrder(accountNumber) { async createLoanRemainingOrder(accountNumber, passportSerie = null, passportId = null) {
try { try {
const response = await authService.createLoanRemainingOrder(accountNumber); const response = await authService.createLoanRemainingOrder(accountNumber, passportSerie, passportId);
return { success: true, message: response.message }; return { success: true, message: response.message };
} catch (error) { } catch (error) {
return { success: false, error: error.message }; return { success: false, error: error.message };
@@ -124,9 +124,9 @@ class ApiService {
} }
} }
async updateLoanRemainingOrder(orderId, accountNumber) { async updateLoanRemainingOrder(orderId, accountNumber, passportSerie = null, passportId = null) {
try { try {
const response = await authService.updateLoanRemainingOrder(orderId, accountNumber); const response = await authService.updateLoanRemainingOrder(orderId, accountNumber, passportSerie, passportId);
return { success: true, message: response.message }; return { success: true, message: response.message };
} catch (error) { } catch (error) {
return { success: false, error: error.message }; return { success: false, error: error.message };

View File

@@ -184,15 +184,21 @@ class AuthService {
return this.makeRequest('/loan-remaining-order', null, true, 'GET'); return this.makeRequest('/loan-remaining-order', null, true, 'GET');
} }
// CREATE order (requires only account number passport details are fetched from user profile) // CREATE order (passport can be supplied or fetched from profile)
async createLoanRemainingOrder(accountNumber) { async createLoanRemainingOrder(accountNumber, passportSerie = null, passportId = null) {
const user = await this.getStoredUser(); let serie = passportSerie;
if (!user?.passport_serie || !user?.passport_id) { let pid = passportId;
throw new Error('Passport details are missing from profile'); if (!serie || !pid) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
} }
const payload = { const payload = {
passport_serie: user.passport_serie, passport_serie: serie,
passport_id: user.passport_id, passport_id: pid,
account_number: accountNumber, account_number: accountNumber,
}; };
return this.makeRequest('/loan-remaining-order', payload, true, 'POST'); return this.makeRequest('/loan-remaining-order', payload, true, 'POST');
@@ -204,14 +210,20 @@ class AuthService {
} }
// UPDATE order (only account number can change; passport details stay the same) // UPDATE order (only account number can change; passport details stay the same)
async updateLoanRemainingOrder(orderId, accountNumber) { async updateLoanRemainingOrder(orderId, accountNumber, passportSerie = null, passportId = null) {
const user = await this.getStoredUser(); let serie = passportSerie;
if (!user?.passport_serie || !user?.passport_id) { let pid = passportId;
throw new Error('Passport details are missing from profile'); if (!serie || !pid) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
} }
const payload = { const payload = {
passport_serie: user.passport_serie, passport_serie: serie,
passport_id: user.passport_id, passport_id: pid,
account_number: accountNumber, account_number: accountNumber,
}; };
return this.makeRequest(`/loan-remaining-order/${orderId}`, payload, true, 'POST'); return this.makeRequest(`/loan-remaining-order/${orderId}`, payload, true, 'POST');