Files
web-antrean/composables/useQueue.js
2026-01-08 12:44:40 +07:00

272 lines
8.6 KiB
JavaScript

// composables/useQueue.js
import { ref, computed } from "vue";
import { useQueueStore } from "../stores/queueStore";
export const useQueue = (adminType = "loket") => {
const queueStore = useQueueStore();
// Local state
const snackbar = ref(false);
const snackbarText = ref("");
const snackbarColor = ref("success");
// Dialog states
const showKlinikDialog = ref(false);
const showPenunjangDialog = ref(false);
const showChangeKlinikDialog = ref(false);
const klinikSearch = ref("");
const penunjangSearch = ref("");
const changeKlinikSearch = ref("");
const selectedPatientForPenunjang = ref(null);
// FIXED: Get stage patients once, then derive others from it
const stagePatients = computed(() => {
// Don't use .value here - getPatientsByStage returns a computed already
const patients = queueStore.getPatientsByStage(adminType);
return patients.value;
});
// Computed from store - filtered by stage
const currentProcessingPatient = computed(() => {
return queueStore.currentProcessingPatient[adminType];
});
// Derive from stagePatients - ADD DEBUG LOGS
const diLoketPatients = computed(() => {
const patients = stagePatients.value.diLoket || [];
console.log('🔍 useQueue - diLoketPatients:', patients.length);
if (patients.length > 0) {
console.log('🔍 First diLoket patient:', patients[0]);
console.log('🔍 First diLoket patient fastTrack:', patients[0].fastTrack);
}
return patients;
});
const terlambatPatients = computed(() => {
const patients = stagePatients.value.terlambat || [];
console.log('🔍 useQueue - terlambatPatients:', patients.length);
return patients;
});
const pendingPatients = computed(() => {
const patients = stagePatients.value.pending || [];
console.log('🔍 useQueue - pendingPatients:', patients.length);
return patients;
});
const waitingPatients = computed(() => stagePatients.value.waiting || []);
// Pasien yang belum dipanggil (status "menunggu")
const menungguPatients = computed(() => stagePatients.value.menunggu || []);
const nextPatient = computed(() => {
// Prioritaskan pasien menunggu, baru waiting
return menungguPatients.value[0] || waitingPatients.value[0] || null;
});
// Total pasien hanya untuk stage admin ini
const totalPasien = computed(() => {
const total = queueStore.getTotalPasienByStage(adminType);
return total.value;
});
const quotaUsed = computed(() => queueStore.quotaUsed);
// Expose dev helper to refresh seed data
const resetPatients = () => queueStore.resetPatients();
// Filtered lists
const filteredKliniks = computed(() => {
if (!klinikSearch.value) return queueStore.kliniks;
return queueStore.kliniks.filter((k) =>
k.name.toLowerCase().includes(klinikSearch.value.toLowerCase())
);
});
const filteredPenunjangs = computed(() => {
if (!penunjangSearch.value) return queueStore.penunjangs;
return queueStore.penunjangs.filter((p) =>
p.name.toLowerCase().includes(penunjangSearch.value.toLowerCase())
);
});
const filteredChangeKliniks = computed(() => {
if (!changeKlinikSearch.value) return queueStore.kliniks;
return queueStore.kliniks.filter((k) =>
k.name.toLowerCase().includes(changeKlinikSearch.value.toLowerCase())
);
});
// Methods
const showSnackbar = (text, color = "success") => {
snackbarText.value = text;
snackbarColor.value = color;
snackbar.value = true;
};
const callNext = () => {
const result = queueStore.callNext(adminType);
showSnackbar(result.message, result.success ? "success" : "warning");
};
const callMultiplePatients = (count) => {
const result = queueStore.callMultiplePatients(count, adminType);
showSnackbar(result.message, result.success ? "success" : "warning");
};
const processPatient = (patient, action) => {
const result = queueStore.processPatient(patient, action, adminType);
let color = "success";
if (action === "terlambat") color = "warning";
else if (action === "pending") color = "info";
showSnackbar(result.message, color);
};
// Helper function untuk mendapatkan pasien yang sedang diproses dari store
const getCurrentProcessingPatientFromStore = () => {
try {
const processingPatient = queueStore.currentProcessingPatient?.[adminType];
if (!processingPatient) return null;
// Dapatkan data terbaru dari allPatients langsung (bukan dari getPatientsByStage yang sudah difilter)
// allPatients adalah ref yang di-export dari Pinia store, bisa diakses langsung atau dengan .value
// Coba akses langsung dulu, jika undefined baru coba dengan .value
let allPatients = [];
if (queueStore.allPatients) {
// Jika allPatients adalah ref (punya .value)
allPatients = Array.isArray(queueStore.allPatients)
? queueStore.allPatients
: (queueStore.allPatients.value || []);
}
// Cari pasien berdasarkan no, barcode, atau noAntrian
const latestPatient = allPatients.find(
p => (p && p.no === processingPatient.no) ||
(p && p.barcode && p.barcode === processingPatient.barcode) ||
(p && p.noAntrian && p.noAntrian === processingPatient.noAntrian)
);
// Jika ditemukan, return data terbaru, jika tidak return data dari currentProcessingPatient
return latestPatient || processingPatient;
} catch (error) {
console.error('Error in getCurrentProcessingPatientFromStore:', error);
// Fallback: return processingPatient dari store jika ada
return queueStore.currentProcessingPatient?.[adminType] || null;
}
};
const selectKlinik = (klinik) => {
// Pastikan currentProcessingPatient valid, jika tidak, coba dapatkan dari store
let patient = currentProcessingPatient.value || getCurrentProcessingPatientFromStore();
if (!patient) {
showSnackbar("Tidak ada pasien yang sedang diproses", "error");
showKlinikDialog.value = false;
return;
}
const result = queueStore.createAntreanKlinik(klinik, patient, adminType);
showSnackbar(result.message, "success");
showKlinikDialog.value = false;
};
const selectPenunjang = (penunjang) => {
// Pastikan currentProcessingPatient valid, jika tidak, coba dapatkan dari store
let patient = currentProcessingPatient.value || getCurrentProcessingPatientFromStore();
if (!patient) {
showSnackbar("Tidak ada pasien yang sedang diproses", "error");
showPenunjangDialog.value = false;
selectedPatientForPenunjang.value = null;
return;
}
const result = queueStore.createAntreanPenunjang(
penunjang,
patient,
adminType
);
showSnackbar(result.message, "success");
showPenunjangDialog.value = false;
selectedPatientForPenunjang.value = null;
};
const openPenunjangDialog = (patient = null) => {
selectedPatientForPenunjang.value = patient;
showPenunjangDialog.value = true;
};
const changeKlinik = (klinik) => {
// Pastikan currentProcessingPatient valid, jika tidak, coba dapatkan dari store
let patient = currentProcessingPatient.value || getCurrentProcessingPatientFromStore();
if (!patient) {
showSnackbar("Tidak ada pasien yang sedang diproses", "error");
showChangeKlinikDialog.value = false;
return;
}
const result = queueStore.changeKlinik(
patient,
klinik,
adminType
);
showSnackbar(result.message, result.success ? "success" : "error");
showChangeKlinikDialog.value = false;
};
const processNextQueue = () => {
const result = queueStore.processNextQueue(adminType);
showSnackbar(result.message, result.success ? "success" : "warning");
};
const getRowClass = (item) => {
if (item.status === "current") {
return "text-success font-weight-bold";
}
return "";
};
return {
// State
snackbar,
snackbarText,
snackbarColor,
showKlinikDialog,
showPenunjangDialog,
showChangeKlinikDialog,
klinikSearch,
penunjangSearch,
changeKlinikSearch,
selectedPatientForPenunjang,
// Computed
currentProcessingPatient,
diLoketPatients,
terlambatPatients,
pendingPatients,
waitingPatients,
menungguPatients,
nextPatient,
totalPasien,
quotaUsed,
filteredKliniks,
filteredPenunjangs,
filteredChangeKliniks,
stagePatients,
// Methods
showSnackbar,
callNext,
callMultiplePatients,
processPatient,
selectKlinik,
selectPenunjang,
openPenunjangDialog,
changeKlinik,
processNextQueue,
getRowClass,
};
};