Files
vigilcare-records/vigilcare-records-web/src/stores/batches.ts
T

243 lines
6.5 KiB
TypeScript

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { get, post, put, del, patch, uploadFile } from '../api/client'
import type {
BatchDetailResponse,
BatchDraft,
DraftPatient,
DraftEncounter,
DraftObservation,
BatchListResponse,
FieldCheck,
PatientDigitizationHistoryResponse,
} from '../types'
export const useBatchStore = defineStore('batches', () => {
const batches = ref<BatchDetailResponse[]>([])
const currentBatch = ref<BatchDetailResponse | null>(null)
const currentDraft = ref<BatchDraft | null>(null)
const totalCount = ref(0)
const loading = ref(false)
const error = ref<string | null>(null)
const documentUrl = computed(() => currentBatch.value?.documentUrl ?? null)
async function listBatches(params: {
status?: string
batchType?: string
assignedTo?: string
track?: string
page?: number
pageSize?: number
}): Promise<void> {
loading.value = true
error.value = null
try {
const response = await get<BatchListResponse>(
'digitization-batches',
params as Record<string, unknown>
)
if (response.success && response.data) {
batches.value = response.data.items
totalCount.value = response.data.totalCount
}
} catch (e: unknown) {
error.value = e instanceof Error ? e.message : 'Failed to load batches'
} finally {
loading.value = false
}
}
async function getBatch(id: string): Promise<void> {
loading.value = true
error.value = null
try {
const response = await get<BatchDetailResponse>(
`digitization-batches/${id}`
)
if (response.success && response.data) {
currentBatch.value = response.data
}
} catch (e: unknown) {
error.value = e instanceof Error ? e.message : 'Failed to load batch'
} finally {
loading.value = false
}
}
async function uploadBatch(
file: File,
batchType: string,
track: string,
patientId?: string,
supersedesBatchId?: string,
): Promise<BatchDetailResponse | null> {
loading.value = true
error.value = null
try {
const fields: Record<string, string> = { batchType, track }
if (patientId) fields.patientId = patientId
if (supersedesBatchId) fields.supersedesBatchId = supersedesBatchId
const response = await uploadFile<BatchDetailResponse>(
'digitization-batches',
file,
fields
)
if (response.success && response.data) {
return response.data
}
return null
} catch (e: unknown) {
error.value = e instanceof Error ? e.message : 'Upload failed'
return null
} finally {
loading.value = false
}
}
async function assignBatch(batchId: string, entryClerkUserId: string): Promise<void> {
const response = await patch<BatchDetailResponse>(`digitization-batches/${batchId}/assign`, {
entryClerkUserId,
})
if (!response.success) {
throw new Error(response.error?.message ?? 'Assignment failed')
}
}
async function getDraft(batchId: string): Promise<void> {
loading.value = true
try {
const response = await get<BatchDraft>(
`digitization-batches/${batchId}/draft`
)
if (response.success && response.data) {
currentDraft.value = response.data
}
} finally {
loading.value = false
}
}
async function saveDraftPatient(
batchId: string,
patient: Partial<DraftPatient>
): Promise<void> {
await put<DraftPatient>(
`digitization-batches/${batchId}/draft/patient`,
patient
)
}
async function saveDraftEncounter(
batchId: string,
encounter: Partial<DraftEncounter>
): Promise<void> {
await put<DraftEncounter>(
`digitization-batches/${batchId}/draft/encounter`,
encounter
)
}
async function addObservation(
batchId: string,
observation: Partial<DraftObservation>
): Promise<void> {
await post<DraftObservation>(
`digitization-batches/${batchId}/draft/observations`,
observation
)
await getDraft(batchId) // refresh draft to get new observation ID
}
async function updateObservation(
batchId: string,
obsId: string,
observation: Partial<DraftObservation>
): Promise<void> {
await put<DraftObservation>(
`digitization-batches/${batchId}/draft/observations/${obsId}`,
observation
)
}
async function deleteObservation(batchId: string, obsId: string): Promise<void> {
await del<void>(`digitization-batches/${batchId}/draft/observations/${obsId}`)
await getDraft(batchId)
}
async function submitForVerification(batchId: string): Promise<void> {
await post<void>(`digitization-batches/${batchId}/submit-for-verification`)
}
async function verifyBatch(
batchId: string,
fieldChecks: FieldCheck[],
passed: boolean
): Promise<void> {
await post<void>(`digitization-batches/${batchId}/verify`, {
fieldChecks,
passed,
})
}
async function rejectBatch(batchId: string, reason: string): Promise<void> {
await post<void>(`digitization-batches/${batchId}/reject`, { reason })
}
async function approveBatch(
batchId: string,
enableRetroactiveAlerts: boolean = false
): Promise<{ status?: number; data?: { mrn: string; encounterId: string; observationIds: string[] } }> {
const response = await post<{ mrn: string; encounterId: string; observationIds: string[] }>(
`digitization-batches/${batchId}/approve`,
{ enableRetroactiveAlerts },
{ 'Idempotency-Key': crypto.randomUUID() }
)
return { data: response.data ?? undefined }
}
async function getPatientHistory(patientId: string): Promise<PatientDigitizationHistoryResponse | null> {
loading.value = true
error.value = null
try {
const response = await get<PatientDigitizationHistoryResponse>(
`patients/${patientId}/digitization-history`,
)
if (response.success && response.data) {
return response.data
}
return null
} catch (e: unknown) {
error.value = e instanceof Error ? e.message : 'Failed to load patient history'
return null
} finally {
loading.value = false
}
}
return {
batches,
currentBatch,
currentDraft,
documentUrl,
totalCount,
loading,
error,
listBatches,
getBatch,
uploadBatch,
assignBatch,
getDraft,
saveDraftPatient,
saveDraftEncounter,
addObservation,
updateObservation,
deleteObservation,
submitForVerification,
verifyBatch,
rejectBatch,
approveBatch,
getPatientHistory,
}
})