import { useEffect, useState } from "react"; import { FileText, AlertCircle, Clock, CheckCircle2 } from "lucide-react"; import { getRecordView, getRVScreen } from "../api/viewService"; import { StatsSkeleton } from "./Skeleton"; import { ALL_INVOICES_RV_SCREEN_UUID, RECORD_VIEW_IDS } from "../config"; const ALL_INVOICES_VIEW = ALL_INVOICES_RV_SCREEN_UUID; interface Stats { total: number; pendingClarification: number; financeReview: number; approved: number; } export default function DashboardStats() { const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchStats() { try { const rvScreen = await getRVScreen(ALL_INVOICES_VIEW); const id = rvScreen.rv_template_uid; const rvUid = RECORD_VIEW_IDS.ALL_INVOICES; // Step 1: get exact total from pagination const countRes = await getRecordView(id, rvUid, { page: 1, limit: 1 }); const total = countRes.pagination?.total_count ?? 0; let pendingClarification = 0, financeReview = 0, approved = 0; if (total > 0) { // Step 2: fetch all rows in one call using exact total as limit const allRes = await getRecordView(id, rvUid, { page: 1, limit: total }); for (const row of allRes.data ?? []) { const state = String(row.current_state_name ?? ""); if (state === "Awaiting Clarification") pendingClarification++; else if (state === "Finance Review") financeReview++; else if (state === "Approved") approved++; } } setStats({ total, pendingClarification, financeReview, approved }); } catch { setStats({ total: 0, pendingClarification: 0, financeReview: 0, approved: 0 }); } finally { setLoading(false); } } fetchStats(); }, []); if (loading) return ; if (!stats) return null; const cards = [ { label: "Total Invoices", value: stats.total, icon: FileText, color: "text-slate-500 dark:text-zinc-400", bg: "bg-slate-100 dark:bg-zinc-800" }, { label: "Pending Clarification", value: stats.pendingClarification, icon: AlertCircle, color: "text-amber-600 dark:text-amber-400", bg: "bg-amber-50 dark:bg-amber-950/40" }, { label: "Finance Review", value: stats.financeReview, icon: Clock, color: "text-indigo-600 dark:text-indigo-400", bg: "bg-indigo-50 dark:bg-indigo-950/40" }, { label: "Approved", value: stats.approved, icon: CheckCircle2, color: "text-emerald-600 dark:text-emerald-400", bg: "bg-emerald-50 dark:bg-emerald-950/40" }, ]; return (
{cards.map((card) => { const Icon = card.icon; return (
{card.value}
{card.label}
); })}
); }