"use client"; import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { RefreshCw } from "lucide-react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card"; import { Button } from "@/components/ui/Button"; import { AccountingNav } from "@/components/accounting/AccountingNav"; import { formatCurrency } from "@/lib/utils"; import api from "@/lib/api"; import type { TrialBalanceLine, ProfitLossReport, BalanceSheetReport, CashFlowReport, } from "@/types/index"; type ReportTab = "trial-balance" | "profit-loss" | "balance-sheet" | "cash-flow"; const TABS: { key: ReportTab; label: string }[] = [ { key: "trial-balance", label: "Trial Balance" }, { key: "profit-loss", label: "Profit & Loss" }, { key: "balance-sheet", label: "Balance Sheet" }, { key: "cash-flow", label: "Cash Flow" }, ]; // ─── Trial Balance ───────────────────────────────────────────────────────────── function TrialBalance({ dateFrom, dateTo }: { dateFrom: string; dateTo: string }) { const { data, isLoading } = useQuery({ queryKey: ["report-trial-balance", dateFrom, dateTo], queryFn: async () => { const res = await api.get(`/api/v1/reports/trial-balance?dateFrom=${dateFrom}&dateTo=${dateTo}`); const d = res.data; if (Array.isArray(d)) return d; return (d as { data?: TrialBalanceLine[] }).data ?? d as TrialBalanceLine[]; }, }); const lines = data ?? []; const totalDebit = lines.reduce((s, l) => s + Number(l.debit), 0); const totalCredit = lines.reduce((s, l) => s + Number(l.credit), 0); if (isLoading) return
; return ( Trial Balance {lines.length === 0 ? (

No data for this period

) : ( {lines.map((l, i) => ( ))}
Code Account Debit Credit Balance
{l.code} {l.name} {Number(l.debit) > 0 ? formatCurrency(Number(l.debit)) : "—"} {Number(l.credit) > 0 ? formatCurrency(Number(l.credit)) : "—"} {formatCurrency(Math.abs(Number(l.balance)))} {Number(l.balance) < 0 && " Cr"}
Totals {formatCurrency(totalDebit)} {formatCurrency(totalCredit)} {Math.abs(totalDebit - totalCredit) < 0.01 ? ( ✓ Balanced ) : ( Off by {formatCurrency(Math.abs(totalDebit - totalCredit))} )}
)}
); } // ─── P&L ────────────────────────────────────────────────────────────────────── function ProfitLoss({ dateFrom, dateTo }: { dateFrom: string; dateTo: string }) { const { data, isLoading } = useQuery({ queryKey: ["report-profit-loss", dateFrom, dateTo], queryFn: async () => { const res = await api.get(`/api/v1/reports/profit-loss?dateFrom=${dateFrom}&dateTo=${dateTo}`); return res.data as ProfitLossReport; }, }); if (isLoading) return
; if (!data) return

No data for this period

; const netIncome = Number(data.netIncome ?? (Number(data.totalRevenue) - Number(data.totalExpenses))); return ( Profit & Loss Statement
{/* Revenue */}

Revenue

{(data.revenue ?? []).map((r, i) => (
{r.name} {formatCurrency(Number(r.amount))}
))}
Total Revenue {formatCurrency(Number(data.totalRevenue))}
{/* Expenses */}

Expenses

{(data.expenses ?? []).map((e, i) => (
{e.name} {formatCurrency(Number(e.amount))}
))}
Total Expenses {formatCurrency(Number(data.totalExpenses))}
{/* Net Income */}
= 0 ? "bg-green-50 text-green-800" : "bg-red-50 text-red-800"}`}> Net Income {formatCurrency(netIncome)}
); } // ─── Balance Sheet ───────────────────────────────────────────────────────────── function BalanceSheet({ asOf }: { asOf: string }) { const { data, isLoading } = useQuery({ queryKey: ["report-balance-sheet", asOf], queryFn: async () => { const res = await api.get(`/api/v1/reports/balance-sheet?asOf=${asOf}`); return res.data as BalanceSheetReport; }, }); if (isLoading) return
; if (!data) return

No data

; function Section({ title, items, total, color }: { title: string; items: Array<{ name: string; amount: number }>; total: number; color: string }) { return (

{title}

{items.map((item, i) => (
{item.name} {formatCurrency(Number(item.amount))}
))}
Total {title} {formatCurrency(Number(total))}
); } return ( Balance Sheet
Total Liabilities + Equity {formatCurrency(Number(data.totalLiabilities) + Number(data.totalEquity))}
); } // ─── Cash Flow ───────────────────────────────────────────────────────────────── function CashFlow({ dateFrom, dateTo }: { dateFrom: string; dateTo: string }) { const { data, isLoading } = useQuery({ queryKey: ["report-cash-flow", dateFrom, dateTo], queryFn: async () => { const res = await api.get(`/api/v1/reports/cash-flow?dateFrom=${dateFrom}&dateTo=${dateTo}`); return res.data as CashFlowReport; }, }); if (isLoading) return
; if (!data) return

No data for this period

; function CashSection({ title, items, net }: { title: string; items: Array<{ name: string; amount: number }>; net: number }) { return (

{title}

{items.map((item, i) => (
{item.name} {formatCurrency(Number(item.amount))}
))}
Net {title} = 0 ? "text-green-700" : "text-red-600"}> {formatCurrency(Number(net))}
); } return ( Cash Flow Statement
= 0 ? "bg-green-50 text-green-800" : "bg-red-50 text-red-800"}`}> Net Cash Flow {formatCurrency(Number(data.netCashFlow))}
); } // ─── Main Page ───────────────────────────────────────────────────────────────── export default function AccountingReportsPage() { const today = new Date().toISOString().split("T")[0]; const firstOfYear = `${new Date().getFullYear()}-01-01`; const [activeTab, setActiveTab] = useState("trial-balance"); const [dateFrom, setDateFrom] = useState(firstOfYear); const [dateTo, setDateTo] = useState(today); const [asOf, setAsOf] = useState(today); return (

Accounting

Financial statements and accounting reports

{activeTab !== "balance-sheet" ? (
setDateFrom(e.target.value)} className="border rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" /> setDateTo(e.target.value)} className="border rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
) : (
setAsOf(e.target.value)} className="border rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
)}
{/* Report tabs */}
{TABS.map(({ key, label }) => ( ))}
{activeTab === "trial-balance" && } {activeTab === "profit-loss" && } {activeTab === "balance-sheet" && } {activeTab === "cash-flow" && }
); }