feat(frontend): Claims page wires live tail + TailStatusPill

This commit is contained in:
Tyler
2026-06-20 17:11:56 -06:00
parent f1407dbb1d
commit 365e64e25a
2 changed files with 147 additions and 2 deletions
+36 -2
View File
@@ -27,9 +27,12 @@ import { FilterChips, type FilterChipOption } from "@/components/ui/filter-chips
import { Pagination } from "@/components/ui/pagination";
import { useClaims } from "@/hooks/useClaims";
import { useDrawerUrlState } from "@/hooks/useDrawerUrlState";
import { useTailStream } from "@/hooks/useTailStream";
import { useMergedTail } from "@/hooks/useMergedTail";
import { TailStatusPill } from "@/components/TailStatusPill";
import { useAppStore } from "@/store";
import { fmt } from "@/lib/format";
import type { ClaimStatus } from "@/types";
import type { Claim, ClaimStatus } from "@/types";
import { cn } from "@/lib/utils";
const ALL = "all" as const;
@@ -74,7 +77,28 @@ export function Claims() {
};
const { data, isLoading, isError, error, refetch, dataUpdatedAt } = useClaims(params);
const items = data?.items ?? [];
// SP5 live-tail wiring (sub-project 5, Phase 5 Task 22).
//
// The tail stream emits every claim that lands in the DB — including
// ones that don't match the user's current `status` / `provider_npi`
// filter. Mirror the server-side filter the page already applies via
// `useClaims` so a newly-arrived item that wouldn't pass the same
// predicate is dropped before it can show up in the table. `useMergedTail`
// applies this to the tail slice only; base items are already filtered
// server-side.
const tailFilterFn = useMemo(
() => (c: Claim) => {
if (status !== ALL && c.status !== status) return false;
if (npi !== ALL && c.providerNpi !== npi) return false;
return true;
},
[status, npi],
);
const { status: tailStatus, lastEventAt: tailLastEventAt, forceReconnect } =
useTailStream("claims");
const items = useMergedTail("claims", data?.items ?? [], tailFilterFn);
const totals = useMemo(
() => ({
@@ -190,6 +214,16 @@ export function Claims() {
))}
</SelectContent>
</Select>
{/* SP5: live-tail status pill. `ml-auto` pins it to the right
edge of the toolbar so it doesn't crowd the search input. */}
<div className="ml-auto">
<TailStatusPill
status={tailStatus}
lastEventAt={tailLastEventAt}
onReconnect={forceReconnect}
/>
</div>
</div>
<div className="mt-3">