feat(frontend): refactor Upload page to use useParse hook
This commit is contained in:
+39
-34
@@ -28,6 +28,7 @@ import {
|
|||||||
import { api, type ParseProgress } from "@/lib/api";
|
import { api, type ParseProgress } from "@/lib/api";
|
||||||
import { fmt, toNum } from "@/lib/format";
|
import { fmt, toNum } from "@/lib/format";
|
||||||
import { useAppStore } from "@/store";
|
import { useAppStore } from "@/store";
|
||||||
|
import { useParse } from "@/hooks/useParse";
|
||||||
import type {
|
import type {
|
||||||
ClaimOutput,
|
ClaimOutput,
|
||||||
ClaimPayment,
|
ClaimPayment,
|
||||||
@@ -465,7 +466,6 @@ export function Upload() {
|
|||||||
const [file, setFile] = useState<File | null>(null);
|
const [file, setFile] = useState<File | null>(null);
|
||||||
const [kind, setKind] = useState<ParsedBatchKind>("837p");
|
const [kind, setKind] = useState<ParsedBatchKind>("837p");
|
||||||
const [payer, setPayer] = useState<string>(PAYERS_837[0]!.value);
|
const [payer, setPayer] = useState<string>(PAYERS_837[0]!.value);
|
||||||
const [running, setRunning] = useState(false);
|
|
||||||
const [stream, setStream] = useState<StreamState>({
|
const [stream, setStream] = useState<StreamState>({
|
||||||
items: [],
|
items: [],
|
||||||
expectedTotal: null,
|
expectedTotal: null,
|
||||||
@@ -474,11 +474,16 @@ export function Upload() {
|
|||||||
});
|
});
|
||||||
const addParsedBatch = useAppStore((s) => s.addParsedBatch);
|
const addParsedBatch = useAppStore((s) => s.addParsedBatch);
|
||||||
const parsedBatches = useAppStore((s) => s.parsedBatches);
|
const parsedBatches = useAppStore((s) => s.parsedBatches);
|
||||||
|
// useParse wires the mutation; on success it invalidates every list query
|
||||||
|
// (batches, claims, remittances, providers, activity) so the other pages
|
||||||
|
// see the new data without manual refetching.
|
||||||
|
const parseMutation = useParse(kind);
|
||||||
|
|
||||||
const payerOptions = kind === "837p" ? PAYERS_837 : PAYERS_835;
|
const payerOptions = kind === "837p" ? PAYERS_837 : PAYERS_835;
|
||||||
|
|
||||||
const expectedTotal = stream.expectedTotal;
|
const expectedTotal = stream.expectedTotal;
|
||||||
const totalSoFar = stream.items.length;
|
const totalSoFar = stream.items.length;
|
||||||
|
const running = parseMutation.isPending;
|
||||||
const progressPct = useMemo(() => {
|
const progressPct = useMemo(() => {
|
||||||
if (!expectedTotal || expectedTotal <= 0) return 0;
|
if (!expectedTotal || expectedTotal <= 0) return 0;
|
||||||
return Math.min(100, Math.round((totalSoFar / expectedTotal) * 100));
|
return Math.min(100, Math.round((totalSoFar / expectedTotal) * 100));
|
||||||
@@ -497,39 +502,41 @@ export function Upload() {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setRunning(true);
|
|
||||||
setStream({ items: [], expectedTotal: null, passed: 0, failed: 0 });
|
setStream({ items: [], expectedTotal: null, passed: 0, failed: 0 });
|
||||||
const startedAt = new Date().toISOString();
|
|
||||||
const items: StreamedClaim[] = [];
|
const items: StreamedClaim[] = [];
|
||||||
try {
|
const onProgress: ParseProgress = (event) => {
|
||||||
const onProgress: ParseProgress = (event) => {
|
if (event.type === "claim") {
|
||||||
if (event.type === "claim") {
|
items.push({ kind: "837p", data: event.data });
|
||||||
items.push({ kind: "837p", data: event.data });
|
setStream((s) => ({
|
||||||
setStream((s) => ({
|
...s,
|
||||||
...s,
|
items: [...items],
|
||||||
items: [...items],
|
}));
|
||||||
}));
|
} else if (event.type === "claim_payment") {
|
||||||
} else if (event.type === "claim_payment") {
|
items.push({ kind: "835", data: event.data });
|
||||||
items.push({ kind: "835", data: event.data });
|
setStream((s) => ({
|
||||||
setStream((s) => ({
|
...s,
|
||||||
...s,
|
items: [...items],
|
||||||
items: [...items],
|
}));
|
||||||
}));
|
} else if (event.type === "summary") {
|
||||||
} else if (event.type === "summary") {
|
setStream((s) => ({
|
||||||
setStream((s) => ({
|
...s,
|
||||||
...s,
|
expectedTotal: event.data.total_claims,
|
||||||
expectedTotal: event.data.total_claims,
|
passed: event.data.passed,
|
||||||
passed: event.data.passed,
|
failed: event.data.failed,
|
||||||
failed: event.data.failed,
|
}));
|
||||||
}));
|
}
|
||||||
}
|
// financial_info / trace / payer / payee are accepted silently;
|
||||||
// financial_info / trace / payer / payee are accepted silently;
|
// the page summary at the end reports the real pass/fail counts.
|
||||||
// the page summary at the end reports the real pass/fail counts.
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const summary = await (kind === "837p"
|
try {
|
||||||
? api.parse837(file, { payer, onProgress })
|
// mutateAsync triggers the mutation; the streaming callbacks above
|
||||||
: api.parse835(file, { payer, onProgress }));
|
// populate `stream` as claims arrive, and the resolver returns the
|
||||||
|
// final BatchSummary from the "summary" NDJSON line.
|
||||||
|
const summary = await parseMutation.mutateAsync({
|
||||||
|
file,
|
||||||
|
options: { payer, onProgress },
|
||||||
|
});
|
||||||
|
|
||||||
// The final return value is a BatchSummary in the streaming case.
|
// The final return value is a BatchSummary in the streaming case.
|
||||||
const finalSummary =
|
const finalSummary =
|
||||||
@@ -548,7 +555,7 @@ export function Upload() {
|
|||||||
id,
|
id,
|
||||||
kind,
|
kind,
|
||||||
inputFilename: file.name,
|
inputFilename: file.name,
|
||||||
parsedAt: startedAt,
|
parsedAt: new Date().toISOString(),
|
||||||
claimCount: finalSummary.total_claims,
|
claimCount: finalSummary.total_claims,
|
||||||
passed: finalSummary.passed,
|
passed: finalSummary.passed,
|
||||||
failed: finalSummary.failed,
|
failed: finalSummary.failed,
|
||||||
@@ -567,8 +574,6 @@ export function Upload() {
|
|||||||
toast.error(
|
toast.error(
|
||||||
err instanceof Error ? err.message : "Failed to parse file"
|
err instanceof Error ? err.message : "Failed to parse file"
|
||||||
);
|
);
|
||||||
} finally {
|
|
||||||
setRunning(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user