diff --git a/src/screens/Loan/CreateLoanPaidOffLetterOrderScreen.js b/src/screens/Loan/CreateLoanPaidOffLetterOrderScreen.js new file mode 100644 index 0000000..9557add --- /dev/null +++ b/src/screens/Loan/CreateLoanPaidOffLetterOrderScreen.js @@ -0,0 +1,221 @@ +import React, { useState } from 'react'; +import { Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView, SafeAreaView } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { useNavigation } from '@react-navigation/native'; +import { COLORS } from '../../constants/colors'; +import Input from '../../components/Input'; +import { StatusBar } from 'expo-status-bar'; +import apiService from '../../services/apiService'; + +const CreateLoanPaidOffLetterOrderScreen = () => { + const navigation = useNavigation(); + + // Form states (required fields only) + const [region, setRegion] = useState(''); + const [branchId, setBranchId] = useState(''); + const [customerName, setCustomerName] = useState(''); + const [customerSurname, setCustomerSurname] = useState(''); + const [passportSerie, setPassportSerie] = useState(''); + const [passportId, setPassportId] = useState(''); + const [bornAt, setBornAt] = useState(''); + const [phone, setPhone] = useState(''); + const [contractNumber, setContractNumber] = useState(''); + const [contractDate, setContractDate] = useState(''); + const [loanAmount, setLoanAmount] = useState(''); + const [loanReason, setLoanReason] = useState(''); + const [loading, setLoading] = useState(false); + + const handleSubmit = async () => { + // Basic validation – ensure all required fields are filled + if ( + !region || + !branchId || + !customerName || + !customerSurname || + !passportSerie || + !passportId || + !bornAt || + !phone || + !contractNumber || + !contractDate || + !loanAmount || + !loanReason + ) { + Alert.alert('Error', 'Please fill in all required fields'); + return; + } + + const payload = { + region, + branch_id: parseInt(branchId), + customer_name: customerName, + customer_surname: customerSurname, + passport_serie: passportSerie, + passport_id: parseInt(passportId), + born_at: bornAt, + phone: parseInt(phone), + loan_contract_number: contractNumber, + loan_contract_date: contractDate, + loan_amount: loanAmount, + loan_reason: loanReason, + }; + + try { + setLoading(true); + const res = await apiService.createLoanPaidOffLetterOrder(payload); + setLoading(false); + + if (res.success) { + Alert.alert('Success', res.message || 'Order created successfully', [ + { text: 'OK', onPress: () => navigation.goBack() }, + ]); + } else { + Alert.alert('Error', res.error || 'Could not create order'); + } + } catch (error) { + setLoading(false); + Alert.alert('Error', error.message || 'Could not create order'); + } + }; + + return ( + + + navigation.goBack()}> + + + + + Täze güwanama sargyt et + + {/* Region & Branch */} + + + + {/* Customer */} + + + + {/* Passport */} + + + + {/* Other personal */} + + + + {/* Loan contract */} + + + + + + + {loading ? ( + + ) : ( + Ýatda sakla + )} + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: COLORS.backgroundSecondary, + paddingHorizontal: 24, + paddingTop: 40, + }, + backBtn: { + marginBottom: 24, + }, + title: { + fontSize: 24, + fontWeight: 'bold', + color: COLORS.textPrimary, + marginBottom: 24, + }, + submitBtn: { + marginTop: 32, + backgroundColor: COLORS.primary, + paddingVertical: 16, + borderRadius: 8, + alignItems: 'center', + }, + submitText: { + color: COLORS.white, + fontSize: 16, + fontWeight: '600', + }, +}); + +export default CreateLoanPaidOffLetterOrderScreen; \ No newline at end of file diff --git a/src/screens/Loan/LoanPaidOffLetterOrderDetailsScreen.js b/src/screens/Loan/LoanPaidOffLetterOrderDetailsScreen.js new file mode 100644 index 0000000..f6fd36c --- /dev/null +++ b/src/screens/Loan/LoanPaidOffLetterOrderDetailsScreen.js @@ -0,0 +1,148 @@ +import React, { useEffect, useState } from 'react'; +import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, SafeAreaView } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { useNavigation, useRoute } from '@react-navigation/native'; +import apiService from '../../services/apiService'; +import { COLORS } from '../../constants/colors'; +import { StatusBar } from 'expo-status-bar'; + +const LoanPaidOffLetterOrderDetailsScreen = () => { + const navigation = useNavigation(); + const route = useRoute(); + const { orderId } = route.params || {}; + + const [loading, setLoading] = useState(true); + const [order, setOrder] = useState(null); + + const fetchDetails = async () => { + setLoading(true); + const res = await apiService.getLoanPaidOffLetterOrder(orderId); + if (res.success) { + setOrder(res.data); + } else { + Alert.alert('Error', res.error || 'Could not fetch details'); + } + setLoading(false); + }; + + useEffect(() => { + fetchDetails(); + }, []); + + const handleDelete = () => { + Alert.alert('Confirm', 'Are you sure you want to delete this order?', [ + { text: 'Cancel', style: 'cancel' }, + { text: 'Delete', style: 'destructive', onPress: deleteOrder }, + ]); + }; + + const deleteOrder = async () => { + const res = await apiService.deleteLoanPaidOffLetterOrder(orderId); + if (res.success) { + Alert.alert('Deleted', res.message || 'Order deleted', [ + { text: 'OK', onPress: () => navigation.goBack() }, + ]); + } else { + Alert.alert('Error', res.error || 'Could not delete'); + } + }; + + if (loading) { + return ( + + + + ); + } + + if (!order) { + return ( + + No data + + ); + } + + return ( + + + navigation.goBack()}> + + + + + Güwanama detallary + + + {Object.entries(order).map(([key, value]) => ( + + {key} + {String(value)} + + ))} + + + + Poz + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: COLORS.backgroundSecondary, + paddingHorizontal: 24, + paddingTop: 40, + }, + centered: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + backBtn: { + alignSelf: 'flex-end', + marginBottom: 16, + }, + title: { + fontSize: 24, + fontWeight: 'bold', + color: COLORS.textPrimary, + marginBottom: 24, + }, + detailCard: { + backgroundColor: COLORS.white, + borderRadius: 12, + padding: 20, + marginBottom: 32, + }, + detailRow: { + flexDirection: 'row', + justifyContent: 'space-between', + marginBottom: 12, + }, + detailKey: { + fontWeight: '600', + color: COLORS.textSecondary, + }, + detailValue: { + color: COLORS.textPrimary, + maxWidth: '60%', + textAlign: 'right', + }, + deleteBtn: { + backgroundColor: COLORS.error, + paddingVertical: 14, + borderRadius: 8, + alignItems: 'center', + }, + deleteText: { + color: COLORS.white, + fontSize: 16, + fontWeight: '600', + }, +}); + +export default LoanPaidOffLetterOrderDetailsScreen; \ No newline at end of file diff --git a/src/screens/Loan/LoanPaidOffLetterOrdersScreen.js b/src/screens/Loan/LoanPaidOffLetterOrdersScreen.js new file mode 100644 index 0000000..fd95022 --- /dev/null +++ b/src/screens/Loan/LoanPaidOffLetterOrdersScreen.js @@ -0,0 +1,145 @@ +import React, { useState, useCallback } from 'react'; +import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, SafeAreaView } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { useNavigation, useFocusEffect } from '@react-navigation/native'; +import apiService from '../../services/apiService'; +import { COLORS } from '../../constants/colors'; +import { StatusBar } from 'expo-status-bar'; + +const CARD_BG = '#F1F9F1'; +const CIRCLE_BG = '#A2E4A4'; + +const LoanPaidOffLetterOrdersScreen = () => { + const navigation = useNavigation(); + const [orders, setOrders] = useState([]); + const [loading, setLoading] = useState(true); + const [refreshing, setRefreshing] = useState(false); + + const fetchOrders = async () => { + try { + const res = await apiService.getLoanPaidOffLetterOrders(); + if (res.success) { + setOrders(Array.isArray(res.data) ? res.data : []); + } else { + console.warn(res.error); + } + } catch (e) { + console.warn(e.message); + } finally { + setLoading(false); + setRefreshing(false); + } + }; + + useFocusEffect( + useCallback(() => { + fetchOrders(); + }, []) + ); + + const onRefresh = () => { + setRefreshing(true); + fetchOrders(); + }; + + const renderItem = ({ item }) => { + const passportLine = `Pasport: ${item.passport_serie} ${item.passport_id}`; + const accountLine = `Karz hasaby:`; + const created = item.created_at ? new Date(item.created_at).toLocaleDateString() : ''; + + return ( + navigation.navigate('LoanPaidOffLetterOrderDetails', { orderId: item.id })}> + + {item.id} + + + {passportLine} + {accountLine} + {item.loan_contract_number || '-'} + {created} + + + ); + }; + + if (loading) { + return ( + + + + ); + } + + return ( + + + {/* Header */} + + navigation.goBack()} style={{ paddingRight: 12 }}> + + + Ýapylandygy barada güwanamalar + + + it.id?.toString()} + renderItem={renderItem} + contentContainerStyle={orders.length === 0 && styles.emptyContainer} + refreshControl={} + ListEmptyComponent={No orders yet} + /> + + navigation.navigate('CreateLoanPaidOffLetterOrder')}> + + + + ); +}; + +const styles = StyleSheet.create({ + container: { flex: 1, backgroundColor: COLORS.backgroundSecondary }, + centered: { flex: 1, alignItems: 'center', justifyContent: 'center' }, + header: { flexDirection: 'row', alignItems: 'center', padding: 16 }, + headerTitle: { fontSize: 18, fontWeight: 'bold', color: COLORS.textPrimary, marginLeft: 12 }, + card: { + flexDirection: 'row', + backgroundColor: CARD_BG, + marginHorizontal: 24, + marginTop: 16, + borderRadius: 12, + padding: 16, + alignItems: 'center', + }, + circle: { + width: 40, + height: 40, + borderRadius: 20, + backgroundColor: CIRCLE_BG, + alignItems: 'center', + justifyContent: 'center', + marginRight: 16, + }, + circleText: { color: COLORS.white, fontWeight: '600' }, + cardContent: { flex: 1 }, + passportText: { fontWeight: '700', color: COLORS.textPrimary, marginBottom: 4 }, + accountLabel: { color: COLORS.textSecondary, fontSize: 14 }, + accountValue: { color: COLORS.textPrimary, marginBottom: 4 }, + dateText: { color: COLORS.textSecondary, fontSize: 12 }, + emptyContainer: { flex: 1, justifyContent: 'center', alignItems: 'center' }, + emptyText: { fontSize: 16, color: COLORS.textSecondary }, + fab: { + position: 'absolute', + right: 24, + bottom: 40, + width: 56, + height: 56, + borderRadius: 28, + backgroundColor: COLORS.primary, + alignItems: 'center', + justifyContent: 'center', + elevation: 4, + }, +}); + +export default LoanPaidOffLetterOrdersScreen; \ No newline at end of file