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 { fmt, toNum } from "@/lib/format";
|
||||
import { useAppStore } from "@/store";
|
||||
import { useParse } from "@/hooks/useParse";
|
||||
import type {
|
||||
ClaimOutput,
|
||||
ClaimPayment,
|
||||
@@ -465,7 +466,6 @@ export function Upload() {
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [kind, setKind] = useState<ParsedBatchKind>("837p");
|
||||
const [payer, setPayer] = useState<string>(PAYERS_837[0]!.value);
|
||||
const [running, setRunning] = useState(false);
|
||||
const [stream, setStream] = useState<StreamState>({
|
||||
items: [],
|
||||
expectedTotal: null,
|
||||
@@ -474,11 +474,16 @@ export function Upload() {
|
||||
});
|
||||
const addParsedBatch = useAppStore((s) => s.addParsedBatch);
|
||||
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 expectedTotal = stream.expectedTotal;
|
||||
const totalSoFar = stream.items.length;
|
||||
const running = parseMutation.isPending;
|
||||
const progressPct = useMemo(() => {
|
||||
if (!expectedTotal || expectedTotal <= 0) return 0;
|
||||
return Math.min(100, Math.round((totalSoFar / expectedTotal) * 100));
|
||||
@@ -497,39 +502,41 @@ export function Upload() {
|
||||
);
|
||||
return;
|
||||
}
|
||||
setRunning(true);
|
||||
setStream({ items: [], expectedTotal: null, passed: 0, failed: 0 });
|
||||
const startedAt = new Date().toISOString();
|
||||
const items: StreamedClaim[] = [];
|
||||
try {
|
||||
const onProgress: ParseProgress = (event) => {
|
||||
if (event.type === "claim") {
|
||||
items.push({ kind: "837p", data: event.data });
|
||||
setStream((s) => ({
|
||||
...s,
|
||||
items: [...items],
|
||||
}));
|
||||
} else if (event.type === "claim_payment") {
|
||||
items.push({ kind: "835", data: event.data });
|
||||
setStream((s) => ({
|
||||
...s,
|
||||
items: [...items],
|
||||
}));
|
||||
} else if (event.type === "summary") {
|
||||
setStream((s) => ({
|
||||
...s,
|
||||
expectedTotal: event.data.total_claims,
|
||||
passed: event.data.passed,
|
||||
failed: event.data.failed,
|
||||
}));
|
||||
}
|
||||
// financial_info / trace / payer / payee are accepted silently;
|
||||
// the page summary at the end reports the real pass/fail counts.
|
||||
};
|
||||
const onProgress: ParseProgress = (event) => {
|
||||
if (event.type === "claim") {
|
||||
items.push({ kind: "837p", data: event.data });
|
||||
setStream((s) => ({
|
||||
...s,
|
||||
items: [...items],
|
||||
}));
|
||||
} else if (event.type === "claim_payment") {
|
||||
items.push({ kind: "835", data: event.data });
|
||||
setStream((s) => ({
|
||||
...s,
|
||||
items: [...items],
|
||||
}));
|
||||
} else if (event.type === "summary") {
|
||||
setStream((s) => ({
|
||||
...s,
|
||||
expectedTotal: event.data.total_claims,
|
||||
passed: event.data.passed,
|
||||
failed: event.data.failed,
|
||||
}));
|
||||
}
|
||||
// financial_info / trace / payer / payee are accepted silently;
|
||||
// the page summary at the end reports the real pass/fail counts.
|
||||
};
|
||||
|
||||
const summary = await (kind === "837p"
|
||||
? api.parse837(file, { payer, onProgress })
|
||||
: api.parse835(file, { payer, onProgress }));
|
||||
try {
|
||||
// mutateAsync triggers the mutation; the streaming callbacks above
|
||||
// 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.
|
||||
const finalSummary =
|
||||
@@ -548,7 +555,7 @@ export function Upload() {
|
||||
id,
|
||||
kind,
|
||||
inputFilename: file.name,
|
||||
parsedAt: startedAt,
|
||||
parsedAt: new Date().toISOString(),
|
||||
claimCount: finalSummary.total_claims,
|
||||
passed: finalSummary.passed,
|
||||
failed: finalSummary.failed,
|
||||
@@ -567,8 +574,6 @@ export function Upload() {
|
||||
toast.error(
|
||||
err instanceof Error ? err.message : "Failed to parse file"
|
||||
);
|
||||
} finally {
|
||||
setRunning(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user