"use client"; import { useState } from "react"; import { useQuery, useMutation } from "@tanstack/react-query"; import { toast } from "sonner"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card"; import { Button } from "@/components/ui/Button"; import { Input } from "@/components/ui/Input"; import { Table, TableHead, TableBody, TableRow, Th, Td, EmptyState } from "@/components/ui/Table"; import { Modal } from "@/components/ui/Modal"; import { AccountingNav } from "@/components/accounting/AccountingNav"; import { formatCurrency } from "@/lib/utils"; import api from "@/lib/api"; import type { Expense, Account } from "@/types/index"; function formatDate(iso: string) { return new Date(iso).toLocaleDateString("en-PH", { year: "numeric", month: "short", day: "numeric" }); } export default function ExpensesPage() { const today = new Date().toISOString().split("T")[0]; const firstOfMonth = new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString().split("T")[0]; const [from, setFrom] = useState(firstOfMonth); const [to, setTo] = useState(today); const [showAdd, setShowAdd] = useState(false); const [form, setForm] = useState({ accountId: "", amount: "", date: today, vendor: "", description: "" }); const { data: expenses = [], isLoading, refetch } = useQuery({ queryKey: ["expenses", from, to], queryFn: async () => { const res = await api.get(`/api/v1/expenses?dateFrom=${from}&dateTo=${to}`); const d = res.data; return Array.isArray(d) ? d : (d as { data: Expense[] }).data ?? []; }, }); const { data: accounts = [] } = useQuery({ queryKey: ["accounts-expense"], queryFn: async () => { const res = await api.get("/api/v1/accounts?type=EXPENSE"); const d = res.data; return (Array.isArray(d) ? d : (d as { data: Account[] }).data ?? []).filter((a) => a.isActive && a.type === "EXPENSE"); }, }); const addMutation = useMutation({ mutationFn: async () => { await api.post("/api/v1/expenses", { accountId: form.accountId, amount: parseFloat(form.amount), date: form.date, vendor: form.vendor || undefined, description: form.description || undefined, }); }, onSuccess: () => { toast.success("Expense recorded"); setShowAdd(false); setForm({ accountId: "", amount: "", date: today, vendor: "", description: "" }); refetch(); }, onError: () => toast.error("Failed to record expense"), }); const totalAmount = expenses.reduce((s, e) => s + Number(e.amount), 0); return (

Accounting

Track business expenses

{/* Date filter */}
setFrom(e.target.value)} className="border rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" /> setTo(e.target.value)} className="border rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
Expenses ({expenses.length}) {expenses.length > 0 && ( Total: {formatCurrency(totalAmount)} )} {isLoading ? ( Array.from({ length: 4 }).map((_, i) => ( {[1,2,3,4,5].map((j) => ( ))} )) ) : expenses.length === 0 ? ( ) : ( expenses.map((e) => ( )) )}
Date Vendor Account Amount Description
{formatDate(e.date)} {e.vendor ?? } {e.account ? `${e.account.code} — ${e.account.name}` : "—"} {formatCurrency(Number(e.amount))} {e.description ?? }
setShowAdd(false)} title="Record Expense">
{ e.preventDefault(); addMutation.mutate(); }} className="space-y-4">
setForm((f) => ({ ...f, amount: e.target.value }))} placeholder="0.00" /> setForm((f) => ({ ...f, date: e.target.value }))} />
setForm((f) => ({ ...f, vendor: e.target.value }))} placeholder="e.g. PLDT, Globe" /> setForm((f) => ({ ...f, description: e.target.value }))} placeholder="What was this expense for?" />
); }