// DashboardPage — home page at `/`. // // Converged onto the `/reports/cartes` model (Issue #279, epic #260): the KPI // row, top movers and budget adherence are the exact Cartes presentational // components, sourced from the same `getCartesSnapshot` reference-month // snapshot. Two Dashboard-specific widgets remain: the top-expense-categories // ranked bar chart (replacing the former expense-only pie) and the net-worth // tile (from the Bilan — a different metric from every transactional widget // here, see NetWorthTile's own header comment). import { useState, useCallback, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { useDashboard } from "../hooks/useDashboard"; import { PageHelp } from "../components/shared/PageHelp"; import PeriodSelector from "../components/dashboard/PeriodSelector"; import CategoryBarChart from "../components/reports/CategoryBarChart"; import CategoriesV1DiscoveryBanner from "../components/dashboard/CategoriesV1DiscoveryBanner"; import NetWorthTile from "../components/dashboard/NetWorthTile"; import FilterPanel from "../components/reports/FilterPanel"; import KpiCard from "../components/reports/cards/KpiCard"; import IncomeExpenseOverlayChart from "../components/reports/cards/IncomeExpenseOverlayChart"; import TopMoversList from "../components/reports/cards/TopMoversList"; import BudgetAdherenceCard from "../components/reports/cards/BudgetAdherenceCard"; import CategoryOverTimeChart from "../components/reports/CategoryOverTimeChart"; import TransactionDetailModal from "../components/shared/TransactionDetailModal"; import type { CategoryBreakdownItem } from "../shared/types"; import { computeDateRange, buildMonthOptions } from "../utils/dateRange"; export default function DashboardPage() { const { t, i18n } = useTranslation(); const { state, setPeriod, setCustomDates, setReferencePeriod, setAccountIds, } = useDashboard(); const { categoryBreakdown, categoryOverTime, cartesSnapshot, 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 monthOptions = useMemo(() => buildMonthOptions(i18n.language), [i18n.language]); const { dateFrom, dateTo } = computeDateRange(period, state.customDateFrom, state.customDateTo); return (

{t("dashboard.title")}

{state.error && (
{state.error}
)} } accountIds={state.accountIds} onAccountIdsChange={setAccountIds} accounts={state.accounts} />

{t("dashboard.kpiSectionTitle")}

{cartesSnapshot && ( <>
)}
{cartesSnapshot && ( <>
)}

{t("dashboard.expensesByCategory")}

{t("dashboard.expensesOverTime")}

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