import { useState, useCallback } from "react"; import { useTranslation } from "react-i18next"; import { Wallet, TrendingUp, TrendingDown } from "lucide-react"; import { useDashboard } from "../hooks/useDashboard"; import { PageHelp } from "../components/shared/PageHelp"; import PeriodSelector from "../components/dashboard/PeriodSelector"; import CategoryPieChart from "../components/dashboard/CategoryPieChart"; import CategoryOverTimeChart from "../components/reports/CategoryOverTimeChart"; import BudgetVsActualTable from "../components/reports/BudgetVsActualTable"; import TransactionDetailModal from "../components/shared/TransactionDetailModal"; import type { CategoryBreakdownItem, DashboardPeriod } from "../shared/types"; const fmt = new Intl.NumberFormat("en-CA", { style: "currency", currency: "CAD" }); function computeDateRange( period: DashboardPeriod, customDateFrom?: string, customDateTo?: string, ): { dateFrom?: string; dateTo?: string } { if (period === "all") return {}; if (period === "custom" && customDateFrom && customDateTo) { return { dateFrom: customDateFrom, dateTo: customDateTo }; } const now = new Date(); const year = now.getFullYear(); const month = now.getMonth(); const day = now.getDate(); const dateTo = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`; let from: Date; switch (period) { case "month": from = new Date(year, month, 1); break; case "3months": from = new Date(year, month - 2, 1); break; case "6months": from = new Date(year, month - 5, 1); break; case "year": from = new Date(year, 0, 1); break; case "12months": from = new Date(year, month - 11, 1); break; default: from = new Date(year, month, 1); break; } const dateFrom = `${from.getFullYear()}-${String(from.getMonth() + 1).padStart(2, "0")}-${String(from.getDate()).padStart(2, "0")}`; return { dateFrom, dateTo }; } export default function DashboardPage() { const { t } = useTranslation(); const { state, setPeriod, setCustomDates } = useDashboard(); const { summary, categoryBreakdown, categoryOverTime, budgetVsActual, period, isLoading } = state; const [hiddenCategories, setHiddenCategories] = useState>(new Set()); const [detailModal, setDetailModal] = useState(null); const toggleHidden = useCallback((name: string) => { setHiddenCategories((prev) => { const next = new Set(prev); if (next.has(name)) next.delete(name); else next.add(name); return next; }); }, []); const showAll = useCallback(() => setHiddenCategories(new Set()), []); const viewDetails = useCallback((item: CategoryBreakdownItem) => { setDetailModal(item); }, []); const balance = summary.totalAmount; const balanceColor = balance > 0 ? "text-[var(--positive)]" : balance < 0 ? "text-[var(--negative)]" : "text-[var(--primary)]"; const cards = [ { labelKey: "dashboard.balance", value: fmt.format(balance), icon: Wallet, color: balanceColor, }, { labelKey: "dashboard.income", value: fmt.format(summary.incomeTotal), icon: TrendingUp, color: "text-[var(--positive)]", }, { labelKey: "dashboard.expenses", value: fmt.format(Math.abs(summary.expenseTotal)), icon: TrendingDown, color: "text-[var(--negative)]", }, ]; const { dateFrom, dateTo } = computeDateRange(period, state.customDateFrom, state.customDateTo); return (

{t("dashboard.title")}

{cards.map((card) => (
{t(card.labelKey)}

{card.value}

))}

{t("dashboard.expensesByCategory")}

{t("dashboard.budgetVsActual")}

{t("dashboard.expensesOverTime")}

{detailModal && ( setDetailModal(null)} /> )}
); }