352 lines
12 KiB
JavaScript
352 lines
12 KiB
JavaScript
// 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;
|
|
},
|
|
},
|
|
});
|
|
|