// Shared row components used across all screens. Was originally co-located in // screens.jsx with the V1-V5 exploration variants; extracted so screens-detail.jsx // can use them without depending on the (now-disabled) variants file. function SectionHead({ title, more, onMore }) { return (
{title}
{more &&
{more}
}
); } function Stat({ label, value, cls = "", large = false }) { return (
{label}
{value}
); } function AccountRow({ a, large = false, onClick }) { // `ownerName` is the display name ("조범진") set by data.js buildCombined // when merging two users; per-user views don't have it. Showing the slug // (`a.owner = "beomjin_joe"`) was leaking an internal id into the UI. const ownerLabel = a.ownerName || ""; return (
{a.name} {a.id}{ownerLabel ? ` · ${ownerLabel}` : ""}
₩{fmtKRW(a.value, true)} {fmtPct(a.roi)} · {fmtSigned(a.realized + a.unrealized, true)}
); } function FlowRow({ f }) { const meta = FLOW_META[f.category] || FLOW_META.deposit; // Purple = "internal" cash movement that doesn't represent realized // gain/loss: account-to-account transfers, FX swaps, AND buys/sells // (cash → stock or stock → cash inside the same account is just // re-shaping of total assets, not money in/out of the user's wealth). // For these we suppress the +/− sign too — direction is meaningless // here (a buy "spends" cash but builds an equal-value position) and // the user explicitly asked to drop the minus on purple rows. const isInternalMove = f.category === "internal_transfer" || f.category.startsWith("internal_") || f.category.startsWith("fx_") || f.category.endsWith("_buy") || f.category.endsWith("_sell"); const cls = isInternalMove ? "" : (f.amountKrw >= 0 ? "up" : "down"); const colorStyle = isInternalMove ? { color: "var(--purple)" } : {}; const sign = isInternalMove ? "" : (f.amountKrw >= 0 ? "+" : "−"); // Show YYYY-MM-DD on the dim line so the home "최근 자금 흐름" card // makes the date explicit — earlier the section was labeled "오늘의" // even though entries could be days or weeks old. const dateShort = (f.date || "").length === 10 ? f.date.slice(5) // MM-DD : (f.date || ""); return (
{meta.label}{f.ticker ? ` · ${f.ticker}` : ""}{f.qty ? ` ${f.qty}주` : ""} {dateShort} · {f.account}{f.counterparty ? ` → ${f.counterparty}` : ""}
{sign}₩{fmtKRW(Math.abs(f.amountKrw), true)} {f.amountUsd != null && ( {isInternalMove ? "" : (f.amountUsd >= 0 ? "+" : "−")}${Math.abs(f.amountUsd).toLocaleString()} )}
); } Object.assign(window, { SectionHead, Stat, AccountRow, FlowRow });