import { useMemo } from "react"; import { eachDayOfInterval, format } from "date-fns"; import { TimeSeriesChart } from "@/components/charts/TimeSeriesChart"; import { parseLocalDate } from "@/lib/utils"; import { CalendarHeatmap } from "@/components/charts/CalendarHeatmap"; import { Button } from "@/components/ui/button"; import { useTransactionActivity } from "@/hooks/useTransactionActivity"; import type { TransactionFilters } from "@/hooks/useTransactionSearch"; import { useMoney } from "@/hooks/useMoney"; import { toDateString } from "@/lib/format"; import type { CalendarSelection, FlowDirection } from "@/lib/calendarActivity"; import type { Account } from "@/types/finance"; interface Props { filters: TransactionFilters; accounts: Account[]; year: number; direction: FlowDirection; chartType: "line" | "heatmap"; periodDays: number; onSelect: (selection: CalendarSelection | null) => void; } /** A chart-only view; search, dates, totals and the ledger belong to Transactions. */ export function TransactionsActivityChart({ filters, accounts, year, direction, chartType, periodDays, onSelect }: Props) { const from = filters.dateFrom ? toDateString(filters.dateFrom) : undefined; const to = filters.dateTo ? toDateString(filters.dateTo) : undefined; const selection = from || to ? { from: from ?? `${year}-01-01`, to: to ?? `${year}-12-31` } : null; const selectedAccounts = useMemo(() => accounts.filter(a => filters.accountIds?.includes(a.id) ?? (filters.accountId === "all" || a.id === filters.accountId)), [accounts, filters.accountIds, filters.accountId]); const units = [...new Set(selectedAccounts.map(a => a.currency || "XXX"))]; const currency = units.length === 1 ? units[0] : undefined; const { money, compact, date: fmtDate } = useMoney(currency); const activity = useTransactionActivity(filters, year, chartType === "line" ? periodDays : undefined); const lineData = useMemo(() => { if (chartType !== "line" || activity.days.size === 0) return []; const dates = [...activity.days.keys()].sort(); const end = periodDays ? new Date() : parseLocalDate(dates[dates.length - 1]); const start = periodDays ? new Date(end.getFullYear(), end.getMonth(), end.getDate() - periodDays + 1) : parseLocalDate(dates[0]); return eachDayOfInterval({ start, end }).map(day => { const date = toDateString(day); return { date, value: activity.days.get(date)?.[direction] ?? 0 }; }); }, [activity.days, chartType, periodDays, direction]); return (
{selectedAccounts.length === 0 ?

Select at least one account to see daily activity.

: !currency || currency === "XXX" ?

Select accounts with the same confirmed currency to compare daily amounts.

: activity.error ?

Couldn't load daily activity.

: activity.loading ?
Loading daily activity…
: chartType === "line" ? (lineData.length ? :

No transactions for the selected period.

) : }

{from ? `From ${format(filters.dateFrom!, "MMMM d, yyyy")}. ` : ""}{to ? `Through ${format(filters.dateTo!, "MMMM d, yyyy")}.` : ""}

); }