import { useEffect, useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { api, type Category, type Expense } from '../lib/api'; import { translations, getLang } from '../lib/i18n'; import { useTelegramTheme } from '../hooks/useTelegramTheme'; import { useMainButton } from '../hooks/useTelegramUI'; import { Amount } from '../components/Amount'; import { CategoryStrip } from '../components/CategoryStrip'; import { ExpenseSheet } from '../components/ExpenseSheet'; function monthLabel(month: string): string { const [y, m] = month.split('-').map(Number); return new Date(y, m - 1).toLocaleDateString('tr-TR', { month: 'long', year: 'numeric' }); } function dayLabel(date: string): string { const [y, m, d] = date.split('-').map(Number); const dt = new Date(y, m - 1, d); const today = new Date(); const yesterday = new Date(); yesterday.setDate(today.getDate() - 1); const same = (a: Date, b: Date) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate(); if (same(dt, today)) return 'BUGÜN'; if (same(dt, yesterday)) return 'DÜN'; return dt.toLocaleDateString('tr-TR', { day: 'numeric', month: 'long', weekday: 'long' }); } function todayMonth(): string { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`; } export function Home() { useTelegramTheme(); const lang = getLang(); const t = translations[lang]; const { setMainButton } = useMainButton(); const [month, setMonth] = useState(todayMonth()); const [selectedCategoryId, setSelectedCategoryId] = useState(null); const [sheetOpen, setSheetOpen] = useState(false); const [editing, setEditing] = useState(null); const { data: me } = useQuery({ queryKey: ['me'], queryFn: api.me }); const categories: Category[] = me?.categories ?? []; const { data: summary } = useQuery({ queryKey: ['summary', month], queryFn: () => api.summary(month), enabled: !!me, }); const { data: months } = useQuery({ queryKey: ['months'], queryFn: api.months, enabled: !!me, }); const { data: list, refetch } = useQuery({ queryKey: ['expenses', month, selectedCategoryId], queryFn: () => api.listExpenses({ from: `${month}-01`, to: `${month}-31`, categoryId: selectedCategoryId ?? undefined, limit: 100, }), enabled: !!me, }); // Ay gezgini: veri olan aylar + içinde bulunulan ay const navMonths = useMemo(() => { const set = new Set(months ?? []); set.add(todayMonth()); return [...set].sort((a, b) => (a < b ? 1 : -1)); }, [months]); // MainButton: "Harcama ekle" — effect içinde, render sırasında değil useEffect(() => { setMainButton(t.addExpense, () => { setEditing(null); setSheetOpen(true); }); }, [setMainButton, t.addExpense]); const grouped = useMemo(() => { const map = new Map(); for (const e of list?.items ?? []) { const arr = map.get(e.spentAt) ?? []; arr.push(e); map.set(e.spentAt, arr); } return [...map.entries()].sort((a, b) => (a[0] < b[0] ? 1 : -1)); }, [list]); const totalMinor = summary?.totalMinor ?? 0; const prevTotal = summary?.prevMonthTotalMinor ?? 0; const delta = prevTotal > 0 ? ((totalMinor - prevTotal) / prevTotal) * 100 : null; const closeSheet = () => { setSheetOpen(false); setEditing(null); }; return (
{/* Ay gezgini */}
{monthLabel(month)}
{/* Büyük tutar */}
{/* Geçen aya göre */}
{delta === null ? ( {t.same} ) : ( = 0 ? 'text-[var(--kurus-negative)]' : 'text-[var(--kurus-positive)]'}> {t.prevMonth} {delta >= 0 ? t.up : t.down} %{Math.abs(delta).toFixed(1)} )}
{/* Kategori şeridi */}
setSelectedCategoryId(id)} selectedCategoryId={selectedCategoryId} />
{/* Liste */} {!list && !months &&
{t.loading}
} {list && list.items.length === 0 && (
{totalMinor === 0 && (months?.length ?? 0) === 0 ? t.emptyNoData : t.emptyMonth(monthLabel(month))}
)} {grouped.map(([date, items]) => (
{dayLabel(date)}
{items.map((e) => ( ))}
))} {sheetOpen && ( { if (editing) { await api.updateExpense(editing.id, data); } else { await api.createExpense(data); } refetch(); }} onDelete={async (expense) => { await api.deleteExpense(expense.id); refetch(); }} onClose={closeSheet} /> )}
); }