"use client"; import { useEffect, useState, useCallback } from "react"; import { RefreshCw, PiggyBank } from "lucide-react"; interface Goal { name: string; amount: number; } interface SavingsData { goals: Goal[]; total: number; error?: string; } function formatMoney(n: number): string { return n.toLocaleString("ru-RU") + " ₽"; } // Целевые суммы (максимум для прогресс-бара) const TARGETS: Record = { "🏠 Квартира": 500000, "✈️ Отпуск": 200000, }; export function SavingsWidget() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const fetchData = useCallback(async () => { setLoading(true); try { const res = await fetch("/api/savings", { cache: "no-store" }); setData(await res.json()); } catch { setData({ goals: [], total: 0, error: "Ошибка загрузки" }); } finally { setLoading(false); } }, []); useEffect(() => { fetchData(); }, [fetchData]); return (
Накопления
{loading ? (
{[1, 2].map(i =>
)}
) : data?.error ? (
{data.error}
) : ( <> {/* Total */}
Итого накоплено {formatMoney(data?.total || 0)}
{/* Goals */}
{(data?.goals || []).map(goal => { const target = TARGETS[goal.name]; const pct = target ? Math.min(100, (goal.amount / target) * 100) : null; const color = goal.name.includes("Квартир") ? "#6366f1" : goal.name.includes("Отпуск") ? "#f59e0b" : "#10b981"; return (
{goal.name}
{formatMoney(goal.amount)} {target && / {formatMoney(target)}}
{pct !== null && (
)} {target && (
{pct?.toFixed(0)}% от цели
)}
); })}
)}
); }