"use client"; import { useState } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { RefreshCw, ArrowLeftRight, CheckCircle, Plus } from "lucide-react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card"; import { Table, TableHead, TableBody, TableRow, Th, Td, EmptyState } from "@/components/ui/Table"; import { Badge } from "@/components/ui/Badge"; import { Button } from "@/components/ui/Button"; import { Modal } from "@/components/ui/Modal"; import { formatDate, formatCurrency } from "@/lib/utils"; import api from "@/lib/api"; import { toast } from "sonner"; interface Payment { id: string; clientId: string; amount: string; channel: string; paymentDate?: string; createdAt: string; client?: { firstName: string; lastName: string; accountNumber: string }; } interface Remittance { id: string; collectorId?: string; collector?: { firstName: string; lastName: string }; totalAmount: number | string; notes?: string; status: string; payments?: Payment[]; createdAt: string; } const statusVariant: Record = { CONFIRMED: "success", PENDING: "warning", DISPUTED: "muted", }; export default function RemittancesPage() { const qc = useQueryClient(); const [showSubmit, setShowSubmit] = useState(false); const [notes, setNotes] = useState(""); const [selectedPaymentIds, setSelectedPaymentIds] = useState([]); const [selected, setSelected] = useState(null); const { data: remittances = [], isLoading, refetch } = useQuery({ queryKey: ["remittances"], queryFn: async () => { const res = await api.get("/api/v1/remittances?limit=50"); const d = res.data; return Array.isArray(d) ? d : d.data ?? []; }, }); const { data: unremitted = [] } = useQuery({ queryKey: ["unremitted-payments"], queryFn: async () => { const res = await api.get("/api/v1/payments/unremitted"); return Array.isArray(res.data) ? res.data : (res.data as any).data ?? []; }, enabled: showSubmit, }); const confirm = useMutation({ mutationFn: async (id: string) => { await api.patch(`/api/v1/remittances/${id}/confirm`); }, onSuccess: () => { toast.success("Remittance confirmed!"); qc.invalidateQueries({ queryKey: ["remittances"] }); }, onError: (e: any) => toast.error(e.response?.data?.message ?? "Failed to confirm"), }); const submitRemittance = useMutation({ mutationFn: async () => { await api.post("/api/v1/remittances", { paymentIds: selectedPaymentIds, notes: notes || undefined }); }, onSuccess: () => { toast.success("Remittance submitted!"); setShowSubmit(false); setSelectedPaymentIds([]); setNotes(""); qc.invalidateQueries({ queryKey: ["remittances"] }); qc.invalidateQueries({ queryKey: ["unremitted-payments"] }); }, onError: (e: any) => toast.error(e.response?.data?.message ?? "Failed to submit remittance"), }); const togglePayment = (id: string) => { setSelectedPaymentIds(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id] ); }; const selectedTotal = unremitted .filter(p => selectedPaymentIds.includes(p.id)) .reduce((sum, p) => sum + Number(p.amount), 0); return (

Remittances

{remittances.length} remittances

{isLoading ? ( Array.from({ length: 5 }).map((_, i) => ( )) ) : remittances.length === 0 ? ( } /> ) : remittances.map(r => ( setSelected(r)} className="cursor-pointer hover:bg-blue-50 transition-colors"> ))}
DateCollectorAmountStatusNotes
{formatDate(r.createdAt)} {r.collector ? `${r.collector.firstName} ${r.collector.lastName}` : "—"} {formatCurrency(Number(r.amount))} {r.status} {r.notes ?? "—"} {r.status === "PENDING" && ( )}
{/* Remittance Detail Modal */} setSelected(null)} title="Remittance Details" className="max-w-lg"> {selected && (
Collector {selected.collector ? `${selected.collector.firstName} ${selected.collector.lastName}` : "—"}
Total Amount {formatCurrency(Number(selected.totalAmount))}
Status {selected.status}
Date {formatDate(selected.createdAt)}
{selected.notes &&
Notes{selected.notes}
}
{selected.payments && selected.payments.length > 0 && (

Included Payments ({selected.payments.length})

{selected.payments.map(p => (
{p.client ? `${p.client.firstName} ${p.client.lastName}` : p.clientId.slice(0, 8)} {formatCurrency(Number(p.amount))}
))}
)}
{selected.status === "PENDING" && ( )}
)}
{/* Submit Remittance Modal */} setShowSubmit(false)} title="Submit Remittance" className="max-w-xl">

Select payments to include in this remittance.

{unremitted.length === 0 ? (
No unremitted payments available.
) : ( <>
{unremitted.length} unremitted payments
{unremitted.map(p => ( ))}
{selectedPaymentIds.length} payments selected {formatCurrency(selectedTotal)}
)}