update WS admin loket dan checkin

This commit is contained in:
Fanrouver
2026-02-11 09:34:42 +07:00
parent c02905e954
commit a7a654b72a
5 changed files with 153 additions and 31 deletions
+97 -17
View File
@@ -20,8 +20,42 @@ export const useQueueStore = defineStore('queue', () => {
const isLoadingPatients = ref(false);
const apiPatientsError = ref(null);
// Scoped Refresh Logic: track which lokets are currently being viewed
const activeLoketInterest = ref({}); // { [loketId]: count }
const globalInterestCount = ref(0); // Tracks pages that need ALL loket data (e.g. CheckInPasien)
const registerInterest = (loketId) => {
if (!loketId) return;
const id = String(loketId);
activeLoketInterest.value[id] = (activeLoketInterest.value[id] || 0) + 1;
console.log(`🔌 [queueStore] Registered interest in Loket ${id}. Active:`, activeLoketInterest.value);
};
const unregisterInterest = (loketId) => {
if (!loketId) return;
const id = String(loketId);
if (activeLoketInterest.value[id]) {
activeLoketInterest.value[id] = Math.max(0, activeLoketInterest.value[id] - 1);
if (activeLoketInterest.value[id] === 0) {
delete activeLoketInterest.value[id];
}
}
console.log(`🔌 [queueStore] Unregistered interest in Loket ${id}. Active:`, activeLoketInterest.value);
};
const registerGlobalInterest = () => {
globalInterestCount.value++;
console.log(`🌐 [queueStore] Global interest registered. Total: ${globalInterestCount.value}`);
};
const unregisterGlobalInterest = () => {
globalInterestCount.value = Math.max(0, globalInterestCount.value - 1);
console.log(`🌐 [queueStore] Global interest unregistered. Total: ${globalInterestCount.value}`);
};
// Throttle mechanism: track last fetch time per loket
const lastFetchTime = ref({});
const lastGlobalFetchTime = ref(0); // Cooldown for bulk refreshes
// Synchronization Guard: track last update time to break loops across tabs
const lastUpdated = ref(Date.now());
@@ -68,18 +102,36 @@ export const useQueueStore = defineStore('queue', () => {
isWsConnected.value = false;
},
onMessage: (data) => {
console.log('📨 [queueStore] Global WS Message:', data);
console.log('📨 [queueStore] Global WS Message received:', data);
// TRIGGER STRATEGIC REFRESHES
// 1. Refetch patients for all active lokets in the store
Object.keys(apiPatientsPerLoket.value).forEach(loketId => {
fetchPatientsForLoket(loketId);
});
const messageData = data?.data || data;
const targetLoketId = messageData?.loketId || messageData?.idloket;
// 2. Refetch clinics to update quotas/availability
if (targetLoketId) {
// 1. If message specifies a loket, refresh that one specifically
console.log(`🎯 [queueStore] WS targeting Loket ${targetLoketId}: Refreshing...`);
fetchPatientsForLoket(targetLoketId);
} else if (globalInterestCount.value > 0) {
// 2. If it's a generic message and we have global interest (Check-in page open)
// Trigger bulk staggered refresh
console.log(`📡 [queueStore] WS generic message: Global Interest active, triggering staggered bulk refresh...`);
fetchAllPatients();
} else {
// 3. Otherwise, only refresh lokets that currently have active interest (Admin tabs open)
const interestingLokets = Object.keys(activeLoketInterest.value);
if (interestingLokets.length > 0) {
console.log(`🌐 [queueStore] WS generic message: Refreshing ${interestingLokets.length} active lokets:`, interestingLokets);
interestingLokets.forEach(loketId => {
fetchPatientsForLoket(loketId);
});
} else {
console.log(`🔕 [queueStore] WS generic message: No active interest, skipping bulk refresh.`);
}
}
// 4. Base data sync
clinicStore.fetchRegulerClinics();
// 3. Ensure base data is synced
ensureInitialData();
}
});
@@ -450,17 +502,40 @@ export const useQueueStore = defineStore('queue', () => {
/**
* Global fetcher for all patients across all available lokets
*/
const fetchAllPatients = async () => {
console.log('🔄 [queueStore] Fetching all patients for all lokets...');
/**
* Global fetcher for all patients across all available lokets
* Uses staggered fetching to prevent 429 Too Many Requests errors.
*/
const fetchAllPatients = async (force = false) => {
// 1. Cooldown Check: Prevent global refresh spam (max once every 5 seconds)
const now = Date.now();
if (!force && now - lastGlobalFetchTime.value < 5000) {
console.log(`⏭️ [queueStore] fetchAllPatients: Global refresh on cooldown (${Math.round((now - lastGlobalFetchTime.value)/1000)}s ago)`);
return;
}
lastGlobalFetchTime.value = now;
console.log('🔄 [queueStore] Fetching all patients for all lokets (Staggered)...');
const allLokets = loketStore.lokets || [];
if (allLokets.length === 0) {
console.warn('⚠️ [queueStore] No lokets available for fetchAllPatients');
return;
}
// Use Promise.all for faster fetching
await Promise.all(allLokets.map(l => fetchPatientsForLoket(l.id)));
console.log(`✅ [queueStore] All patients fetched. Total: ${allPatients.value.length}`);
// 2. Staggered Fetch: Instead of Promise.all, we fetch one by one with a small delay
// This spreads the load and stays under the 429 threshold
for (const loket of allLokets) {
const id = loket.id || loket.no;
if (id) {
// We use await to wait for the fetch to finish, then wait a bit more
await fetchPatientsForLoket(id);
// Wait 150ms between requests (not too long, but enough to breathe)
await new Promise(resolve => setTimeout(resolve, 150));
}
}
console.log(`✅ [queueStore] Staggered bulk fetch completed. Total: ${allPatients.value.length} patients in memory.`);
};
/**
@@ -810,11 +885,11 @@ export const useQueueStore = defineStore('queue', () => {
// For example: { 'loket-1': patient, 'loket-2': patient, 'klinik-3': patient }
const currentProcessingPatient = ref({});
// Daftar klinik untuk dropdown diambil 1 pintu dari clinicStore
const kliniks = ref(clinicStore.clinics || []);
// Daftar klinik untuk dropdown diambil 1 pintu dari clinicStore (Computed for stability)
const kliniks = computed(() => clinicStore.clinics || []);
// Penunjang data - reference dari penunjangStore
const penunjangs = ref(penunjangStore.penunjangs || []);
// Penunjang data - reference dari penunjangStore (Computed for stability)
const penunjangs = computed(() => penunjangStore.penunjangList || []);
const RESET_HOUR = 2; // 2 AM reset threshold
@@ -2582,6 +2657,11 @@ export const useQueueStore = defineStore('queue', () => {
initWebSocket,
disconnectWebSocket,
isWsConnected,
registerInterest,
unregisterInterest,
activeLoketInterest,
registerGlobalInterest,
unregisterGlobalInterest,
};
}, {