feat(frontend): RemitDrawer component with CAS adjustments + parties + claim payments
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { api, ApiError } from "@/lib/api";
|
||||
import type { Remittance } from "@/types";
|
||||
|
||||
/**
|
||||
* UI-facing remittance detail shape returned by `GET /api/remittances/{id}`.
|
||||
*
|
||||
* The backend mapper (`cyclone.store.to_ui_remittance_with_adjustments`)
|
||||
* returns the standard `Remittance` fields plus the labeled `adjustments`
|
||||
* array. We extend the base type locally with the additional 835-derived
|
||||
* fields the backend emits — `payerClaimControlNumber` and `totalCharge`
|
||||
* (which aren't part of the v1 `Remittance` interface but ARE part of the
|
||||
* backend's `/api/remittances/{id}` payload). All newly-added fields are
|
||||
* optional so the component degrades gracefully when the backend hasn't
|
||||
* populated them (e.g. earlier rows without those columns populated).
|
||||
*
|
||||
* `payer` and `payee` blocks are also optional — the current detail
|
||||
* endpoint does not surface these yet, but the PartiesGrid renders them
|
||||
* when present so a future backend version lights up the cards without a
|
||||
* frontend change.
|
||||
*/
|
||||
export interface RemitDetail extends Remittance {
|
||||
payerClaimControlNumber?: string;
|
||||
totalCharge?: number;
|
||||
paymentMethod?: string | null;
|
||||
paymentDate?: string | null;
|
||||
payer?: {
|
||||
name?: string | null;
|
||||
id?: string | null;
|
||||
address?: {
|
||||
line1?: string;
|
||||
line2?: string | null;
|
||||
city?: string;
|
||||
state?: string;
|
||||
zip?: string;
|
||||
} | null;
|
||||
} | null;
|
||||
payee?: {
|
||||
name?: string | null;
|
||||
npi?: string | null;
|
||||
address?: {
|
||||
line1?: string;
|
||||
line2?: string | null;
|
||||
city?: string;
|
||||
state?: string;
|
||||
zip?: string;
|
||||
} | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-remittance detail drawer query (RemitDrawer).
|
||||
*
|
||||
* Mirror of `useClaimDetail` — same return shape, same retry semantics.
|
||||
* Returns `{ data, isLoading, isError, error, refetch }`:
|
||||
* - `id === null` (drawer closed): the query is disabled and the hook
|
||||
* short-circuits to the empty drawer state so a closed drawer doesn't
|
||||
* burn a network request or a TanStack cache slot.
|
||||
* - `id` is set: fetches `GET /api/remittances/{id}` via
|
||||
* `api.getRemittance`. Cached 30 s so j/k navigation across remits
|
||||
* reuses prior fetches within the drawer session.
|
||||
* - On 404: the hook's retry predicate short-circuits (no retries) so
|
||||
* the drawer's not-found state appears immediately rather than being
|
||||
* masked by three back-to-back retry attempts.
|
||||
*/
|
||||
export function useRemitDetail(id: string | null): {
|
||||
data: RemitDetail | null;
|
||||
isLoading: boolean;
|
||||
isError: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => void;
|
||||
} {
|
||||
const q = useQuery<RemitDetail>({
|
||||
queryKey: ["remit-detail", id],
|
||||
queryFn: () => api.getRemittance<RemitDetail>(id as string),
|
||||
enabled: id !== null,
|
||||
staleTime: 30 * 1000,
|
||||
retry: (failureCount, error) => {
|
||||
if (error instanceof ApiError && error.status === 404) return false;
|
||||
return failureCount < 3;
|
||||
},
|
||||
});
|
||||
|
||||
if (id === null) {
|
||||
return {
|
||||
data: null,
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
error: null,
|
||||
refetch: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
data: q.data ?? null,
|
||||
isLoading: q.isLoading,
|
||||
isError: q.isError,
|
||||
error: q.error,
|
||||
refetch: () => {
|
||||
void q.refetch();
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user