import { useCallback } from 'react'; import { environment } from '../environments/environment.ts'; import { useHttpService } from './HttpService.tsx'; import type { RecordsIntake as BaseRecordsIntake, RecordsRequest } from './RecordsService.tsx'; import type { ReferralRequestScope } from '../utils/referralRequestScope'; // Originals received for an outgoing records request: upload slots, received faxes, matching and filing. // The server pins each original to the version that scanned clean and decides every step. const API_URL = environment.orgAuthorizationApi; /** A received original, as the shared Records service reads it; a fax original names its fax. */ export type RecordsIntake = BaseRecordsIntake & { channel: 'upload' | 'fax' | 'connection'; faxItemId?: string }; export interface RecordsFaxItem { faxItemId: string; kind: 'referral' | 'records' | 'unclassified'; label?: string; pages?: number; document?: string; receivedAt?: string; } export interface RecordsFilingReceipt { receiptId: string; intakeId: string; patientId: string; filed?: { documentReferenceId: string; versionId: string }; state: 'filed' | 'evidence-owed' | 'partial'; } export interface RecordsWrite { operationId: string; expectedVersion: number; } const requestUrl = (requestId: string) => API_URL + '/records/requests/' + encodeURIComponent(requestId); // The opening a call belongs to: admitted before it is sent, cancelled when it retires, pinned to its practice. const scoped = (scope?: ReferralRequestScope) => (scope ? { admit: scope.admit, signal: scope.signal, organizationId: scope.organizationId } : {}); export const useRecordsIntakeService = () => { const { get, post } = useHttpService(); /** Opens an upload slot and puts the file in it; the slot is received separately, once its scan is clean. */ const uploadOriginal = useCallback(async (requestId: string, write: RecordsWrite, file: File, scope?: ReferralRequestScope) => { const opened = await post<{ intake: RecordsIntake; request: RecordsRequest; uploadUrl: string }>(requestUrl(requestId) + '/intakes', write, scoped(scope)); scope?.admit(); const put = await fetch(opened.uploadUrl, { method: 'PUT', body: file, headers: { 'Content-Type': 'application/pdf' }, signal: scope?.signal }); if (!put.ok) throw new Error('The original did not upload: ' + put.status); return opened; }, [post]); const receiveOriginal = useCallback( async (requestId: string, intakeId: string, write: RecordsWrite, scope?: ReferralRequestScope) => post<{ intake: RecordsIntake; request: RecordsRequest }>(requestUrl(requestId) + '/intakes/' + encodeURIComponent(intakeId) + '/received', write, scoped(scope)), [post], ); const takeFax = useCallback( async (requestId: string, faxItemId: string, write: RecordsWrite, scope?: ReferralRequestScope) => post<{ intake: RecordsIntake; request: RecordsRequest }>(requestUrl(requestId) + '/intakes/from-fax', { ...write, faxItemId }, scoped(scope)), [post], ); const matchPatient = useCallback( async (requestId: string, patientId: string, write: RecordsWrite, scope?: ReferralRequestScope) => post<{ request: RecordsRequest }>(requestUrl(requestId) + '/match', { ...write, patientId }, scoped(scope)), [post], ); const fileOriginal = useCallback( async (requestId: string, intakeId: string, write: RecordsWrite, scope?: ReferralRequestScope) => post<{ receipt: RecordsFilingReceipt; request: RecordsRequest }>(requestUrl(requestId) + '/intakes/' + encodeURIComponent(intakeId) + '/file', write, scoped(scope)), [post], ); const listFaxItems = useCallback( async (scope?: ReferralRequestScope) => (await get<{ items: RecordsFaxItem[] }>(API_URL + '/records/fax-items', scoped(scope))).items, [get], ); /** Moves a received fax between Referrals and Records, only from the queue the caller saw it in. */ const classifyFax = useCallback( async (faxItemId: string, from: RecordsFaxItem['kind'], to: 'records' | 'referral', scope?: ReferralRequestScope) => post<{ item: RecordsFaxItem }>(API_URL + '/records/fax-items/' + encodeURIComponent(faxItemId) + '/classify', { from, to }, scoped(scope)), [post], ); return { uploadOriginal, receiveOriginal, takeFax, matchPatient, fileOriginal, listFaxItems, classifyFax }; };