feat(frontend): wire Vite app to FastAPI parser with NDJSON streaming + Upload page
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
// UI-shaped types (used by the existing pages; backed by in-memory sample data
|
||||
// when no API is configured). Keep these stable — the rest of the app reads
|
||||
// from them.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type ClaimStatus =
|
||||
| "draft"
|
||||
| "submitted"
|
||||
| "accepted"
|
||||
| "denied"
|
||||
| "paid"
|
||||
| "pending";
|
||||
|
||||
export type RemittanceStatus = "received" | "posted" | "reconciled";
|
||||
|
||||
export type ActivityKind =
|
||||
| "claim_submitted"
|
||||
| "claim_paid"
|
||||
| "claim_denied"
|
||||
| "claim_accepted"
|
||||
| "remit_received"
|
||||
| "provider_added";
|
||||
|
||||
export interface Claim {
|
||||
id: string;
|
||||
patientName: string;
|
||||
providerNpi: string;
|
||||
payerName: string;
|
||||
cptCode: string;
|
||||
billedAmount: number;
|
||||
receivedAmount: number;
|
||||
status: ClaimStatus;
|
||||
submissionDate: string;
|
||||
denialReason?: string;
|
||||
}
|
||||
|
||||
export interface Provider {
|
||||
npi: string;
|
||||
name: string;
|
||||
taxId: string;
|
||||
address: string;
|
||||
city: string;
|
||||
state: string;
|
||||
zip: string;
|
||||
phone: string;
|
||||
claimCount: number;
|
||||
outstandingAr: number;
|
||||
}
|
||||
|
||||
export interface Remittance {
|
||||
id: string;
|
||||
claimId: string;
|
||||
payerName: string;
|
||||
paidAmount: number;
|
||||
adjustmentAmount: number;
|
||||
receivedDate: string;
|
||||
checkNumber: string;
|
||||
status: RemittanceStatus;
|
||||
}
|
||||
|
||||
export interface Activity {
|
||||
id: string;
|
||||
kind: ActivityKind;
|
||||
message: string;
|
||||
timestamp: string;
|
||||
npi?: string;
|
||||
amount?: number;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Backend-aligned types (snake_case to match FastAPI JSON output 1:1).
|
||||
// These mirror the Pydantic models in
|
||||
// backend/src/cyclone/parsers/models.py (837P)
|
||||
// backend/src/cyclone/parsers/models_835.py (835 ERA)
|
||||
// Numeric fields are strings (Decimals serialized); dates are ISO strings.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// --- 837P ------------------------------------------------------------------
|
||||
|
||||
export interface Address {
|
||||
line1: string;
|
||||
line2?: string | null;
|
||||
city: string;
|
||||
state: string;
|
||||
zip: string;
|
||||
}
|
||||
|
||||
export interface BillingProvider {
|
||||
name: string;
|
||||
npi: string;
|
||||
tax_id?: string | null;
|
||||
address?: Address | null;
|
||||
}
|
||||
|
||||
export interface Subscriber {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
member_id: string;
|
||||
dob?: string | null;
|
||||
gender?: "M" | "F" | "U" | null;
|
||||
address?: Address | null;
|
||||
}
|
||||
|
||||
export interface Payer {
|
||||
name: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ClaimHeader {
|
||||
claim_id: string;
|
||||
total_charge: string; // Decimal serialized
|
||||
place_of_service?: string | null;
|
||||
facility_code_qualifier?: string | null;
|
||||
frequency_code?: string | null;
|
||||
provider_signature?: string | null;
|
||||
assignment?: string | null;
|
||||
release_of_info?: string | null;
|
||||
prior_auth?: string | null;
|
||||
}
|
||||
|
||||
export interface Diagnosis {
|
||||
code: string;
|
||||
qualifier?: string | null;
|
||||
}
|
||||
|
||||
export interface Procedure {
|
||||
qualifier: string;
|
||||
code: string;
|
||||
modifiers: string[];
|
||||
}
|
||||
|
||||
export interface ServiceLine {
|
||||
line_number: number;
|
||||
procedure: Procedure;
|
||||
charge: string; // Decimal serialized
|
||||
unit_type?: string | null;
|
||||
units?: string | null; // Decimal serialized
|
||||
place_of_service?: string | null;
|
||||
service_date?: string | null;
|
||||
provider_reference?: string | null;
|
||||
}
|
||||
|
||||
export interface ValidationIssue {
|
||||
rule: string;
|
||||
severity: "error" | "warning";
|
||||
message: string;
|
||||
segment_index?: number | null;
|
||||
}
|
||||
|
||||
export interface ValidationReport {
|
||||
passed: boolean;
|
||||
errors: ValidationIssue[];
|
||||
warnings: ValidationIssue[];
|
||||
}
|
||||
|
||||
export interface Envelope {
|
||||
sender_id: string;
|
||||
receiver_id: string;
|
||||
control_number: string;
|
||||
transaction_date: string; // ISO date
|
||||
transaction_time?: string | null;
|
||||
implementation_guide?: string | null;
|
||||
}
|
||||
|
||||
export interface BatchSummary {
|
||||
input_file: string;
|
||||
control_number?: string | null;
|
||||
transaction_date?: string | null;
|
||||
total_claims: number;
|
||||
passed: number;
|
||||
failed: number;
|
||||
failed_claim_ids: string[];
|
||||
issues_by_rule: Record<string, number>;
|
||||
output_dir?: string | null;
|
||||
}
|
||||
|
||||
export interface ClaimOutput {
|
||||
claim_id: string;
|
||||
control_number: string;
|
||||
transaction_date: string; // ISO date
|
||||
billing_provider: BillingProvider;
|
||||
subscriber: Subscriber;
|
||||
payer: Payer;
|
||||
claim: ClaimHeader;
|
||||
diagnoses: Diagnosis[];
|
||||
service_lines: ServiceLine[];
|
||||
validation: ValidationReport;
|
||||
raw_segments: string[][];
|
||||
}
|
||||
|
||||
export interface ParseResult837 {
|
||||
envelope: Envelope | null;
|
||||
claims: ClaimOutput[];
|
||||
summary: BatchSummary;
|
||||
}
|
||||
|
||||
// --- 835 ERA ---------------------------------------------------------------
|
||||
|
||||
export interface FinancialInfo {
|
||||
handling_code: string;
|
||||
paid_amount: string; // Decimal serialized
|
||||
credit_debit_flag: string;
|
||||
payment_method?: string | null;
|
||||
payer_tax_id?: string | null;
|
||||
payment_date?: string | null; // ISO date
|
||||
}
|
||||
|
||||
export interface ReassociationTrace {
|
||||
trace_type_code: string;
|
||||
trace_number: string;
|
||||
originating_company_id: string;
|
||||
payer_id?: string | null;
|
||||
}
|
||||
|
||||
export interface Payer835 {
|
||||
name: string;
|
||||
id?: string | null;
|
||||
address?: Address | null;
|
||||
contact_url?: string | null;
|
||||
}
|
||||
|
||||
export interface Payee835 {
|
||||
name: string;
|
||||
npi: string;
|
||||
address?: Address | null;
|
||||
}
|
||||
|
||||
export interface ClaimAdjustment {
|
||||
group_code: string;
|
||||
reason_code: string;
|
||||
amount: string; // Decimal serialized
|
||||
quantity?: string | null;
|
||||
}
|
||||
|
||||
export interface ServicePayment {
|
||||
line_number: number;
|
||||
procedure_qualifier: string;
|
||||
procedure_code: string;
|
||||
modifiers: string[];
|
||||
charge: string;
|
||||
payment: string;
|
||||
units?: string | null;
|
||||
unit_type?: string | null;
|
||||
service_date?: string | null;
|
||||
adjustments: ClaimAdjustment[];
|
||||
ref_benefit_plan?: string | null;
|
||||
}
|
||||
|
||||
export interface ClaimPayment {
|
||||
payer_claim_control_number: string;
|
||||
status_code: string;
|
||||
status_label?: string | null;
|
||||
total_charge: string;
|
||||
total_paid: string;
|
||||
patient_responsibility?: string | null;
|
||||
claim_filing_indicator?: string | null;
|
||||
original_claim_id?: string | null;
|
||||
facility_type?: string | null;
|
||||
frequency_code?: string | null;
|
||||
per_diem_covered_days?: string | null;
|
||||
ref_benefit_plan?: string | null;
|
||||
service_payments: ServicePayment[];
|
||||
raw_segments: string[][];
|
||||
}
|
||||
|
||||
export interface ParseResult835 {
|
||||
envelope: Envelope;
|
||||
financial_info: FinancialInfo;
|
||||
trace: ReassociationTrace;
|
||||
payer: Payer835;
|
||||
payee: Payee835;
|
||||
claims: ClaimPayment[];
|
||||
summary: BatchSummary;
|
||||
validation?: ValidationReport | null;
|
||||
}
|
||||
|
||||
// --- NDJSON streaming ------------------------------------------------------
|
||||
// The backend emits one JSON object per line during an NDJSON stream:
|
||||
// { "type": "<event>", "data": <object> }
|
||||
// See backend/src/cyclone/api.py:_ndjson_stream* for the source of truth.
|
||||
|
||||
export type NdjsonEventType =
|
||||
| "envelope"
|
||||
| "claim"
|
||||
| "claim_payment"
|
||||
| "financial_info"
|
||||
| "trace"
|
||||
| "payer"
|
||||
| "payee"
|
||||
| "summary";
|
||||
|
||||
export interface NdjsonEvent<T = unknown> {
|
||||
type: NdjsonEventType;
|
||||
data: T;
|
||||
}
|
||||
|
||||
// --- Parsed-batch slice (used by the Upload page + store) ------------------
|
||||
|
||||
export type ParsedBatchKind = "837p" | "835";
|
||||
|
||||
export interface ParsedBatch {
|
||||
id: string;
|
||||
kind: ParsedBatchKind;
|
||||
inputFilename: string;
|
||||
parsedAt: string; // ISO timestamp
|
||||
claimCount: number;
|
||||
passed: number;
|
||||
failed: number;
|
||||
claimIds: string[];
|
||||
summary: BatchSummary;
|
||||
}
|
||||
Reference in New Issue
Block a user