Files
Neon-Desk/components/financials/normalization-summary.tsx
francy51 17de3dd72d Add history window controls and expand taxonomy pack support
- add 3Y/5Y/10Y financial history filtering and reorganize normalization details UI
- add new fiscal taxonomy surface/income bridge/KPI packs and update Rust taxonomy loading
- auto-detect Homebrew SQLite for native `sqlite-vec` in local dev/e2e with docs and env guidance
2026-03-18 23:40:28 -04:00

133 lines
3.8 KiB
TypeScript

"use client";
import { AlertTriangle } from "lucide-react";
import type { NormalizationMetadata } from "@/lib/types";
import { cn } from "@/lib/utils";
type NormalizationSummaryProps = {
normalization: NormalizationMetadata;
showHeader?: boolean;
className?: string;
};
function SummaryField(props: {
label: string;
value: string;
tone?: "default" | "warning";
}) {
return (
<div
className={cn(
"py-2",
props.tone === "warning" && "border-l-2 border-[#7f6250] pl-3",
)}
>
<p className="text-[11px] text-[color:var(--terminal-muted)]">
{props.label}
</p>
<p
className={cn(
"text-sm font-semibold",
props.tone === "warning"
? "text-[#ffd7bf]"
: "text-[color:var(--terminal-bright)]",
)}
>
{props.value}
</p>
</div>
);
}
export function NormalizationSummary({
normalization,
showHeader = true,
className,
}: NormalizationSummaryProps) {
const hasMaterialUnmapped = normalization.materialUnmappedRowCount > 0;
const hasWarnings = normalization.warnings.length > 0;
return (
<section
className={cn(
showHeader ? "border-t border-[color:var(--line-weak)] pt-4" : "",
className,
)}
>
{showHeader ? (
<header className="mb-3">
<h3 className="text-sm font-semibold text-[color:var(--terminal-bright)]">
Normalization Summary
</h3>
<p className="text-xs text-[color:var(--terminal-muted)]">
Pack, parser, and residual mapping health for the compact statement
surface.
</p>
</header>
) : null}
<div className="grid gap-x-6 gap-y-1 md:grid-cols-4 xl:grid-cols-8">
<SummaryField
label="Pack"
value={normalization.fiscalPack ?? "unknown"}
/>
<SummaryField label="Regime" value={normalization.regime} />
<SummaryField
label="Parser"
value={`${normalization.parserEngine} ${normalization.parserVersion}`}
/>
<SummaryField
label="Surface Rows"
value={String(normalization.surfaceRowCount)}
/>
<SummaryField
label="Detail Rows"
value={String(normalization.detailRowCount)}
/>
<SummaryField
label="KPI Rows"
value={String(normalization.kpiRowCount)}
/>
<SummaryField
label="Unmapped Rows"
value={String(normalization.unmappedRowCount)}
/>
<SummaryField
label="Material Unmapped"
value={String(normalization.materialUnmappedRowCount)}
tone={hasMaterialUnmapped ? "warning" : "default"}
/>
</div>
{hasWarnings ? (
<div className="mt-3 border-t border-[color:var(--line-weak)] pt-3">
<p className="text-[11px] text-[color:var(--terminal-muted)]">
Parser Warnings
</p>
<div className="mt-2 flex flex-wrap gap-2">
{normalization.warnings.map((warning) => (
<span
key={warning}
className="rounded border border-[color:var(--line-weak)] bg-[rgba(88,102,122,0.16)] px-2 py-0.5 text-xs text-[color:var(--terminal-bright)]"
>
{warning}
</span>
))}
</div>
</div>
) : null}
{hasMaterialUnmapped ? (
<div className="mt-3 flex items-start gap-2 border-l-2 border-[#7f6250] pl-3 text-sm text-[#f5d5c0]">
<AlertTriangle className="mt-0.5 size-4 shrink-0" />
<p>
Material unmapped rows were detected for this filing set. Use the
inspector and detail rows before relying on cross-company
comparisons.
</p>
</div>
) : null}
</section>
);
}