update bug ws checkin loket
This commit is contained in:
@@ -85,6 +85,24 @@
|
||||
</div>
|
||||
<div class="patient-klinik-pembayaran">{{ patient.klinik }} | {{ patient.pembayaran }}</div>
|
||||
</div>
|
||||
|
||||
<!-- NEW: Option to process next even if current is active -->
|
||||
<div class="next-action-shortcut mt-2" v-if="hasNextQueue">
|
||||
<v-btn
|
||||
block
|
||||
variant="tonal"
|
||||
color="primary-600"
|
||||
size="small"
|
||||
class="text-none font-weight-bold"
|
||||
@click="$emit('process-next')"
|
||||
>
|
||||
<v-icon start size="16">mdi-skip-next</v-icon>
|
||||
Panggil Berikutnya
|
||||
</v-btn>
|
||||
<div class="info-text text-center mt-1" style="font-size: 10px; color: var(--color-neutral-600);">
|
||||
(Gunakan jika lupa klik Selesai pada pasien ini)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="create-queue-buttons mt-4">
|
||||
<div class="create-buttons-container">
|
||||
|
||||
+328
-311
@@ -3289,331 +3289,348 @@ const checkInManual = async () => {
|
||||
console.log("🔍 Original input:", originalInput);
|
||||
console.log("📊 Total patients in store:", queueStore.allPatients.length);
|
||||
|
||||
// Cari pasien dengan dua metode:
|
||||
// 1. EXACT barcode match (prioritas tertinggi) - format: YYMMDD + 5 digit (contoh: 26011500001)
|
||||
// 2. EXACT nomor antrean match - format: RA020, F-RA001, EA013, dll
|
||||
// Menggunakan matchNoAntrian helper untuk memastikan kode + angka match dengan benar
|
||||
const foundPatient = queueStore.allPatients.find((p) => {
|
||||
if (!p) return false;
|
||||
let foundPatient: any = null;
|
||||
let freshPatient: any = null;
|
||||
|
||||
// Normalize barcode untuk comparison (remove whitespace, case-insensitive)
|
||||
const patientBarcode = String(p.barcode || "").trim();
|
||||
try {
|
||||
// Cari pasien dengan dua metode:
|
||||
// ...
|
||||
foundPatient = queueStore.allPatients.find((p) => {
|
||||
try {
|
||||
if (!p) return false;
|
||||
|
||||
// 1. EXACT barcode match (case-insensitive, whitespace-insensitive) - PRIORITAS TERTINGGI
|
||||
if (
|
||||
patientBarcode === cleanInput ||
|
||||
patientBarcode.toLowerCase() === cleanInput.toLowerCase()
|
||||
) {
|
||||
console.log(
|
||||
"✅ Found by exact barcode match:",
|
||||
patientBarcode,
|
||||
"===",
|
||||
cleanInput,
|
||||
// Normalize barcode untuk comparison (remove whitespace, case-insensitive)
|
||||
const patientBarcode = String(p.barcode || "").trim();
|
||||
|
||||
// 1. EXACT barcode match (case-insensitive, whitespace-insensitive) - PRIORITAS TERTINGGI
|
||||
if (
|
||||
patientBarcode === cleanInput ||
|
||||
patientBarcode.toLowerCase() === cleanInput.toLowerCase()
|
||||
) {
|
||||
console.log(
|
||||
"✅ Found by exact barcode match:",
|
||||
patientBarcode,
|
||||
"===",
|
||||
cleanInput,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. EXACT nomor antrean match (untuk manual input)
|
||||
// Menggunakan matchNoAntrian helper untuk memastikan kode + angka match dengan benar
|
||||
if (p.noAntrian && typeof matchNoAntrian === "function") {
|
||||
if (matchNoAntrian(originalInput, p.noAntrian)) {
|
||||
console.log(
|
||||
"✅ Found by exact nomor antrean match:",
|
||||
p.noAntrian,
|
||||
"===",
|
||||
originalInput,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (innerErr) {
|
||||
console.warn("⚠️ Error in patient find loop for patient:", p, innerErr);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!foundPatient) {
|
||||
// Tiket belum di-generate (tidak ada di queueStore)
|
||||
console.error("❌ Patient not found. Input:", inputValue);
|
||||
console.error("🔍 Extracted barcode/patientId:", searchBarcode);
|
||||
console.error(
|
||||
"📋 Available patients (first 10):",
|
||||
queueStore.allPatients.slice(0, 10).map((p) => ({
|
||||
no: p.no,
|
||||
barcode: p.barcode,
|
||||
noAntrian: p.noAntrian?.split(" |")[0],
|
||||
})),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. EXACT nomor antrean match (untuk manual input)
|
||||
// Menggunakan matchNoAntrian helper untuk memastikan kode + angka match dengan benar
|
||||
// Ini mencegah false positive seperti RA020 terdeteksi sebagai RA002
|
||||
if (p.noAntrian && matchNoAntrian(originalInput, p.noAntrian)) {
|
||||
console.log(
|
||||
"✅ Found by exact nomor antrean match:",
|
||||
p.noAntrian,
|
||||
"===",
|
||||
originalInput,
|
||||
saveToHistory({
|
||||
patientId: searchBarcode || inputValue,
|
||||
queueNumber: null,
|
||||
klinikQueueNumber: null,
|
||||
pembayaran: "N/A",
|
||||
status: "failed",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: "N/A",
|
||||
kodeKlinik: null,
|
||||
});
|
||||
|
||||
// RESET lastCheckInResult for failure to avoid success color bleed
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: searchBarcode || inputValue,
|
||||
status: "NOT_FOUND",
|
||||
};
|
||||
|
||||
const errorMsg = `❌ Tiket Tidak Ditemukan!\n\nInput: ${inputValue}\n\nTiket dengan nomor antrean atau barcode tersebut tidak ditemukan di sistem.\n\nPastikan:\n- Nomor antrean atau barcode sudah benar\n- Tiket sudah di-generate terlebih dahulu\n- Format input: RA020, F-RA001, atau 26011500001`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Error",
|
||||
"Tiket tidak ditemukan. Pastikan nomor antrean atau barcode sudah benar.",
|
||||
"error",
|
||||
"mdi-alert-circle",
|
||||
);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
// CATATAN: Validasi processStage dihapus karena terlalu ketat
|
||||
// Yang penting adalah status pasien (waiting/pending), bukan processStage
|
||||
// Pasien yang sudah dipanggil (status: waiting) harus bisa check-in
|
||||
// meskipun processStage-nya bukan 'loket' (bisa 'klinik' atau 'penunjang')
|
||||
// Validasi processStage akan dilakukan di checkInPatient() di queueStore
|
||||
// yang akan mengecek status pasien secara real-time
|
||||
|
||||
if (!foundPatient) {
|
||||
// Tiket belum di-generate (tidak ada di queueStore)
|
||||
console.error("❌ Patient not found. Input:", inputValue);
|
||||
console.error("🔍 Extracted barcode/patientId:", searchBarcode);
|
||||
console.error(
|
||||
"📋 Available patients (first 10):",
|
||||
queueStore.allPatients.slice(0, 10).map((p) => ({
|
||||
no: p.no,
|
||||
barcode: p.barcode,
|
||||
noAntrian: p.noAntrian?.split(" |")[0],
|
||||
})),
|
||||
);
|
||||
// IMPORTANT: Refresh data pasien dari queueStore untuk mendapatkan status REAL-TIME
|
||||
// Jangan gunakan foundPatient.status karena mungkin sudah stale
|
||||
// Cari ulang pasien dari queueStore dengan EXACT match (barcode atau nomor antrean)
|
||||
freshPatient = queueStore.allPatients.find((p) => {
|
||||
if (!p) return false;
|
||||
|
||||
saveToHistory({
|
||||
patientId: searchBarcode || inputValue,
|
||||
queueNumber: null,
|
||||
klinikQueueNumber: null,
|
||||
pembayaran: "N/A",
|
||||
status: "failed",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: "N/A",
|
||||
kodeKlinik: null,
|
||||
// Match by barcode
|
||||
const patientBarcode = String(p.barcode || "").trim();
|
||||
if (
|
||||
foundPatient && (
|
||||
patientBarcode === foundPatient.barcode ||
|
||||
patientBarcode === searchBarcode ||
|
||||
patientBarcode === cleanInput
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Match by nomor antrean (jika input adalah nomor antrean)
|
||||
if (foundPatient && p.noAntrian && p.no === foundPatient.no) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// RESET lastCheckInResult for failure to avoid success color bleed
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: searchBarcode || inputValue,
|
||||
status: "NOT_FOUND",
|
||||
};
|
||||
if (!freshPatient) {
|
||||
console.error("❌ Patient not found in queueStore after refresh");
|
||||
saveToHistory({
|
||||
patientId: foundPatient.barcode,
|
||||
queueNumber: foundPatient.noAntrian,
|
||||
klinikQueueNumber:
|
||||
foundPatient.noAntrian?.split(" |")[0] || foundPatient.noAntrian,
|
||||
pembayaran: foundPatient.pembayaran || "N/A",
|
||||
status: "failed",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: foundPatient.klinik || "N/A",
|
||||
kodeKlinik: foundPatient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
const errorMsg = `❌ Tiket Tidak Ditemukan!\n\nInput: ${inputValue}\n\nTiket dengan nomor antrean atau barcode tersebut tidak ditemukan di sistem.\n\nPastikan:\n- Nomor antrean atau barcode sudah benar\n- Tiket sudah di-generate terlebih dahulu\n- Format input: RA020, F-RA001, atau 26011500001`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
// RESET lastCheckInResult for failure
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: foundPatient.barcode,
|
||||
status: "REFRESH_NOT_FOUND",
|
||||
};
|
||||
|
||||
const errorMsg = `❌ Pasien tidak ditemukan di sistem setelah refresh data.`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Error",
|
||||
"Pasien tidak ditemukan di sistem",
|
||||
"error",
|
||||
"mdi-alert-circle",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Gunakan data pasien yang fresh untuk validasi
|
||||
const patientStatus = freshPatient.status;
|
||||
const klinikQueueNumber =
|
||||
freshPatient.noAntrian?.split(" |")[0] || freshPatient.noAntrian || "N/A";
|
||||
|
||||
console.log("🔍 Fresh patient status:", {
|
||||
barcode: freshPatient.barcode,
|
||||
noAntrian: freshPatient.noAntrian,
|
||||
status: patientStatus,
|
||||
processStage: freshPatient.processStage,
|
||||
});
|
||||
|
||||
// Cek apakah sudah check-in (status === 'di-loket') - gunakan data fresh
|
||||
if (patientStatus === "di-loket") {
|
||||
// Sudah check-in sebelumnya
|
||||
saveToHistory({
|
||||
patientId: freshPatient.barcode,
|
||||
queueNumber: freshPatient.noAntrian,
|
||||
klinikQueueNumber: klinikQueueNumber,
|
||||
pembayaran: freshPatient.pembayaran || "N/A",
|
||||
status: "failed",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: freshPatient.klinik || "N/A",
|
||||
kodeKlinik: freshPatient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: freshPatient.barcode,
|
||||
status: "ALREADY_CHECKED_IN",
|
||||
};
|
||||
|
||||
const errorMsg = `⚠️ Sudah Check-in!\n\nNomor Antrean ${klinikQueueNumber} sudah melakukan check-in sebelumnya.`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Warning",
|
||||
`Tiket ${klinikQueueNumber} sudah check-in sebelumnya`,
|
||||
"warning",
|
||||
"mdi-check-circle",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (patientStatus === "menunggu") {
|
||||
// Status "menunggu" = belum dipanggil oleh admin loket, belum muncul di AntrianLoket
|
||||
// TIDAK BOLEH check-in
|
||||
saveToHistory({
|
||||
patientId: freshPatient.barcode,
|
||||
queueNumber: freshPatient.noAntrian,
|
||||
klinikQueueNumber: klinikQueueNumber,
|
||||
pembayaran: freshPatient.pembayaran || "N/A",
|
||||
status: "NOT_ALLOWED",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: freshPatient.klinik || "N/A",
|
||||
kodeKlinik: freshPatient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: freshPatient.barcode,
|
||||
status: "NOT_ALLOWED",
|
||||
};
|
||||
|
||||
const errorMsg = `⏳ Belum Diizinkan Check-in\n\nNomor Antrean ${klinikQueueNumber} belum dipanggil oleh admin loket. Mohon menunggu hingga nomor antrean Anda dipanggil dan muncul di layar Antrian Loket.`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "kembali";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Info",
|
||||
`Tiket ${klinikQueueNumber} belum dipanggil. Mohon menunggu.`,
|
||||
"info",
|
||||
"mdi-clock-alert",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Status "waiting" atau "pending" → BOLEH check-in
|
||||
// Panggil checkInPatient untuk validasi dan update status ke "di-loket"
|
||||
// Gunakan barcode pasien yang fresh, bukan inputValue (untuk memastikan format benar)
|
||||
const patientBarcodeForCheckIn =
|
||||
freshPatient.barcode || searchBarcode || inputValue;
|
||||
console.log(
|
||||
"🔍 Calling checkInPatient with barcode (fresh):",
|
||||
patientBarcodeForCheckIn,
|
||||
);
|
||||
console.log(
|
||||
"🔍 Original input:",
|
||||
inputValue,
|
||||
"| Extracted barcode:",
|
||||
searchBarcode,
|
||||
);
|
||||
const checkInResult = await queueStore.checkInPatient(
|
||||
patientBarcodeForCheckIn,
|
||||
);
|
||||
|
||||
if (checkInResult.success && checkInResult.patient) {
|
||||
// Check-in berhasil
|
||||
const successKlinikQueueNumber =
|
||||
checkInResult.patient.noAntrian?.split(" |")[0] ||
|
||||
checkInResult.patient.noAntrian ||
|
||||
"N/A";
|
||||
|
||||
lastCheckInResult.value = {
|
||||
success: true,
|
||||
patientId: checkInResult.patient.barcode,
|
||||
status: "ALLOWED",
|
||||
};
|
||||
|
||||
saveToHistory({
|
||||
patientId: checkInResult.patient.barcode,
|
||||
queueNumber: checkInResult.patient.noAntrian,
|
||||
klinikQueueNumber: successKlinikQueueNumber,
|
||||
pembayaran: checkInResult.patient.pembayaran || "N/A",
|
||||
status: "success",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: checkInResult.patient.klinik || "N/A",
|
||||
kodeKlinik: checkInResult.patient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
const successMsg = `✅ Check-in Berhasil!\n\nPasien ${successKlinikQueueNumber} berhasil melakukan check-in dan status berubah menjadi di loket.`;
|
||||
infoMessage.value = successMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Berhasil",
|
||||
`Check-in manual berhasil. Tiket ${successKlinikQueueNumber} siap diproses.`,
|
||||
"success",
|
||||
"mdi-check-circle",
|
||||
);
|
||||
|
||||
manualInput.value = "";
|
||||
if (manualForm.value) {
|
||||
(manualForm.value as any).reset();
|
||||
}
|
||||
} else {
|
||||
// Check-in gagal (misalnya validasi di checkInPatient gagal)
|
||||
saveToHistory({
|
||||
patientId: foundPatient.barcode,
|
||||
queueNumber: foundPatient.noAntrian,
|
||||
klinikQueueNumber: klinikQueueNumber,
|
||||
pembayaran: foundPatient.pembayaran || "N/A",
|
||||
status: "failed",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: foundPatient.klinik || "N/A",
|
||||
kodeKlinik: foundPatient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: foundPatient.barcode,
|
||||
status: "FAILED",
|
||||
};
|
||||
|
||||
const errorMsg = `❌ Check-in Gagal!\n\n${checkInResult?.message || "Status pasien tidak memungkinkan untuk check-in."}`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Gagal",
|
||||
checkInResult?.message || "Check-in manual gagal dilakukan",
|
||||
"error",
|
||||
"mdi-close-circle",
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("❌ Fatal Error in checkInManual:", error);
|
||||
showSnackbar(
|
||||
"Error",
|
||||
"Tiket tidak ditemukan. Pastikan nomor antrean atau barcode sudah benar.",
|
||||
"Fatal Error",
|
||||
"Terjadi kesalahan sistem saat check-in manual",
|
||||
"error",
|
||||
"mdi-alert-circle",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// CATATAN: Validasi processStage dihapus karena terlalu ketat
|
||||
// Yang penting adalah status pasien (waiting/pending), bukan processStage
|
||||
// Pasien yang sudah dipanggil (status: waiting) harus bisa check-in
|
||||
// meskipun processStage-nya bukan 'loket' (bisa 'klinik' atau 'penunjang')
|
||||
// Validasi processStage akan dilakukan di checkInPatient() di queueStore
|
||||
// yang akan mengecek status pasien secara real-time
|
||||
|
||||
// IMPORTANT: Refresh data pasien dari queueStore untuk mendapatkan status REAL-TIME
|
||||
// Jangan gunakan foundPatient.status karena mungkin sudah stale
|
||||
// Cari ulang pasien dari queueStore dengan EXACT match (barcode atau nomor antrean)
|
||||
const freshPatient = queueStore.allPatients.find((p) => {
|
||||
if (!p) return false;
|
||||
|
||||
// Match by barcode
|
||||
const patientBarcode = String(p.barcode || "").trim();
|
||||
if (
|
||||
patientBarcode === foundPatient.barcode ||
|
||||
patientBarcode === searchBarcode ||
|
||||
patientBarcode === cleanInput
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Match by nomor antrean (jika input adalah nomor antrean)
|
||||
if (p.noAntrian && p.no === foundPatient.no) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!freshPatient) {
|
||||
console.error("❌ Patient not found in queueStore after refresh");
|
||||
saveToHistory({
|
||||
patientId: foundPatient.barcode,
|
||||
queueNumber: foundPatient.noAntrian,
|
||||
klinikQueueNumber:
|
||||
foundPatient.noAntrian?.split(" |")[0] || foundPatient.noAntrian,
|
||||
pembayaran: foundPatient.pembayaran || "N/A",
|
||||
status: "failed",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: foundPatient.klinik || "N/A",
|
||||
kodeKlinik: foundPatient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
// RESET lastCheckInResult for failure
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: foundPatient.barcode,
|
||||
status: "REFRESH_NOT_FOUND",
|
||||
};
|
||||
|
||||
const errorMsg = `❌ Pasien tidak ditemukan di sistem setelah refresh data.`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Error",
|
||||
"Pasien tidak ditemukan di sistem",
|
||||
"error",
|
||||
"mdi-alert-circle",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Gunakan data pasien yang fresh untuk validasi
|
||||
const patientStatus = freshPatient.status;
|
||||
const klinikQueueNumber =
|
||||
freshPatient.noAntrian?.split(" |")[0] || freshPatient.noAntrian || "N/A";
|
||||
|
||||
console.log("🔍 Fresh patient status:", {
|
||||
barcode: freshPatient.barcode,
|
||||
noAntrian: freshPatient.noAntrian,
|
||||
status: patientStatus,
|
||||
processStage: freshPatient.processStage,
|
||||
});
|
||||
|
||||
// Cek apakah sudah check-in (status === 'di-loket') - gunakan data fresh
|
||||
if (patientStatus === "di-loket") {
|
||||
// Sudah check-in sebelumnya
|
||||
saveToHistory({
|
||||
patientId: freshPatient.barcode,
|
||||
queueNumber: freshPatient.noAntrian,
|
||||
klinikQueueNumber: klinikQueueNumber,
|
||||
pembayaran: freshPatient.pembayaran || "N/A",
|
||||
status: "failed",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: freshPatient.klinik || "N/A",
|
||||
kodeKlinik: freshPatient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: freshPatient.barcode,
|
||||
status: "ALREADY_CHECKED_IN",
|
||||
};
|
||||
|
||||
const errorMsg = `⚠️ Sudah Check-in!\n\nNomor Antrean ${klinikQueueNumber} sudah melakukan check-in sebelumnya.`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Warning",
|
||||
`Tiket ${klinikQueueNumber} sudah check-in sebelumnya`,
|
||||
"warning",
|
||||
"mdi-check-circle",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (patientStatus === "menunggu") {
|
||||
// Status "menunggu" = belum dipanggil oleh admin loket, belum muncul di AntrianLoket
|
||||
// TIDAK BOLEH check-in
|
||||
saveToHistory({
|
||||
patientId: freshPatient.barcode,
|
||||
queueNumber: freshPatient.noAntrian,
|
||||
klinikQueueNumber: klinikQueueNumber,
|
||||
pembayaran: freshPatient.pembayaran || "N/A",
|
||||
status: "NOT_ALLOWED",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: freshPatient.klinik || "N/A",
|
||||
kodeKlinik: freshPatient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: freshPatient.barcode,
|
||||
status: "NOT_ALLOWED",
|
||||
};
|
||||
|
||||
const errorMsg = `⏳ Belum Diizinkan Check-in\n\nNomor Antrean ${klinikQueueNumber} belum dipanggil oleh admin loket. Mohon menunggu hingga nomor antrean Anda dipanggil dan muncul di layar Antrian Loket.`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "kembali";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Info",
|
||||
`Tiket ${klinikQueueNumber} belum dipanggil. Mohon menunggu.`,
|
||||
"info",
|
||||
"mdi-clock-alert",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Status "waiting" atau "pending" → BOLEH check-in
|
||||
// Panggil checkInPatient untuk validasi dan update status ke "di-loket"
|
||||
// Gunakan barcode pasien yang fresh, bukan inputValue (untuk memastikan format benar)
|
||||
const patientBarcodeForCheckIn =
|
||||
freshPatient.barcode || searchBarcode || inputValue;
|
||||
console.log(
|
||||
"🔍 Calling checkInPatient with barcode (fresh):",
|
||||
patientBarcodeForCheckIn,
|
||||
);
|
||||
console.log(
|
||||
"🔍 Original input:",
|
||||
inputValue,
|
||||
"| Extracted barcode:",
|
||||
searchBarcode,
|
||||
);
|
||||
const checkInResult = await queueStore.checkInPatient(
|
||||
patientBarcodeForCheckIn,
|
||||
);
|
||||
|
||||
if (checkInResult.success && checkInResult.patient) {
|
||||
// Check-in berhasil
|
||||
const successKlinikQueueNumber =
|
||||
checkInResult.patient.noAntrian?.split(" |")[0] ||
|
||||
checkInResult.patient.noAntrian ||
|
||||
"N/A";
|
||||
|
||||
lastCheckInResult.value = {
|
||||
success: true,
|
||||
patientId: checkInResult.patient.barcode,
|
||||
status: "ALLOWED",
|
||||
};
|
||||
|
||||
saveToHistory({
|
||||
patientId: checkInResult.patient.barcode,
|
||||
queueNumber: checkInResult.patient.noAntrian,
|
||||
klinikQueueNumber: successKlinikQueueNumber,
|
||||
pembayaran: checkInResult.patient.pembayaran || "N/A",
|
||||
status: "success",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: checkInResult.patient.klinik || "N/A",
|
||||
kodeKlinik: checkInResult.patient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
const successMsg = `✅ Check-in Berhasil!\n\nPasien ${successKlinikQueueNumber} berhasil melakukan check-in dan status berubah menjadi di loket.`;
|
||||
infoMessage.value = successMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Berhasil",
|
||||
`Check-in manual berhasil. Tiket ${successKlinikQueueNumber} siap diproses.`,
|
||||
"success",
|
||||
"mdi-check-circle",
|
||||
);
|
||||
|
||||
manualInput.value = "";
|
||||
if (manualForm.value) {
|
||||
(manualForm.value as any).reset();
|
||||
}
|
||||
} else {
|
||||
// Check-in gagal (misalnya validasi di checkInPatient gagal)
|
||||
saveToHistory({
|
||||
patientId: foundPatient.barcode,
|
||||
queueNumber: foundPatient.noAntrian,
|
||||
klinikQueueNumber: klinikQueueNumber,
|
||||
pembayaran: foundPatient.pembayaran || "N/A",
|
||||
status: "failed",
|
||||
checkInTime: new Date().toISOString(),
|
||||
checkInDate: new Date().toISOString(),
|
||||
method: "Manual",
|
||||
klinik: foundPatient.klinik || "N/A",
|
||||
kodeKlinik: foundPatient.kodeKlinik || null,
|
||||
});
|
||||
|
||||
lastCheckInResult.value = {
|
||||
success: false,
|
||||
patientId: foundPatient.barcode,
|
||||
status: "FAILED",
|
||||
};
|
||||
|
||||
const errorMsg = `❌ Check-in Gagal!\n\n${checkInResult.message || "Status pasien tidak memungkinkan untuk check-in."}`;
|
||||
infoMessage.value = errorMsg;
|
||||
infoAction.value = "checkin";
|
||||
infoDialog.value = true;
|
||||
showSnackbar(
|
||||
"Gagal",
|
||||
checkInResult.message || "Check-in manual gagal dilakukan",
|
||||
"error",
|
||||
"mdi-close-circle",
|
||||
"mdi-alert-octagon",
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user