- 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
101 lines
3.5 KiB
TypeScript
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>
|
|
);
|
|
}
|