"use client"; import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { RefreshCw, CreditCard, AlertCircle } from "lucide-react"; import { Card, CardContent, CardHeader } 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"; interface Payment { id: string; clientId: string; client?: { firstName: string; lastName: string; accountNumber: string }; invoice?: { invoiceNumber: string; total: string }; invoiceId?: string; amount: string; channel: string; referenceNumber?: string; orNumber?: string; notes?: string; paymentDate?: string; createdAt: string; recordedBy?: { firstName: string; lastName: string }; } interface PaymentsResponse { data: Payment[]; total: number; page: number; limit: number; } const channelVariant: Record = { CASH: "success", GCASH: "default", MAYA: "default", BANK_TRANSFER: "warning", CHECK: "muted", }; const channelFilters = ["", "CASH", "GCASH", "MAYA", "BANK_TRANSFER", "CHECK"]; export default function PaymentsPage() { const [search, setSearch] = useState(""); const [channelFilter, setChannelFilter] = useState(""); const [page, setPage] = useState(1); const [selected, setSelected] = useState(null); const { data, isLoading, isError, refetch } = useQuery({ queryKey: ["payments", search, channelFilter, page], queryFn: async () => { const params = new URLSearchParams({ page: String(page), limit: "20" }); if (search) params.set("search", search); if (channelFilter) params.set("channel", channelFilter); const res = await api.get(`/api/v1/payments?${params}`); return res.data; }, }); const payments = data?.data ?? []; const total = data?.total ?? 0; return (

Payments

{total} total payments

{ setSearch(e.target.value); setPage(1); }} />
{channelFilters.map(c => ( ))}
{isLoading ? ( Array.from({ length: 8 }).map((_, i) => ( )) ) : isError ? ( ) : payments.length === 0 ? ( } /> ) : payments.map(p => ( setSelected(p)} className="cursor-pointer hover:bg-blue-50 transition-colors"> ))}
DateClientAmountMethodReferenceInvoice
Failed to load payments.
{p.paymentDate ? formatDate(p.paymentDate) : formatDate(p.createdAt)} {p.client ? `${p.client.firstName} ${p.client.lastName}` : "—"}
{p.client?.accountNumber}
{formatCurrency(Number(p.amount))} {p.channel} {p.referenceNumber ?? p.orNumber ?? "—"} {p.invoice?.invoiceNumber ?? (p.invoiceId ? p.invoiceId.slice(0, 8) : "—")} View →
{total > 20 && (
Showing {(page - 1) * 20 + 1}–{Math.min(page * 20, total)} of {total}
)}
{/* Payment Detail Modal */} setSelected(null)} title="Payment Details"> {selected && (
Client {selected.client ? `${selected.client.firstName} ${selected.client.lastName}` : "—"}
Account # {selected.client?.accountNumber ?? "—"}

Amount {formatCurrency(Number(selected.amount))}
Method {selected.channel}
{(selected.referenceNumber || selected.orNumber) && (
Reference # {selected.referenceNumber ?? selected.orNumber}
)}
Invoice {selected.invoice?.invoiceNumber ?? (selected.invoiceId ? selected.invoiceId.slice(0, 8) : "—")}
Payment Date {selected.paymentDate ? formatDate(selected.paymentDate) : formatDate(selected.createdAt)}
{selected.notes && (
Notes {selected.notes}
)} {selected.recordedBy && (
Recorded By {selected.recordedBy.firstName} {selected.recordedBy.lastName}
)}
)}
); }