// 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 (
);
}
function Stat({ label, value, cls = "", large = false }) {
return (
);
}
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 });