feat(sp28): Acks page Claims badge column with orphan/single/many variants

This commit is contained in:
Nora
2026-07-02 11:40:50 -06:00
parent 602dc352c5
commit d8f3fb15f9
2 changed files with 243 additions and 2 deletions
+83 -1
View File
@@ -1,5 +1,5 @@
import { useCallback, useMemo, useState } from "react";
import { CheckCircle2, Download, Mail, ShieldCheck } from "lucide-react";
import { CheckCircle2, Download, Link2, Mail, ShieldCheck } from "lucide-react";
import {
Table,
TableBody,
@@ -374,6 +374,14 @@ export function Acks() {
/>
<TableHead>ID</TableHead>
<TableHead>Source Batch</TableHead>
{/* SP28: "Claims" column. The badge carries
the distinct-claim link count (per-AK2
granularity — D1 — so a 999 with two AK2s
and one linked claim still shows "1").
Empty cell means orphan (no auto-link
resolved); on click the operator can run
a manual match from the AckDrawer. */}
<TableHead>Claims</TableHead>
<TableHead className="text-right">
Accepted
</TableHead>
@@ -438,6 +446,9 @@ export function Acks() {
a.sourceBatchId
)}
</TableCell>
<TableCell>
<ClaimsBadge count={a.linkedClaimIds?.length ?? 0} />
</TableCell>
<TableCell className="text-right display mono text-[hsl(var(--success))]">
{a.acceptedCount}
</TableCell>
@@ -750,6 +761,14 @@ function Ta1AcksSection() {
<TableRow>
<TableHead className="w-10" aria-label="Status" />
<TableHead>Control #</TableHead>
{/* SP28: TA1 acks also surface a "Claims" badge
(it's really a Batches badge TA1 is
envelope-level and links to originating
Batch rows per D4 but the operator-facing
column header is "Claims" to match the 999
register's vocabulary). Distinct-batch
count, just like the 999 column. */}
<TableHead>Batches</TableHead>
<TableHead>Ack</TableHead>
<TableHead>Note</TableHead>
<TableHead>Interchange date</TableHead>
@@ -776,6 +795,9 @@ function Ta1AcksSection() {
<TableCell className="display mono text-[13px] text-foreground">
{t.controlNumber || "—"}
</TableCell>
<TableCell>
<ClaimsBadge count={t.linkedClaimIds?.length ?? 0} />
</TableCell>
<TableCell>
<Ta1CodeBadge code={t.ackCode} />
</TableCell>
@@ -842,3 +864,63 @@ function Ta1CodeBadge({ code }: { code: Ta1Ack["ackCode"] }) {
</span>
);
}
// ---------------------------------------------------------------------------
// ClaimsBadge — SP28. Cell content for the "Claims" column on the 999
// register and the "Batches" column on the TA1 register.
//
// The badge carries the distinct-claim link count (per-AK2 granularity
// — D1 — so a 999 with two AK2s and one linked claim still shows "1").
//
// - count == 0 → amber "Orphan" pill. The ack has no resolved links;
// the operator can drill in and run a manual match.
// - count == 1 → muted mono text "{count} claim". Single-link case;
// the operator can click through to the matched ClaimDrawer.
// - count > 1 → success "{count} claims" badge. Multiple distinct
// claims resolved — usually a 999 with several AK2s each pointing
// to a different claim batch.
// ---------------------------------------------------------------------------
function ClaimsBadge({ count }: { count: number }) {
if (count === 0) {
return (
<span
className="inline-flex items-center gap-1 rounded-sm border px-2 py-0.5 mono text-[10.5px] font-semibold uppercase tracking-[0.14em]"
style={{
color: "hsl(var(--warning))",
backgroundColor: "hsl(var(--warning) / 0.10)",
borderColor: "hsl(var(--warning) / 0.30)",
}}
data-testid="claims-badge-orphan"
title="No auto-link resolved — click to manually match"
>
<Link2 className="h-3 w-3" strokeWidth={1.75} aria-hidden />
Orphan
</span>
);
}
if (count === 1) {
return (
<span
className="mono text-[11.5px] text-foreground"
data-testid="claims-badge-single"
data-claims-count="1"
>
1 claim
</span>
);
}
return (
<span
className="inline-flex items-center gap-1 rounded-sm border px-2 py-0.5 mono text-[10.5px] font-semibold uppercase tracking-[0.14em]"
style={{
color: "hsl(var(--success))",
backgroundColor: "hsl(var(--success) / 0.10)",
borderColor: "hsl(var(--success) / 0.30)",
}}
data-testid="claims-badge-many"
data-claims-count={count}
>
{count} claims
</span>
);
}