1
0
Fork 0
polaris-task-force/src/components/frontend/banking/AccountDetail.tsx
Z8MB1E 8c10719124 feat(banking): currency emblem image with CurrencyAmount display wrapper
- GameRules currencySymbol switches from text to a media upload
- new CurrencyAmount/CurrencySymbol components; render sites across banking,
  base management, dashboard, market, campaigns and profiles are wired to
  show the emblem inline with amounts
- migration 20260921_140000 (text column out, media fk in); registers the
  five pending migrations in the migrations index
2026-09-21 20:47:52 -04:00

101 lines
3.5 KiB
TypeScript

"use client";
import Link from "next/link";
import { ArrowLeftIcon } from "lucide-react";
import type { BankAccount, LedgerEntry } from "@/payload-types";
import { Item, ItemContent, ItemHeader, ItemTitle } from "@/components/ui/item";
import type { CurrencyConfig } from "@/lib/banking/format";
import { CurrencyAmount } from "@/components/frontend/banking/CurrencyAmount";
import { type AccountStatus, accountStatusBase, accountStatusClass } from "@/lib/banking/ui";
import { accountTypeInfo } from "@/components/frontend/banking/AccountCard";
import { BankTransactionDialog } from "@/components/frontend/banking/BankTransactionDialog";
import { LedgerTable } from "@/components/frontend/banking/LedgerTable";
interface AccountDetailProps {
account: BankAccount;
ledger: LedgerEntry[];
otherAccounts: { id: number; name: string }[];
canTransact: boolean;
currencyConfig: CurrencyConfig;
}
export function AccountDetail({
account,
ledger,
otherAccounts,
canTransact,
currencyConfig,
}: AccountDetailProps) {
const meta = accountTypeInfo(account.accountType);
const Icon = meta.icon;
const currency = typeof account.currency === "object" ? account.currency : null;
const statusKey = (account.status ?? "open") as AccountStatus;
const owner =
account.accountType === "personal"
? typeof account.ownerUser === "object" && account.ownerUser
? (account.ownerUser.displayName ?? account.ownerUser.username)
: null
: account.accountType === "faction" && typeof account.ownerFaction === "object"
? account.ownerFaction?.name
: null;
return (
<div className="flex flex-col gap-6">
<Link
href="/logistics/banking"
className="text-sm text-muted-foreground hover:text-primary transition-colors flex items-center gap-1 w-fit"
>
<ArrowLeftIcon className="size-3" />
Back to Banking
</Link>
<div className="flex items-start justify-between gap-4">
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2">
<Icon className={`size-5 ${meta.accent}`} />
<h1 className="text-lg font-semibold">{account.name}</h1>
</div>
<div className="flex items-center gap-2">
<span
className={`${accountStatusBase} ${accountStatusClass[statusKey] ?? accountStatusClass.open}`}
>
{statusKey}
</span>
<span className="text-xs text-muted-foreground">
{meta.label}
{owner ? ` · ${owner}` : ""}
</span>
</div>
</div>
<div className="text-right">
<p className="font-mono text-[10px] text-muted-foreground uppercase tracking-wider">
Balance
</p>
<p className="text-2xl font-semibold font-mono">
<CurrencyAmount
value={account.balance ?? 0}
currency={currencyConfig.resourceName ? currencyConfig : currency}
/>
</p>
</div>
</div>
{canTransact && (
<BankTransactionDialog accountId={account.id} otherAccounts={otherAccounts} />
)}
<Item variant="outline">
<ItemHeader>
<ItemTitle>Ledger</ItemTitle>
<span className="text-xs text-muted-foreground">
{ledger.length} entr{ledger.length !== 1 ? "ies" : "y"}
</span>
</ItemHeader>
<ItemContent>
<LedgerTable entries={ledger} />
</ItemContent>
</Item>
</div>
);
}