From 53a510f23d47611a6222f946b2c733dbb5c88e93 Mon Sep 17 00:00:00 2001 From: bagus-arie05 Date: Mon, 2 Feb 2026 11:04:28 +0700 Subject: [PATCH] update status waiting dan update post data pasien --- MAPPING_DATA_TO_ERD.md | 321 ------------------ .../features/queue/TabelPatientData.vue | 12 +- components/preview/LoketPreview.vue | 6 +- composables/useQueue.js | 8 +- composables/useQueueAPI.ts | 4 +- pages/AdminKlinikRuang/[kodeKlinik].vue | 6 +- pages/AdminLoket/[id].vue | 20 +- pages/Anjungan/AntreanMasuk/[id].vue | 4 +- pages/Anjungan/AntrianKlinik/[id].vue | 6 +- .../AntrianKlinikRuang/[kodeKlinik].vue | 4 +- pages/Anjungan/AntrianLoket/[id].vue | 2 +- pages/Anjungan/AntrianPenunjang.vue | 10 +- pages/CheckInPasien/checkIn.vue | 6 +- stores/queueStore.js | 135 +++++--- 14 files changed, 140 insertions(+), 404 deletions(-) delete mode 100644 MAPPING_DATA_TO_ERD.md diff --git a/MAPPING_DATA_TO_ERD.md b/MAPPING_DATA_TO_ERD.md deleted file mode 100644 index 19f9863..0000000 --- a/MAPPING_DATA_TO_ERD.md +++ /dev/null @@ -1,321 +0,0 @@ -# Mapping Data Structure ke ERD - -Dokumen ini menjelaskan mapping antara struktur data pasien di `queueStore.js` (baris 607-622) ke tabel-tabel dalam ERD. - -## Struktur Data di Code (queueStore.js) - -```javascript -{ - no: newNo, - jamPanggil: "HH:MM", - barcode: "26011395625", - noAntrian: "KL0001 | Klinik - 26011395625", - shift: "Shift 1", - klinik: "KANDUNGAN", - fastTrack: "TIDAK" | "YA", - pembayaran: "BPJS" | "UMUM", - status: "di-loket" | "waiting" | ..., - processStage: "klinik" | "loket" | ..., - createdAt: "2026-01-13T16:51:35.502Z", - referencePatient: "UM1001 | Online - 26011395625" | null, - loket: "Loket A" (optional), - loketId: 1 (optional) -} -``` - ---- - -## Mapping ke Tabel ERD - -### 1. **data_kunjungan_antrean** (Tabel Utama Kunjungan) - -| Field Code | Field ERD | Keterangan | -|------------|-----------|------------| -| `barcode` | `Barcode` | Barcode unik pasien (string) | -| `createdAt` | `Tanggal_daftar` | Tanggal dan waktu pendaftaran antrian | -| - | `Pasien` | FK ke `data_pasien.id` (harus dicari/lookup berdasarkan barcode atau dibuat baru) | -| - | `Tanggal_periksa` | Tanggal pemeriksaan (bisa sama dengan Tanggal_daftar atau null) | -| - | `Tanggal_check_in` | Tanggal check-in (null jika belum check-in) | -| - | `Check_in` | Status check-in (boolean/flag) | -| - | `Surat_rujukan` | Surat rujukan (null jika tidak ada) | -| - | `Surat_kontrol` | Surat kontrol (null jika tidak ada) | -| - | `SEP` | SEP BPJS (null jika tidak ada) | -| - | `Status_active` | Status aktif (default: 1 = Active) | - -**Catatan:** -- `barcode` langsung map ke field `Barcode` -- `createdAt` map ke `Tanggal_daftar` -- `referencePatient` bisa digunakan untuk tracking kunjungan sebelumnya (relasi ke `data_kunjungan_antrean` lain) - ---- - -### 2. **data_kunjungan_tempat_layanan** (Detail Tempat Layanan) - -| Field Code | Field ERD | Keterangan | -|------------|-----------|------------| -| `no` | `Nomor_tiket` | Nomor urut antrian (integer) | -| `noAntrian` | - | Bisa disimpan sebagai informasi tambahan atau di-generate dari `Nomor_tiket` | -| `klinik` | `Jenis_layanan` (?) | FK ke `data_jenis_layanan.id` (harus lookup berdasarkan nama klinik) | -| `pembayaran` | `Penjamin` | FK ke `daftar_penjamin.id` (harus lookup: "BPJS" → id penjamin BPJS, "UMUM" → id penjamin UMUM) | -| `loket` | `Loket` | FK ke `data_loket.id` (harus lookup berdasarkan nama loket) | -| `loketId` | `Loket` | FK ke `data_loket.id` (jika ada, langsung gunakan) | -| `fastTrack` | `Status_fasttrack` | FK ke lookup `ID: Status_fasttrack` (1 = True jika "YA", 0 = False jika "TIDAK") | -| `fastTrack` | `Alasan_fasttrack` | Alasan fast track (string, bisa null jika "TIDAK") | -| `processStage` | `Status_kunjungan` | FK ke lookup `ID: Status_kunjungan` (harus mapping: "loket" → 1, "klinik" → 2, dll) | -| `shift` | - | Shift diambil dari `data_jenis_layanan_shift` berdasarkan jadwal | -| - | `FK_kunjunganantrean_ten` | FK ke `data_kunjungan_antrean.id` | -| - | `Jenis_kunjungan` | FK ke `daftar_jenis_kunjungan.id` (default atau lookup) | -| - | `Jenis_pelayanan` | FK ke `daftar_jenis_pelayanan.id` (bisa dari `data_jenis_layanan.Jenis_pelayanan`) | -| - | `Dokter` | FK ke `data_pegawai.id` (null jika belum ditentukan) | -| - | `Jam_awal` | Jam mulai pelayanan (bisa dari `jamPanggil` atau null) | -| - | `Jam_selesai` | Jam selesai pelayanan (null jika belum selesai) | -| - | `Tanggal_ambil_hasil` | Tanggal ambil hasil (null jika belum) | -| - | `Status_active` | Status aktif (default: 1 = Active) | - -**Mapping Status:** -- `status: "di-loket"` → `Status_kunjungan` = 1 (LOKET) -- `status: "waiting"` → `Status_kunjungan` = 2 (PENDING) atau sesuai lookup -- `processStage: "klinik"` → `Status_kunjungan` = 2 (KLINIK) -- `processStage: "loket"` → `Status_kunjungan` = 1 (LOKET) - -**Mapping FastTrack:** -- `fastTrack: "YA"` → `Status_fasttrack` = 1 (True) -- `fastTrack: "TIDAK"` → `Status_fasttrack` = 0 (False) - ---- - -### 3. **data_kunjungan_tempat_panggilan** (Riwayat Panggilan) - -| Field Code | Field ERD | Keterangan | -|------------|-----------|------------| -| `jamPanggil` | `Jam_panggilan` | Jam panggilan pasien (format: "HH:MM") | -| `status` | `Status_panggilan` | FK ke lookup `ID: Status_panggilan` (harus mapping berdasarkan context) | -| `processStage` | `Status_kunjungan` | FK ke lookup `ID: Status_kunjungan` | -| - | `Nama_tempat_panggilan` | Nama tempat panggilan (bisa dari `loket` atau `klinik`) | -| - | `FK_kunjungantempallayana` | FK ke `data_kunjungan_tempat_layanan.id` | -| - | `Status_active` | Status aktif (default: 1 = Active) | - -**Mapping Status Panggilan:** -- Panggilan di Anjungan → `Status_panggilan` = 1 (ANJUNGAN) -- Panggilan di Pendaftaran → `Status_panggilan` = 2 (PENDAFTARAN) -- Panggilan di Pelayanan → `Status_panggilan` = 3 (PELAYANAN) -- Panggilan ambil hasil → `Status_panggilan` = 4 (AMBIL HASIL) - ---- - -### 4. **data_kunjungan_tempat_layanan_detail** (Detail Status Kunjungan) - -| Field Code | Field ERD | Keterangan | -|------------|-----------|------------| -| `createdAt` | `Tanggal_detail` | Tanggal detail status (bisa dari `createdAt`) | -| `status` | `Status_kunjungan` | FK ke lookup `ID: Status_kunjungan` | -| - | `FK_kunjungantempallayana` | FK ke `data_kunjungan_tempat_layanan.id` | -| - | `Status_active` | Status aktif (default: 1 = Active) | - -**Catatan:** Tabel ini untuk tracking perubahan status kunjungan dari waktu ke waktu. - ---- - -### 5. **data_pasien** (Data Pasien - Jika Belum Ada) - -| Field Code | Field ERD | Keterangan | -|------------|-----------|------------| -| `barcode` | `Nomor_rekamedik` | Bisa digunakan sebagai nomor rekam medis sementara | -| - | `Nama` | Nama pasien (harus diinput atau dari sistem lain) | -| - | `Nomor_identitas` | NIK/KTP (harus diinput atau dari sistem lain) | -| - | `Nomor_bpjs` | Nomor BPJS (jika `pembayaran` = "BPJS") | -| - | `Status_antrean` | Status antrian pasien | -| - | `Status_active` | Status aktif (default: 1 = Active) | - -**Catatan:** Jika pasien belum ada di database, harus dibuat record baru di `data_pasien` terlebih dahulu. - ---- - -### 6. **Lookup Tables yang Digunakan** - -#### **ID: Status_fasttrack** -- 0: False -- 1: True - -#### **ID: Status_kunjungan** -- 1: LOKET -- 2: KLINIK -- 3: FARMASI -- 4: PENUNJANG -- 5: RAWAT INAP - -**Atau (versi status):** -- 1: ACTIVE -- 2: PENDING -- 3: TERLAMBAT -- 4: KONSUL -- 5: BATAL -- 6: GAGAL -- 7: AMBIL HASIL -- 8: SELESAI PELAYANAN - -#### **ID: Status_panggilan** -- 1: ANJUNGAN -- 2: PENDAFTARAN -- 3: PELAYANAN -- 4: AMBIL HASIL - -#### **ID: Status_active** -- 0: Disabled -- 1: Active - ---- - -## Alur Penyimpanan Data - -### Step 1: Cek/Create Pasien -1. Cari `data_pasien` berdasarkan `barcode` atau `Nomor_rekamedik` -2. Jika tidak ada, buat record baru di `data_pasien` - -### Step 2: Create Kunjungan Antrean -1. Insert ke `data_kunjungan_antrean`: - - `Barcode` = `barcode` - - `Pasien` = `data_pasien.id` (dari step 1) - - `Tanggal_daftar` = `createdAt` - - `Status_active` = 1 - -### Step 3: Create Tempat Layanan -1. Lookup `data_jenis_layanan.id` berdasarkan `klinik` (nama klinik) -2. Lookup `daftar_penjamin.id` berdasarkan `pembayaran` ("BPJS" atau "UMUM") -3. Lookup `data_loket.id` berdasarkan `loket` atau `loketId` -4. Insert ke `data_kunjungan_tempat_layanan`: - - `Nomor_tiket` = `no` - - `FK_kunjunganantrean_ten` = `data_kunjungan_antrean.id` (dari step 2) - - `Jenis_layanan` = `data_jenis_layanan.id` - - `Penjamin` = `daftar_penjamin.id` - - `Loket` = `data_loket.id` - - `Status_fasttrack` = 1 jika `fastTrack` = "YA", else 0 - - `Status_kunjungan` = mapping dari `processStage` atau `status` - - `Status_active` = 1 - -### Step 4: Create Panggilan (Jika Ada) -1. Insert ke `data_kunjungan_tempat_panggilan`: - - `FK_kunjungantempallayana` = `data_kunjungan_tempat_layanan.id` (dari step 3) - - `Jam_panggilan` = `jamPanggil` - - `Nama_tempat_panggilan` = `loket` atau `klinik` - - `Status_panggilan` = mapping berdasarkan context - - `Status_kunjungan` = mapping dari `processStage` - - `Status_active` = 1 - -### Step 5: Create Detail Status (Optional) -1. Insert ke `data_kunjungan_tempat_layanan_detail`: - - `FK_kunjungantempallayana` = `data_kunjungan_tempat_layanan.id` - - `Tanggal_detail` = `createdAt` - - `Status_kunjungan` = mapping dari `status` atau `processStage` - - `Status_active` = 1 - ---- - -## Field yang Tidak Langsung Map - -### Field yang Perlu Lookup/Transform: -1. **`klinik`** → Perlu lookup ke `data_jenis_layanan.id` berdasarkan nama -2. **`pembayaran`** → Perlu lookup ke `daftar_penjamin.id` berdasarkan value ("BPJS" atau "UMUM") -3. **`loket`** → Perlu lookup ke `data_loket.id` berdasarkan nama loket -4. **`shift`** → Perlu lookup ke `data_jenis_layanan_shift.id` berdasarkan shift dan jadwal -5. **`status`** → Perlu mapping ke lookup `ID: Status_kunjungan` -6. **`processStage`** → Perlu mapping ke lookup `ID: Status_kunjungan` -7. **`fastTrack`** → Perlu mapping ke lookup `ID: Status_fasttrack` (0 atau 1) - -### Field yang Hanya untuk Display/Reference: -1. **`noAntrian`** → Format display, bisa di-generate ulang dari `Nomor_tiket` dan `Barcode` -2. **`referencePatient`** → Reference ke kunjungan sebelumnya (relasi ke `data_kunjungan_antrean` lain) - ---- - -## Contoh Mapping Lengkap - -### Input Data: -```javascript -{ - no: 1, - jamPanggil: "12:49", - barcode: "26011395625", - noAntrian: "UM1001 | Online - 26011395625", - shift: "Shift 1", - klinik: "KANDUNGAN", - fastTrack: "YA", - pembayaran: "BPJS", - status: "di-loket", - processStage: "loket", - createdAt: "2026-01-13T16:51:35.502Z", - loket: "Loket A", - loketId: 1 -} -``` - -### Output ke Database: - -#### data_kunjungan_antrean: -```sql -INSERT INTO data_kunjungan_antrean ( - Barcode, - Pasien, - Tanggal_daftar, - Status_active -) VALUES ( - '26011395625', - [data_pasien.id], -- dari lookup - '2026-01-13T16:51:35.502Z', - 1 -); -``` - -#### data_kunjungan_tempat_layanan: -```sql -INSERT INTO data_kunjungan_tempat_layanan ( - Nomor_tiket, - FK_kunjunganantrean_ten, - Penjamin, -- lookup dari "BPJS" - Jenis_layanan, -- lookup dari "KANDUNGAN" - Loket, -- lookup dari "Loket A" atau langsung 1 - Status_fasttrack, -- 1 (karena "YA") - Status_kunjungan, -- 1 (karena "loket" → LOKET) - Status_active -) VALUES ( - 1, - [data_kunjungan_antrean.id], - [daftar_penjamin.id WHERE Penjamin = 'BPJS'], - [data_jenis_layanan.id WHERE Nama_jenis_layanan = 'KANDUNGAN'], - 1, - 1, - 1, - 1 -); -``` - -#### data_kunjungan_tempat_panggilan: -```sql -INSERT INTO data_kunjungan_tempat_panggilan ( - FK_kunjungantempallayana, - Jam_panggilan, - Nama_tempat_panggilan, - Status_panggilan, -- 2 (PENDAFTARAN) atau sesuai context - Status_kunjungan, -- 1 (LOKET) - Status_active -) VALUES ( - [data_kunjungan_tempat_layanan.id], - '12:49', - 'Loket A', - 2, -- PENDAFTARAN - 1, -- LOKET - 1 -); -``` - ---- - -## Catatan Penting - -1. **Foreign Key Lookups**: Banyak field yang memerlukan lookup ke tabel lain sebelum insert -2. **Status Mapping**: Field `status` dan `processStage` perlu mapping ke lookup table `ID: Status_kunjungan` -3. **Default Values**: Field yang tidak ada di code perlu diisi dengan default value atau null -4. **Relasi**: `referencePatient` bisa digunakan untuk membuat relasi ke `data_kunjungan_antrean` sebelumnya -5. **Shift**: Field `shift` perlu diambil dari `data_jenis_layanan_shift` berdasarkan jadwal dan jenis layanan - - diff --git a/components/features/queue/TabelPatientData.vue b/components/features/queue/TabelPatientData.vue index 9cceddc..045e2e5 100644 --- a/components/features/queue/TabelPatientData.vue +++ b/components/features/queue/TabelPatientData.vue @@ -190,7 +190,7 @@ const props = defineProps({ type: Number, default: 0 }, - waitingCount: { + anjunganCount: { type: Number, default: 0 }, @@ -289,12 +289,12 @@ const statusOptions = computed(() => { }); } - // Tambahkan kategori "Menunggu" (pasien yang sudah dipanggil tapi belum check-in) - if (props.waitingCount > 0) { + // Tambahkan kategori "Anjungan" (pasien yang sudah dipanggil tapi belum check-in) + if (props.anjunganCount > 0) { baseOptions.push({ - value: 'waiting', - label: 'Menunggu', - count: props.waitingCount, + value: 'anjungan', + label: 'Anjungan', + count: props.anjunganCount, icon: 'mdi-clock-outline' }); } diff --git a/components/preview/LoketPreview.vue b/components/preview/LoketPreview.vue index 778b5c7..61f8a1f 100644 --- a/components/preview/LoketPreview.vue +++ b/components/preview/LoketPreview.vue @@ -113,9 +113,9 @@ const loketData = computed(() => { // Mock queue data untuk preview const mockQueues = ref([ { no: 1, noAntrian: 'RT001', klinik: 'R. TINDAKAN', status: 'current' }, - { no: 2, noAntrian: 'RT002', klinik: 'R. TINDAKAN', status: 'waiting' }, - { no: 3, noAntrian: 'RD001', klinik: 'RADIOTERAPI', status: 'waiting' }, - { no: 4, noAntrian: 'RM001', klinik: 'REHAB MEDIK', status: 'waiting' }, + { no: 2, noAntrian: 'RT002', klinik: 'R. TINDAKAN', status: 'anjungan' }, + { no: 3, noAntrian: 'RD001', klinik: 'RADIOTERAPI', status: 'anjungan' }, + { no: 4, noAntrian: 'RM001', klinik: 'REHAB MEDIK', status: 'anjungan' }, ]) // Simulasi klinik dengan queue diff --git a/composables/useQueue.js b/composables/useQueue.js index 3bdf497..368769a 100644 --- a/composables/useQueue.js +++ b/composables/useQueue.js @@ -64,14 +64,14 @@ export const useQueue = (adminType = "loket", specificId = null) => { return patients; }); - const waitingPatients = computed(() => stagePatients.value.waiting || []); + const anjunganPatients = computed(() => stagePatients.value.anjungan || []); // Pasien yang belum dipanggil (status "menunggu") const menungguPatients = computed(() => stagePatients.value.menunggu || []); const nextPatient = computed(() => { - // Prioritaskan pasien menunggu, baru waiting - return menungguPatients.value[0] || waitingPatients.value[0] || null; + // Prioritaskan pasien menunggu, baru anjungan + return menungguPatients.value[0] || anjunganPatients.value[0] || null; }); // Total pasien hanya untuk stage admin ini @@ -314,7 +314,7 @@ export const useQueue = (adminType = "loket", specificId = null) => { diLoketPatients, terlambatPatients, pendingPatients, - waitingPatients, + anjunganPatients, menungguPatients, nextPatient, totalPasien, diff --git a/composables/useQueueAPI.ts b/composables/useQueueAPI.ts index ce36825..b18686c 100644 --- a/composables/useQueueAPI.ts +++ b/composables/useQueueAPI.ts @@ -10,7 +10,7 @@ export interface Patient { klinik: string; fastTrack: string; pembayaran: string; - status: 'waiting' | 'pending' | 'di-loket' | 'di-klinik' | 'selesai' | 'terlambat'; + status: 'anjungan' | 'pending' | 'di-loket' | 'di-klinik' | 'selesai' | 'terlambat'; processStage: 'loket' | 'klinik' | 'penunjang'; createdAt: string; registrationType?: 'online' | 'onsite'; @@ -127,7 +127,7 @@ export const useQueueAPI = () => { idOrBarcode: string, updates: { status?: string; processStage?: string } ): Promise => { - return updatePatient(idOrBarcode, updates); + return updatePatient(idOrBarcode, updates as Partial); }; /** diff --git a/pages/AdminKlinikRuang/[kodeKlinik].vue b/pages/AdminKlinikRuang/[kodeKlinik].vue index a5e7ac8..0b789a5 100644 --- a/pages/AdminKlinikRuang/[kodeKlinik].vue +++ b/pages/AdminKlinikRuang/[kodeKlinik].vue @@ -937,7 +937,7 @@ const getAllPatientsForRoom = (ruang) => { p.ruang === ruang.namaRuang && p.processStage === 'klinik-ruang' && // Include semua pasien dengan status yang relevan - (p.status === 'waiting' || p.status === 'di-loket' || p.status === 'terlambat' || p.status === 'pending') + (p.status === 'anjungan' || p.status === 'di-loket' || p.status === 'terlambat' || p.status === 'pending') ); }; @@ -1134,7 +1134,7 @@ const getAvailablePatientsForKelola = () => { let patients = queueStore.allPatients.filter(p => p.kodeKlinik === klinikData.value?.kodeKlinik && p.processStage === 'klinik-ruang' && - (p.status === 'waiting' || p.status === 'di-loket' || p.status === 'terlambat' || p.status === 'pending') + (p.status === 'anjungan' || p.status === 'di-loket' || p.status === 'terlambat' || p.status === 'pending') ); // Apply search filter @@ -1694,7 +1694,7 @@ const handleProcessPendingPatient = (ruang, patient) => { // Update status pasien dari pending menjadi waiting queueStore.allPatients[patientIndex] = { ...queueStore.allPatients[patientIndex], - status: 'waiting' + status: 'anjungan' }; // Set sebagai current processing diff --git a/pages/AdminLoket/[id].vue b/pages/AdminLoket/[id].vue index 5700b15..80afcfb 100644 --- a/pages/AdminLoket/[id].vue +++ b/pages/AdminLoket/[id].vue @@ -81,7 +81,7 @@ v-model:selected-fast-track="selectedFastTrack" :di-loket-count="filteredDiLoketCount" :diproses-count="currentProcessingPatient ? 1 : 0" - :waiting-count="filteredWaitingCount" + :anjungan-count="filteredAnjunganCount" :terlambat-count="filteredTerlambatCount" :pending-count="filteredPendingCount" :show-diproses="false" @@ -261,7 +261,7 @@ const { diLoketPatients, terlambatPatients, pendingPatients, - waitingPatients, + anjunganPatients, menungguPatients, nextPatient, menungguCount, @@ -436,7 +436,7 @@ const allPatientsForStage = computed(() => { if (isLoketEksekutif) { // For EKSEKUTIF loket, use seed data (filter from allPatients) // IMPORTANT: Do NOT include menungguPatients - they are only called via QueueActionsCard - basePatients = diLoketPatients.value.concat(waitingPatients.value, terlambatPatients.value, pendingPatients.value); + basePatients = diLoketPatients.value.concat(anjunganPatients.value, terlambatPatients.value, pendingPatients.value); } else { // For REGULER loket, use API data from allPatients (which is reactive) // Filter patients that belong to this loket and are from API @@ -525,14 +525,14 @@ const allPatientsForStage = computed(() => { status: "pending", })); - const waiting = (waitingPatients.value || []) + const anjungan = (anjunganPatients.value || []) .filter(isPatientForThisLoket) .map((p) => ({ ...p, - status: "waiting", + status: "anjungan", })); - combined = [...diLoket, ...waiting, ...terlambat, ...pending]; + combined = [...diLoket, ...anjungan, ...terlambat, ...pending]; } else { // Use API data, but EXCLUDE patients with status "menunggu" // They should only be called via QueueActionsCard, not displayed in table @@ -549,8 +549,8 @@ const allPatientsForStage = computed(() => { // Computed status counts based on filtered allPatientsForStage // These counts are ONLY for patients that belong to this specific loket -const filteredWaitingCount = computed(() => { - return allPatientsForStage.value.filter(p => p.status === 'waiting').length; +const filteredAnjunganCount = computed(() => { + return allPatientsForStage.value.filter(p => p.status === 'anjungan').length; }); const filteredDiLoketCount = computed(() => { @@ -598,8 +598,8 @@ const filteredMenungguCount = computed(() => { } }); -const waitingCount = computed(() => { - return (waitingPatients.value || []).length; +const anjunganCount = computed(() => { + return (anjunganPatients.value || []).length; }); const nextQueueInfo = computed(() => { diff --git a/pages/Anjungan/AntreanMasuk/[id].vue b/pages/Anjungan/AntreanMasuk/[id].vue index 931172d..e7226fd 100644 --- a/pages/Anjungan/AntreanMasuk/[id].vue +++ b/pages/Anjungan/AntreanMasuk/[id].vue @@ -313,7 +313,7 @@ const calledForCheckIn = computed(() => { .filter(p => { // Must be called (waiting status = sudah dipanggil dari status menunggu) // and not yet checked in (processStage still 'loket') - const isCalled = p.status === 'waiting' && p.processStage === 'loket' + const isCalled = p.status === 'anjungan' && p.processStage === 'loket' // Filter berdasarkan loketId yang dikonfigurasi di screen // Handle potential undefined or number types @@ -432,7 +432,7 @@ const statistics = computed(() => { // Menunggu = belum dipanggil (status 'menunggu') const menungguCount = allLoketTickets.filter(p => p && p.status === 'menunggu').length - // Dipanggil untuk check-in = sudah dipanggil (status 'waiting') + // Dipanggil untuk check-in = sudah dipanggil (status 'anjungan') const calledForCheckInArray = Array.isArray(calledForCheckIn.value) ? calledForCheckIn.value : [] const activeCount = calledForCheckInArray.length diff --git a/pages/Anjungan/AntrianKlinik/[id].vue b/pages/Anjungan/AntrianKlinik/[id].vue index b18bbec..3dd04fd 100644 --- a/pages/Anjungan/AntrianKlinik/[id].vue +++ b/pages/Anjungan/AntrianKlinik/[id].vue @@ -261,7 +261,7 @@ const displayedClinics = computed(() => { // Current queue: prioritaskan di-loket, lalu waiting, lalu pending (dengan card merah) const currentQueue = queues.find((q) => q.status === "di-loket") || - queues.find((q) => q.status === "waiting") || + queues.find((q) => q.status === "anjungan") || queues.find((q) => q.status === "pending") || null; @@ -269,7 +269,7 @@ const displayedClinics = computed(() => { const nextQueues = queues.filter( (q) => q.no !== currentQueue?.no && - (q.status === "waiting" || q.status === "di-loket" || q.status === "pending") + (q.status === "anjungan" || q.status === "di-loket" || q.status === "pending") ); // Pending queues: pasien dengan status pending yang tidak di current atau next @@ -321,7 +321,7 @@ const statistics = computed(() => { return { total: all.length, - waiting: all.filter((p) => p.status === "waiting").length, + anjungan: all.filter((p) => p.status === "anjungan").length, active: all.filter((p) => p.status === "di-loket").length, }; }); diff --git a/pages/Anjungan/AntrianKlinikRuang/[kodeKlinik].vue b/pages/Anjungan/AntrianKlinikRuang/[kodeKlinik].vue index 48cc124..f7b43e1 100644 --- a/pages/Anjungan/AntrianKlinikRuang/[kodeKlinik].vue +++ b/pages/Anjungan/AntrianKlinikRuang/[kodeKlinik].vue @@ -328,7 +328,7 @@ const displayedRuang = computed(() => { // Next queues: exclude current patient dan pasien dengan status 'di-loket' (yang sudah dipanggil) const next = queues.filter(q => q.no !== current?.no && - q.status === 'waiting' // Hanya yang waiting (belum dipanggil) + q.status === 'anjungan' // Hanya yang anjungan (belum dipanggil) ).slice(0, 3) // Show max 3 next queues return { current, next } } @@ -389,7 +389,7 @@ const statistics = computed(() => { const all = klinikPatients.value return { total: all.length, - waiting: all.filter(p => p.status === 'waiting').length, + anjungan: all.filter(p => p.status === 'anjungan').length, active: all.filter(p => p.status === 'di-loket').length } }) diff --git a/pages/Anjungan/AntrianLoket/[id].vue b/pages/Anjungan/AntrianLoket/[id].vue index fbefd1a..425912e 100644 --- a/pages/Anjungan/AntrianLoket/[id].vue +++ b/pages/Anjungan/AntrianLoket/[id].vue @@ -256,7 +256,7 @@ const loketPatients = computed(() => { // Include 'di-loket' (serving/called), 'waiting' (next in line) and 'pending' (on hold) return allPatients.filter(p => p.processStage === 'loket' && - (p.status === 'di-loket' || p.status === 'waiting' || p.status === 'pending') + (p.status === 'di-loket' || p.status === 'anjungan' || p.status === 'pending') ); }); diff --git a/pages/Anjungan/AntrianPenunjang.vue b/pages/Anjungan/AntrianPenunjang.vue index cfa8dd8..4aed028 100644 --- a/pages/Anjungan/AntrianPenunjang.vue +++ b/pages/Anjungan/AntrianPenunjang.vue @@ -110,7 +110,7 @@ mdi-clock-alert-outline
-
{{ statistics.waiting }}
+
{{ statistics.anjungan }}
Menunggu
@@ -161,7 +161,7 @@ const displayedPenunjangs = computed(() => { .sort((a, b) => { const statusPriority = { 'di-loket': 1, - 'waiting': 2, + 'anjungan': 2, 'terlambat': 3, 'pending': 4 } @@ -175,11 +175,11 @@ const displayedPenunjangs = computed(() => { }) const currentQueue = queues.find(q => q.status === 'di-loket') || - (queues.find(q => q.status === 'waiting') || null) + (queues.find(q => q.status === 'anjungan') || null) const nextQueues = queues.filter(q => q.no !== currentQueue?.no && - (q.status === 'waiting' || q.status === 'di-loket') + (q.status === 'anjungan' || q.status === 'di-loket') ) return { @@ -203,7 +203,7 @@ const statistics = computed(() => { const all = penunjangPatients.value return { total: all.length, - waiting: all.filter(p => p.status === 'waiting').length, + anjungan: all.filter(p => p.status === 'anjungan').length, active: all.filter(p => p.status === 'di-loket').length } }) diff --git a/pages/CheckInPasien/checkIn.vue b/pages/CheckInPasien/checkIn.vue index db4a77e..09c5580 100644 --- a/pages/CheckInPasien/checkIn.vue +++ b/pages/CheckInPasien/checkIn.vue @@ -3535,15 +3535,15 @@ const todayStats = computed(() => { const statsWaiting = computed(() => { // Ambil data menunggu dari queueStore untuk stage 'loket' - // Menghitung pasien dengan status 'menunggu' (belum dipanggil) atau 'waiting' (sudah dipanggil tapi belum check-in) + // Menghitung pasien dengan status 'menunggu' (belum dipanggil) atau 'anjungan' (sudah dipanggil tapi belum check-in) // Di halaman CheckInPasien, kita menghitung total yang masih menunggu check-in (belum + sudah dipanggil) try { const loketPatients = queueStore.getPatientsByStage('loket'); const menungguPatients = loketPatients.value.menunggu || []; - const waitingPatients = loketPatients.value.waiting || []; + const anjunganPatients = loketPatients.value.anjungan || []; // Total pasien yang masih menunggu check-in (belum dipanggil + sudah dipanggil tapi belum check-in) - return menungguPatients.length + waitingPatients.length; + return menungguPatients.length + anjunganPatients.length; } catch (error) { console.error('Error calculating statsWaiting:', error); return 0; diff --git a/stores/queueStore.js b/stores/queueStore.js index 410d093..1a7eec3 100644 --- a/stores/queueStore.js +++ b/stores/queueStore.js @@ -59,20 +59,20 @@ export const useQueueStore = defineStore('queue', () => { /** * Reference mapping for patient status from API idvisit * idvisit 1, 2 = menunggu (CT ANJUNGAN, RT ANJUNGAN) - * idvisit 3, 4 = waiting (PG ANJUNGAN, RT CHECK-IN) + * idvisit 3, 4 = anjungan (PG ANJUNGAN, RT CHECK-IN) * idvisit 5, 6 = di-loket (PS CHECK-IN, TP LOKET) */ const PATIENT_STATUS_MAP = { 1: 'menunggu', 2: 'menunggu', - 3: 'waiting', - 4: 'waiting', + 3: 'anjungan', + 4: 'anjungan', 5: 'di-loket', 6: 'di-loket', "1": 'menunggu', "2": 'menunggu', - "3": 'waiting', - "4": 'waiting', + "3": 'anjungan', + "4": 'anjungan', "5": 'di-loket', "6": 'di-loket' }; @@ -87,7 +87,7 @@ export const useQueueStore = defineStore('queue', () => { /** * Map status dari deskripsi API ke status internal * menunggu (id 1, 2): "Cetak Tiket Antrian" atau "Ruang Tunggu Anjungan" - * waiting (id 3, 4): "Panggilan loket ke Anjungan" atau "Tunggu Pasien Check-In" + * anjungan (id 3, 4): "Panggilan loket ke Anjungan" atau "Tunggu Pasien Check-In" * di-loket (id 5, 6): "Pasien Sudah Check-In" atau "Tunggu Panggilan Loket" */ const mapStatusFromDeskripsi = (deskripsi) => { @@ -100,9 +100,9 @@ export const useQueueStore = defineStore('queue', () => { return 'di-loket'; } - // waiting (id 3, 4): PG ANJUNGAN (Panggilan loket ke Anjungan), RT CHECK-IN (Tunggu Pasien Check-In) + // anjungan (id 3, 4): PG ANJUNGAN (Panggilan loket ke Anjungan), RT CHECK-IN (Tunggu Pasien Check-In) if (desc.includes('PANGGILAN LOKET KE ANJUNGAN') || desc.includes('TUNGGU PASIEN CHECK-IN') || desc.includes('PG ANJUNGAN') || desc.includes('RT CHECK-IN')) { - return 'waiting'; + return 'anjungan'; } // menunggu (id 1, 2): CT ANJUNGAN (Cetak Tiket Antrian), RT ANJUNGAN (Ruang Tunggu Anjungan) @@ -131,8 +131,8 @@ export const useQueueStore = defineStore('queue', () => { if (apiPatient.posisi && Array.isArray(apiPatient.posisi) && apiPatient.posisi.length > 0) { // Find the "best" status among all positions - // Priority: di-loket > waiting > menunggu - const statusPriority = { 'di-loket': 3, 'waiting': 2, 'menunggu': 1 }; + // Priority: di-loket > anjungan > menunggu + const statusPriority = { 'di-loket': 3, 'anjungan': 2, 'menunggu': 1 }; let bestPriority = 0; apiPatient.posisi.forEach(pos => { @@ -259,8 +259,8 @@ export const useQueueStore = defineStore('queue', () => { if (!existing) { deduplicatedMap.set(id, p); } else { - // Priority: di-loket > waiting > menunggu - const statusPriority = { 'di-loket': 3, 'waiting': 2, 'menunggu': 1 }; + // Priority: di-loket > anjungan > menunggu + const statusPriority = { 'di-loket': 3, 'anjungan': 2, 'menunggu': 1 }; const pPrio = statusPriority[p.status] || 0; const ePrio = statusPriority[existing.status] || 0; @@ -296,9 +296,9 @@ export const useQueueStore = defineStore('queue', () => { allPatients.value.forEach(p => { const key = p.idtiket ? `id-${p.idtiket}` : `bc-${p.barcode}`; if (newPatientMap.has(key)) { - // If existing patient has more advanced status (waiting/di-loket), preserve it! + // If existing patient has more advanced status (anjungan/di-loket), preserve it! // This handles cases where we updated status locally ('onsite' or 'api') but API is lagging - const statusPriority = { 'di-loket': 3, 'waiting': 2, 'menunggu': 1 }; + const statusPriority = { 'di-loket': 3, 'anjungan': 2, 'menunggu': 1 }; const existingPrio = statusPriority[p.status] || 0; const newPatient = newPatientMap.get(key); const newPrio = statusPriority[newPatient.status] || 0; @@ -577,7 +577,7 @@ export const useQueueStore = defineStore('queue', () => { // kodeKlinik: "KD", // fastTrack: "TIDAK", // pembayaran: "Eksekutif", - // status: "waiting", + // status: "anjungan", // processStage: "loket", // createdAt: new Date().toISOString(), // registrationType: 'online', @@ -598,7 +598,7 @@ export const useQueueStore = defineStore('queue', () => { // kodeKlinik: "IP", // fastTrack: "TIDAK", // pembayaran: "Eksekutif", - // status: "waiting", + // status: "anjungan", // processStage: "loket", // createdAt: new Date().toISOString(), // registrationType: 'online', @@ -619,7 +619,7 @@ export const useQueueStore = defineStore('queue', () => { // kodeKlinik: "SR", // fastTrack: "YA", // pembayaran: "Eksekutif", - // status: "waiting", + // status: "anjungan", // processStage: "loket", // createdAt: new Date().toISOString(), // registrationType: 'online', @@ -640,7 +640,7 @@ export const useQueueStore = defineStore('queue', () => { // kodeKlinik: "TH", // fastTrack: "TIDAK", // pembayaran: "VIP", - // status: "waiting", + // status: "anjungan", // processStage: "loket", // createdAt: new Date().toISOString(), // registrationType: 'online', @@ -890,7 +890,7 @@ export const useQueueStore = defineStore('queue', () => { return { all: patients, - waiting: patients.filter(p => p.status === 'waiting'), + anjungan: patients.filter(p => p.status === 'anjungan'), menunggu: patients.filter(p => p.status === 'menunggu'), diLoket: patients.filter(p => p.status === 'di-loket'), terlambat: patients.filter(p => p.status === 'terlambat'), @@ -977,20 +977,47 @@ export const useQueueStore = defineStore('queue', () => { return { success: false, message: "Kuota sudah penuh" }; } - // Update status menjadi 'waiting' (Masuk ke antrean aktif) + // Update status menjadi 'anjungan' (Masuk ke antrean aktif) const callTimestamp = new Date().toISOString(); const index = allPatients.value.findIndex(p => p.no === nextPatient.no); if (index !== -1) { allPatients.value[index] = { ...allPatients.value[index], - status: "waiting", + status: "anjungan", // Assign to this specific loket if it was unassigned loketId: (adminType === 'loket' && targetId) ? parseInt(targetId) : allPatients.value[index].loketId, lastCalledAt: callTimestamp }; // SYNC to apiPatientsPerLoket if it's an API patient - syncApiPatientStatus(allPatients.value[index], "waiting"); + syncApiPatientStatus(allPatients.value[index], "anjungan"); + + // POST to external API when patient is called + try { + fetch('http://10.10.150.131:8089/api/v1/tiket/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + idtiket: nextPatient.barcode || "", + statuspasien: "3", + statuspasien2: "4", + idklinikstatus: "1", + idklinikstatus2: "1" + }) + }).then(response => { + if (response.ok) { + console.log(`✅ Successfully posted status update for patient ${nextPatient.barcode}`); + } else { + console.error(`⚠️ Failed to post status update for patient ${nextPatient.barcode}:`, response.status); + } + }).catch(error => { + console.error(`❌ Error posting status update for patient ${nextPatient.barcode}:`, error); + }); + } catch (error) { + console.error(`❌ Error initiating status update for patient ${nextPatient.barcode}:`, error); + } } return { @@ -1045,10 +1072,10 @@ export const useQueueStore = defineStore('queue', () => { const patientsToCall = menungguList.slice(0, maxCallable); const callTimestamp = new Date().toISOString(); - patientsToCall.forEach((patient) => { + patientsToCall.forEach(async (patient) => { const index = allPatients.value.findIndex(p => p.no === patient.no); if (index !== -1) { - const newStatus = "waiting"; + const newStatus = "anjungan"; const newLoketId = (adminType === 'loket' && targetId) ? targetId : allPatients.value[index].loketId; allPatients.value[index] = { @@ -1060,6 +1087,31 @@ export const useQueueStore = defineStore('queue', () => { // SYNC to apiPatientsPerLoket if it's an API patient syncApiPatientStatus(allPatients.value[index], newStatus); + + // POST to external API when patient is called + try { + const response = await fetch('http://10.10.150.131:8089/api/v1/tiket/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + idtiket: patient.barcode || "", + statuspasien: "3", + statuspasien2: "4", + idklinikstatus: "1", + idklinikstatus2: "1" + }) + }); + + if (response.ok) { + console.log(`✅ Successfully posted status update for patient ${patient.barcode}`); + } else { + console.error(`⚠️ Failed to post status update for patient ${patient.barcode}:`, response.status); + } + } catch (error) { + console.error(`❌ Error posting status update for patient ${patient.barcode}:`, error); + } } }); @@ -1375,7 +1427,7 @@ export const useQueueStore = defineStore('queue', () => { fastTrack: patient ? (patient.fastTrack || "TIDAK") : "TIDAK", pembayaran: patient ? patient.pembayaran : "UMUM", noRM: patient ? patient.noRM : null, - status: "waiting", + status: "anjungan", processStage: "klinik-ruang", // Set ke klinik-ruang langsung createdAt: timestamp.toISOString(), referencePatient: patient ? patient.noAntrian : null, @@ -1517,7 +1569,7 @@ export const useQueueStore = defineStore('queue', () => { tipeLayanan: tipeLayanan, fastTrack: sourcePatient.fastTrack || "TIDAK", pembayaran: sourcePatient.pembayaran || "UMUM", - status: "waiting", + status: "anjungan", processStage: "klinik-ruang", createdAt: sourcePatient.createdAt || timestamp.toISOString(), // Gunakan createdAt dari pasien awal referencePatient: sourcePatient.noAntrian, @@ -1618,7 +1670,7 @@ export const useQueueStore = defineStore('queue', () => { tipeLayanan: tipeLayanan, fastTrack: sourcePatient.fastTrack || "TIDAK", pembayaran: sourcePatient.pembayaran || "UMUM", - status: "waiting", + status: "anjungan", processStage: "klinik-ruang", createdAt: sourcePatient.createdAt || timestamp.toISOString(), // Gunakan createdAt dari pasien awal referencePatient: sourcePatient.noAntrian, @@ -1649,7 +1701,7 @@ export const useQueueStore = defineStore('queue', () => { return { all: patients, - waiting: patients.filter(p => p.status === 'waiting'), + anjungan: patients.filter(p => p.status === 'anjungan'), diLoket: patients.filter(p => p.status === 'di-loket'), terlambat: patients.filter(p => p.status === 'terlambat'), pending: patients.filter(p => p.status === 'pending'), @@ -1664,10 +1716,10 @@ export const useQueueStore = defineStore('queue', () => { p.nomorRuang === nomorRuang && p.tipeLayanan === tipeLayanan && p.processStage === 'klinik-ruang' && - (p.status === 'waiting' || (allowMultiple && p.status === 'di-loket')) + (p.status === 'anjungan' || (allowMultiple && p.status === 'di-loket')) ).sort((a, b) => { - // Sort by status priority first: waiting=1, di-loket=2 - const statusPriority = { 'waiting': 1, 'di-loket': 2 }; + // Sort by status priority first: anjungan=1, di-loket=2 + const statusPriority = { 'anjungan': 1, 'di-loket': 2 }; const priorityDiff = (statusPriority[a.status] || 99) - (statusPriority[b.status] || 99); if (priorityDiff !== 0) return priorityDiff; @@ -1895,12 +1947,17 @@ export const useQueueStore = defineStore('queue', () => { const idloket = targetLoket ? String(targetLoket.id) : "2"; // Default fallback to "2" if not found - // 2. Prepare API Body + // 2. Determine idpembayaran based on paymentType + // BPJS (JKN) = "2", UMUM and others = "1" + const idpembayaran = paymentType === "BPJS" ? "2" : "1"; + + // 3. Prepare API Body const body = { idloket: idloket, dokter: "", idklinik: String(clinic.id), namaklinik: clinic.name, + idpembayaran: idpembayaran, statuspasien: "1", statuspasien2: "2", idklinikstatus: "1" @@ -2046,7 +2103,7 @@ export const useQueueStore = defineStore('queue', () => { }; - // Check-in patient (update status from waiting to di-loket) + // Check-in patient (update status from anjungan to di-loket) // IMPORTANT: Hanya menggunakan EXACT barcode match untuk menghindari false positive // Format barcode: YYMMDD + 5 digit (contoh: 26011500001) // Jangan gunakan fallback ke noAntrian atau no karena bisa menyebabkan false positive @@ -2096,7 +2153,7 @@ export const useQueueStore = defineStore('queue', () => { processStage: patient.processStage }); - // Only allow check-in if status is waiting (sudah dipanggil) or pending + // Only allow check-in if status is anjungan (sudah dipanggil) or pending // Pasien dengan status "menunggu" belum bisa check-in (belum dipanggil) if (patient.status === 'menunggu') { console.log('⚠️ Patient status is menunggu (belum dipanggil):', patient.status); @@ -2115,8 +2172,8 @@ export const useQueueStore = defineStore('queue', () => { }; } - if (patient.status !== 'waiting' && patient.status !== 'pending') { - console.log('⚠️ Patient status is not waiting/pending:', patient.status); + if (patient.status !== 'anjungan' && patient.status !== 'pending') { + console.log('⚠️ Patient status is not anjungan/pending:', patient.status); return { success: false, message: `Pasien tidak dapat check-in. Status saat ini: ${patient.status}` @@ -2155,7 +2212,7 @@ export const useQueueStore = defineStore('queue', () => { console.log(`🚀 [processNextQueue] Processing for ${key} (Stage: ${targetStage})`); - // 2. Find next patient (Status: 'menunggu' -> 'waiting') + // 2. Find next patient (Status: 'menunggu' -> 'anjungan') // Prioritaskan yang assigned ke loket ini (loketId) jika ada match let nextPatient = null; @@ -2177,10 +2234,10 @@ export const useQueueStore = defineStore('queue', () => { ); } - // Fallback: Check 'waiting' status if needed (though usually 'menunggu' is for calling) + // Fallback: Check 'anjungan' status if needed (though usually 'menunggu' is for calling) if (!nextPatient) { nextPatient = allPatients.value.find(p => - p.status === 'waiting' && + p.status === 'anjungan' && p.processStage === targetStage && (adminType !== 'loket' || String(p.loketId) === String(specificId)) );