push update admin loket

This commit is contained in:
Fanrouver
2026-01-27 15:21:42 +07:00
parent 083fe3e364
commit f6060451c0
10 changed files with 1138 additions and 832 deletions
+78 -11
View File
@@ -1,9 +1,18 @@
// composables/useQueue.js
import { ref, computed } from "vue";
import { useQueueStore } from "../stores/queueStore";
import { useLoketStore } from "../stores/loketStore";
export const useQueue = (adminType = "loket") => {
export const useQueue = (adminType = "loket", specificId = null) => {
const queueStore = useQueueStore();
const loketStore = useLoketStore();
// Normalize specificId to a reactive value
const idValue = computed(() => {
if (typeof specificId === 'function') return specificId();
if (specificId && typeof specificId === 'object' && 'value' in specificId) return specificId.value;
return specificId;
});
// Local state
const snackbar = ref(false);
@@ -26,9 +35,10 @@ export const useQueue = (adminType = "loket") => {
return patients.value;
});
// Computed from store - filtered by stage
// Computed from store - isolated by specificId if provided
const currentProcessingPatient = computed(() => {
return queueStore.currentProcessingPatient[adminType];
const key = idValue.value ? `${adminType}-${idValue.value}` : adminType;
return queueStore.currentProcessingPatient[key];
});
// Derive from stagePatients - ADD DEBUG LOGS
@@ -70,7 +80,61 @@ export const useQueue = (adminType = "loket") => {
return total.value;
});
const quotaUsed = computed(() => queueStore.quotaUsed);
// Helper to check if a patient is relevant to the current admin view
const isPatientRelevant = (p) => {
if (p.processStage !== adminType) return false;
const targetId = idValue.value;
if (!targetId) return true; // No specific ID, show all for this stage
if (adminType === 'loket') {
const thisLoket = loketStore.getLoketById(parseInt(targetId));
if (!thisLoket) return String(p.loketId) === String(targetId);
// Must be assigned to this loket OR unassigned but clinic is served by this loket
const isAssignedToThis = p.loketId && String(p.loketId) === String(targetId);
const isServedByThis = !p.loketId && thisLoket.pelayanan && Array.isArray(thisLoket.pelayanan) && thisLoket.pelayanan.includes(p.kodeKlinik);
// User requested "match loket id AND klinik id" logic for calling?
// Actually, "match loket and clinic" usually means:
// if it has a clinic, it must be in our services.
// let's be strict: clinic must ALWAYS be in services if loketId is specified
if (thisLoket.pelayanan && Array.isArray(thisLoket.pelayanan)) {
if (!thisLoket.pelayanan.includes(p.kodeKlinik)) return false;
}
return isAssignedToThis || isServedByThis;
}
if (adminType === 'klinik') {
// Filter by clinic code or clinic name
return String(p.kodeKlinik) === String(targetId) || String(p.klinik) === String(targetId);
}
if (adminType === 'penunjang') {
// Penunjang usually uses clinic name as the identifier in seeds
return String(p.klinik) === String(targetId) || String(p.kodeKlinik) === String(targetId);
}
return true;
};
// 1. Menunggu Count (Backlog ONLY - Strictly status 'menunggu')
const menungguCount = computed(() => {
let list = menungguPatients.value || [];
return list.filter(isPatientRelevant).length;
});
// 2. Calculated Quota Used (Dynamic - any ticket NOT 'menunggu' counts as used)
const calculatedQuotaUsed = computed(() => {
const list = queueStore.allPatients || [];
return list.filter(p => {
if (!isPatientRelevant(p)) return false;
// Status is NOT 'menunggu' (meaning it's being served or finished)
return p.status !== 'menunggu';
}).length;
});
const quotaUsed = computed(() => calculatedQuotaUsed.value);
// Expose dev helper to refresh seed data
const resetPatients = () => queueStore.resetPatients();
@@ -104,18 +168,20 @@ export const useQueue = (adminType = "loket") => {
snackbar.value = true;
};
const callNext = () => {
const result = queueStore.callNext(adminType);
const callNext = (specificIdOverride = null) => {
const targetId = specificIdOverride || idValue.value;
const result = queueStore.callNext(adminType, targetId);
showSnackbar(result.message, result.success ? "success" : "warning");
};
const callMultiplePatients = (count) => {
const result = queueStore.callMultiplePatients(count, adminType);
const callMultiplePatients = (count, specificIdOverride = null) => {
const targetId = specificIdOverride || idValue.value;
const result = queueStore.callMultiplePatients(count, adminType, targetId);
showSnackbar(result.message, result.success ? "success" : "warning");
};
const processPatient = (patient, action) => {
const result = queueStore.processPatient(patient, action, adminType);
const result = queueStore.processPatient(patient, action, adminType, idValue.value);
let color = "success";
if (action === "terlambat") color = "warning";
@@ -127,7 +193,8 @@ export const useQueue = (adminType = "loket") => {
// Helper function untuk mendapatkan pasien yang sedang diproses dari store
const getCurrentProcessingPatientFromStore = () => {
try {
const processingPatient = queueStore.currentProcessingPatient?.[adminType];
const key = idValue.value ? `${adminType}-${idValue.value}` : adminType;
const processingPatient = queueStore.currentProcessingPatient?.[key];
if (!processingPatient) return null;
// Dapatkan data terbaru dari allPatients langsung (bukan dari getPatientsByStage yang sudah difilter)
@@ -218,7 +285,7 @@ export const useQueue = (adminType = "loket") => {
};
const processNextQueue = () => {
const result = queueStore.processNextQueue(adminType);
const result = queueStore.processNextQueue(adminType, idValue.value);
showSnackbar(result.message, result.success ? "success" : "warning");
};