"use client"; import Link from "next/link"; import type { ReactNode } from "react"; import { ClickableUserId } from "@/components/clickable-user-id"; import { formatRcLabelFromCoinsBigInt } from "@/lib/coins-rc"; /** Ledger rows are per player; both players pay → show `1.0 RC x 2 = 2.0 RC`. */ function rcPerPlayerTimesTwoLine(coinStr: string | null): string { if (coinStr == null || String(coinStr).trim() === "") return "—"; try { const perPlayer = BigInt(String(coinStr).trim()); const bothPlayers = perPlayer * BigInt(2); return `${formatRcLabelFromCoinsBigInt(perPlayer)} x 2 = ${formatRcLabelFromCoinsBigInt(bothPlayers)}`; } catch { return "—"; } } function entryCombinedPerPlayerTimesTwoLine( feeCoins: string | null, holdCoins: string | null, ): string { if ( feeCoins == null || holdCoins == null || String(feeCoins).trim() === "" || String(holdCoins).trim() === "" ) { return "—"; } try { const perPlayer = BigInt(String(feeCoins).trim()) + BigInt(String(holdCoins).trim()); const bothPlayers = perPlayer * BigInt(2); return `${formatRcLabelFromCoinsBigInt(perPlayer)} x 2 = ${formatRcLabelFromCoinsBigInt(bothPlayers)}`; } catch { return "—"; } } type PlayerSide = { id: number | null; username: string | null; cc: number | null; rc: number | null; color: "red" | "blue"; }; type Props = { matchId: number; statusLabel: string; createdAtLabel: ReactNode; /** Ledger `entry_fee` / player as coin string; null if unknown. */ entryFeeCoins: string | null; /** Ledger `entry_hold` / player as coin string; null if unknown. */ entryHoldPerPlayerCoins: string | null; /** Preformatted `prize_cc` for display (e.g. with grouping). */ prizeCcLabel: string; left: PlayerSide; right: PlayerSide; /** May be string when `bigint` is JSON-serialized. */ winnerId: number | string | null; }; function idsMatch( a: number | string | null | undefined, b: number | string | null | undefined, ): boolean { if (a == null || b == null) return false; const na = typeof a === "number" ? a : Number(a); const nb = typeof b === "number" ? b : Number(b); return Number.isFinite(na) && Number.isFinite(nb) && na === nb; } function sideStyles(color: PlayerSide["color"]) { if (color === "red") { return { panel: "border-rose-500/60 bg-gradient-to-br from-rose-700/80 via-fuchsia-700/70 to-violet-700/80", tag: "bg-rose-500/90 text-rose-50", iconBg: "bg-rose-500/30 text-rose-100", score: "text-rose-100", }; } return { panel: "border-sky-500/60 bg-gradient-to-br from-sky-700/80 via-indigo-700/70 to-violet-700/80", tag: "bg-sky-500/90 text-sky-50", iconBg: "bg-sky-500/30 text-sky-100", score: "text-sky-100", }; } function initials(name: string | null): string { if (!name || name.trim() === "") return "?"; const compact = name.trim().slice(0, 2); return compact.toUpperCase(); } function playerLabel(side: PlayerSide): string { if (side.id == null) return "Open slot"; if (side.username && side.username.trim() !== "") return side.username; return `Player ${side.id}`; } function winnerLabel( winnerId: number | string | null, left: PlayerSide, right: PlayerSide, ): string { if (winnerId == null || winnerId === "") return "No winner yet"; if (idsMatch(winnerId, left.id)) return `${playerLabel(left)} won`; if (idsMatch(winnerId, right.id)) return `${playerLabel(right)} won`; return `Winner #${winnerId}`; } function PlayerPanel({ side, isWinner, isDimmed, }: { side: PlayerSide; isWinner: boolean; isDimmed: boolean; }) { const s = sideStyles(side.color); return (
{playerLabel(side)}
ID:{" "}
{side.id != null ? (