import { useState, useEffect, useCallback } from 'react'; import type { Account, AnalyticsSummaryResponse, ByCategoryItem, TimeseriesItem, Granularity, } from '@family-budget/shared'; import { getAccounts } from '../api/accounts'; import { getSummary, getByCategory, getTimeseries } from '../api/analytics'; import { PeriodSelector, type PeriodState, } from '../components/PeriodSelector'; import { SummaryCards } from '../components/SummaryCards'; import { TimeseriesChart } from '../components/TimeseriesChart'; import { CategoryChart } from '../components/CategoryChart'; import { toISODate } from '../utils/format'; function getDefaultPeriod(): PeriodState { const now = new Date(); return { mode: 'month', from: toISODate(new Date(now.getFullYear(), now.getMonth(), 1)), to: toISODate(now), }; } export function AnalyticsPage() { const [period, setPeriod] = useState(getDefaultPeriod); const [accountId, setAccountId] = useState(''); const [onlyConfirmed, setOnlyConfirmed] = useState(false); const [accounts, setAccounts] = useState([]); const [summary, setSummary] = useState( null, ); const [byCategory, setByCategory] = useState([]); const [timeseries, setTimeseries] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { getAccounts().then(setAccounts).catch(() => {}); }, []); const fetchAll = useCallback(async () => { if (!period.from || !period.to) return; setLoading(true); let gran: Granularity; switch (period.mode) { case 'week': gran = 'day'; break; case 'month': gran = 'week'; break; default: gran = 'month'; break; } const base = { from: period.from, to: period.to, ...(accountId ? { accountId: Number(accountId) } : {}), ...(onlyConfirmed ? { onlyConfirmed: true } : {}), }; try { const [s, bc, ts] = await Promise.all([ getSummary(base), getByCategory(base), getTimeseries({ ...base, granularity: gran }), ]); setSummary(s); setByCategory(bc); setTimeseries(ts); } catch { // 401 handled by interceptor } finally { setLoading(false); } }, [period, accountId, onlyConfirmed]); useEffect(() => { fetchAll(); }, [fetchAll]); return (

Аналитика

{loading ? (
Загрузка данных...
) : ( <> {summary && }

Динамика

По категориям

)}
); }