// stores/loketStore.js import { defineStore } from 'pinia'; import { ref, computed } from 'vue'; import { useClinicStore } from './clinicStore'; import { useAnjunganStore } from './anjunganStore'; // Helper function: Convert nomor loket ke huruf (1 -> A, 2 -> B, dst) const numberToLetter = (num) => { if (num < 1) return 'A'; // 1 -> A (65), 2 -> B (66), ..., 26 -> Z (90) const charCode = 64 + num; // 64 = '@', 65 = 'A' return String.fromCharCode(Math.min(charCode, 90)); // Maksimal Z (90) }; // Helper function: Get pelayanan contoh dari master anjungan // Mengambil data klinik dari anjungan pertama (Reguler) sebagai contoh const getPelayananContohDariAnjungan = (anjunganItems) => { // Ambil data klinik dari anjungan pertama (Reguler) jika ada let klinikAnjunganReguler = []; if (anjunganItems && anjunganItems.length > 0) { // Cari anjungan dengan jenisPasien 'Reguler' atau ambil yang pertama const anjunganReguler = anjunganItems.find(a => a.jenisPasien === 'Reguler') || anjunganItems[0]; klinikAnjunganReguler = anjunganReguler.klinik || []; } // Jika tidak ada data dari anjungan, gunakan data default dari master anjungan if (klinikAnjunganReguler.length === 0) { klinikAnjunganReguler = ['AN', 'AS', 'BD', 'GR', 'HO', 'GI', 'GZ', 'IP', 'JT', 'JW', 'KK', 'MT', 'OB', 'PR', 'RT', 'RM', 'SR']; } // Distribusi pelayanan ke beberapa loket sebagai contoh // Menggunakan data klinik yang tersedia dari master anjungan return { loket1: klinikAnjunganReguler.filter(k => ['AN','RT', 'RM', 'TD'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['RT', 'RM', 'TD'].includes(k)) : klinikAnjunganReguler.slice(0, 3), // Ambil 3 pertama jika tidak ada match loket2: klinikAnjunganReguler.filter(k => ['JW', 'SR'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['JW', 'SR'].includes(k)) : klinikAnjunganReguler.slice(3, 5), // Ambil 2 berikutnya loket3: klinikAnjunganReguler.filter(k => ['AS', 'JT'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['AS', 'JT'].includes(k)) : klinikAnjunganReguler.slice(5, 7), // Ambil 2 berikutnya loket4: klinikAnjunganReguler.filter(k => ['KK', 'PR'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['KK', 'PR'].includes(k)) : klinikAnjunganReguler.slice(7, 9), // Ambil 2 berikutnya loket5: klinikAnjunganReguler.filter(k => ['BD', 'GI'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['BD', 'GI'].includes(k)) : klinikAnjunganReguler.slice(9, 11), // Ambil 2 berikutnya loket6: klinikAnjunganReguler.filter(k => ['GR', 'GZ'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['GR', 'GZ'].includes(k)) : klinikAnjunganReguler.slice(11, 13), // Ambil 2 berikutnya loket7: klinikAnjunganReguler.filter(k => ['IP', 'MT'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['IP', 'MT'].includes(k)) : klinikAnjunganReguler.slice(13, 15), // Ambil 2 berikutnya loket8: klinikAnjunganReguler.filter(k => ['OB', 'HO'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['OB', 'HO'].includes(k)) : klinikAnjunganReguler.slice(15, 17), // Ambil 2 berikutnya loket9: klinikAnjunganReguler.filter(k => ['AN', 'BD'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['AN', 'BD'].includes(k)) : klinikAnjunganReguler.slice(0, 2), // Ambil 2 pertama jika tidak ada match loket10: klinikAnjunganReguler.filter(k => ['GI', 'GZ'].includes(k)).length > 0 ? klinikAnjunganReguler.filter(k => ['GI', 'GZ'].includes(k)) : klinikAnjunganReguler.slice(2, 4), // Ambil 2 berikutnya }; }; export const useLoketStore = defineStore('loket', () => { const clinicStore = useClinicStore(); const anjunganStore = useAnjunganStore(); // Get pelayanan contoh dari master anjungan secara dinamis // Menggunakan computed untuk mendapatkan data terbaru dari anjunganStore const getPelayananContoh = () => { // getAllAnjungan adalah computed yang mengembalikan anjunganItems.value // Jadi langsung akses tanpa .value karena computed sudah handle itu try { const anjunganItems = anjunganStore.getAllAnjungan || []; return getPelayananContohDariAnjungan(anjunganItems); } catch { // Fallback jika store belum terinisialisasi console.warn('AnjunganStore belum terinisialisasi, menggunakan data default'); return getPelayananContohDariAnjungan([]); } }; // Inisialisasi data loket dengan pelayanan dari master anjungan // Data akan diupdate saat store diinisialisasi const initLoketData = () => { const pelayananContoh = getPelayananContoh(); // Base loket (A-J) dengan pelayanan dari contoh const baseLoket = [ { id: 1, no: 1, namaLoket: "Loket A", kuota: 500, pelayanan: pelayananContoh.loket1, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 2, no: 2, namaLoket: "Loket B", kuota: 666, pelayanan: pelayananContoh.loket2, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 3, no: 3, namaLoket: "Loket C", kuota: 666, pelayanan: pelayananContoh.loket3, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 4, no: 4, namaLoket: "Loket D", kuota: 3676, pelayanan: pelayananContoh.loket4, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 5, no: 5, namaLoket: "Loket E", kuota: 500, pelayanan: pelayananContoh.loket5, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 6, no: 6, namaLoket: "Loket F", kuota: 500, pelayanan: pelayananContoh.loket6, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 7, no: 7, namaLoket: "Loket G", kuota: 500, pelayanan: pelayananContoh.loket7, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 8, no: 8, namaLoket: "Loket H", kuota: 500, pelayanan: pelayananContoh.loket8, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 9, no: 9, namaLoket: "Loket I", kuota: 500, pelayanan: pelayananContoh.loket9, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 10, no: 10, namaLoket: "Loket J", kuota: 500, pelayanan: pelayananContoh.loket10, // Dari master anjungan pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, ]; return baseLoket; }; // State - Loket Data // Data pelayanan diambil dari contoh master anjungan const initialData = initLoketData(); // Initialize with default data, will be overridden by persisted data if exists const loketData = ref(initialData); // After store is created, check if data needs migration // This runs after Pinia restores from localStorage // If loketData has less than 10 items, reinitialize with default data (A-J) if (loketData.value && loketData.value.length < 10) { loketData.value = initialData; } // Computed - Available services (reference dari clinicStore) // Mengambil data dari clinicStore untuk dropdown pelayanan // Menggunakan getAllClinics computed untuk memastikan reactivity const availableServices = computed(() => { try { // Gunakan getAllClinics computed dari clinicStore // Ini akan otomatis reactive ketika clinics berubah const clinicsComputed = clinicStore.getAllClinics; if (!clinicsComputed) { console.warn('clinicStore.getAllClinics is not available'); return []; } // getAllClinics adalah computed, akses .value untuk mendapatkan array // Vue akan otomatis track dependency ini const clinicsArray = clinicsComputed.value || []; // Pastikan clinicsArray adalah array if (!Array.isArray(clinicsArray)) { console.warn('getAllClinics.value is not an array:', typeof clinicsArray, clinicsArray); return []; } if (clinicsArray.length === 0) { console.warn('No clinics available from clinicStore'); return []; } // Map ke format yang dibutuhkan form: { id, nama, kode } // id menggunakan kode untuk kompatibilitas dengan form yang menggunakan item-value="id" return clinicsArray.map(c => { if (!c || !c.kode || !c.name) { console.warn('Invalid clinic data:', c); return null; } return { id: c.kode, // Menggunakan kode sebagai id (sesuai dengan item-value="id" di form) nama: c.name, kode: c.kode, }; }).filter(Boolean); // Filter out null values } catch (error) { console.error('Error getting available services from clinicStore:', error); return []; } }); // Actions - CRUD Operations const addLoket = (loketPayload) => { const newId = Math.max(...loketData.value.map(l => l.id), 0) + 1; const newNo = loketData.value.length + 1; // Jika namaLoket tidak disediakan atau masih menggunakan angka, ubah ke huruf let namaLoket = loketPayload.namaLoket; if (!namaLoket || namaLoket.match(/Loket \d+/)) { const letter = numberToLetter(newNo); namaLoket = `Loket ${letter}`; } const newLoket = { id: newId, no: newNo, ...loketPayload, namaLoket: namaLoket, }; loketData.value.push(newLoket); return { success: true, message: `Loket ${newLoket.namaLoket} berhasil ditambahkan`, data: newLoket }; }; const updateLoket = (loketPayload) => { const index = loketData.value.findIndex(l => l.id === loketPayload.id); if (index !== -1) { loketData.value[index] = { ...loketData.value[index], ...loketPayload, }; return { success: true, message: `Loket ${loketPayload.namaLoket} berhasil diupdate` }; } return { success: false, message: 'Loket tidak ditemukan' }; }; const deleteLoket = (loketId) => { const index = loketData.value.findIndex(l => l.id === loketId); if (index !== -1) { const loketName = loketData.value[index].namaLoket; loketData.value.splice(index, 1); loketData.value.forEach((l, idx) => { l.no = idx + 1; }); return { success: true, message: `Loket ${loketName} berhasil dihapus` }; } return { success: false, message: 'Loket tidak ditemukan' }; }; const getLoketById = (id) => { return loketData.value.find(l => l.id === id); }; // Helper function untuk convert nomor ke huruf (export untuk digunakan di komponen) const getLoketLetter = (num) => numberToLetter(num); return { // State loketData, availableServices, // Actions addLoket, updateLoket, deleteLoket, getLoketById, getLoketLetter, }; }, { persist: { key: 'loket-store-state', storage: typeof window !== 'undefined' ? localStorage : undefined, paths: ['loketData'], serializer: { deserialize: JSON.parse, serialize: JSON.stringify, }, restore: (value) => { // Ensure loketData is always an array if (value && value.loketData && !Array.isArray(value.loketData)) { value.loketData = []; } // If restored data has less than 10 lokets, reinitialize with default data (A-J) if (value && value.loketData && Array.isArray(value.loketData) && value.loketData.length < 10) { // Reinitialize with default data (A-J) - this will happen on next store initialization // For now, we'll let the store initialization handle it value.loketData = null; // Force reinitialization } return value; }, }, });