// src/pages/DashboardPage/BillingPage/billingExportQuery.ts // (Billing-Aware Export), Task 9: pure query-string builder for GET /R4/BillingExport, kept // out of BillingExportService.tsx so the URL-encoding contract is unit-testable with no // fetch/HttpService/React in the loop. Filters mirror the export dialog's fields; `start`/`end`/ // `format` are the server-required trio, `provider`/`encounterType` are optional narrowing filters // the handler treats as "no filter" when absent - so a blank string must be OMITTED, not sent as // `provider=`, or the server would have to special-case an empty value as "no filter" itself. export type BillingExportFilters = { start: string; end: string; provider?: string; encounterType?: string; format: 'csv' | 'json'; }; // Built on URLSearchParams (not manual string concatenation) so every value is correctly // percent-encoded per application/x-www-form-urlencoded rules - this is also why the brief specifies // "a URLSearchParams string" rather than a hand-rolled one. export const buildBillingExportQuery = (f: BillingExportFilters): string => { const params = new URLSearchParams(); params.set('start', f.start); params.set('end', f.end); params.set('format', f.format); if (f.provider && f.provider.trim() !== '') { params.set('provider', f.provider); } if (f.encounterType && f.encounterType.trim() !== '') { params.set('encounterType', f.encounterType); } return params.toString(); }; // Client-side download filename - the server sets Content-Disposition too, but the browser download // (via a Blob + ) needs its own filename, and this keeps it human-readable and stable // across csv/json without depending on response headers. export const exportFilename = (f: { start: string; end: string }, format: 'csv' | 'json'): string => { return `billing-export_${f.start}_${f.end}.${format}`; };