feat(release): v0.2.0 — batch 837 export, ClaimCard, theme tokens

Backend:

- New POST /api/batches/{id}/export-837: regenerate X12 837 files
  for a list of claim_ids into a ZIP using HCPF file naming standards,
  with a unique interchange/group control number per export. Wire
  the clearhouse Loop 1000A (NM1*41 + PER) and per-payer receiver
  (NM1*40) blocks so the serializer no longer falls back to
  CYCLONE / RECEIVER placeholders.
- /api/parse-837 and /api/parse-835 now surface the server-side
  batch_id in both JSON and NDJSON response shapes so the frontend
  can hit batch-scoped endpoints without an extra listBatches
  round-trip.
- Filename helpers and the 837 serializer updated to match the new
  HCPF envelope; tests cover batch export, parse batch_id, and the
  serializer's control-number uniqueness guarantee.

Frontend:
- New shared components: ClaimCard, ClaimCard837, DominantKpiCard,
  EditorialNote, ExportBar, TickerTape, and a charts/ set
  (BarChart, HBarChart, SegmentedBar, AgingBars).
- New useBatchExport hook driving ExportBar's download flow against
  the new endpoint.
- ClaimDrawer, Lane, and Layout migrated from raw CSS-variable
  colors to Tailwind theme tokens (bg-card, text-foreground,
  border/60, etc.) for consistency with the rest of the instrument
  chrome; the active tab indicator gains a subtle accent glow.
- Upload, Inbox, Batches, BatchDiff, Reconciliation, and Acks pages
  reworked to compose the new shared components and consume the new
  batch-scoped API surface (notably ExportBar wired into Batches).

Tooling / Docs:
- Add audit-uiux.mjs and a docs/goodclaim.x12 sample fixture.
- Update ClaimDrawer testids and add coverage for the new
  components and the useBatchExport hook.

Rolls up into the v0.2.0 release tag.
This commit is contained in:
Tyler
2026-06-22 11:01:58 -06:00
parent 35298907bc
commit 9bca4b608a
54 changed files with 6224 additions and 3871 deletions
+48 -17
View File
@@ -127,36 +127,49 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
/* Subtle "lit from above" wash — gives every page a slightly
lighter zone in the upper third without lifting the base
color. A vertical gradient + a soft top-center halo, both
very low opacity. The composition is additive: a soft glow
behind the page header, fading to nothing well before the
fold. Pointer-events unaffected (it's a background). */
background-image:
radial-gradient(ellipse 90% 38% at 50% -6%, hsla(220, 28%, 26%, 0.22), transparent 62%),
linear-gradient(180deg, hsla(220, 22%, 14%, 0.30) 0%, hsla(220, 22%, 8%, 0.10) 22%, transparent 42%);
background-attachment: fixed;
}
/* A single, precise light source anchored top-right.
One light, not two — an instrument, not a wash. */
/* A precise top-right accent + a complementary soft top-center
softbox. Two light sources, both very subtle — the result reads
as "the chrome is being lit from above" rather than "there's a
gradient in the background". The softbox adds the small lift
the cards sit in; the accent preserves the instrument character. */
body::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
background: radial-gradient(
55rem 35rem at 100% -15%,
hsla(212, 100%, 60%, 0.07),
transparent 62%
);
background:
radial-gradient(ellipse 70% 38% at 50% 0%, hsla(220, 32%, 28%, 0.16), transparent 65%),
radial-gradient(55rem 35rem at 100% -15%, hsla(212, 100%, 60%, 0.09), transparent 62%);
}
/* Hairline grid — the substrate of a precision instrument.
Sits behind everything, gives the dark surfaces a sense of
scale and the work a sense of "field". */
scale and the work a sense of "field". Slightly more present
than before so the texture actually reads against the softer
top wash. */
body::after {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
opacity: 0.5;
opacity: 0.6;
background-image:
linear-gradient(to right, hsl(222 10% 16% / 0.18) 1px, transparent 1px),
linear-gradient(to bottom, hsl(222 10% 16% / 0.18) 1px, transparent 1px);
linear-gradient(to right, hsl(222 10% 18% / 0.20) 1px, transparent 1px),
linear-gradient(to bottom, hsl(222 10% 18% / 0.20) 1px, transparent 1px);
background-size: 64px 64px;
mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, black 30%, transparent 80%);
-webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, black 30%, transparent 80%);
@@ -226,22 +239,40 @@
}
/* Soft card surface — a 1px hairline + a 1px inner highlight to
give the surface a sense of depth without a heavy shadow. */
give the surface a sense of depth without a heavy shadow.
The vertical gradient (lighter at top, darker at bottom) plus
a slightly more present inner highlight makes the card read
as a subtle "lit from above" panel — each card becomes its
own small lighter area without lifting the base card color. */
.surface {
background-color: hsl(var(--card));
background: linear-gradient(
180deg,
hsl(222 16% 10.5%) 0%,
hsl(222 16% 8.5%) 55%,
hsl(222 16% 7.5%) 100%
);
border: 1px solid hsl(var(--border));
box-shadow:
inset 0 1px 0 0 hsl(0 0% 100% / 0.04),
inset 0 1px 0 0 hsl(0 0% 100% / 0.06),
0 1px 2px 0 hsl(0 0% 0% / 0.4);
}
/* Subtle elevated surface — used for cards that should lift a
little more than the default. */
little more than the default. Same "lit from above" treatment
as .surface, with a touch more lift in the gradient stops and
a more visible inner highlight. The card body becomes a
slightly more present lighter area than the surrounding
chrome. */
.surface-2 {
background: linear-gradient(180deg, hsl(222 16% 9%) 0%, hsl(222 16% 7.5%) 100%);
background: linear-gradient(
180deg,
hsl(222 16% 11%) 0%,
hsl(222 16% 9%) 55%,
hsl(222 16% 7.5%) 100%
);
border: 1px solid hsl(var(--border));
box-shadow:
inset 0 1px 0 0 hsl(0 0% 100% / 0.05),
inset 0 1px 0 0 hsl(0 0% 100% / 0.08),
0 1px 3px 0 hsl(0 0% 0% / 0.5);
}