update anjungan fast track dan tampilan ruang
This commit is contained in:
No files matched your search
@@ -108,20 +108,20 @@
|
||||
<!-- Compact status indicators - only show icons if called -->
|
||||
<v-chip
|
||||
v-if="patient.calledPemeriksaanAwal"
|
||||
size="x-small"
|
||||
size="small"
|
||||
color="primary"
|
||||
class="status-chip"
|
||||
class="status-chip status-chip-pawal"
|
||||
>
|
||||
<v-icon start size="10">mdi-check-circle</v-icon>
|
||||
<v-icon start size="18">mdi-check-circle</v-icon>
|
||||
P.Awal
|
||||
</v-chip>
|
||||
<v-chip
|
||||
v-if="patient.calledTindakan"
|
||||
size="x-small"
|
||||
size="small"
|
||||
color="secondary"
|
||||
class="status-chip"
|
||||
class="status-chip status-chip-tindakan"
|
||||
>
|
||||
<v-icon start size="10">mdi-check-circle</v-icon>
|
||||
<v-icon start size="18">mdi-check-circle</v-icon>
|
||||
Tindakan
|
||||
</v-chip>
|
||||
</div>
|
||||
@@ -1417,10 +1417,11 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.patient-queue-number {
|
||||
font-size: 15px;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: var(--color-neutral-900);
|
||||
line-height: 1.2;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.patient-queue-status-chips {
|
||||
@@ -1428,17 +1429,46 @@ onMounted(() => {
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.status-chip {
|
||||
font-size: 10px !important;
|
||||
height: 18px !important;
|
||||
font-weight: 700 !important;
|
||||
height: 20px !important;
|
||||
padding: 0 6px !important;
|
||||
min-width: 60px !important;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08) !important;
|
||||
border: 1px solid transparent !important;
|
||||
letter-spacing: 0.1px !important;
|
||||
}
|
||||
|
||||
.status-chip-pawal {
|
||||
background: #6366f1 !important;
|
||||
color: white !important;
|
||||
border-color: #4f46e5 !important;
|
||||
}
|
||||
|
||||
.status-chip-pawal:hover {
|
||||
background: #4f46e5 !important;
|
||||
box-shadow: 0 1px 3px rgba(99, 102, 241, 0.15) !important;
|
||||
}
|
||||
|
||||
.status-chip-tindakan {
|
||||
background: #14b8a6 !important;
|
||||
color: white !important;
|
||||
border-color: #0d9488 !important;
|
||||
}
|
||||
|
||||
.status-chip-tindakan:hover {
|
||||
background: #0d9488 !important;
|
||||
box-shadow: 0 1px 3px rgba(20, 184, 166, 0.15) !important;
|
||||
}
|
||||
|
||||
.status-chip .v-icon {
|
||||
font-size: 10px !important;
|
||||
margin-right: 2px;
|
||||
font-size: 11px !important;
|
||||
margin-right: 2px !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
/* Right Section: Actions */
|
||||
|
||||
@@ -24,13 +24,9 @@
|
||||
<div class="guide-item">
|
||||
<span class="guide-number">2</span>
|
||||
<span class="guide-text"
|
||||
>Pilih: Daftar Sekarang atau Jadwal Lain</span
|
||||
>Pilih jenis pembayaran dan buat nomor antrian</span
|
||||
>
|
||||
</div>
|
||||
<div class="guide-item">
|
||||
<span class="guide-number">3</span>
|
||||
<span class="guide-text">Pilih Jenis Pembayaran</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -237,39 +233,112 @@
|
||||
<v-divider />
|
||||
|
||||
<v-card-text class="pa-4">
|
||||
<v-row dense>
|
||||
<v-col cols="6">
|
||||
<v-btn
|
||||
color="success-600"
|
||||
class="text-white"
|
||||
size="large"
|
||||
block
|
||||
@click="selectVisitType('SEKARANG')"
|
||||
:disabled="isShift1Full(selectedClinic) || (isEksekutif && !selectedDoctor)"
|
||||
:class="{ 'btn-disabled': isShift1Full(selectedClinic) || (isEksekutif && !selectedDoctor) }"
|
||||
>
|
||||
DAFTAR SEKARANG
|
||||
</v-btn>
|
||||
<p v-if="isShift1Full(selectedClinic)" class="disabled-hint">
|
||||
Kuota hari ini habis
|
||||
</p>
|
||||
<p v-else-if="isEksekutif && !selectedDoctor" class="disabled-hint">
|
||||
Pilih dokter terlebih dahulu
|
||||
</p>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<!-- For Eksekutif: Show DAFTAR SEKARANG button -->
|
||||
<div v-if="isEksekutif">
|
||||
<v-row dense>
|
||||
<v-col cols="12">
|
||||
<v-btn
|
||||
color="success-600"
|
||||
class="text-white"
|
||||
size="large"
|
||||
block
|
||||
@click="registerPatientDirectly('Eksekutif')"
|
||||
:disabled="isShift1Full(selectedClinic) || !selectedDoctor"
|
||||
:class="{ 'btn-disabled': isShift1Full(selectedClinic) || !selectedDoctor }"
|
||||
>
|
||||
DAFTAR SEKARANG
|
||||
</v-btn>
|
||||
<p v-if="isShift1Full(selectedClinic)" class="disabled-hint">
|
||||
Kuota hari ini habis
|
||||
</p>
|
||||
<p v-else-if="!selectedDoctor" class="disabled-hint">
|
||||
Pilih dokter terlebih dahulu
|
||||
</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
|
||||
<!-- For Non-Eksekutif: Show 3 payment type buttons -->
|
||||
<div v-else>
|
||||
<v-row dense>
|
||||
<v-col cols="4">
|
||||
<v-btn
|
||||
color="success-600"
|
||||
class="text-white payment-type-btn"
|
||||
size="large"
|
||||
block
|
||||
@click="registerPatientDirectly('BPJS')"
|
||||
:disabled="isShift1Full(selectedClinic)"
|
||||
:class="{ 'btn-disabled': isShift1Full(selectedClinic) }"
|
||||
>
|
||||
BPJS
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="4">
|
||||
<v-btn
|
||||
color="secondary-600"
|
||||
class="text-white payment-type-btn"
|
||||
size="large"
|
||||
block
|
||||
@click="registerPatientDirectly('UMUM')"
|
||||
:disabled="isShift1Full(selectedClinic)"
|
||||
:class="{ 'btn-disabled': isShift1Full(selectedClinic) }"
|
||||
>
|
||||
UMUM / JKMM / SPM / DLL
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="4">
|
||||
<v-btn
|
||||
color="primary-600"
|
||||
class="text-white payment-type-btn"
|
||||
size="large"
|
||||
block
|
||||
@click="selectVisitType('JADWAL_LAIN')"
|
||||
>
|
||||
JADWAL LAIN
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<p v-if="isShift1Full(selectedClinic)" class="disabled-hint mt-2">
|
||||
Kuota hari ini habis
|
||||
</p>
|
||||
|
||||
<!-- Fast Track button for non-eksekutif -->
|
||||
<v-row dense class="mt-3">
|
||||
<v-col cols="4" offset="4">
|
||||
<v-btn
|
||||
color="yellow-darken-2"
|
||||
class="text-white"
|
||||
size="large"
|
||||
block
|
||||
@click="registerPatientDirectly('FAST_TRACK')"
|
||||
:disabled="isShift1Full(selectedClinic)"
|
||||
:class="{ 'btn-disabled': isShift1Full(selectedClinic) }"
|
||||
>
|
||||
Fast Track
|
||||
</v-btn>
|
||||
<p v-if="isShift1Full(selectedClinic)" class="disabled-hint">
|
||||
Kuota hari ini habis
|
||||
</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
|
||||
<!-- JADWAL LAIN button for eksekutif -->
|
||||
<v-row v-if="isEksekutif" dense class="mt-3">
|
||||
<v-col cols="12">
|
||||
<v-btn
|
||||
color="primary-600"
|
||||
class="text-white"
|
||||
size="large"
|
||||
block
|
||||
@click="selectVisitType('JADWAL_LAIN')"
|
||||
:disabled="isEksekutif && !selectedDoctor"
|
||||
:class="{ 'btn-disabled': isEksekutif && !selectedDoctor }"
|
||||
:disabled="!selectedDoctor"
|
||||
:class="{ 'btn-disabled': !selectedDoctor }"
|
||||
>
|
||||
JADWAL LAIN
|
||||
</v-btn>
|
||||
<p v-if="isEksekutif && !selectedDoctor" class="disabled-hint">
|
||||
<p v-if="!selectedDoctor" class="disabled-hint">
|
||||
Pilih dokter terlebih dahulu
|
||||
</p>
|
||||
</v-col>
|
||||
@@ -288,47 +357,6 @@
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-dialog
|
||||
v-model="showPaymentTypeDialog"
|
||||
max-width="400"
|
||||
@click:outside="showPaymentTypeDialog = false"
|
||||
>
|
||||
<v-card class="dialog-card">
|
||||
<v-card-title class="dialog-header-simple"
|
||||
>Jenis Pembayaran</v-card-title
|
||||
>
|
||||
<v-divider />
|
||||
<v-card-text class="pa-4">
|
||||
<v-btn
|
||||
color="success-600"
|
||||
class="mb-3 payment-btn text-white"
|
||||
size="x-large"
|
||||
block
|
||||
@click="selectPaymentType('BPJS')"
|
||||
>
|
||||
BPJS
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="secondary-600"
|
||||
class="payment-btn text-white"
|
||||
size="x-large"
|
||||
block
|
||||
@click="selectPaymentType('UMUM')"
|
||||
>
|
||||
UMUM / JKMM / SPM / DLL
|
||||
</v-btn>
|
||||
</v-card-text>
|
||||
<v-card-actions class="justify-center pa-4 pt-0">
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
color="neutral-600"
|
||||
@click="showPaymentTypeDialog = false"
|
||||
>
|
||||
Tutup
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<!-- Dialog Pemilihan Dokter untuk Pasien Eksekutif -->
|
||||
<v-dialog
|
||||
@@ -883,14 +911,12 @@ const filteredClinics = computed(() => {
|
||||
});
|
||||
|
||||
const showVisitTypeDialog = ref(false);
|
||||
const showPaymentTypeDialog = ref(false);
|
||||
const showBookingFormDialog = ref(false);
|
||||
const showDoctorSelectionDialog = ref(false);
|
||||
const showPrintDialog = ref(false);
|
||||
const lastRegisteredPatient = ref(null);
|
||||
const selectedClinic = ref(null);
|
||||
const selectedDoctor = ref(null);
|
||||
const pendingPaymentType = ref(null);
|
||||
const snackbar = ref(false);
|
||||
const snackbarText = ref("");
|
||||
const snackbarColor = ref("success");
|
||||
@@ -1003,9 +1029,7 @@ const selectVisitType = (type) => {
|
||||
|
||||
showVisitTypeDialog.value = false;
|
||||
|
||||
if (type === "SEKARANG") {
|
||||
showPaymentTypeDialog.value = true;
|
||||
} else if (type === "JADWAL_LAIN") {
|
||||
if (type === "JADWAL_LAIN") {
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
const tomorrowStr = tomorrow.toISOString().substring(0, 10);
|
||||
@@ -1020,14 +1044,30 @@ const selectVisitType = (type) => {
|
||||
}
|
||||
};
|
||||
|
||||
const selectPaymentType = (paymentType) => {
|
||||
showPaymentTypeDialog.value = false;
|
||||
const registerPatientDirectly = async (paymentType) => {
|
||||
// Validasi: untuk pasien Eksekutif, dokter harus dipilih
|
||||
if (isEksekutif.value && !selectedDoctor.value) {
|
||||
showSnackbar("Mohon pilih dokter terlebih dahulu", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validasi kuota
|
||||
if (isShift1Full(selectedClinic.value)) {
|
||||
showSnackbar("Kuota hari ini sudah habis", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
showVisitTypeDialog.value = false;
|
||||
|
||||
// Untuk pasien Eksekutif, dokter sudah dipilih di dialog sebelumnya
|
||||
// Untuk Reguler/BPJS, tidak perlu dokter
|
||||
const namaDokter = isEksekutif.value ? selectedDoctor.value : null;
|
||||
|
||||
registerPatient('SEKARANG', paymentType, namaDokter);
|
||||
// Handle Fast Track - paymentType akan menjadi 'UMUM' atau 'BPJS' tapi dengan flag fastTrack
|
||||
const isFastTrack = paymentType === 'FAST_TRACK';
|
||||
const actualPaymentType = isFastTrack ? 'UMUM' : paymentType;
|
||||
|
||||
await registerPatient('SEKARANG', actualPaymentType, namaDokter, isFastTrack);
|
||||
};
|
||||
|
||||
// Fungsi ini tidak lagi digunakan karena dokter dipilih di dialog konfirmasi
|
||||
@@ -1041,10 +1081,11 @@ const confirmDoctorSelection = () => {
|
||||
showDoctorSelectionDialog.value = false;
|
||||
|
||||
// Register dengan dokter yang dipilih untuk kunjungan hari ini
|
||||
registerPatient('SEKARANG', pendingPaymentType.value, selectedDoctor.value);
|
||||
// Untuk eksekutif, paymentType adalah "Eksekutif"
|
||||
registerPatient('SEKARANG', 'Eksekutif', selectedDoctor.value);
|
||||
};
|
||||
|
||||
const registerPatient = async (visitType, paymentType, namaDokter) => {
|
||||
const registerPatient = async (visitType, paymentType, namaDokter, isFastTrack = false) => {
|
||||
try {
|
||||
// Validasi bahwa fungsi registerPatientFromAnjungan ada
|
||||
if (!queueStore) {
|
||||
@@ -1068,12 +1109,14 @@ const registerPatient = async (visitType, paymentType, namaDokter) => {
|
||||
visitType,
|
||||
null,
|
||||
'Shift 1',
|
||||
namaDokter
|
||||
namaDokter,
|
||||
isFastTrack
|
||||
);
|
||||
|
||||
if (result && result.success && result.patient) {
|
||||
const doctorInfo = namaDokter ? ` dengan dokter ${namaDokter}` : '';
|
||||
const message = `Pendaftaran ${selectedClinic.value.name} untuk kunjungan HARI INI dengan pembayaran ${paymentType}${doctorInfo} berhasil diproses. Nomor antrean: ${result.patient.noAntrian?.split(" |")[0] || result.patient.noAntrian || 'N/A'}`;
|
||||
const fastTrackInfo = isFastTrack ? ' (Fast Track)' : '';
|
||||
const message = `Pendaftaran ${selectedClinic.value.name} untuk kunjungan HARI INI dengan pembayaran ${paymentType}${fastTrackInfo}${doctorInfo} berhasil diproses. Nomor antrean: ${result.patient.noAntrian?.split(" |")[0] || result.patient.noAntrian || 'N/A'}`;
|
||||
showSnackbar(message, "success");
|
||||
|
||||
// Simpan data pasien untuk print
|
||||
@@ -1094,7 +1137,6 @@ const registerPatient = async (visitType, paymentType, namaDokter) => {
|
||||
} finally {
|
||||
selectedClinic.value = null;
|
||||
selectedDoctor.value = null;
|
||||
pendingPaymentType.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -188,9 +188,12 @@ let timeInterval = null
|
||||
|
||||
const klinikPatients = computed(() => {
|
||||
// Get patients from klinik-ruang stage (created from AdminKlinikRuang)
|
||||
// Filter out finished patients (status: 'processed' or 'selesai')
|
||||
return queueStore.allPatients.filter(p =>
|
||||
p.processStage === 'klinik-ruang' &&
|
||||
p.kodeKlinik === kodeKlinik.value
|
||||
p.kodeKlinik === kodeKlinik.value &&
|
||||
p.status !== 'processed' &&
|
||||
p.status !== 'selesai'
|
||||
)
|
||||
})
|
||||
|
||||
@@ -789,12 +792,16 @@ watch(anjunganClientId, (newClientId, oldClientId) => {
|
||||
}
|
||||
|
||||
.tipe-label {
|
||||
font-size: 12px;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: var(--color-success-700);
|
||||
margin-bottom: 8px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 12px;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
padding: 8px 12px;
|
||||
background: var(--color-success-200);
|
||||
border-radius: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.empty-state-small {
|
||||
@@ -1036,6 +1043,11 @@ watch(anjunganClientId, (newClientId, oldClientId) => {
|
||||
font-size: clamp(56px, 4.17vw, 80px);
|
||||
}
|
||||
|
||||
.tipe-label {
|
||||
font-size: clamp(16px, 1.04vw, 20px);
|
||||
padding: clamp(6px, 0.42vw, 8px) clamp(10px, 0.63vw, 12px);
|
||||
}
|
||||
|
||||
.footer-stats-bar {
|
||||
padding: clamp(12px, 1.04vw, 20px) clamp(24px, 2.08vw, 40px);
|
||||
gap: clamp(16px, 1.67vw, 32px);
|
||||
@@ -1125,6 +1137,11 @@ watch(anjunganClientId, (newClientId, oldClientId) => {
|
||||
font-size: 72px;
|
||||
}
|
||||
|
||||
.tipe-label {
|
||||
font-size: 18px;
|
||||
padding: 6px 10px;
|
||||
}
|
||||
|
||||
.next-item {
|
||||
font-size: 20px;
|
||||
padding: 6px 14px;
|
||||
|
||||
@@ -1105,7 +1105,7 @@ export const useQueueStore = defineStore('queue', () => {
|
||||
};
|
||||
|
||||
// Register patient from Anjungan (onsite registration)
|
||||
const registerPatientFromAnjungan = (clinic, paymentType, visitType = 'SEKARANG', visitDate = null, shift = 'Shift 1', namaDokter = null) => {
|
||||
const registerPatientFromAnjungan = (clinic, paymentType, visitType = 'SEKARANG', visitDate = null, shift = 'Shift 1', namaDokter = null, isFastTrack = false) => {
|
||||
const newNo = allPatients.value.length > 0
|
||||
? Math.max(...allPatients.value.map(p => p.no)) + 1
|
||||
: 1;
|
||||
@@ -1124,8 +1124,10 @@ export const useQueueStore = defineStore('queue', () => {
|
||||
|
||||
// Generate nomor antrean dengan format baru: R/E + Loket (A-N) + 3 digit
|
||||
// Format: RA001 (Reguler), EA001 (Eksekutif/Grand Pavilion), RB001, RB002, dll
|
||||
// Untuk Fast Track, tambahkan prefix "F" di depan: FRA001, FEA001, dll
|
||||
const queueNumber = generateQueueNumber(clinic, paymentType, isEksekutif);
|
||||
const noAntrian = `${queueNumber} | Onsite - ${barcode}`;
|
||||
const finalQueueNumber = isFastTrack ? `F${queueNumber}` : queueNumber;
|
||||
const noAntrian = `${finalQueueNumber} | Onsite - ${barcode}`;
|
||||
|
||||
// Status awal untuk pasien dari anjungan adalah "menunggu" (belum dipanggil)
|
||||
// Hanya setelah dipanggil oleh admin loket, status berubah menjadi "waiting" (bisa check-in)
|
||||
@@ -1138,7 +1140,7 @@ export const useQueueStore = defineStore('queue', () => {
|
||||
noAntrian: noAntrian,
|
||||
shift: shift,
|
||||
klinik: clinic.name || clinic,
|
||||
fastTrack: "TIDAK", // Default, bisa diubah nanti
|
||||
fastTrack: isFastTrack ? "YA" : "TIDAK",
|
||||
pembayaran: paymentType,
|
||||
status: status,
|
||||
processStage: "loket",
|
||||
|
||||
Reference in New Issue
Block a user