Files
web-antrean/composables/useQueueAPI.ts
T
2026-01-06 14:51:28 +07:00

194 lines
5.1 KiB
TypeScript

// composables/useQueueAPI.ts
// Composable untuk API calls terkait antrian pasien
export interface Patient {
no: number;
jamPanggil: string;
barcode: string;
noAntrian: string;
shift: string;
klinik: string;
fastTrack: string;
pembayaran: string;
status: 'waiting' | 'pending' | 'di-loket' | 'di-klinik' | 'selesai' | 'terlambat';
processStage: 'loket' | 'klinik' | 'penunjang';
createdAt: string;
registrationType?: 'online' | 'onsite';
visitType?: string;
visitDate?: string;
}
export interface QueueAPIResponse<T = any> {
success: boolean;
data?: T;
message?: string;
error?: string;
}
export const useQueueAPI = () => {
const config = useRuntimeConfig();
const baseURL = config.public.apiBaseUrl || '/api/queue';
/**
* Fetch all patients from database
*/
const fetchAllPatients = async (): Promise<Patient[]> => {
try {
const response = await $fetch<QueueAPIResponse<Patient[]>>(`${baseURL}/patients`, {
method: 'GET',
});
if (response.success && response.data) {
return response.data;
}
throw new Error(response.message || 'Failed to fetch patients');
} catch (error: any) {
console.error('❌ Error fetching patients:', error);
throw error;
}
};
/**
* Fetch single patient by ID or barcode
*/
const fetchPatient = async (idOrBarcode: string): Promise<Patient | null> => {
try {
const response = await $fetch<QueueAPIResponse<Patient>>(`${baseURL}/patients/${idOrBarcode}`, {
method: 'GET',
});
if (response.success && response.data) {
return response.data;
}
return null;
} catch (error: any) {
console.error('❌ Error fetching patient:', error);
return null;
}
};
/**
* Create new patient (register from Anjungan)
*/
const createPatient = async (patientData: Partial<Patient>): Promise<Patient> => {
try {
const response = await $fetch<QueueAPIResponse<Patient>>(`${baseURL}/patients`, {
method: 'POST',
body: patientData,
});
if (response.success && response.data) {
return response.data;
}
throw new Error(response.message || 'Failed to create patient');
} catch (error: any) {
console.error('❌ Error creating patient:', error);
throw error;
}
};
/**
* Update patient status (check-in, process, etc)
*/
const updatePatient = async (
idOrBarcode: string,
updates: Partial<Patient>
): Promise<Patient> => {
try {
const response = await $fetch<QueueAPIResponse<Patient>>(
`${baseURL}/patients/${idOrBarcode}`,
{
method: 'PATCH',
body: updates,
}
);
if (response.success && response.data) {
return response.data;
}
throw new Error(response.message || 'Failed to update patient');
} catch (error: any) {
console.error('❌ Error updating patient:', error);
throw error;
}
};
/**
* Check-in patient (update status to di-loket)
*/
const checkInPatient = async (idOrBarcode: string): Promise<Patient> => {
return updatePatient(idOrBarcode, { status: 'di-loket' });
};
/**
* Process patient at loket (update status and processStage)
*/
const processPatientAtLoket = async (
idOrBarcode: string,
updates: { status?: string; processStage?: string }
): Promise<Patient> => {
return updatePatient(idOrBarcode, updates);
};
/**
* Sync local state with database
*/
const syncWithDatabase = async (localPatients: Patient[]): Promise<Patient[]> => {
try {
// Fetch latest from database
const dbPatients = await fetchAllPatients();
// Merge strategy: prefer database data, but keep local if newer
const merged = new Map<string, Patient>();
// Add database patients
dbPatients.forEach(patient => {
merged.set(patient.barcode, patient);
});
// Add local patients that don't exist in DB or are newer
localPatients.forEach(localPatient => {
const existing = merged.get(localPatient.barcode);
if (!existing || new Date(localPatient.createdAt) > new Date(existing.createdAt)) {
merged.set(localPatient.barcode, localPatient);
}
});
return Array.from(merged.values());
} catch (error: any) {
console.error('❌ Error syncing with database:', error);
// Return local patients as fallback
return localPatients;
}
};
/**
* Batch sync: save multiple patients to database
*/
const batchSyncPatients = async (patients: Patient[]): Promise<boolean> => {
try {
const response = await $fetch<QueueAPIResponse>(`${baseURL}/patients/batch`, {
method: 'POST',
body: { patients },
});
return response.success || false;
} catch (error: any) {
console.error('❌ Error batch syncing patients:', error);
return false;
}
};
return {
fetchAllPatients,
fetchPatient,
createPatient,
updatePatient,
checkInPatient,
processPatientAtLoket,
syncWithDatabase,
batchSyncPatients,
};
};