feat(frontend): wire Vite app to FastAPI parser with NDJSON streaming + Upload page

This commit is contained in:
Tyler
2026-06-19 17:31:59 -06:00
parent 999889ecb3
commit 3d3bdfb07c
44 changed files with 7811 additions and 0 deletions
+178
View File
@@ -0,0 +1,178 @@
import type { Activity, Claim, Provider, Remittance } from "@/types";
export const sampleProviders: Provider[] = [
{
npi: "1730187395",
name: "Cedar Park Family Medicine",
taxId: "47-3829104",
address: "1401 Medical Pkwy",
city: "Cedar Park",
state: "TX",
zip: "78613",
phone: "(512) 555-0142",
claimCount: 1284,
outstandingAr: 184320,
},
{
npi: "1528471902",
name: "Lakeside Orthopedics",
taxId: "83-1172654",
address: "900 W Lake Dr",
city: "Austin",
state: "TX",
zip: "78746",
phone: "(512) 555-0188",
claimCount: 742,
outstandingAr: 221540,
},
{
npi: "1982036471",
name: "Hill Country Pediatrics",
taxId: "74-5520183",
address: "205 State Hwy 27",
city: "Marble Falls",
state: "TX",
zip: "78654",
phone: "(830) 555-0117",
claimCount: 956,
outstandingAr: 96210,
},
];
const payers = [
"Blue Cross Blue Shield",
"United Healthcare",
"Aetna",
"Cigna",
"Humana",
"Medicare",
"Medicaid TX",
];
const cpts = ["99213", "99214", "99203", "93000", "85025", "80053", "73721", "20610"];
const firstNames = [
"Avery",
"Jordan",
"Riley",
"Casey",
"Morgan",
"Quinn",
"Reese",
"Sasha",
"Drew",
"Hayden",
];
const lastNames = [
"Nguyen",
"Patel",
"Garcia",
"Cohen",
"Okafor",
"Martinez",
"Hwang",
"Brooks",
"Singh",
"Tanaka",
];
function rand<T>(arr: T[]): T {
return arr[Math.floor(Math.random() * arr.length)]!;
}
function daysAgo(n: number): string {
const d = new Date();
d.setDate(d.getDate() - n);
return d.toISOString();
}
function buildClaims(): Claim[] {
const claims: Claim[] = [];
for (let i = 0; i < 96; i++) {
const provider = rand(sampleProviders);
const status = rand<Claim["status"]>([
"submitted",
"accepted",
"denied",
"paid",
"paid",
"paid",
"pending",
]);
const billed = 80 + Math.floor(Math.random() * 1400);
const received =
status === "paid" ? Math.floor(billed * (0.6 + Math.random() * 0.4))
: status === "denied" ? 0
: 0;
claims.push({
id: `CLM-${(10428 + i).toString()}`,
patientName: `${rand(firstNames)} ${rand(lastNames)}`,
providerNpi: provider.npi,
payerName: rand(payers),
cptCode: rand(cpts),
billedAmount: billed,
receivedAmount: received,
status,
submissionDate: daysAgo(Math.floor(Math.random() * 200)),
denialReason:
status === "denied" ?
rand([
"CO-97: Service included in another service",
"CO-16: Claim lacks information",
"CO-50: Non-covered service",
"PR-1: Deductible amount",
])
: undefined,
});
}
return claims.sort(
(a, b) => new Date(b.submissionDate).getTime() - new Date(a.submissionDate).getTime()
);
}
function buildRemittances(claims: Claim[]): Remittance[] {
const paid = claims.filter((c) => c.status === "paid");
return paid.slice(0, 24).map((c, i) => ({
id: `REM-${(7782 + i).toString()}`,
claimId: c.id,
payerName: c.payerName,
paidAmount: c.receivedAmount,
adjustmentAmount: Math.max(0, c.billedAmount - c.receivedAmount - 5),
receivedDate: c.submissionDate,
checkNumber: `EFT-${100000 + Math.floor(Math.random() * 899999)}`,
status: rand<Remittance["status"]>(["received", "posted", "reconciled"]),
}));
}
function buildActivity(claims: Claim[]): Activity[] {
const events: Activity[] = claims.slice(0, 28).map((c) => {
const kind: Activity["kind"] =
c.status === "paid" ? "claim_paid" :
c.status === "denied" ? "claim_denied" :
c.status === "accepted" ? "claim_accepted" :
"claim_submitted";
return {
id: `ACT-${c.id}`,
kind,
message:
kind === "claim_paid" ?
`Paid ${c.id} · ${c.patientName}` :
kind === "claim_denied" ?
`Denied ${c.id} · ${c.patientName}` :
kind === "claim_accepted" ?
`Accepted ${c.id} · ${c.patientName}` :
`Submitted ${c.id} · ${c.patientName}`,
timestamp: c.submissionDate,
npi: c.providerNpi,
amount: c.billedAmount,
};
});
return events.sort(
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
);
}
const claims = buildClaims();
export const sampleClaims: Claim[] = claims;
export const sampleRemittances: Remittance[] = buildRemittances(claims);
export const sampleActivity: Activity[] = buildActivity(claims);