feat(sp7): wire LineReconciliationTab into ClaimDrawer
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { useMemo } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
||||
import { ApiError } from "@/lib/api";
|
||||
import { useClaimDetail } from "@/hooks/useClaimDetail";
|
||||
import { useDrawerKeyboard } from "@/hooks/useDrawerKeyboard";
|
||||
import { useLineReconciliation } from "@/hooks/useLineReconciliation";
|
||||
import { ClaimDrawerHeader } from "./ClaimDrawerHeader";
|
||||
import { ValidationPanel } from "./ValidationPanel";
|
||||
import { ServiceLinesTable } from "./ServiceLinesTable";
|
||||
@@ -11,6 +12,7 @@ import { PartiesGrid } from "./PartiesGrid";
|
||||
import { RawSegmentsPanel } from "./RawSegmentsPanel";
|
||||
import { MatchedRemitCard } from "./MatchedRemitCard";
|
||||
import { StateHistoryTimeline } from "./StateHistoryTimeline";
|
||||
import { LineReconciliationTab } from "./LineReconciliationTab";
|
||||
import { ClaimDrawerSkeleton } from "./ClaimDrawerSkeleton";
|
||||
import { ClaimDrawerError } from "./ClaimDrawerError";
|
||||
|
||||
@@ -71,6 +73,12 @@ export function ClaimDrawer({
|
||||
onToggleHelp,
|
||||
}: ClaimDrawerProps) {
|
||||
const { data, isLoading, isError, error, refetch } = useClaimDetail(claimId);
|
||||
// SP7: tab state. The Line Reconciliation tab lazy-fetches the
|
||||
// per-line projection when first activated.
|
||||
const [activeTab, setActiveTab] = useState<"details" | "line-reconciliation">("details");
|
||||
const lr = useLineReconciliation(
|
||||
activeTab === "line-reconciliation" ? claimId : null
|
||||
);
|
||||
|
||||
// j/k navigation: derive next/prev IDs based on the current claim's
|
||||
// index in the parent list. Wrap around at both ends. If the current
|
||||
@@ -157,17 +165,84 @@ export function ClaimDrawer({
|
||||
data-testid="claim-drawer-content"
|
||||
>
|
||||
<ClaimDrawerHeader claim={data} onClose={onClose} />
|
||||
<div className="flex flex-col divide-y divide-[color:var(--m-border-heavy)]/15">
|
||||
<ValidationPanel validation={data.validation} />
|
||||
<ServiceLinesTable serviceLines={data.serviceLines} />
|
||||
<DiagnosesList diagnoses={data.diagnoses} />
|
||||
<PartiesGrid parties={data.parties} />
|
||||
{data.matchedRemittance ? (
|
||||
<MatchedRemitCard matchedRemittance={data.matchedRemittance} />
|
||||
) : null}
|
||||
<RawSegmentsPanel rawSegments={data.rawSegments} />
|
||||
<StateHistoryTimeline history={data.stateHistory} />
|
||||
<div
|
||||
className="flex gap-2 px-6 pt-4 border-b"
|
||||
style={{ borderColor: "var(--tt-bg)" }}
|
||||
data-testid="claim-drawer-tabs"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveTab("details")}
|
||||
className="font-mono text-xs uppercase tracking-wider px-3 py-2"
|
||||
style={{
|
||||
color:
|
||||
activeTab === "details"
|
||||
? "var(--tt-ink, currentColor)"
|
||||
: "var(--tt-ink-dim, rgba(255,255,255,0.5))",
|
||||
borderBottom:
|
||||
activeTab === "details"
|
||||
? "2px solid var(--tt-amber)"
|
||||
: "2px solid transparent",
|
||||
}}
|
||||
data-testid="tab-button-details"
|
||||
data-active={activeTab === "details" ? "true" : "false"}
|
||||
>
|
||||
Details
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveTab("line-reconciliation")}
|
||||
className="font-mono text-xs uppercase tracking-wider px-3 py-2"
|
||||
style={{
|
||||
color:
|
||||
activeTab === "line-reconciliation"
|
||||
? "var(--tt-ink, currentColor)"
|
||||
: "var(--tt-ink-dim, rgba(255,255,255,0.5))",
|
||||
borderBottom:
|
||||
activeTab === "line-reconciliation"
|
||||
? "2px solid var(--tt-amber)"
|
||||
: "2px solid transparent",
|
||||
}}
|
||||
data-testid="tab-button-line-reconciliation"
|
||||
data-active={activeTab === "line-reconciliation" ? "true" : "false"}
|
||||
>
|
||||
Line Reconciliation
|
||||
</button>
|
||||
</div>
|
||||
{activeTab === "line-reconciliation" ? (
|
||||
lr.loading ? (
|
||||
<p
|
||||
className="px-6 py-4 text-sm text-[color:var(--m-ink-tertiary)]"
|
||||
data-testid="line-reconciliation-loading"
|
||||
>
|
||||
Loading line reconciliation…
|
||||
</p>
|
||||
) : lr.error ? (
|
||||
<p
|
||||
className="px-6 py-4 text-sm text-[color:var(--m-ink-tertiary)]"
|
||||
data-testid="line-reconciliation-error"
|
||||
>
|
||||
Failed to load line reconciliation.
|
||||
</p>
|
||||
) : lr.data ? (
|
||||
<LineReconciliationTab data={lr.data} />
|
||||
) : null
|
||||
) : (
|
||||
<div className="flex flex-col divide-y divide-[color:var(--m-border-heavy)]/15">
|
||||
<ValidationPanel validation={data.validation} />
|
||||
<ServiceLinesTable
|
||||
serviceLines={data.serviceLines}
|
||||
lineReconciliation={data.lineReconciliation}
|
||||
/>
|
||||
<DiagnosesList diagnoses={data.diagnoses} />
|
||||
<PartiesGrid parties={data.parties} />
|
||||
{data.matchedRemittance ? (
|
||||
<MatchedRemitCard matchedRemittance={data.matchedRemittance} />
|
||||
) : null}
|
||||
<RawSegmentsPanel rawSegments={data.rawSegments} />
|
||||
<StateHistoryTimeline history={data.stateHistory} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</DialogContent>
|
||||
|
||||
@@ -11,3 +11,4 @@ export { MatchedRemitCard } from "./MatchedRemitCard";
|
||||
export { StateHistoryTimeline } from "./StateHistoryTimeline";
|
||||
export { ClaimDrawerSkeleton } from "./ClaimDrawerSkeleton";
|
||||
export { ClaimDrawerError } from "./ClaimDrawerError";
|
||||
export { LineReconciliationTab } from "./LineReconciliationTab";
|
||||
|
||||
Reference in New Issue
Block a user