128 lines
3.7 KiB
JavaScript
128 lines
3.7 KiB
JavaScript
// stores/doctorStore.js
|
|
import { defineStore } from 'pinia';
|
|
import { ref } from 'vue';
|
|
|
|
export const useDoctorStore = defineStore('doctor', () => {
|
|
const doctorsByKlinikId = ref({});
|
|
const lastSyncTimestamp = ref(null);
|
|
const loadingDoctors = ref({});
|
|
|
|
/**
|
|
* Check if sync is needed based on 2 AM schedule
|
|
*/
|
|
const isSyncNeeded = () => {
|
|
if (!lastSyncTimestamp.value) return true;
|
|
|
|
const now = new Date();
|
|
const lastSync = new Date(lastSyncTimestamp.value);
|
|
|
|
// Create a 2 AM today date
|
|
const today2AM = new Date(now);
|
|
today2AM.setHours(2, 0, 0, 0);
|
|
|
|
// If last sync was before 2 AM today, and it's already past 2 AM today, we need to sync
|
|
if (lastSync < today2AM && now >= today2AM) {
|
|
return true;
|
|
}
|
|
|
|
// If last sync was on a different day and it's before 2 AM, but more than 24h passed
|
|
// (This is a safety check for long-running sessions)
|
|
const diffInHours = (now - lastSync) / (1000 * 60 * 60);
|
|
if (diffInHours > 24) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Fetch doctors for a clinic from API
|
|
*/
|
|
const fetchDoctorsForClinic = async (clinic, force = false) => {
|
|
if (!clinic || !clinic.id) return;
|
|
|
|
const idklinik = clinic.id;
|
|
|
|
// Skip if already in cache and not forced, and sync not needed
|
|
if (!force && doctorsByKlinikId.value[idklinik] && !isSyncNeeded()) {
|
|
return doctorsByKlinikId.value[idklinik];
|
|
}
|
|
|
|
// Skip if already loading
|
|
if (loadingDoctors.value[idklinik]) {
|
|
return;
|
|
}
|
|
|
|
loadingDoctors.value[idklinik] = true;
|
|
|
|
try {
|
|
console.log(`🔄 [doctorStore] Fetching doctors for klinik ID: ${idklinik} (${clinic.name})`);
|
|
const data = await $fetch(
|
|
`http://10.10.150.131:8089/api/v1/dokter/${idklinik}`
|
|
);
|
|
|
|
let doctorList = [];
|
|
if (Array.isArray(data)) {
|
|
doctorList = data;
|
|
} else if (data && typeof data === 'object') {
|
|
if (Array.isArray(data.data)) {
|
|
doctorList = data.data;
|
|
} else if (Array.isArray(data.result)) {
|
|
doctorList = data.result;
|
|
}
|
|
}
|
|
|
|
const doctorNames = doctorList
|
|
.map((d) => d.nama_dokter || d.nama_lengkap || d.Nama_dokter || d.name || d.nama)
|
|
.filter(Boolean);
|
|
|
|
doctorsByKlinikId.value[idklinik] = doctorNames;
|
|
|
|
// Update sync timestamp if this was a refresh
|
|
if (force) {
|
|
lastSyncTimestamp.value = new Date().toISOString();
|
|
}
|
|
|
|
console.log(`✅ [doctorStore] Loaded ${doctorNames.length} doctors untuk klinik ${clinic.name}`);
|
|
return doctorNames;
|
|
} catch (error) {
|
|
console.error(`❌ [doctorStore] Gagal mengambil dokter untuk klinik ID ${idklinik}:`, error);
|
|
// Don't overwrite existing data on failure unless it's empty
|
|
if (!doctorsByKlinikId.value[idklinik]) {
|
|
doctorsByKlinikId.value[idklinik] = [];
|
|
}
|
|
} finally {
|
|
loadingDoctors.value[idklinik] = false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Sync doctors for all provided clinics
|
|
*/
|
|
const syncAllDoctors = async (clinics) => {
|
|
console.log(`🔄 [doctorStore] Syncing all doctors for ${clinics.length} clinics...`);
|
|
|
|
// Filter clinics that need sync (only Reguler clinics usually have dynamic doctors)
|
|
const clinicsToSync = clinics.filter(c => c.id);
|
|
|
|
await Promise.all(clinicsToSync.map(c => fetchDoctorsForClinic(c, true)));
|
|
|
|
lastSyncTimestamp.value = new Date().toISOString();
|
|
console.log(`✅ [doctorStore] Global doctor sync complete at ${lastSyncTimestamp.value}`);
|
|
};
|
|
|
|
return {
|
|
doctorsByKlinikId,
|
|
lastSyncTimestamp,
|
|
loadingDoctors,
|
|
fetchDoctorsForClinic,
|
|
syncAllDoctors,
|
|
isSyncNeeded
|
|
};
|
|
}, {
|
|
persist: {
|
|
key: 'doctor-store',
|
|
pick: ['doctorsByKlinikId', 'lastSyncTimestamp']
|
|
}
|
|
});
|