import { useState, useCallback, useMemo, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { Hash, Table, BarChart3 } from "lucide-react"; import { useReports } from "../hooks/useReports"; import { PageHelp } from "../components/shared/PageHelp"; import type { ReportTab, CategoryBreakdownItem, ImportSource } from "../shared/types"; import { getAllSources } from "../services/importSourceService"; import PeriodSelector from "../components/dashboard/PeriodSelector"; import MonthlyTrendsChart from "../components/reports/MonthlyTrendsChart"; import MonthlyTrendsTable from "../components/reports/MonthlyTrendsTable"; import CategoryBarChart from "../components/reports/CategoryBarChart"; import CategoryTable from "../components/reports/CategoryTable"; import CategoryOverTimeChart from "../components/reports/CategoryOverTimeChart"; import CategoryOverTimeTable from "../components/reports/CategoryOverTimeTable"; import BudgetVsActualTable from "../components/reports/BudgetVsActualTable"; import DynamicReport from "../components/reports/DynamicReport"; import ReportFilterPanel from "../components/reports/ReportFilterPanel"; import TransactionDetailModal from "../components/shared/TransactionDetailModal"; import { computeDateRange, buildMonthOptions } from "../utils/dateRange"; const TABS: ReportTab[] = ["trends", "byCategory", "overTime", "budgetVsActual", "dynamic"]; export default function ReportsPage() { const { t, i18n } = useTranslation(); const { state, setTab, setPeriod, setCustomDates, setBudgetMonth, setPivotConfig, setSourceId, setCategoryType } = useReports(); const [sources, setSources] = useState([]); useEffect(() => { getAllSources().then(setSources); }, []); const [hiddenCategories, setHiddenCategories] = useState>(new Set()); const [detailModal, setDetailModal] = useState(null); const [showAmounts, setShowAmounts] = useState(() => localStorage.getItem("reports-show-amounts") === "true"); const [viewMode, setViewMode] = useState<"chart" | "table">(() => (localStorage.getItem("reports-view-mode") as "chart" | "table") || "chart" ); 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 { dateFrom, dateTo } = computeDateRange(state.period, state.customDateFrom, state.customDateTo); const filterCategories = useMemo(() => { if (state.tab === "byCategory") { return state.categorySpending.map((c) => ({ name: c.category_name, color: c.category_color })); } if (state.tab === "overTime") { return state.categoryOverTime.categories.map((name) => ({ name, color: state.categoryOverTime.colors[name] || "#9ca3af", })); } return []; }, [state.tab, state.categorySpending, state.categoryOverTime]); const monthOptions = useMemo(() => buildMonthOptions(i18n.language), [i18n.language]); const hasCategories = ["byCategory", "overTime"].includes(state.tab) && filterCategories.length > 0; const showFilterPanel = hasCategories || (state.tab === "trends" && sources.length > 1); return (
{state.tab === "budgetVsActual" ? (

{t("reports.bva.titlePrefix")}

) : (

{t("reports.title")}

)}
{state.tab !== "budgetVsActual" && ( )}
{TABS.map((tab) => ( ))} {["trends", "byCategory", "overTime"].includes(state.tab) && ( <>
{([ { mode: "chart" as const, icon: , label: t("reports.pivot.viewChart") }, { mode: "table" as const, icon: , label: t("reports.pivot.viewTable") }, ]).map(({ mode, icon, label }) => ( ))} {viewMode === "chart" && ( <>
)} )}
{state.error && (
{state.error}
)}
{state.tab === "trends" && ( viewMode === "chart" ? ( ) : ( ) )} {state.tab === "byCategory" && ( viewMode === "chart" ? ( ) : ( ) )} {state.tab === "overTime" && ( viewMode === "chart" ? ( ) : ( ) )} {state.tab === "budgetVsActual" && ( )} {state.tab === "dynamic" && ( )}
{showFilterPanel && ( )}
{detailModal && ( setDetailModal(null)} /> )} ); }