update klinik ruang dan status fast track
This commit is contained in:
@@ -8,7 +8,10 @@
|
||||
<v-card
|
||||
class="patient-card"
|
||||
elevation="2"
|
||||
:class="{ 'clickable-card': isClickable }"
|
||||
:class="{
|
||||
'clickable-card': isClickable,
|
||||
'fast-track-card': isFastTrack
|
||||
}"
|
||||
@click="handleCardClick"
|
||||
v-bind="isClickable ? tooltipProps : {}"
|
||||
>
|
||||
@@ -18,7 +21,7 @@
|
||||
<div class="header-left">
|
||||
<div class="queue-number">{{ patient.noAntrian.split(" |")[0] }}</div>
|
||||
<v-icon
|
||||
v-if="patient.fastTrack === 'YA'"
|
||||
v-if="isFastTrack"
|
||||
color="warning"
|
||||
size="20"
|
||||
class="fast-track-icon"
|
||||
@@ -107,6 +110,11 @@ const isClickable = computed(() => {
|
||||
return props.patient.status === 'diloket' || props.patient.status === 'pending';
|
||||
});
|
||||
|
||||
const isFastTrack = computed(() => {
|
||||
const fastTrack = (props.patient.fastTrack ?? "").toString().trim().toUpperCase();
|
||||
return fastTrack === 'YA';
|
||||
});
|
||||
|
||||
const handleCardClick = () => {
|
||||
if (isClickable.value) {
|
||||
emit('action', props.patient, 'proses');
|
||||
@@ -161,6 +169,16 @@ const getStatusLabel = (status) => {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
&.fast-track-card {
|
||||
background: rgba(255, 230, 198, 0.35) !important;
|
||||
border-color: rgba(255, 185, 95, 0.4);
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 230, 198, 0.45) !important;
|
||||
border-color: rgba(255, 185, 95, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
|
||||
@@ -38,16 +38,6 @@
|
||||
</div>
|
||||
<div class="patient-details">
|
||||
<div class="action-buttons mt-3">
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="flat"
|
||||
size="small"
|
||||
class="text-white mr-2 mb-2"
|
||||
@click="handleCallPatientByTipe(ruang, 'Pemeriksaan Awal')"
|
||||
>
|
||||
<v-icon start size="18">mdi-bullhorn</v-icon>
|
||||
Panggil Pemeriksaan Awal
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="secondary"
|
||||
variant="flat"
|
||||
@@ -103,71 +93,78 @@
|
||||
:key="patient.no"
|
||||
:class="getPatientCardClass(patient)"
|
||||
>
|
||||
<div class="patient-queue-number">
|
||||
{{ patient.noAntrian?.split(" |")[0] || patient.barcode || '-' }}
|
||||
<!-- Left Section: Number and Status -->
|
||||
<div class="patient-card-left">
|
||||
<div class="patient-queue-number">
|
||||
{{ patient.noAntrian?.split(" |")[0] || patient.barcode || '-' }}
|
||||
</div>
|
||||
<div class="patient-queue-status-chips">
|
||||
<!-- Compact status indicators - only show icons if called -->
|
||||
<v-chip
|
||||
v-if="patient.calledPemeriksaanAwal"
|
||||
size="x-small"
|
||||
color="primary"
|
||||
class="status-chip"
|
||||
>
|
||||
<v-icon start size="10">mdi-check-circle</v-icon>
|
||||
P.Awal
|
||||
</v-chip>
|
||||
<v-chip
|
||||
v-if="patient.calledTindakan"
|
||||
size="x-small"
|
||||
color="secondary"
|
||||
class="status-chip"
|
||||
>
|
||||
<v-icon start size="10">mdi-check-circle</v-icon>
|
||||
Tindakan
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="patient-queue-info">
|
||||
<!-- Penanda Panggilan Pemeriksaan Awal -->
|
||||
<v-chip
|
||||
v-if="patient.calledPemeriksaanAwal"
|
||||
size="x-small"
|
||||
color="primary"
|
||||
class="mr-1"
|
||||
>
|
||||
<v-icon start size="12">mdi-check-circle</v-icon>
|
||||
Pemeriksaan Awal
|
||||
</v-chip>
|
||||
<!-- Penanda Panggilan Tindakan -->
|
||||
<v-chip
|
||||
v-if="patient.calledTindakan"
|
||||
size="x-small"
|
||||
color="secondary"
|
||||
class="mr-1"
|
||||
>
|
||||
<v-icon start size="12">mdi-check-circle</v-icon>
|
||||
Tindakan
|
||||
</v-chip>
|
||||
<!-- Penanda Status Pending -->
|
||||
<v-chip
|
||||
v-if="patient.status === 'pending'"
|
||||
size="x-small"
|
||||
color="error"
|
||||
class="mr-1"
|
||||
>
|
||||
<v-icon start size="12">mdi-pause-circle</v-icon>
|
||||
Pending
|
||||
</v-chip>
|
||||
</div>
|
||||
<div class="patient-queue-actions">
|
||||
<v-btn
|
||||
icon
|
||||
size="x-small"
|
||||
variant="text"
|
||||
@click="showPatientDetail(patient)"
|
||||
>
|
||||
<v-icon size="16">mdi-eye</v-icon>
|
||||
<v-tooltip activator="parent">Lihat Detail</v-tooltip>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
icon
|
||||
size="x-small"
|
||||
variant="text"
|
||||
color="warning"
|
||||
@click="handlePindahRuang(patient, ruang)"
|
||||
>
|
||||
<v-icon size="16">mdi-swap-horizontal</v-icon>
|
||||
<v-tooltip activator="parent">Pindah Ruang</v-tooltip>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
size="x-small"
|
||||
variant="flat"
|
||||
color="primary"
|
||||
class="text-white"
|
||||
@click="patient.status === 'pending' ? handleProcessPendingPatient(ruang, patient) : handleProcessPatient(ruang, patient)"
|
||||
>
|
||||
<v-icon start size="14">mdi-play</v-icon>
|
||||
Proses
|
||||
</v-btn>
|
||||
|
||||
<!-- Right Section: Actions -->
|
||||
<div class="patient-card-right">
|
||||
<!-- Action Buttons -->
|
||||
<div class="patient-queue-actions">
|
||||
<v-btn
|
||||
icon
|
||||
size="x-small"
|
||||
variant="text"
|
||||
@click="showPatientDetail(patient)"
|
||||
>
|
||||
<v-icon size="16">mdi-eye</v-icon>
|
||||
<v-tooltip activator="parent">Lihat Detail</v-tooltip>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
icon
|
||||
size="x-small"
|
||||
variant="text"
|
||||
color="warning"
|
||||
@click="handlePindahRuang(patient, ruang)"
|
||||
>
|
||||
<v-icon size="16">mdi-swap-horizontal</v-icon>
|
||||
<v-tooltip activator="parent">Pindah Ruang</v-tooltip>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
size="x-small"
|
||||
variant="flat"
|
||||
color="primary"
|
||||
class="text-white call-btn"
|
||||
@click="handleCallPatientFromList(ruang, patient, 'Pemeriksaan Awal')"
|
||||
>
|
||||
<v-icon start size="14">mdi-bullhorn</v-icon>
|
||||
Pemeriksaan Awal
|
||||
</v-btn>
|
||||
<v-btn
|
||||
size="x-small"
|
||||
variant="flat"
|
||||
color="success"
|
||||
class="text-white"
|
||||
@click="patient.status === 'pending' ? handleProcessPendingPatient(ruang, patient) : handleProcessPatient(ruang, patient)"
|
||||
>
|
||||
<v-icon start size="14">mdi-play</v-icon>
|
||||
Proses
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -602,15 +599,31 @@ const confirmPindahRuang = () => {
|
||||
selectedRuangBaru.value = null;
|
||||
};
|
||||
|
||||
const handleCallPatientByTipe = (ruang, tipeLayanan) => {
|
||||
const current = getCurrentProcessingForRoom(ruang);
|
||||
if (!current || !current.no) {
|
||||
showSnackbar('Tidak ada pasien yang sedang diproses', 'error');
|
||||
// Handle call patient from list (dari card pasien di daftar)
|
||||
const handleCallPatientFromList = (ruang, patient, tipeLayanan) => {
|
||||
if (!patient || !patient.no) {
|
||||
showSnackbar('Pasien tidak valid', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Pastikan pasien sudah diproses terlebih dahulu
|
||||
const current = getCurrentProcessingForRoom(ruang);
|
||||
if (!current || current.no !== patient.no) {
|
||||
// Jika pasien belum diproses, proses dulu
|
||||
const processResult = queueStore.processPatientKlinikRuang(
|
||||
patient,
|
||||
'proses',
|
||||
klinikData.value.kodeKlinik,
|
||||
ruang.nomorRuang
|
||||
);
|
||||
if (!processResult.success) {
|
||||
showSnackbar(processResult.message, 'error');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update tipeLayanan pasien untuk tracking panggilan terakhir
|
||||
const patientIndex = queueStore.allPatients.findIndex(p => p.no === current.no);
|
||||
const patientIndex = queueStore.allPatients.findIndex(p => p.no === patient.no);
|
||||
if (patientIndex === -1) {
|
||||
showSnackbar('Pasien tidak ditemukan', 'error');
|
||||
return;
|
||||
@@ -737,6 +750,50 @@ const getStatusLabel = (status) => {
|
||||
};
|
||||
|
||||
|
||||
// Handle call patient by tipe (untuk pasien yang sedang diproses)
|
||||
const handleCallPatientByTipe = (ruang, tipeLayanan) => {
|
||||
const current = getCurrentProcessingForRoom(ruang);
|
||||
if (!current || !current.no) {
|
||||
showSnackbar('Tidak ada pasien yang sedang diproses', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update tipeLayanan pasien untuk tracking panggilan terakhir
|
||||
const patientIndex = queueStore.allPatients.findIndex(p => p.no === current.no);
|
||||
if (patientIndex === -1) {
|
||||
showSnackbar('Pasien tidak ditemukan', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update tracking panggilan berdasarkan tipeLayanan
|
||||
// Update tipeLayanan pasien agar muncul di kolom yang sesuai di Anjungan
|
||||
const updateData = {
|
||||
...queueStore.allPatients[patientIndex],
|
||||
status: 'di-loket',
|
||||
tipeLayanan: tipeLayanan, // Update tipeLayanan untuk display di Anjungan
|
||||
lastCalledAt: new Date().toISOString(),
|
||||
lastCalledTipeLayanan: tipeLayanan
|
||||
};
|
||||
|
||||
// Set penanda panggilan sesuai tipeLayanan
|
||||
if (tipeLayanan === 'Pemeriksaan Awal') {
|
||||
updateData.calledPemeriksaanAwal = true;
|
||||
} else if (tipeLayanan === 'Tindakan') {
|
||||
updateData.calledTindakan = true;
|
||||
}
|
||||
|
||||
queueStore.allPatients[patientIndex] = updateData;
|
||||
|
||||
// Update current processing (tetap 1 pasien, tidak dipisah per tipe)
|
||||
const key = `klinik-ruang-${klinikData.value.kodeKlinik}-${ruang.nomorRuang}`;
|
||||
queueStore.currentProcessingPatient[key] = queueStore.allPatients[patientIndex];
|
||||
|
||||
const patientCode = queueStore.allPatients[patientIndex].noAntrian?.split(" |")[0] ||
|
||||
queueStore.allPatients[patientIndex].barcode ||
|
||||
'-';
|
||||
showSnackbar(`Memanggil pasien ${patientCode} untuk ${tipeLayanan}`, 'success');
|
||||
};
|
||||
|
||||
const handlePatientAction = (ruang, action) => {
|
||||
const current = getCurrentProcessingForRoom(ruang);
|
||||
if (!current) return;
|
||||
@@ -822,12 +879,16 @@ const paginatedAllPatients = (ruang) => {
|
||||
// Helper untuk menentukan class card berdasarkan status pasien
|
||||
const getPatientCardClass = (patient) => {
|
||||
const baseClass = 'patient-queue-item';
|
||||
// Pasien yang sudah digenerate/diproses & pending: warna berbeda
|
||||
if (patient.tipeLayanan || patient.status === 'pending') {
|
||||
// Pasien dengan status pending: warna merah
|
||||
if (patient.status === 'pending') {
|
||||
return `${baseClass} patient-queue-item-pending-status`;
|
||||
}
|
||||
// Pasien yang sudah digenerate/diproses: warna berbeda
|
||||
if (patient.tipeLayanan || patient.calledPemeriksaanAwal || patient.calledTindakan) {
|
||||
return `${baseClass} patient-queue-item-processed`;
|
||||
}
|
||||
// Pasien yang perlu digenerate: warna default
|
||||
return `${baseClass} patient-queue-item-pending`;
|
||||
return `${baseClass} patient-queue-item-default`;
|
||||
};
|
||||
|
||||
|
||||
@@ -1188,57 +1249,122 @@ onMounted(() => {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
gap: 8px;
|
||||
gap: 12px;
|
||||
min-height: 56px;
|
||||
}
|
||||
|
||||
/* Pasien yang sudah digenerate/diproses & pending */
|
||||
/* Pasien dengan status pending: warna merah */
|
||||
.patient-queue-item-pending-status {
|
||||
background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%);
|
||||
border: 2px solid #ef5350;
|
||||
}
|
||||
|
||||
.patient-queue-item-pending-status:hover {
|
||||
background: linear-gradient(135deg, #ffcdd2 0%, #ef9a9a 100%);
|
||||
border-color: #e53935;
|
||||
}
|
||||
|
||||
/* Pasien yang sudah digenerate/diproses */
|
||||
.patient-queue-item-processed {
|
||||
background: var(--color-primary-50);
|
||||
border: 1px solid var(--color-primary-200);
|
||||
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
|
||||
border: 1px solid #90caf9;
|
||||
}
|
||||
|
||||
.patient-queue-item-processed:hover {
|
||||
background: var(--color-primary-100);
|
||||
border-color: var(--color-primary-400);
|
||||
background: linear-gradient(135deg, #bbdefb 0%, #90caf9 100%);
|
||||
border-color: #64b5f6;
|
||||
}
|
||||
|
||||
/* Pasien yang perlu digenerate */
|
||||
.patient-queue-item-pending {
|
||||
/* Pasien default */
|
||||
.patient-queue-item-default {
|
||||
background: var(--color-neutral-100);
|
||||
border: 1px solid var(--color-neutral-300);
|
||||
}
|
||||
|
||||
.patient-queue-item-pending:hover {
|
||||
background: var(--color-warning-100);
|
||||
border-color: var(--color-warning-400);
|
||||
.patient-queue-item-default:hover {
|
||||
background: var(--color-neutral-200);
|
||||
border-color: var(--color-neutral-400);
|
||||
}
|
||||
|
||||
/* Left Section: Number and Status */
|
||||
.patient-card-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
min-width: 100px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.patient-queue-number {
|
||||
font-size: 14px;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: var(--color-neutral-900);
|
||||
min-width: 80px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.patient-queue-info {
|
||||
.patient-queue-status-chips {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.status-chip {
|
||||
font-size: 10px !important;
|
||||
height: 18px !important;
|
||||
padding: 0 6px !important;
|
||||
}
|
||||
|
||||
.status-chip .v-icon {
|
||||
font-size: 10px !important;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
/* Right Section: Actions */
|
||||
.patient-card-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.patient-queue-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.patient-queue-actions .v-btn {
|
||||
text-transform: none;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.call-btn {
|
||||
min-width: 130px;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.call-btn .v-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
/* Responsive untuk card */
|
||||
@media (max-width: 1400px) {
|
||||
.call-btn {
|
||||
min-width: 100px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.call-btn .v-icon {
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1400px) {
|
||||
|
||||
@@ -514,15 +514,11 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => {
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin: 0 -8px;
|
||||
}
|
||||
|
||||
.content-grid > .v-col {
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
min-width: 0; /* Prevent flex item overflow */
|
||||
}
|
||||
|
||||
.content-grid > .v-col:first-child {
|
||||
@@ -570,8 +566,6 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => {
|
||||
position: sticky;
|
||||
top: 16px;
|
||||
align-self: flex-start;
|
||||
max-height: calc(100vh - 32px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.filters {
|
||||
|
||||
Reference in New Issue
Block a user