"use client";
import * as React from "react";
import Link from "next/link";
import { Skeleton, ProgressCircleRoot, ProgressCircleTrack, ProgressCircleRange } from "@seed-design/react";
import { Card, AmountToggle, HideAmountsToggle } from "../../ds";
import { tugrikShortRaw } from "../../ds/money";
import { useNetWorth, useAnalyzeMonth, useAnalyzeToday, useBudget } from "../../api/hooks/reads";
import { buildHome, type HomeData } from "./buildHome";
import { sample } from "./sample";
import { homeStrings as s } from "./strings";
/** A number that's redacted with a Seed skeleton block while loading, and a
* tap-to-reveal `AmountToggle` once real data has arrived. Mirrors iOS's
* `.skeleton(loading)` view modifier, which redacts the finished layout in
* place rather than swapping in a separate spinner. */
function Amount({ value, loading, width = "72px" }: { value: number; loading: boolean; width?: string }) {
if (loading) return ;
return ;
}
/** The circular "₮" badge used on every card (togrogCircle in DashboardView.swift). */
function TugrikCircle({ bg, fg }: { bg: string; fg: string }) {
return (
₮
);
}
/** The Нүүр (home) dashboard: header, safe-to-spend hero, daily-limit +
* top budgets, this-month spend, and recent income/expense. Figures come
* from `buildHome` (real where the backend has them, `sample` otherwise).
* Ported from ios/Mercury/Features/Home/DashboardView.swift. */
export function DashboardView() {
const netWorthQ = useNetWorth();
const monthQ = useAnalyzeMonth();
const todayQ = useAnalyzeToday();
const budgetQ = useBudget();
const loading = netWorthQ.isLoading || monthQ.isLoading || todayQ.isLoading || budgetQ.isLoading;
const built = buildHome({
netWorth: netWorthQ.data,
month: monthQ.data,
today: todayQ.data,
budget: budgetQ.data,
});
const data: HomeData = built ?? sample;
const budgetDenominator = data.availableBudget;
const fraction = budgetDenominator > 0 ? Math.min(1, data.monthlyExpense / budgetDenominator) : 0;
const dailyFraction = data.dailyLimitTotal > 0 ? Math.min(1, data.dailyLimitUsed / data.dailyLimitTotal) : 0;
return (
{s.wordmark}
{/* Safe-to-spend hero (green): how much is left to spend this month
after committed obligations and what's already been spent. */}
{data.overspent ? s.overspent : s.safeToSpend}
{s.spent} / {tugrikShortRaw(budgetDenominator)}
{/* Daily limit + top budgets (blue). */}
{s.dailyLimit}
{" / "}
{s.todaySpent}:
{data.budgets.map((b) => (
{b.name} / {b.range}
))}
{/* This month's spend (white). */}
{s.thisMonth}