import type { ProvenanceDTO } from "@dci/core";
import { ExternalLink } from "lucide-react";
import type { ReactNode } from "react";
import { ConfidenceBadge, EstimateMark, ScopeBadge } from "@/components/ui/badge";
import { SourceBadge } from "@/components/ui/source-badge";
import { cn } from "@/components/ui/cn";
import { ProvenancePopover } from "@/components/ui/popover";
import { EmptyState } from "@/components/ui/states";
import { TBody, THead, Table, Td, Th, Tr } from "@/components/ui/table";
import { fieldLabel, valueHint } from "@/lib/field-labels";
import { fmtDate, fmtValue } from "@/lib/format";
/** Provenance rows backing one or more fields (API field names are camelCase; snake_case tolerated). */
export function provFor(items: ProvenanceDTO[] | undefined, ...fields: string[]): ProvenanceDTO[] {
if (!items?.length) return [];
const want = new Set(fields.flatMap((f) => [f, f.replace(/[A-Z]/g, (m) => `_${m.toLowerCase()}`), f.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase())]));
return items.filter((p) => want.has(p.field));
}
export { FIELD_LABEL, fieldLabel } from "@/lib/field-labels";
/** Value + inline provenance popover for the rows backing `fields`. Renders nothing extra when no provenance exists. */
export function WithProvenance({ items, fields, children, className }: { items: ProvenanceDTO[] | undefined; fields: string | string[]; children: ReactNode; className?: string }) {
const rows = provFor(items, ...(Array.isArray(fields) ? fields : [fields]));
return (
{children}
{rows.length > 0 &&
| Field | Value | Source | First observed | Last observed | Confidence | Method | Link |
|---|---|---|---|---|---|---|---|
| {fieldLabel(p.field)} {p.isWinner && ( shown )} |
{p.isEstimate && |
{p.sourceName}
|
{fmtDate(p.firstObserved)} | {fmtDate(p.lastObserved)} |
|
{p.method ?? "—"} |
source |