import React, { useState, useCallback } from "react"; import { View, ScrollView, ActivityIndicator } from "react-native"; import { useSirouRouter } from "@sirou/react-native"; import { AppRoutes } from "@/lib/routes"; import { Stack, useLocalSearchParams, useFocusEffect } from "expo-router"; import { Text } from "@/components/ui/text"; import { Button } from "@/components/ui/button"; import { User, Calendar, Clock, Building2, Hash, Send } from "@/lib/icons"; import { ScreenWrapper } from "@/components/ScreenWrapper"; import { StandardHeader } from "@/components/StandardHeader"; import { api } from "@/lib/api"; import { useColorScheme } from "nativewind"; import { toast } from "@/lib/toast-store"; const STATUS_THEME: Record< string, { label: string; bg: string; text: string; dot: string } > = { DRAFT: { label: "Draft", bg: "bg-slate-500/10", text: "text-slate-600", dot: "bg-slate-500", }, SENT: { label: "Sent", bg: "bg-primary/10", text: "text-primary", dot: "bg-primary", }, OPENED: { label: "Opened", bg: "bg-blue-500/10", text: "text-blue-600", dot: "bg-blue-500", }, PAID: { label: "Paid", bg: "bg-emerald-500/10", text: "text-emerald-600", dot: "bg-emerald-500", }, EXPIRED: { label: "Expired", bg: "bg-red-500/10", text: "text-red-600", dot: "bg-red-500", }, CANCELLED: { label: "Cancelled", bg: "bg-slate-500/10", text: "text-slate-600", dot: "bg-slate-500", }, }; function safeVal(v: any): number { if (v == null) return 0; if (typeof v === "object") return Number(v.value) || 0; return Number(v) || 0; } function fmt(v: number, currency = "ETB") { return `${currency} ${v.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; } export default function PaymentRequestDetailScreen() { const nav = useSirouRouter(); const { id } = useLocalSearchParams(); const { colorScheme } = useColorScheme(); const isDark = colorScheme === "dark"; const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [sending, setSending] = useState(false); const fetch = useCallback(async () => { try { setLoading(true); const reqId = Array.isArray(id) ? id[0] : id; if (!reqId) return; const result = await api.paymentRequests.getById({ params: { id: reqId }, }); setData(result); await api.paymentRequests.open({ params: { id: reqId } }).catch(() => {}); } catch (err: any) { toast.error("Error", "Failed to load payment request"); } finally { setLoading(false); } }, [id]); useFocusEffect( useCallback(() => { fetch(); }, [fetch]), ); const handleSendEmail = async () => { try { setSending(true); const reqId = Array.isArray(id) ? id[0] : id; await api.paymentRequests.sendEmail({ params: { id: reqId } }); toast.success("Sent", "Payment request emailed to customer"); } catch (err: any) { toast.error("Error", err?.message || "Failed to send email"); } finally { setSending(false); } }; if (loading || !data) { return ( ); } const statusKey = (data.status || "DRAFT").toUpperCase(); const theme = STATUS_THEME[statusKey] || STATUS_THEME.DRAFT; const items: any[] = data.items || []; const accounts: any[] = data.accounts || []; const currency = data.currency || "ETB"; const amount = safeVal(data.amount); const subtotal = items.reduce((s: number, i: any) => s + safeVal(i.total), 0); const tax = safeVal(data.taxAmount); const discount = safeVal(data.discountAmount); const total = amount || subtotal + tax - discount; return ( {/* Customer + Dates cluster */} Customer {data.customerName || "—"} {(data.customerEmail || data.customerPhone) && ( {[data.customerEmail, data.customerPhone] .filter(Boolean) .join(" · ")} )} Issued {data.issueDate ? new Date(data.issueDate).toLocaleDateString() : "—"} Due {data.dueDate ? new Date(data.dueDate).toLocaleDateString() : "—"} {/* Description */} {data.description ? ( Description {data.description} ) : null} {/* Items */} {items.length > 0 && ( Items ({items.length}) {items.map((item: any, idx: number) => ( {item.description || `Item ${idx + 1}`} {fmt(safeVal(item.total), currency)} {safeVal(item.quantity)} ×{" "} {fmt(safeVal(item.unitPrice), currency)} ))} )} {/* Totals */} Summary {subtotal > 0 && ( Subtotal {fmt(subtotal, currency)} )} {tax > 0 && ( Tax {fmt(tax, currency)} )} {discount > 0 && ( Discount -{fmt(discount, currency)} )} Total {fmt(total, currency)} {/* Accounts */} {accounts.length > 0 && ( Bank Accounts ({accounts.length}) {accounts.map((acc: any, idx: number) => ( {acc.bankName || "Bank"} {acc.currency || currency} {acc.accountName || "—"} {acc.accountNumber || "—"} ))} )} {/* Notes */} {data.notes ? ( Notes {data.notes} ) : null} {/* Actions */} {!data.customerEmail && ( No customer email on file )} ); }