feat(frontend): Claims page wires click-to-open drawer with URL sync
This commit is contained in:
+43
-3
@@ -18,12 +18,14 @@ import {
|
||||
} from "@/components/ui/table";
|
||||
import { StatusBadge } from "@/components/StatusBadge";
|
||||
import { NewClaimDialog } from "@/components/NewClaimDialog";
|
||||
import { ClaimDrawer } from "@/components/ClaimDrawer";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { EmptyState } from "@/components/ui/empty-state";
|
||||
import { ErrorState } from "@/components/ui/error-state";
|
||||
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 { useAppStore } from "@/store";
|
||||
import { fmt } from "@/lib/format";
|
||||
import type { ClaimStatus } from "@/types";
|
||||
@@ -48,6 +50,12 @@ export function Claims() {
|
||||
const [page, setPage] = useState(1);
|
||||
const searchRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// SP4 drawer wiring: the URL is the source of truth for "which claim is
|
||||
// open". `open(id)` pushState's a new history entry (Back returns to the
|
||||
// list); `close()` pushState's the bare URL; `setClaimId(id)` replaceState's
|
||||
// so j/k navigation doesn't pollute history with one entry per keystroke.
|
||||
const { claimId, open, close, setClaimId } = useDrawerUrlState();
|
||||
|
||||
const providers = useAppStore((s) => s.providers);
|
||||
const providerMap = useMemo(
|
||||
() => Object.fromEntries(providers.map((p) => [p.npi, p])),
|
||||
@@ -89,9 +97,35 @@ export function Claims() {
|
||||
|
||||
const filtered = status !== ALL || npi !== ALL;
|
||||
|
||||
// Dim the background list while the drawer is open so the user's eye
|
||||
// lands on the drawer. `pointer-events-none` prevents accidental clicks
|
||||
// on the dimmed list (e.g., clicking a row would open yet another
|
||||
// drawer on top).
|
||||
const dimBackground = claimId !== null;
|
||||
|
||||
return (
|
||||
<div className="space-y-8 animate-fade-in">
|
||||
<header className="flex items-end justify-between gap-6 flex-wrap">
|
||||
<>
|
||||
<ClaimDrawer
|
||||
claimId={claimId}
|
||||
// Pass the full ordered list of ids from the current page so j/k
|
||||
// can wrap around without an extra round-trip. `items` is the API
|
||||
// response (post-pagination, post-search); that's the same set the
|
||||
// user is looking at, so wrap-around feels right.
|
||||
claims={items.map((c) => ({ id: c.id }))}
|
||||
onClose={close}
|
||||
onNavigate={setClaimId}
|
||||
onToggleHelp={() => {
|
||||
// T22 wires the KeyboardCheatsheet overlay; no-op for now.
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
data-testid="claims-page-body"
|
||||
className={cn(
|
||||
"space-y-8 animate-fade-in transition-opacity",
|
||||
dimBackground && "pointer-events-none opacity-60"
|
||||
)}
|
||||
>
|
||||
<header className="flex items-end justify-between gap-6 flex-wrap">
|
||||
<div>
|
||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
||||
<span className="inline-block h-px w-6 bg-border" />
|
||||
@@ -225,8 +259,13 @@ export function Claims() {
|
||||
return (
|
||||
<TableRow
|
||||
key={`${c.id}-${dataUpdatedAt}`}
|
||||
// Click anywhere on the row to open the drawer for
|
||||
// this claim. `cursor-pointer` makes the affordance
|
||||
// obvious; the existing `hover:bg-muted/30` from the
|
||||
// TableRow primitive stays in place.
|
||||
onClick={() => open(c.id)}
|
||||
className={cn(
|
||||
"animate-row-flash",
|
||||
"animate-row-flash cursor-pointer",
|
||||
// Re-keying on dataUpdatedAt re-mounts the row on
|
||||
// every refetch (initial load, filter change, parse
|
||||
// invalidation) so the row-flash keyframe replays.
|
||||
@@ -277,5 +316,6 @@ export function Claims() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user