import { useState, useEffect } from 'react'; import { View, Text, TextInput, TouchableOpacity, ScrollView, Alert, ActivityIndicator } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { router, useLocalSearchParams } from 'expo-router'; import { api } from '../../../services/api'; const METHODS = [ { id: 'CASH', label: 'Cash' }, { id: 'GCASH', label: 'GCash' }, { id: 'MAYA', label: 'Maya' }, { id: 'BANK', label: 'Bank Transfer' }, ]; export default function RecordPaymentScreen() { // Prefill params when navigated from client detail const params = useLocalSearchParams<{ prefillClientId?: string; prefillName?: string; prefillAccountNumber?: string; }>(); const [search, setSearch] = useState(''); const [client, setClient] = useState(null); const [amount, setAmount] = useState(''); const [method, setMethod] = useState('CASH'); const [reference, setReference] = useState(''); const [loading, setLoading] = useState(false); const [searching, setSearching] = useState(false); // Auto-fill client if navigated from client detail useEffect(() => { if (params.prefillClientId && params.prefillName) { setClient({ id: params.prefillClientId, firstName: params.prefillName.split(' ')[0] ?? '', lastName: params.prefillName.split(' ').slice(1).join(' ') ?? '', accountNumber: params.prefillAccountNumber ?? '', }); } }, []); const searchClient = async () => { if (!search.trim()) return; setSearching(true); try { const res = await api.get(`/api/v1/clients?search=${encodeURIComponent(search.trim())}&limit=5`); const found = res.data?.data ?? res.data ?? []; if (Array.isArray(found) && found.length === 1) { setClient(found[0]); } else if (Array.isArray(found) && found.length > 1) { // Show picker if multiple results Alert.alert( 'Multiple clients found', found.map((c: any, i: number) => `${i + 1}. ${c.firstName} ${c.lastName} (${c.accountNumber})`).join('\n'), [ ...found.slice(0, 5).map((c: any, i: number) => ({ text: `${i + 1}. ${c.firstName} ${c.lastName}`, onPress: () => setClient(c), })), { text: 'Cancel', style: 'cancel' as const }, ] ); } else { Alert.alert('Not Found', 'No client found. Try account number or full name.'); } } catch { Alert.alert('Error', 'Search failed. Please try again.'); } finally { setSearching(false); } }; const submit = async () => { if (!client) return Alert.alert('Required', 'Search and select a client first.'); const amt = Number(amount); if (!amount || isNaN(amt) || amt <= 0) return Alert.alert('Required', 'Enter a valid amount.'); setLoading(true); try { await api.post('/api/v1/payments', { clientId: client.id, amount: amt, channel: method, // API uses `channel` not `paymentMethod` referenceNumber: reference.trim() || undefined, paymentDate: new Date().toISOString(), }); Alert.alert('Payment Recorded!', `₱${amt.toLocaleString()} from ${client.firstName} ${client.lastName}`, [ { text: 'Record Another', onPress: () => { setClient(null); setAmount(''); setSearch(''); setReference(''); } }, { text: 'Done', onPress: () => router.back() }, ]); } catch (e: any) { const msg = e?.response?.data?.message; Alert.alert('Error', Array.isArray(msg) ? msg.join('\n') : msg ?? 'Payment failed.'); } finally { setLoading(false); } }; const canSubmit = !!client && !!amount && Number(amount) > 0; return ( {/* Header */} router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}> ← Back Record Payment Field collection {/* Client section */} Client {client ? ( {client.firstName} {client.lastName} {client.accountNumber} { setClient(null); setSearch(''); }} style={{ marginTop: 10 }} hitSlop={{ top: 8, bottom: 8, left: 0, right: 8 }}> × Change client ) : ( {search.length > 0 && ( setSearch('')} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}> × )} {searching ? : Find } Search by account number, first name, or last name )} {/* Amount */} Amount (₱) {/* Payment method */} Payment Method {METHODS.map(m => ( setMethod(m.id)} style={{ flex: 1, borderRadius: 14, paddingVertical: 14, alignItems: 'center', marginHorizontal: 4, backgroundColor: method === m.id ? '#0891B2' : '#FFF', borderWidth: 1.5, borderColor: method === m.id ? '#0891B2' : '#E2E8F0' }} activeOpacity={0.7} > {m.label} ))} {/* Reference */} Reference # (optional) {loading ? : {canSubmit ? `Record ₱${Number(amount || 0).toLocaleString()} Payment` : 'Record Payment'} } ); }