Files
web-antrean/composables/useCheckIn.ts
2026-01-05 08:32:59 +07:00

204 lines
6.3 KiB
TypeScript

import { ref, readonly } from 'vue'
import type { CheckInResult } from '~/types/checkin'
export interface UseCheckInOptions {
showSnackbar: (title: string, message: string, color: string, icon: string) => void
saveToHistory: (item: {
patientId: string
queueNumber?: string
status: string
checkInTime: string
checkInDate: string
method: string
}) => void
saveSuccessfulScan: (qrData: string) => void
onCheckInSuccess: (result: {
success: boolean
patientId: string
status: string
message: string
action: 'checkin' | 'kembali'
}) => void
autoCloseDialog: () => void
}
export const useCheckIn = (options: UseCheckInOptions) => {
const { showSnackbar, saveToHistory, saveSuccessfulScan, onCheckInSuccess, autoCloseDialog } = options
// State
const lastCheckInResult = ref<CheckInResult | null>(null)
// Perform check-in
const performCheckIn = async (data: string, method: string = 'QR Scan'): Promise<boolean> => {
await new Promise(resolve => setTimeout(resolve, 1000))
const success = Math.random() < 0.8
// History akan disimpan di processQRCode setelah performCheckIn selesai
// Jadi kita hanya perlu return hasil check-in
return success
}
// Process QR code (rename dari onDetect)
const processQRCode = async (decodedText: string) => {
const [patientId, status] = decodedText.split('|')
// Validasi format QR code
if (!patientId || !status) {
showSnackbar('Error', 'QR Code tidak valid. Format harus: ID_PASIEN|STATUS', 'error', 'mdi-close-circle')
return
}
// Cek apakah pasien diperbolehkan check-in
const isAllowed = status === 'ALLOWED'
if (isAllowed) {
// Jika diperbolehkan, langsung proses check-in
const checkinSuccess = await performCheckIn(decodedText, 'QR Scan')
// Simpan hasil check-in
lastCheckInResult.value = {
success: checkinSuccess,
patientId: patientId,
status: status
}
// Simpan ke history check-in dengan status hasil check-in
saveToHistory({
patientId: patientId || 'Unknown',
status: checkinSuccess ? 'success' : 'failed',
checkInTime: new Date().toISOString(),
checkInDate: new Date().toISOString(),
method: 'QR Scan'
})
// Tampilkan dialog dengan hasil check-in
if (checkinSuccess) {
// Simpan QR code yang berhasil di-scan untuk mencegah scan ulang
saveSuccessfulScan(decodedText)
onCheckInSuccess({
success: true,
patientId: patientId,
status: status,
message: `✅ Check-in Berhasil!\n\nPasien ${patientId} berhasil melakukan check-in.`,
action: 'checkin'
})
} else {
onCheckInSuccess({
success: false,
patientId: patientId,
status: status,
message: `❌ Check-in Gagal!\n\nPasien ${patientId} diperbolehkan check-in, namun proses check-in gagal. Silakan coba lagi.`,
action: 'checkin'
})
}
autoCloseDialog()
} else {
// Jika belum diperbolehkan, tampilkan pesan
lastCheckInResult.value = {
success: false,
patientId: patientId,
status: status
}
// Simpan ke history check-in untuk NOT_ALLOWED
saveToHistory({
patientId: patientId || 'Unknown',
status: 'NOT_ALLOWED',
checkInTime: new Date().toISOString(),
checkInDate: new Date().toISOString(),
method: 'QR Scan'
})
onCheckInSuccess({
success: false,
patientId: patientId,
status: status,
message: `⏳ Belum Diizinkan Check-in\n\nAntrean Pasien ${patientId} belum diperbolehkan check-in. Mohon menunggu hingga antrean Anda dipanggil.`,
action: 'kembali'
})
autoCloseDialog()
}
}
// Check-in manual
const checkInManual = async (
patientId: string,
onSuccess: () => void,
onError: () => void
) => {
try {
if (!patientId || !patientId.trim()) {
showSnackbar('Error', 'Mohon isi nomor antrean atau ID pasien', 'error', 'mdi-alert')
onError()
return
}
const trimmedPatientId = patientId.trim()
// Simulasi check-in manual
const success = await performCheckIn(`${trimmedPatientId}|ALLOWED`, 'Manual')
// Simpan hasil check-in
lastCheckInResult.value = {
success: success,
patientId: trimmedPatientId,
status: 'ALLOWED',
}
// Simpan ke history check-in
saveToHistory({
patientId: trimmedPatientId,
status: success ? 'success' : 'failed',
checkInTime: new Date().toISOString(),
checkInDate: new Date().toISOString(),
method: 'Manual'
})
if (success) {
// Simpan QR code yang berhasil untuk mencegah double antrian (jika menggunakan format yang sama)
saveSuccessfulScan(`${trimmedPatientId}|ALLOWED`)
showSnackbar('Berhasil!', 'Check-in manual berhasil dilakukan.', 'success', 'mdi-check-circle')
// Update info dialog
onCheckInSuccess({
success: true,
patientId: trimmedPatientId,
status: 'ALLOWED',
message: `✅ Check-in Berhasil!\n\nPasien ${trimmedPatientId} berhasil melakukan check-in secara manual.`,
action: 'checkin'
})
autoCloseDialog()
onSuccess()
} else {
showSnackbar('Gagal!', 'Check-in manual gagal dilakukan. Silakan coba lagi!', 'error', 'mdi-close-circle')
// Update info dialog untuk gagal
onCheckInSuccess({
success: false,
patientId: trimmedPatientId,
status: 'ALLOWED',
message: `❌ Check-in Gagal!\n\nPasien ${trimmedPatientId} gagal melakukan check-in secara manual. Silakan coba lagi.`,
action: 'checkin'
})
autoCloseDialog()
onError()
}
} catch (error) {
console.error('Error in checkInManual:', error)
showSnackbar('Error', 'Terjadi kesalahan saat melakukan check-in. Silakan coba lagi.', 'error', 'mdi-alert')
onError()
}
}
return {
lastCheckInResult: readonly(lastCheckInResult),
performCheckIn,
processQRCode,
checkInManual,
}
}