From 213a8c106f77f08e95f1633480279de20252b468 Mon Sep 17 00:00:00 2001 From: Z8MB1E Date: Tue, 22 Sep 2026 14:52:44 -0400 Subject: [PATCH] feat(banking): inline currency emblem display with optional label hiding --- .../intelligence/factions/[id]/page.tsx | 14 +++++++------- .../frontend/banking/CurrencyAmount.tsx | 16 ++++++++++------ .../frontend/banking/CurrencySymbol.tsx | 2 +- src/lib/banking/format.ts | 8 ++++++-- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/app/(frontend)/intelligence/factions/[id]/page.tsx b/src/app/(frontend)/intelligence/factions/[id]/page.tsx index 663aa4b..febd623 100644 --- a/src/app/(frontend)/intelligence/factions/[id]/page.tsx +++ b/src/app/(frontend)/intelligence/factions/[id]/page.tsx @@ -3,7 +3,7 @@ import { getPayload } from "payload"; import { notFound } from "next/navigation"; import Link from "next/link"; import { headers as nextHeaders } from "next/headers"; -import type { BankAccount, Campaign, Faction, Media, Mission, Resource } from "@/payload-types"; +import type { BankAccount, Campaign, Faction, Media, Mission } from "@/payload-types"; import { RichText } from "@payloadcms/richtext-lexical/react"; import { convertLexicalToPlaintext } from "@payloadcms/richtext-lexical/plaintext"; import { @@ -16,7 +16,8 @@ import { } from "lucide-react"; import { Item, ItemContent, ItemHeader, ItemTitle } from "@/components/ui/item"; import { MissionCard } from "@/components/frontend/intelligence/MissionCard"; -import { formatAmount } from "@/lib/banking/format"; +import { getCurrencyConfig } from "@/lib/banking"; +import { CurrencyAmount } from "@/components/frontend/banking/CurrencyAmount"; interface FactionDetailPageProps { params: Promise<{ id: string }>; @@ -118,10 +119,9 @@ export default async function FactionDetailPage({ params }: FactionDetailPagePro }) .catch(() => ({ docs: [] })); const bankAccount = (bankRes.docs[0] as BankAccount | undefined) ?? null; - const bankCurrency = - bankAccount && typeof bankAccount.currency === "object" - ? (bankAccount.currency as Resource) - : null; + // Currency emblem/label is shared across all accounts (from Game Rules), so + // the bank balance renders the same emblem the banking surfaces show. + const currencyConfig = await getCurrencyConfig(payload); // Missions involving this faction const missionsRes = await payload @@ -365,7 +365,7 @@ export default async function FactionDetailPage({ params }: FactionDetailPagePro
- {formatAmount(bankAccount.balance ?? 0, bankCurrency)} + {bankAccount.name} {bankAccount.status !== "open" && ( diff --git a/src/components/frontend/banking/CurrencyAmount.tsx b/src/components/frontend/banking/CurrencyAmount.tsx index 4a8c7b0..c8f1154 100644 --- a/src/components/frontend/banking/CurrencyAmount.tsx +++ b/src/components/frontend/banking/CurrencyAmount.tsx @@ -1,11 +1,13 @@ -import { formatAmount } from "@/lib/banking/format"; +import { formatAmount, isCurrencyConfig } from "@/lib/banking/format"; import type { CurrencyDisplay } from "@/lib/banking/format"; import { CurrencySymbol } from "./CurrencySymbol"; /** * Renders the currency emblem inline with the formatted amount. Delegates - * symbol rendering to and formatting to formatAmount. - * Renders nothing when currency is null/undefined/number (no emblem to show). + * symbol rendering to and formatting to formatAmount. When an + * emblem is configured the unit label (e.g. "credits") is dropped so the icon + * sits beside the number without a trailing word; renders nothing when no + * emblem is configured. */ export function CurrencyAmount({ value, @@ -14,10 +16,12 @@ export function CurrencyAmount({ readonly value: number; readonly currency?: CurrencyDisplay | null; }) { + const showSymbol = + currency != null && typeof currency === "object" && isCurrencyConfig(currency) && !!currency.symbol; return ( - <> +
- {formatAmount(value, currency)} - + {formatAmount(value, currency, showSymbol ? { hideLabel: true } : undefined)} +
); } diff --git a/src/components/frontend/banking/CurrencySymbol.tsx b/src/components/frontend/banking/CurrencySymbol.tsx index 1d80af2..563ca69 100644 --- a/src/components/frontend/banking/CurrencySymbol.tsx +++ b/src/components/frontend/banking/CurrencySymbol.tsx @@ -35,7 +35,7 @@ export function CurrencySymbol({ aria-hidden={ariaHidden} loading="lazy" className={cn( - "inline-block h-[0.85em] align-text-bottom max-h-[1.15em] object-contain", + "inline-block h-[0.85em] align-middle max-h-[1.15em] object-contain", className, )} /> diff --git a/src/lib/banking/format.ts b/src/lib/banking/format.ts index 93197a0..4705a31 100644 --- a/src/lib/banking/format.ts +++ b/src/lib/banking/format.ts @@ -44,9 +44,13 @@ export function currencyLabel(currency?: CurrencyDisplay, amount = 2): string { ); } -export function formatAmount(amount: number, currency?: CurrencyDisplay): string { +export function formatAmount( + amount: number, + currency?: CurrencyDisplay, + options?: { readonly hideLabel?: boolean }, +): string { const n = amount.toLocaleString(); - const label = currencyLabel(currency, amount); + const label = options?.hideLabel ? "" : currencyLabel(currency, amount); return label ? `${n} ${label}` : n; }