"use client"; import { Archive, ArchiveRestore, ArrowDown, ArrowUp, ChevronDown, EyeOff, MoreHorizontal, Pencil, Plus, } from "lucide-react"; import { useState, useTransition } from "react"; import { toast } from "sonner"; import { IconBadge } from "@/components/appearance/swatch"; import { AlertDialog, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { tr } from "@/i18n/tr"; import { cn } from "@/lib/utils"; import { ACCOUNT_TYPES, isLiabilityType } from "@/shared/accounts"; import { formatMoney } from "@/shared/format"; import { reorderAccountAction, setAccountArchivedAction } from "../actions"; import type { AccountTotals, AccountView } from "../service"; import { AccountFormDialog } from "./account-form-dialog"; const t = tr.accounts; function BalanceText({ account }: { account: AccountView }) { if (account.balanceMinor === null) { return ( {t.hidden} ); } const liability = isLiabilityType(account.type); const value = account.balanceMinor; return ( {liability ? {t.debt} : null} {formatMoney(liability ? Math.abs(value) : value)} ); } export function AccountsView({ accounts, totals, members, canEdit, }: { accounts: AccountView[]; totals: AccountTotals; members: { id: string; name: string }[]; canEdit: boolean; }) { const [dialog, setDialog] = useState<{ account?: AccountView } | null>(null); const [archiving, setArchiving] = useState(null); const [pending, startTransition] = useTransition(); const active = accounts.filter((a) => !a.archived); const archived = accounts.filter((a) => a.archived); const memberName = (id: string | null) => members.find((m) => m.id === id)?.name; const paymentAccounts = active .filter((a) => ["bank", "cash", "savings"].includes(a.type)) .map((a) => ({ id: a.id, name: a.name })); function run(promise: Promise<{ ok: boolean; error?: string }>, success?: string) { startTransition(async () => { const r = await promise; if (r.ok) { if (success) toast.success(success); } else toast.error(r.error ?? tr.common.genericError); }); } function Row({ a, index }: { a: AccountView; index: number }) { const owner = memberName(a.ownerUserId); return (
  • {a.name}

    {a.type === "meal_card" && a.mealCardProvider ? ( {t.providers[a.mealCardProvider]} ) : null} {a.institution ? {a.institution} : null} {owner ? · {owner} : null} {a.isPrivate ? {t.privateBadge} : null} {a.overdraft ? ( {t.overdraftBadge(formatMoney(a.overdraft.limitMinor))} ) : null} {a.creditCard ? ( <> {t.limitLabel(formatMoney(a.creditCard.limitMinor))} {t.statementLabel(a.creditCard.statementDay)} ) : null}
    {canEdit ? ( {a.archived ? ( run(setAccountArchivedAction(a.id, false), t.unarchivedToast(a.name)) } > {t.unarchive} ) : ( <> setDialog({ account: a })}> {tr.common.edit} run(reorderAccountAction(a.id, "up"))} > {tr.categories.moveUp} run(reorderAccountAction(a.id, "down"))} > {tr.categories.moveDown} setArchiving(a)}> {t.archive} )} ) : null}
  • ); } const summary = [ { label: t.summary.assets, value: totals.assetsMinor, tone: "text-income" }, { label: t.summary.cardDebt, value: Math.abs(totals.cardDebtMinor), tone: totals.cardDebtMinor ? "text-expense" : "", }, { label: t.summary.net, value: totals.netMinor, tone: totals.netMinor < 0 ? "text-expense" : "", }, ]; return (
    {summary.map((s) => ( {s.label} {formatMoney(s.value)} ))}
    {totals.includesHidden || totals.excludesHidden ? (

    {totals.excludesHidden ? t.summary.excludesHidden : t.summary.includesHidden}

    ) : null}
    {!canEdit ?

    {t.ownerOnly}

    : null} {canEdit ? ( ) : null}
    {active.length === 0 ? (

    {t.empty}

    {canEdit ?

    {t.emptyOwnerHint}

    : null}
    ) : ( ACCOUNT_TYPES.map((type) => { const group = active.filter((a) => a.type === type); if (!group.length) return null; return (

    {t.typeGroups[type]}

      {group.map((a) => ( ))}
    ); }) )} {archived.length ? (
      {archived.map((a) => ( ))}
    ) : null} !o && setDialog(null)} /> !o && setArchiving(null)}> {t.archiveTitle} {archiving ? t.archiveDescription(archiving.name) : null} {tr.common.cancel}
    ); }