// stores/masterStore.js - Integrated dengan Penunjang import { defineStore } from 'pinia'; import { ref, computed } from 'vue'; import { useClinicStore } from './clinicStore'; export const useMasterStore = defineStore('master', () => { // Store referensi utama daftar klinik (single source of truth) const clinicStore = useClinicStore(); // ============================================ // MASTER KLINIK // ============================================ const klinikData = ref([ { id: 1, no: 1, kode: 'AN', nama: 'ANAK', shift: 1, totalQuota: 1000, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 1000 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu', 'Jumat'], }, { id: 2, no: 2, kode: 'AS', nama: 'ANESTESI', shift: 2, totalQuota: 1500, jamShiftList: [ { dari: '07:00', sampai: '11:00', kuota: 1000 }, { dari: '13:00', sampai: '16:00', kuota: 500 } ], autoShift: false, jadwalKlinik: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at'], }, { id: 3, no: 3, kode: 'BD', nama: 'BEDAH', shift: 1, totalQuota: 800, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 800 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu', 'Jumat'], }, { id: 4, no: 4, kode: 'GI', nama: 'GIGI DAN MULUT', shift: 3, totalQuota: 2100, jamShiftList: [ { dari: '07:00', sampai: '11:00', kuota: 1000 }, { dari: '13:00', sampai: '16:00', kuota: 700 }, { dari: '18:00', sampai: '20:00', kuota: 400 } ], autoShift: true, jadwalKlinik: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at'], }, { id: 5, no: 5, kode: 'GR', nama: 'GERIATRI', shift: 1, totalQuota: 600, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 600 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu'] }, { id: 6, no: 6, kode: 'GZ', nama: 'GIZI', shift: 1, totalQuota: 500, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 500 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu', 'Jumat'] }, { id: 7, no: 7, kode: 'HO', nama: 'HOM', shift: 1, totalQuota: 750, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 750 }], autoShift: false, jadwalKlinik: ['Senin', 'Selasa', 'Rabu'] }, { id: 8, no: 8, kode: 'IP', nama: 'IPD', shift: 1, totalQuota: 900, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 900 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu', 'Jumat'] }, { id: 9, no: 9, kode: 'JT', nama: 'JANTUNG', shift: 2, totalQuota: 1200, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 800 }, { dari: '13:00', sampai: '16:00', kuota: 400 }], autoShift: false, jadwalKlinik: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at'] }, { id: 10, no: 10, kode: 'JW', nama: 'JIWA', shift: 1, totalQuota: 700, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 700 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu'] }, { id: 11, no: 11, kode: 'KK', nama: 'KULIT KELAMIN', shift: 1, totalQuota: 600, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 600 }], autoShift: false, jadwalKlinik: ['Selasa', 'Kamis'] }, { id: 12, no: 12, kode: 'MT', nama: 'MATA', shift: 1, totalQuota: 800, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 800 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu', 'Jumat'] }, { id: 13, no: 13, kode: 'OB', nama: 'KANDUNGAN', shift: 2, totalQuota: 1000, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 600 }, { dari: '13:00', sampai: '16:00', kuota: 400 }], autoShift: false, jadwalKlinik: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at'] }, { id: 14, no: 14, kode: 'PR', nama: 'PARU', shift: 1, totalQuota: 700, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 700 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu'] }, { id: 15, no: 15, kode: 'RT', nama: 'RADIOTERAPI', shift: 1, totalQuota: 500, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 500 }], autoShift: false, jadwalKlinik: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at'] }, { id: 16, no: 16, kode: 'RM', nama: 'REHAB MEDIK', shift: 1, totalQuota: 600, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 600 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu', 'Jumat'] }, { id: 17, no: 17, kode: 'SR', nama: 'SARAF', shift: 1, totalQuota: 700, jamShiftList: [{ dari: '07:00', sampai: '11:00', kuota: 700 }], autoShift: false, jadwalKlinik: ['Senin', 'Rabu'] }, ]); // Computed - Get klinik list for dropdowns // Sumber data kode & nama klinik diambil dari clinicStore (1 pintu), // lalu difilter hanya untuk kode yang terdaftar di master klinik ini. const klinikList = computed(() => { const availableCodes = new Set(klinikData.value.map((k) => k.kode)); // getClinicsForDropdown() sudah mengembalikan { id, name, kode, icon, available } const baseList = typeof clinicStore.getClinicsForDropdown === 'function' ? clinicStore.getClinicsForDropdown() : []; return baseList .filter((c) => availableCodes.has(c.kode)) .map((c) => ({ id: c.id, kode: c.kode, nama: c.name, })); }); // Actions - Klinik const addKlinik = (klinikPayload) => { const newId = Math.max(...klinikData.value.map(k => k.id), 0) + 1; const newNo = klinikData.value.length + 1; const totalQuota = klinikPayload.jamShiftList.reduce((total, shift) => { return total + (parseInt(shift.kuota) || 0); }, 0); const newKlinik = { id: newId, no: newNo, ...klinikPayload, totalQuota: totalQuota, }; klinikData.value.push(newKlinik); return { success: true, message: `Klinik ${newKlinik.nama} berhasil ditambahkan`, data: newKlinik }; }; const updateKlinik = (klinikPayload) => { const index = klinikData.value.findIndex(k => k.id === klinikPayload.id); if (index !== -1) { const totalQuota = klinikPayload.jamShiftList.reduce((total, shift) => { return total + (parseInt(shift.kuota) || 0); }, 0); klinikData.value[index] = { ...klinikData.value[index], ...klinikPayload, totalQuota: totalQuota, }; return { success: true, message: `Klinik ${klinikPayload.nama} berhasil diupdate` }; } return { success: false, message: 'Klinik tidak ditemukan' }; }; const deleteKlinik = (klinikId) => { const index = klinikData.value.findIndex(k => k.id === klinikId); if (index !== -1) { const klinikName = klinikData.value[index].nama; klinikData.value.splice(index, 1); klinikData.value.forEach((k, idx) => { k.no = idx + 1; }); return { success: true, message: `Klinik ${klinikName} berhasil dihapus` }; } return { success: false, message: 'Klinik tidak ditemukan' }; }; const getKlinikById = (id) => { return klinikData.value.find(k => k.id === id); }; const getKlinikByKode = (kode) => { return klinikData.value.find(k => k.kode === kode); }; // ============================================ // MASTER LOKET // ============================================ const loketData = ref([ { id: 1, no: 1, namaLoket: "Loket 1", kuota: 500, pelayanan: ["RT", "RM", "TD"], pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 2, no: 2, namaLoket: "Loket 2", kuota: 666, pelayanan: ["JW", "SR"], pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 3, no: 3, namaLoket: "Loket 3", kuota: 666, pelayanan: ["AS", "JT"], pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, { id: 4, no: 4, namaLoket: "Loket 4", kuota: 3676, pelayanan: ["KK", "PR"], pembayaran: "JKN", keterangan: "ONLINE", statusPelayanan: "RAWAT JALAN", }, ]); const availableServices = computed(() => klinikData.value.map(k => ({ id: k.kode, nama: k.nama, })) ); // Actions - Loket const addLoket = (loketPayload) => { const newId = Math.max(...loketData.value.map(l => l.id), 0) + 1; const newNo = loketData.value.length + 1; const newLoket = { id: newId, no: newNo, ...loketPayload, }; 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); }; // ============================================ // MASTER KLINIK RUANG // ============================================ const ruangData = ref([ { id: 1, no: 1, kodeKlinik: 'AN', namaKlinik: 'ANAK', namaRuang: 'R. TINDAKAN', ruangList: [ { nomorRuang: '1', namaRuang: 'R. TINDAKAN', nomorScreen: '101' } ] }, { id: 2, no: 2, kodeKlinik: 'AS', namaKlinik: 'ANESTESI', namaRuang: 'Ruang 1, Ruang 2', ruangList: [ { nomorRuang: '1', namaRuang: 'Ruang 1', nomorScreen: '201' }, { nomorRuang: '2', namaRuang: 'Ruang 2', nomorScreen: '202' } ] }, { id: 3, no: 3, kodeKlinik: 'GI', namaKlinik: 'GIGI DAN MULUT', namaRuang: 'Ruang 1, Ruang 2, Ruang 3', ruangList: [ { nomorRuang: '1', namaRuang: 'Ruang 1', nomorScreen: '501' }, { nomorRuang: '2', namaRuang: 'Ruang 2', nomorScreen: '502' }, { nomorRuang: '3', namaRuang: 'Ruang 3', nomorScreen: '503' } ] }, ]); // Computed const totalKlinikRuang = computed(() => ruangData.value.length); const totalRuangan = computed(() => { return ruangData.value.reduce((total, klinik) => { return total + klinik.ruangList.length; }, 0); }); // Actions - Ruang const addRuang = (ruangPayload) => { const newId = Math.max(...ruangData.value.map(r => r.id), 0) + 1; const newNo = ruangData.value.length + 1; const namaRuangDisplay = ruangPayload.ruangList .map(r => r.namaRuang) .filter(n => n) .join(', '); const newRuang = { id: newId, no: newNo, ...ruangPayload, namaRuang: namaRuangDisplay, }; ruangData.value.push(newRuang); return { success: true, message: `Ruang klinik ${newRuang.namaKlinik} berhasil ditambahkan`, data: newRuang }; }; const updateRuang = (ruangPayload) => { const index = ruangData.value.findIndex(r => r.id === ruangPayload.id); if (index !== -1) { const namaRuangDisplay = ruangPayload.ruangList .map(r => r.namaRuang) .filter(n => n) .join(', '); ruangData.value[index] = { ...ruangData.value[index], ...ruangPayload, namaRuang: namaRuangDisplay, }; return { success: true, message: `Ruang klinik ${ruangPayload.namaKlinik} berhasil diupdate` }; } return { success: false, message: 'Ruang tidak ditemukan' }; }; const deleteRuang = (ruangId) => { const index = ruangData.value.findIndex(r => r.id === ruangId); if (index !== -1) { const ruangName = `${ruangData.value[index].namaKlinik} - ${ruangData.value[index].namaRuang}`; ruangData.value.splice(index, 1); ruangData.value.forEach((r, idx) => { r.no = idx + 1; }); return { success: true, message: `Ruang ${ruangName} berhasil dihapus` }; } return { success: false, message: 'Ruang tidak ditemukan' }; }; const getRuangByKlinik = (kodeKlinik) => { return ruangData.value.filter(r => r.kodeKlinik === kodeKlinik); }; // Get all ruang list (for antrian display) const getAllRuangList = computed(() => { const allRuang = []; ruangData.value.forEach(klinik => { klinik.ruangList.forEach(ruang => { allRuang.push({ kodeKlinik: klinik.kodeKlinik, namaKlinik: klinik.namaKlinik, ...ruang }); }); }); return allRuang; }); // ============================================ // MASTER PENUNJANG // ============================================ const penunjangData = ref([ { id: 1, no: 1, kode: 'LAB', nama: 'LABORATORIUM', jenis: 'Medis', shift: 3, totalQuota: 150, jamShiftList: [ { dari: '07:00', sampai: '15:00', kuota: 60 }, { dari: '13:00', sampai: '21:00', kuota: 50 }, { dari: '21:00', sampai: '07:00', kuota: 40 } ], autoShift: true, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at', 'Sabtu', 'Minggu'], status: 'Aktif', estimasiLayanan: 30, keterangan: 'Pemeriksaan darah lengkap, urine, dan pemeriksaan laboratorium lainnya' }, { id: 2, no: 2, kode: 'RAD', nama: 'RADIOLOGI', jenis: 'Medis', shift: 2, totalQuota: 100, jamShiftList: [ { dari: '07:00', sampai: '15:00', kuota: 60 }, { dari: '13:00', sampai: '21:00', kuota: 40 } ], autoShift: true, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at', 'Sabtu'], status: 'Aktif', estimasiLayanan: 45, keterangan: 'Rontgen, CT Scan, MRI, USG, dan pemeriksaan radiologi lainnya' }, { id: 3, no: 3, kode: 'PAT', nama: 'PATOLOGI ANATOMI', jenis: 'Medis', shift: 1, totalQuota: 50, jamShiftList: [ { dari: '07:00', sampai: '15:00', kuota: 50 } ], autoShift: false, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at'], status: 'Aktif', estimasiLayanan: 60, keterangan: 'Pemeriksaan jaringan dan sitologi' }, { id: 4, no: 4, kode: 'RHB', nama: 'REHABILITASI MEDIK', jenis: 'Medis', shift: 2, totalQuota: 80, jamShiftList: [ { dari: '07:00', sampai: '13:00', kuota: 40 }, { dari: '13:00', sampai: '19:00', kuota: 40 } ], autoShift: true, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at'], status: 'Aktif', estimasiLayanan: 30, keterangan: 'Fisioterapi, terapi okupasi, dan terapi wicara' }, { id: 5, no: 5, kode: 'RME', nama: 'REKAM MEDIS', jenis: 'Non-Medis', shift: 2, totalQuota: 120, jamShiftList: [ { dari: '07:00', sampai: '15:00', kuota: 70 }, { dari: '13:00', sampai: '21:00', kuota: 50 } ], autoShift: true, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at', 'Sabtu'], status: 'Aktif', estimasiLayanan: 15, keterangan: 'Pengurusan dokumen rekam medis dan surat keterangan' }, { id: 6, no: 6, kode: 'GIZ', nama: 'GIZI', jenis: 'Non-Medis', shift: 2, totalQuota: 60, jamShiftList: [ { dari: '07:00', sampai: '13:00', kuota: 30 }, { dari: '13:00', sampai: '19:00', kuota: 30 } ], autoShift: true, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at'], status: 'Aktif', estimasiLayanan: 20, keterangan: 'Konsultasi gizi dan diet' }, { id: 7, no: 7, kode: 'LND', nama: 'LAUNDRY', jenis: 'Non-Medis', shift: 3, totalQuota: 200, jamShiftList: [ { dari: '06:00', sampai: '14:00', kuota: 80 }, { dari: '14:00', sampai: '22:00', kuota: 70 }, { dari: '22:00', sampai: '06:00', kuota: 50 } ], autoShift: true, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at', 'Sabtu', 'Minggu'], status: 'Aktif', estimasiLayanan: 10, keterangan: 'Layanan laundry linen rumah sakit' }, { id: 8, no: 8, kode: 'INF', nama: 'PELAYANAN INFORMASI', jenis: 'Non-Medis', shift: 2, totalQuota: 150, jamShiftList: [ { dari: '07:00', sampai: '15:00', kuota: 80 }, { dari: '13:00', sampai: '21:00', kuota: 70 } ], autoShift: true, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at', 'Sabtu', 'Minggu'], status: 'Aktif', estimasiLayanan: 10, keterangan: 'Informasi umum rumah sakit dan bantuan navigasi' }, { id: 9, no: 9, kode: 'FRM', nama: 'FARMASI', jenis: 'Medis', shift: 3, totalQuota: 200, jamShiftList: [ { dari: '07:00', sampai: '15:00', kuota: 80 }, { dari: '13:00', sampai: '21:00', kuota: 70 }, { dari: '21:00', sampai: '07:00', kuota: 50 } ], autoShift: true, jadwalOperasional: ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum\'at', 'Sabtu', 'Minggu'], status: 'Aktif', estimasiLayanan: 20, keterangan: 'Pelayanan obat dan konsultasi farmasi' } ]); // Computed - Penunjang const totalPenunjang = computed(() => penunjangData.value.length); const activePenunjang = computed(() => penunjangData.value.filter(p => p.status === 'Aktif')); const penunjangMedis = computed(() => penunjangData.value.filter(p => p.jenis === 'Medis')); const penunjangNonMedis = computed(() => penunjangData.value.filter(p => p.jenis === 'Non-Medis')); // Get penunjang list for dropdowns const penunjangList = computed(() => penunjangData.value .filter(p => p.status === 'Aktif') .map(p => ({ id: p.id, kode: p.kode, nama: p.nama })) ); // Actions - Penunjang const addPenunjang = (penunjangPayload) => { const newId = Math.max(...penunjangData.value.map(p => p.id), 0) + 1; const newNo = penunjangData.value.length + 1; const totalQuota = penunjangPayload.jamShiftList.reduce((total, shift) => { return total + (parseInt(shift.kuota) || 0); }, 0); const newPenunjang = { id: newId, no: newNo, ...penunjangPayload, totalQuota: totalQuota, }; penunjangData.value.push(newPenunjang); return { success: true, message: `Penunjang ${newPenunjang.nama} berhasil ditambahkan`, data: newPenunjang }; }; const updatePenunjang = (penunjangPayload) => { const index = penunjangData.value.findIndex(p => p.id === penunjangPayload.id); if (index !== -1) { const totalQuota = penunjangPayload.jamShiftList.reduce((total, shift) => { return total + (parseInt(shift.kuota) || 0); }, 0); penunjangData.value[index] = { ...penunjangData.value[index], ...penunjangPayload, totalQuota: totalQuota, }; return { success: true, message: `Penunjang ${penunjangPayload.nama} berhasil diupdate` }; } return { success: false, message: 'Penunjang tidak ditemukan' }; }; const deletePenunjang = (penunjangId) => { const index = penunjangData.value.findIndex(p => p.id === penunjangId); if (index !== -1) { const penunjangName = penunjangData.value[index].nama; penunjangData.value.splice(index, 1); penunjangData.value.forEach((p, idx) => { p.no = idx + 1; }); return { success: true, message: `Penunjang ${penunjangName} berhasil dihapus` }; } return { success: false, message: 'Penunjang tidak ditemukan' }; }; const getPenunjangById = (id) => { return penunjangData.value.find(p => p.id === id); }; const getPenunjangByKode = (kode) => { return penunjangData.value.find(p => p.kode === kode); }; // Get active penunjang list (untuk Admin Penunjang) const getActivePenunjangList = () => { return penunjangData.value .filter(p => p.status === 'Aktif') .map(p => ({ id: p.id, name: p.nama, kode: p.kode })); }; // ============================================ // UTILITY FUNCTIONS // ============================================ const getKlinikNameByKode = (kode) => { // Utamakan nama dari clinicStore agar konsisten di seluruh aplikasi if (typeof clinicStore.getClinicByKode === 'function') { const clinic = clinicStore.getClinicByKode(kode); if (clinic) { return clinic.name; } } // Fallback ke data lokal master jika belum terdaftar di clinicStore const klinik = klinikData.value.find((k) => k.kode === kode); return klinik ? klinik.nama : kode; }; const getPenunjangNameByKode = (kode) => { const penunjang = penunjangData.value.find(p => p.kode === kode); return penunjang ? penunjang.nama : kode; }; return { // ============================================ // KLINIK // ============================================ // State klinikData, klinikList, // Actions addKlinik, updateKlinik, deleteKlinik, getKlinikById, getKlinikByKode, // ============================================ // LOKET // ============================================ // State loketData, availableServices, // Actions addLoket, updateLoket, deleteLoket, getLoketById, // ============================================ // RUANG // ============================================ // State ruangData, totalKlinikRuang, totalRuangan, getAllRuangList, // Actions addRuang, updateRuang, deleteRuang, getRuangByKlinik, // ============================================ // PENUNJANG // ============================================ // State penunjangData, totalPenunjang, activePenunjang, penunjangMedis, penunjangNonMedis, penunjangList, // Actions addPenunjang, updatePenunjang, deletePenunjang, getPenunjangById, getPenunjangByKode, getActivePenunjangList, // ============================================ // UTILITIES // ============================================ getKlinikNameByKode, getPenunjangNameByKode, }; });