"use client"; import { useRuleRunDetail } from "@/lib/hooks"; import { formatCategory } from "@/lib/categories"; /** * The expanded body of an Apply History row: which transactions the run touched * and what it changed on each, so Revert is an informed decision rather than a * guess from a count. */ function fmt(n: number) { return new Intl.NumberFormat("en-AU", { style: "currency", currency: "AUD" }).format(n); } function describe(c: { field: string; from: string | null; to: string | null }) { if (c.field === "category") return `${formatCategory(c.from)} → ${formatCategory(c.to)}`; if (c.field === "merchant") return `${c.from ?? "—"} → ${c.to ?? "—"}`; if (c.field === "tags") return `+ tag ${c.to}`; return `split ${c.from ?? "none"} → ${c.to ?? "none"}`; } export function RuleRunDetail({ runId }: { runId: number }) { const { data, isLoading, error } = useRuleRunDetail(runId); if (isLoading) return

Loading…

; if (error) return

Failed to load detail.

; if (!data) return null; const { transactions, still_changed, run } = data; return (
{transactions.length} transactions {run.reverted_at ? ( already reverted — values are back to their originals ) : ( {still_changed} still showing this run's changes )} {still_changed < transactions.length && !run.reverted_at && ( {transactions.length - still_changed} since changed by something else — reverting restores the pre-run value )}
{transactions.map((t) => ( ))}
Date Transaction Amount Changed
{String(t.transaction_date).slice(0, 10)} {t.merchant || t.description} {t.bank_name} {fmt(Number(t.amount_aud ?? t.amount))} {t.changes.length === 0 ? ( no change ) : ( t.changes.map((c, i) => (
{describe(c)}
)) )}
); }