// Inspector — right pane for selected transaction
// Shows: source detail, account picker, ledger preview, approve/override/skip
function AccountPicker({ value, onChange, mru = [] }) {
const accounts = window.AKEFIN_DATA.allAccounts;
const [open, setOpen] = React.useState(false);
const [q, setQ] = React.useState("");
const matches = q
? accounts.filter(a => a.toLowerCase().includes(q.toLowerCase())).slice(0, 8)
: accounts.slice(0, 8);
return (
{open && (
setQ(e.target.value)} placeholder="Search accounts…" />
{mru.length > 0 && !q && (
RECENT
{mru.map(a => (
))}
)}
{q ? "MATCHES" : "ALL ACCOUNTS"}
{matches.map(a => (
))}
)}
);
}
function LedgerPreview({ tx, account }) {
if (!tx || !account) return (
No posting to preview · choose an account
);
const entityHomeCcy = { personal: "KRW", tfox: "KRW", finacode: "EUR" };
const sourceAccount = tx.entity === "personal" ? "Personal:Assets:Bank:Toss"
: tx.entity === "tfox" ? "9TFox:Assets:Bank:Kakao"
: "Finacode:Assets:Bank:Wise";
const isExpense = tx.amount < 0;
const debit = isExpense ? account : sourceAccount;
const credit = isExpense ? sourceAccount : account;
const abs = Math.abs(tx.amount);
const homeCcy = entityHomeCcy[tx.entity];
const needsFx = tx.ccy !== homeCcy;
const fxRate = needsFx ? window.AKEFIN_DATA.fx[tx.ccy] / window.AKEFIN_DATA.fx[homeCcy] : null;
const converted = needsFx ? Math.round(window.AKEFIN_DATA.convert(abs, tx.ccy, homeCcy)) : null;
return (
{tx.date}
"{tx.payee}"
{debit}
{abs.toLocaleString()}
{tx.ccy}
{needsFx && (
↳
@ {fxRate.toFixed(2)} {homeCcy} · FX from ECB · 2026-03-08
)}
{credit}
-{(needsFx ? converted : abs).toLocaleString()}
{needsFx ? homeCcy : tx.ccy}
{needsFx ? `balanced · 2 legs · FX-converted to ${homeCcy}` : "balanced · 2 legs"} · will commit to {tx.entity === "personal" ? "personal" : tx.entity}-2026-03.ldgr
);
}
function Inspector({ tx, onApprove, onSkip }) {
const [account, setAccount] = React.useState(tx?.suggestedAccount || null);
React.useEffect(() => { setAccount(tx?.suggestedAccount || null); }, [tx?.id]);
const mru = ["Personal:Expenses:Food:Coffee", "Personal:Expenses:Groceries", "9TFox:Expenses:Software"];
if (!tx) {
return (
);
}
return (
);
}
Object.assign(window, { Inspector, LedgerPreview, AccountPicker });