diff --git a/assets/scss/_colors.scss b/assets/scss/_colors.scss index 0249914..25c5fb9 100644 --- a/assets/scss/_colors.scss +++ b/assets/scss/_colors.scss @@ -16,6 +16,7 @@ $primary-400: #7898EC; $primary-300: #9AB2F1; $primary-200: #BBCBF5; $primary-100: #DDE5FA; +$primary-50: #EFF3FD; $secondary-700: #E65A0D; $secondary-600: #F16F29; @@ -24,6 +25,7 @@ $secondary-400: #FF9D67; $secondary-300: #FFB58D; $secondary-200: #FFCEB3; $secondary-100: #FFE6D9; +$secondary-50: #FFF3EC; $success-700: #008D65; $success-600: #33A484; @@ -61,6 +63,7 @@ $danger-100: #FBE9E8; --color-primary-300: #{$primary-300}; --color-primary-200: #{$primary-200}; --color-primary-100: #{$primary-100}; + --color-primary-50: #{$primary-50}; // Secondary --color-secondary-700: #{$secondary-700}; @@ -70,6 +73,7 @@ $danger-100: #FBE9E8; --color-secondary-300: #{$secondary-300}; --color-secondary-200: #{$secondary-200}; --color-secondary-100: #{$secondary-100}; + --color-secondary-50: #{$secondary-50}; // Success --color-success-700: #{$success-700}; @@ -142,6 +146,7 @@ $colors: ( 'primary-300': $primary-300, 'primary-200': $primary-200, 'primary-100': $primary-100, + 'primary-50': $primary-50, 'secondary-700': $secondary-700, 'secondary-600': $secondary-600, 'secondary-500': $secondary-500, @@ -149,6 +154,7 @@ $colors: ( 'secondary-300': $secondary-300, 'secondary-200': $secondary-200, 'secondary-100': $secondary-100, + 'secondary-50': $secondary-50, 'success-700': $success-700, 'success-600': $success-600, 'success-500': $success-500, diff --git a/components/common/PageHeader.vue b/components/common/PageHeader.vue index daa6df9..01206b9 100644 --- a/components/common/PageHeader.vue +++ b/components/common/PageHeader.vue @@ -60,17 +60,6 @@ defineEmits(['add-click']); \ No newline at end of file diff --git a/components/features/queue/CurrentPatientCard.vue b/components/features/queue/CurrentPatientCard.vue index 3a6e34b..df30670 100644 --- a/components/features/queue/CurrentPatientCard.vue +++ b/components/features/queue/CurrentPatientCard.vue @@ -5,8 +5,8 @@
SEDANG DIPROSES
-
{{ patient.noAntrian.split(" |")[0] }}
-
-
{{ patient.barcode }}
-
{{ patient.klinik }} | {{ patient.pembayaran }}
+
+
+
{{ patient.noAntrian.split(" |")[0] }}
+
+ + mdi-flash + +
+
+
+ + + + + + + + + + + + +
+
+
+
{{ patient.barcode }}
+
{{ patient.klinik }} | {{ patient.pembayaran }}
-
- - mdi-check - Selesai - - - mdi-clock-alert - Terlambat - - - mdi-pause - Pending - - - mdi-swap-horizontal - {{ changeButtonText }} - +
+
+ + mdi-door + Buat Antrean Ruang + + + mdi-clipboard-pulse + Buat Antrean Penunjang + +
@@ -69,7 +147,9 @@ \ No newline at end of file diff --git a/components/features/queue/PatientCard.vue b/components/features/queue/PatientCard.vue index ec5724d..5256942 100644 --- a/components/features/queue/PatientCard.vue +++ b/components/features/queue/PatientCard.vue @@ -20,14 +20,18 @@
{{ patient.noAntrian.split(" |")[0] }}
- - mdi-flash - + + mdi-flash + +
- +
-
- Jam Panggil: - {{ patient.jamPanggil }} -
- -
- Klinik: - - {{ patient.klinik }} - -
- -
- Tipe Layanan: +
- {{ patient.tipeLayanan }} + {{ patient.klinik }} + + + + {{ displayJenisPasien }}
- -
- Ruang: - {{ patient.ruang }} -
- -
- Pembayaran: - {{ patient.pembayaran }} + +
+ mdi-doctor + {{ patient.namaDokter }}
@@ -115,6 +111,53 @@ const isFastTrack = computed(() => { return fastTrack === 'YA'; }); +const isEksekutif = computed(() => { + const pembayaran = (props.patient.pembayaran ?? "").toString().trim().toUpperCase(); + return pembayaran === 'EKSEKUTIF'; +}); + +// Computed untuk menentukan jenis pasien yang ditampilkan +const displayJenisPasien = computed(() => { + // Prioritas 1: Tipe Layanan jika ada + if (props.patient.tipeLayanan) { + return props.patient.tipeLayanan; + } + // Prioritas 2: Eksekutif jika pasien eksekutif + if (isEksekutif.value) { + return 'Eksekutif'; + } + // Prioritas 3: Tampilkan pembayaran sebagai fallback + if (props.patient.pembayaran) { + return props.patient.pembayaran; + } + return null; +}); + +// Fungsi untuk menentukan color chip berdasarkan jenis pasien +const getJenisPasienColor = (jenis) => { + if (jenis === 'Pemeriksaan Awal') return 'primary'; + if (jenis === 'Tindakan') return 'secondary'; + if (jenis === 'Eksekutif') return 'warning'; + if (jenis === 'Fast Track') return 'warning'; + // Untuk pembayaran biasa (BPJS, UMUM), gunakan neutral-600 untuk kontras + return 'success-500'; +}; + +// Fungsi untuk menentukan variant chip berdasarkan jenis pasien +const getJenisPasienVariant = (jenis) => { + // Semua jenis pasien menggunakan flat (filled) untuk kontras dengan klinik (outlined) + return 'flat'; +}; + +// Fungsi untuk menentukan class chip berdasarkan jenis pasien +const getJenisPasienClass = (jenis) => { + if (jenis === 'Pemeriksaan Awal' || jenis === 'Tindakan' || jenis === 'Eksekutif' || jenis === 'Fast Track') { + return 'text-white layanan-chip'; + } + // Untuk pembayaran biasa (BPJS, UMUM), gunakan text putih untuk kontras dengan background + return 'text-white layanan-chip'; +}; + const handleCardClick = () => { if (isClickable.value) { emit('action', props.patient, 'proses'); @@ -171,12 +214,12 @@ const getStatusLabel = (status) => { } &.fast-track-card { - background: rgba(255, 230, 198, 0.35) !important; - border-color: rgba(255, 185, 95, 0.4); + background: #FBE9E8 !important; + border-color: rgba(255, 132, 65, 0.5); &:hover { - background: rgba(255, 230, 198, 0.45) !important; - border-color: rgba(255, 185, 95, 0.5); + background: #F1B3AE !important; + border-color: rgba(255, 132, 65, 0.6); } } } @@ -201,17 +244,24 @@ const getStatusLabel = (status) => { color: var(--color-neutral-900); } -.fast-track-icon { - animation: pulse 2s ease-in-out infinite; +.fast-track-icon-wrapper { + width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + background: rgba(239, 83, 80, 0.15); + border: 2px solid rgba(229, 57, 53, 0.4); + transition: all 0.2s ease; + flex-shrink: 0; + box-shadow: 0 2px 8px rgba(229, 57, 53, 0.2); } -@keyframes pulse { - 0%, 100% { - opacity: 1; - } - 50% { - opacity: 0.6; - } + +.fast-track-icon-wrapper .fast-track-icon { + color: #E53935 !important; + transition: all 0.2s ease; } .status-chip { @@ -223,46 +273,45 @@ const getStatusLabel = (status) => { .patient-info { display: flex; flex-direction: column; - gap: 10px; + /* Tinggi dinamis berdasarkan konten - card tanpa dokter akan lebih compact */ } -.info-row { +.info-chips-row { display: flex; - justify-content: space-between; align-items: center; - font-size: 13px; gap: 8px; -} - -.payment-info { - display: flex; - align-items: center; - gap: 4px; -} - -.fast-track-badge { - font-size: 10px; - font-weight: 700; - height: 20px; - padding: 0 6px; -} - -.info-label { - color: var(--color-neutral-600); - font-weight: 500; - min-width: 90px; -} - -.info-value { - color: var(--color-neutral-900); - font-weight: 600; - text-align: right; + flex-wrap: wrap; } .klinik-chip { font-size: 11px; font-weight: 600; - border: 1.5px solid currentColor; + height: 24px; + border-color: var(--color-neutral-600) !important; + color: var(--color-neutral-900) !important; + background-color: transparent !important; +} + +.layanan-chip { + font-size: 11px; + font-weight: 600; + height: 24px; +} + +.doctor-info { + display: flex; + align-items: center; + gap: 6px; +} + +.doctor-icon { + flex-shrink: 0; +} + +.doctor-name { + font-size: 12px; + font-weight: 600; + color: var(--color-primary-600); } .card-actions .v-btn { diff --git a/components/features/queue/TabelPatientData.vue b/components/features/queue/TabelPatientData.vue index dcb35ea..d597a5e 100644 --- a/components/features/queue/TabelPatientData.vue +++ b/components/features/queue/TabelPatientData.vue @@ -200,7 +200,7 @@ const props = defineProps({ }, itemsPerPage: { type: Number, - default: 9 + default: 12 }, statusLabels: { type: Object, diff --git a/pages/AdminKlinikRuang/[kodeKlinik].vue b/pages/AdminKlinikRuang/[kodeKlinik].vue index 97acc91..6fd58b2 100644 --- a/pages/AdminKlinikRuang/[kodeKlinik].vue +++ b/pages/AdminKlinikRuang/[kodeKlinik].vue @@ -157,8 +157,36 @@ >
-
- {{ patient.noAntrian?.split(" |")[0] || patient.barcode || '-' }} +
+
+ {{ patient.noAntrian?.split(" |")[0] || patient.barcode || '-' }} +
+
+
+ + mdi-pause + +
+
+ + mdi-flash + +
+
@@ -584,7 +612,7 @@ Fast Track @@ -1571,16 +1599,18 @@ const paginatedAllPatients = (ruang) => { // Helper untuk menentukan class card berdasarkan status pasien const getPatientCardClass = (patient) => { const baseClass = 'patient-queue-item'; - // Pasien dengan status pending: warna merah - if (patient.status === 'pending') { - return `${baseClass} patient-queue-item-pending-status`; - } + const isFastTrack = (patient.fastTrack ?? '').toString().trim().toUpperCase() === 'YA'; + // Pasien yang sudah digenerate/diproses: warna berbeda if (patient.tipeLayanan || patient.calledPemeriksaanAwal || patient.calledTindakan) { - return `${baseClass} patient-queue-item-processed`; + return isFastTrack + ? `${baseClass} patient-queue-item-processed patient-queue-item-fast-track` + : `${baseClass} patient-queue-item-processed`; } - // Pasien yang perlu digenerate: warna default - return `${baseClass} patient-queue-item-default`; + // Pasien yang perlu digenerate: warna default atau fast track + return isFastTrack + ? `${baseClass} patient-queue-item-default patient-queue-item-fast-track` + : `${baseClass} patient-queue-item-default`; }; @@ -2111,20 +2141,6 @@ onMounted(() => { box-sizing: border-box; } -/* Pasien dengan status pending: warna merah soft */ -.patient-queue-item-pending-status { - background: var(--color-danger-200) !important; - border: 1px solid var(--color-danger-300) !important; - cursor: default; - transition: none !important; -} - -.patient-queue-item-pending-status:hover { - background: var(--color-danger-200) !important; - border-color: var(--color-danger-300) !important; - transform: none !important; - box-shadow: none !important; -} /* Pasien yang sudah digenerate/diproses */ .patient-queue-item-processed { @@ -2148,6 +2164,39 @@ onMounted(() => { border-color: var(--color-neutral-400); } +/* Pasien fast track - harus setelah processed dan default agar bisa override */ +.patient-queue-item-fast-track { + background: #FBE9E8 !important; + border-color: rgba(255, 132, 65, 0.5) !important; +} + +.patient-queue-item-fast-track:hover { + background: #F1B3AE !important; + border-color: rgba(255, 132, 65, 0.6) !important; +} + +/* Fast track dengan processed - override processed styling */ +.patient-queue-item-processed.patient-queue-item-fast-track { + background: #FBE9E8 !important; + border-color: rgba(255, 132, 65, 0.5) !important; +} + +.patient-queue-item-processed.patient-queue-item-fast-track:hover { + background: #F1B3AE !important; + border-color: rgba(255, 132, 65, 0.6) !important; +} + +/* Fast track dengan default - override default styling */ +.patient-queue-item-default.patient-queue-item-fast-track { + background: #FBE9E8 !important; + border-color: rgba(255, 132, 65, 0.5) !important; +} + +.patient-queue-item-default.patient-queue-item-fast-track:hover { + background: #F1B3AE !important; + border-color: rgba(255, 132, 65, 0.6) !important; +} + /* Left Section: Number and Status */ .patient-card-left { display: flex; @@ -2159,6 +2208,12 @@ onMounted(() => { flex: 0 0 auto; } +.patient-queue-number-wrapper { + display: flex; + align-items: center; + gap: 8px; +} + .patient-queue-number { font-size: 20px; line-height: 28px; @@ -2170,6 +2225,50 @@ onMounted(() => { white-space: nowrap; } +.patient-status-icons { + display: flex; + align-items: center; + gap: 6px; + flex-shrink: 0; +} + +.status-icon-wrapper { + width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + flex-shrink: 0; +} + +.status-icon-wrapper .status-icon { + transition: all 0.2s ease; +} + +/* Fast Track Icon Styling */ +.status-icon-fast-track { + background: rgba(239, 83, 80, 0.15); + border: 2px solid rgba(229, 57, 53, 0.4); + box-shadow: 0 2px 8px rgba(229, 57, 53, 0.2); +} + +.status-icon-fast-track .status-icon { + color: #E53935 !important; +} + +/* Pending Icon Styling */ +.status-icon-pending { + background: rgba(222, 71, 59, 0.15); + border: 2px solid rgba(216, 39, 25, 0.4); + box-shadow: 0 2px 8px rgba(216, 39, 25, 0.2); +} + +.status-icon-pending .status-icon { + color: var(--color-danger-600) !important; +} + .patient-queue-status-chips { display: flex; gap: 6px; diff --git a/pages/AdminLoket.vue b/pages/AdminLoket.vue index 525ee39..38f0477 100644 --- a/pages/AdminLoket.vue +++ b/pages/AdminLoket.vue @@ -23,6 +23,8 @@ @change-klinik="showChangeKlinikDialog = true" @process-next="handleProcessNext" @call="handleCallPatient" + @open-klinik-ruang="openKlinikRuangDialog" + @open-penunjang="openPenunjangDialog" /> @@ -34,37 +36,6 @@ :has-next="!!nextPatient" @call="handleCall" /> - - -
- - - - mdi-door - Buat Antrean Ruang - - - - - - mdi-clipboard-pulse - Buat Antrean Penunjang - - - -
@@ -536,54 +507,6 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => { padding-right: 0; } -.create-buttons { - width: 100%; - box-sizing: border-box; - overflow: hidden; -} - -.create-buttons :deep(.v-row) { - margin: 0; - width: 100%; - box-sizing: border-box; -} - -.create-buttons :deep(.v-col) { - box-sizing: border-box; -} - -.create-buttons :deep(.v-col:first-child) { - padding-left: 0; -} - -.create-buttons :deep(.v-col:last-child) { - padding-right: 0; -} - -.create-buttons .v-btn { - text-transform: none; - font-weight: 600; - font-size: 16px; - line-height: 24px; - font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; - width: 100%; - max-width: 100%; - box-sizing: border-box; - min-width: 0; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - transition: all 0.2s ease; -} - -.create-buttons .v-btn:hover { - transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); -} - -.create-buttons .v-btn:active { - transform: translateY(0); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); -} - .sticky-wrapper { position: sticky; top: 16px;