From f3e90adea39ea965109aea8ecd4533844c9f3cda Mon Sep 17 00:00:00 2001 From: bagus-arie05 Date: Wed, 14 Jan 2026 08:25:47 +0700 Subject: [PATCH] update warna dan klinik ruang --- components/checkin/CheckInDialog.vue | 12 +- components/common/PageHeader.vue | 20 +- components/common/SelectionDialog.vue | 64 +- .../features/queue/CurrentPatientCard.vue | 71 +- .../features/queue/QueueActionsCard.vue | 14 + composables/useCheckInHistory.ts | 6 +- composables/useThermalPrint.ts | 58 +- pages/AdminKlinikRuang/[kodeKlinik].vue | 1331 +++++++++++++---- pages/AdminLoket.vue | 59 +- pages/Anjungan/AdminAnjungan.vue | 19 +- pages/Anjungan/Anjungan/[id].vue | 19 +- pages/Anjungan/Anjungan/index.vue | 16 +- pages/Anjungan/AntreanMasuk/[id].vue | 20 +- pages/Anjungan/AntrianKlinik/[id].vue | 20 +- .../AntrianKlinikRuang/[kodeKlinik].vue | 25 +- pages/Anjungan/AntrianLoket/[id].vue | 20 +- pages/Anjungan/AntrianPenunjang.vue | 22 +- pages/CheckInPasien/checkIn.vue | 25 +- stores/klinikruangstore.js | 8 +- stores/ruangStore.js | 8 +- 20 files changed, 1492 insertions(+), 345 deletions(-) diff --git a/components/checkin/CheckInDialog.vue b/components/checkin/CheckInDialog.vue index 59d426e..a3de6ff 100644 --- a/components/checkin/CheckInDialog.vue +++ b/components/checkin/CheckInDialog.vue @@ -96,7 +96,7 @@

Waktu Scan

-

{{ new Date().toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' }) }}

+

{{ getCurrentTime() }}

@@ -164,6 +164,16 @@ const handleClose = () => { emit('close') emit('update:modelValue', false) } + +const getCurrentTime = () => { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = new Date().toLocaleTimeString('id-ID', { + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }) + return timeString.replace(/\./g, ':') +} \ No newline at end of file diff --git a/components/features/queue/CurrentPatientCard.vue b/components/features/queue/CurrentPatientCard.vue index 7cd364f..3a6e34b 100644 --- a/components/features/queue/CurrentPatientCard.vue +++ b/components/features/queue/CurrentPatientCard.vue @@ -120,7 +120,20 @@ defineEmits(['action', 'change-klinik', 'process-next', 'call']); .call-button { text-transform: none; font-weight: 600; + font-size: 14px; + line-height: 20px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; +} + +.call-button:hover { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); +} + +.call-button:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } .patient-details { @@ -142,15 +155,16 @@ defineEmits(['action', 'change-klinik', 'process-next', 'call']); .patient-number { font-size: 28px; - font-weight: 800; + line-height: 36px; + font-weight: 700; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: var(--color-neutral-900); - line-height: 1; } .patient-info-text { - font-size: 13px; + font-size: 14px; + line-height: 20px; color: var(--color-neutral-700); - line-height: 1.5; } .action-grid { @@ -160,13 +174,58 @@ defineEmits(['action', 'change-klinik', 'process-next', 'call']); margin-top: 12px; } +.action-grid .v-btn { + text-transform: none; + font-weight: 600; + font-size: 16px; + line-height: 24px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; +} + +.action-grid .v-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); +} + +.action-grid .v-btn:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.action-grid .v-btn:disabled { + opacity: 0.6; + cursor: not-allowed; + transform: none; +} + .empty-state { text-align: center; padding: 32px 16px; } +.empty-state .v-btn { + text-transform: none; + font-weight: 600; + font-size: 16px; + line-height: 24px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; +} + +.empty-state .v-btn:hover:not(:disabled) { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); +} + +.empty-state .v-btn:active:not(:disabled) { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + .empty-text { - font-size: 13px; + font-size: 14px; + line-height: 20px; color: var(--color-neutral-600); margin-top: 8px; } @@ -181,8 +240,10 @@ defineEmits(['action', 'change-klinik', 'process-next', 'call']); .info-text { font-size: 12px; + line-height: 16px; color: var(--color-neutral-700); font-weight: 600; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; } @media (max-width: 960px) { diff --git a/components/features/queue/QueueActionsCard.vue b/components/features/queue/QueueActionsCard.vue index 7482220..a4c7e33 100644 --- a/components/features/queue/QueueActionsCard.vue +++ b/components/features/queue/QueueActionsCard.vue @@ -188,8 +188,22 @@ defineEmits(['call']); .call-buttons .v-btn { font-size: 16px; + line-height: 24px; font-weight: 700; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; height: 44px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; +} + +.call-buttons .v-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); +} + +.call-buttons .v-btn:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } @media (max-width: 960px) { diff --git a/composables/useCheckInHistory.ts b/composables/useCheckInHistory.ts index 897a180..441b2d8 100644 --- a/composables/useCheckInHistory.ts +++ b/composables/useCheckInHistory.ts @@ -78,7 +78,7 @@ export const useCheckInHistory = () => { data: qrData, timestamp: new Date().toISOString(), date: new Date().toLocaleDateString('id-ID'), - time: new Date().toLocaleTimeString('id-ID') + time: new Date().toLocaleTimeString('id-ID').replace(/\./g, ':') }) // Simpan maksimal item sesuai constant @@ -227,11 +227,13 @@ export const useCheckInHistory = () => { const formatDateTime = (dateString: string) => { const date = new Date(dateString) - return date.toLocaleTimeString('id-ID', { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = date.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit' }) + return timeString.replace(/\./g, ':') } const formatDate = (dateString: string) => { diff --git a/composables/useThermalPrint.ts b/composables/useThermalPrint.ts index 72ec848..b6d9dc9 100644 --- a/composables/useThermalPrint.ts +++ b/composables/useThermalPrint.ts @@ -85,17 +85,20 @@ export const useThermalPrint = () => { if (isNaN(date.getTime())) { return new Date().toLocaleTimeString('id-ID', { hour: '2-digit', - minute: '2-digit' + minute: '2-digit', + second: '2-digit' }); } return date.toLocaleTimeString('id-ID', { hour: '2-digit', - minute: '2-digit' + minute: '2-digit', + second: '2-digit' }); } catch (error) { return new Date().toLocaleTimeString('id-ID', { hour: '2-digit', - minute: '2-digit' + minute: '2-digit', + second: '2-digit' }); } }; @@ -155,6 +158,7 @@ export const useThermalPrint = () => { margin: 0; padding: 0; box-sizing: border-box; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; } body { @@ -162,10 +166,10 @@ export const useThermalPrint = () => { max-width: 80mm; margin: 0; padding: 2mm 4mm 6mm 4mm; - font-family: 'Courier New', monospace; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 12px; font-weight: bold; - line-height: 1.2; + line-height: 1.0; background: white; color: black; } @@ -180,36 +184,39 @@ export const useThermalPrint = () => { } .header { - margin-bottom: 3mm; + margin-bottom: 2mm; border-bottom: 2px solid #000; - padding-bottom: 2mm; + padding-bottom: 1mm; margin-top: 0; } .hospital-name { font-size: 14px; font-weight: bold; - margin-bottom: 1mm; + margin-bottom: 0.5mm; text-transform: uppercase; letter-spacing: 1px; + line-height: 1.0; } .hospital-address { font-size: 10px; font-weight: bold; - margin-bottom: 1mm; + margin-bottom: 0.5mm; + line-height: 1.0; } .ticket-title { font-size: 12px; font-weight: bold; - margin-top: 2mm; + margin-top: 1mm; text-transform: uppercase; + line-height: 1.0; } .qr-code-section { - margin-top: -1.5mm; - margin-bottom: 1mm; + margin-top: -1mm; + margin-bottom: 0.5mm; text-align: center; } @@ -231,25 +238,27 @@ export const useThermalPrint = () => { .barcode-number { font-size: 10px; font-weight: bold; - margin-top: -1mm; + margin-top: -0.5mm; word-break: break-all; + line-height: 1.0; } .info-section { - margin-top: 3mm; + margin-top: 2mm; text-align: left; border-top: 1px dashed #000; - padding-top: 2mm; + padding-top: 1mm; padding-left: 3mm; padding-right: 3mm; } .info-row { - margin-bottom: 1.5mm; + margin-bottom: 0.8mm; display: flex; justify-content: space-between; align-items: flex-start; padding: 0; + line-height: 1.0; } .info-label-text { @@ -258,6 +267,7 @@ export const useThermalPrint = () => { text-align: left; text-transform: uppercase; word-break: keep-all; + line-height: 1.0; } .info-colon { @@ -265,6 +275,7 @@ export const useThermalPrint = () => { font-size: 10px; margin-left: auto; padding-right: 2mm; + line-height: 1.0; } .info-label-wrapper { @@ -280,40 +291,45 @@ export const useThermalPrint = () => { font-weight: bold; text-align: right; word-break: break-word; + line-height: 1.0; } .no-antrian { font-size: 28px; font-weight: bold; - margin: 0.5mm 0; + margin: 0.3mm 0; letter-spacing: 2px; text-transform: uppercase; + line-height: 1.0; } .klinik-name { font-size: 14px; font-weight: bold; - margin-top: 0.5mm; + margin-top: 0.3mm; margin-bottom: 0; padding-bottom: 0; text-transform: uppercase; overflow: visible; + line-height: 1.0; } .footer { - margin-top: 3mm; - padding-top: 2mm; + margin-top: 2mm; + padding-top: 1mm; padding-bottom: 0; margin-bottom: 6mm; border-top: 2px solid #000; font-size: 9px; font-weight: bold; text-align: center; + line-height: 1.0; } .footer-text { - margin-bottom: 1mm; + margin-bottom: 0.5mm; font-weight: bold; + line-height: 1.0; } .footer-text:last-child { diff --git a/pages/AdminKlinikRuang/[kodeKlinik].vue b/pages/AdminKlinikRuang/[kodeKlinik].vue index e21e9ec..2defa3f 100644 --- a/pages/AdminKlinikRuang/[kodeKlinik].vue +++ b/pages/AdminKlinikRuang/[kodeKlinik].vue @@ -9,20 +9,51 @@ theme="warning" /> + +
+
+ + + + + mdi-swap-horizontal + Pindah Pasien + +
+
+
-
- +
+
- mdi-door + mdi-door {{ ruang.namaRuang }} - + Kamar : R.{{ ruang.nomorRuang }}
@@ -37,32 +68,32 @@ {{ getCurrentProcessingForRoom(ruang)?.noAntrian?.split(" |")[0] || '-' }}
-
+
mdi-bullhorn Panggil Tindakan mdi-check Selesai mdi-pause @@ -82,12 +113,31 @@
-
+ + +
- mdi-check-circle + mdi-check-circle P.Awal - mdi-check-circle + mdi-check-circle Tindakan
@@ -133,41 +185,31 @@
- mdi-eye + mdi-eye Lihat Detail - mdi-swap-horizontal - Pindah Ruang - - - mdi-bullhorn + mdi-bullhorn Pemeriksaan Awal - mdi-play + mdi-play Proses
@@ -175,17 +217,29 @@
+ + + +
+ + +
+ mdi-filter-remove +
+ Tidak ada pasien yang sesuai dengan filter +
+
+ Coba ubah opsi sorting atau kata kunci pencarian +
- -
@@ -193,35 +247,146 @@
- - - - Pindah Ruang - + + + + Pindah Pasien + mdi-close - -
-
Pasien: {{ selectedPatientForPindah?.noAntrian?.split(" |")[0] }}
-
Ruang Saat Ini: {{ selectedPatientForPindah?.ruang || '-' }}
-
- - + +
+
+ mdi-account + Pilih Pasien +
+ - +
+
+
+
+ {{ patient.noAntrian?.split(" |")[0] || patient.barcode || '-' }} +
+
+
+ mdi-door + {{ patient.ruang || '-' }} (R.{{ patient.nomorRuang || '-' }}) +
+
+
+ + mdi-check-circle + +
+
+ mdi-account-off +
+ Tidak ada pasien yang tersedia +
+
+
+
+ + +
+
+ mdi-door + Pilih Ruang Tujuan +
+
+
+ Pasien: + + {{ selectedPatientForPindah?.noAntrian?.split(" |")[0] || selectedPatientForPindah?.barcode || '-' }} + + + ({{ selectedPatientForPindah?.ruang || '-' }}) + +
+ + mdi-arrow-left + Ubah + +
+
+
+
+ + mdi-door + +
{{ ruangOption.namaRuang }}
+
R.{{ ruangOption.nomorRuang }}
+ + Saat Ini + + + mdi-check-circle + +
+
+
+
- + - Batal - - Pindah Ruang + + mdi-close + Batal + + + mdi-swap-horizontal + Pindah Pasien
@@ -229,15 +394,15 @@ - - - Detail Pasien - + + + Detail Pasien + mdi-close - +
@@ -287,7 +452,7 @@
{{ getStatusLabel(selectedPatientDetail.status) }} @@ -330,15 +496,15 @@ - + - - TUTUP + mdi-close + Tutup @@ -417,6 +583,17 @@ const pendingPage = ref({}); const showPindahRuangDialog = ref(false); const selectedPatientForPindah = ref(null); const selectedRuangBaru = ref(null); +const globalSearchQuery = ref(''); +const sortOptions = ref({}); +const searchPatientQuery = ref(''); + +const sortOptionsList = [ + { title: 'Semua', value: 'default' }, + { title: 'Sudah Pemeriksaan Awal', value: 'sudah-pawal' }, + { title: 'Belum Pemeriksaan Awal', value: 'belum-pawal' }, + { title: 'Sudah Tindakan', value: 'sudah-tindakan' }, + { title: 'Belum Tindakan', value: 'belum-tindakan' } +]; // WebSocket configuration const config = useRuntimeConfig(); @@ -449,31 +626,79 @@ const getAllPatientsForRoom = (ruang) => { p.no !== getCurrentProcessingForRoom(ruang)?.no && // Include semua pasien dengan status yang relevan (p.status === 'waiting' || p.status === 'di-loket' || p.status === 'terlambat' || p.status === 'pending') + ); +}; + +// Get filtered and sorted patients for room +const getFilteredAndSortedPatientsForRoom = (ruang) => { + let patients = getAllPatientsForRoom(ruang); + + // Apply global search filter + if (globalSearchQuery.value) { + const searchLower = globalSearchQuery.value.toLowerCase(); + patients = patients.filter(p => + p.barcode?.toLowerCase().includes(searchLower) || + p.noAntrian?.toLowerCase().includes(searchLower) || + p.nama?.toLowerCase().includes(searchLower) || + p.klinik?.toLowerCase().includes(searchLower) + ); + } + + // Apply sorting + const sortOption = sortOptions.value[ruang.nomorRuang] || 'default'; + + if (sortOption === 'sudah-pawal') { + patients = patients.filter(p => p.calledPemeriksaanAwal); + } else if (sortOption === 'belum-pawal') { + patients = patients.filter(p => !p.calledPemeriksaanAwal); + } else if (sortOption === 'sudah-tindakan') { + patients = patients.filter(p => p.calledTindakan); + } else if (sortOption === 'belum-tindakan') { + patients = patients.filter(p => !p.calledTindakan); + } + + // Default sorting + return patients.sort((a, b) => { + // Prioritaskan yang sudah digenerate/diproses & pending di atas + const aHasTiket = !!a.tipeLayanan; + const bHasTiket = !!b.tipeLayanan; + + // Jika satu sudah punya tiket dan yang lain belum, yang sudah tiket di atas + if (aHasTiket && !bHasTiket) return -1; + if (!aHasTiket && bHasTiket) return 1; + + // Jika keduanya sudah punya tiket atau keduanya belum, sort by status + const statusPriority = { + 'di-loket': 1, + 'waiting': 2, + 'terlambat': 3, + 'pending': 4 + }; + const priorityDiff = (statusPriority[a.status] || 99) - (statusPriority[b.status] || 99); + if (priorityDiff !== 0) return priorityDiff; + + // Sort by time + const timeA = a.jamPanggil?.split(':').map(Number) || [0, 0]; + const timeB = b.jamPanggil?.split(':').map(Number) || [0, 0]; + return timeA[0] * 60 + timeA[1] - (timeB[0] * 60 + timeB[1]); + }); +}; + +// Get global search results across all rooms +const getGlobalSearchResults = () => { + if (!globalSearchQuery.value) return []; + + const searchLower = globalSearchQuery.value.toLowerCase(); + return queueStore.allPatients.filter(p => + p.kodeKlinik === klinikData.value?.kodeKlinik && + p.processStage === 'klinik-ruang' && + ( + p.barcode?.toLowerCase().includes(searchLower) || + p.noAntrian?.toLowerCase().includes(searchLower) || + p.nama?.toLowerCase().includes(searchLower) || + p.klinik?.toLowerCase().includes(searchLower) ) - .sort((a, b) => { - // Prioritaskan yang sudah digenerate/diproses & pending di atas - const aHasTiket = !!a.tipeLayanan; - const bHasTiket = !!b.tipeLayanan; - - // Jika satu sudah punya tiket dan yang lain belum, yang sudah tiket di atas - if (aHasTiket && !bHasTiket) return -1; - if (!aHasTiket && bHasTiket) return 1; - - // Jika keduanya sudah punya tiket atau keduanya belum, sort by status - const statusPriority = { - 'di-loket': 1, - 'waiting': 2, - 'terlambat': 3, - 'pending': 4 - }; - const priorityDiff = (statusPriority[a.status] || 99) - (statusPriority[b.status] || 99); - if (priorityDiff !== 0) return priorityDiff; - - // Sort by time - const timeA = a.jamPanggil?.split(':').map(Number) || [0, 0]; - const timeB = b.jamPanggil?.split(':').map(Number) || [0, 0]; - return timeA[0] * 60 + timeA[1] - (timeB[0] * 60 + timeB[1]); - }); + ); }; // Get pending patients (untuk backward compatibility jika masih digunakan) @@ -558,10 +783,32 @@ const handleGenerateTicket = (patient, currentRuang) => { } }; -const handlePindahRuang = (patient, currentRuang) => { - selectedPatientForPindah.value = patient; +// Get available patients for pindah ruang (all patients in this klinik) +const getAvailablePatientsForPindah = () => { + 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') + ); + + // Apply search filter + if (searchPatientQuery.value) { + const searchLower = searchPatientQuery.value.toLowerCase(); + patients = patients.filter(p => + p.barcode?.toLowerCase().includes(searchLower) || + p.noAntrian?.toLowerCase().includes(searchLower) || + p.nama?.toLowerCase().includes(searchLower) + ); + } + + return patients; +}; + +const closePindahRuangDialog = () => { + showPindahRuangDialog.value = false; + selectedPatientForPindah.value = null; selectedRuangBaru.value = null; - showPindahRuangDialog.value = true; + searchPatientQuery.value = ''; }; const confirmPindahRuang = () => { @@ -616,9 +863,7 @@ const confirmPindahRuang = () => { 'success' ); - showPindahRuangDialog.value = false; - selectedPatientForPindah.value = null; - selectedRuangBaru.value = null; + closePindahRuangDialog(); }; // Handle call patient from list (dari card pasien di daftar) @@ -795,10 +1040,10 @@ const toggleLayananStatus = (tipeLayanan) => { const getStatusColor = (status) => { const colors = { - 'di-loket': 'success', - 'waiting': 'info', - 'terlambat': 'warning', - 'pending': 'error' + 'di-loket': 'success-600', + 'waiting': 'primary-600', + 'terlambat': 'primary-600', + 'pending': 'danger-600' }; return colors[status] || 'grey'; }; @@ -992,7 +1237,7 @@ const handleProcessPendingPatient = (ruang, patient) => { }; const paginatedAllPatients = (ruang) => { - const allPatients = getAllPatientsForRoom(ruang); + const allPatients = getFilteredAndSortedPatientsForRoom(ruang); const page = pendingPage.value[ruang.nomorRuang] || 1; const startIndex = (page - 1) * 10; const endIndex = startIndex + 10; @@ -1021,11 +1266,14 @@ onMounted(() => { router.push('/admin-klinik-ruang'); } - // Initialize pagination for each room + // Initialize pagination and sort options for each room ruangList.value.forEach(ruang => { if (!pendingPage.value[ruang.nomorRuang]) { pendingPage.value[ruang.nomorRuang] = 1; } + if (!sortOptions.value[ruang.nomorRuang]) { + sortOptions.value[ruang.nomorRuang] = 'default'; + } }); }); @@ -1044,7 +1292,8 @@ onMounted(() => { } .section-label { - font-size: 11px; + font-size: 12px; + line-height: 16px; font-weight: 700; letter-spacing: 0.5px; color: var(--color-neutral-600); @@ -1052,7 +1301,8 @@ onMounted(() => { } .section-label-small { - font-size: 10px; + font-size: 12px; + line-height: 16px; font-weight: 700; letter-spacing: 0.5px; color: var(--color-neutral-600); @@ -1061,30 +1311,128 @@ onMounted(() => { .instruction-text { font-size: 12px; + line-height: 16px; color: var(--color-neutral-700); - line-height: 1.4; } .rooms-grid-wrapper { margin-top: 24px; + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + scrollbar-width: thin; + scrollbar-color: var(--color-neutral-500) var(--color-neutral-300); +} + +.rooms-grid-wrapper::-webkit-scrollbar { + height: 8px; +} + +.rooms-grid-wrapper::-webkit-scrollbar-track { + background: var(--color-neutral-300); + border-radius: 4px; +} + +.rooms-grid-wrapper::-webkit-scrollbar-thumb { + background: var(--color-neutral-500); + border-radius: 4px; +} + +.rooms-grid-wrapper::-webkit-scrollbar-thumb:hover { + background: var(--color-neutral-600); } .rooms-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; + min-width: fit-content; +} + +.rooms-grid-scrollable { + display: flex; + flex-direction: row; + gap: 16px; + grid-template-columns: none; +} + +.rooms-grid-scrollable .room-card { + min-width: 700px; + max-width: 700px; + flex-shrink: 0; +} + +.global-search-section { + background: var(--color-neutral-100); + padding: 16px; + border-radius: 12px; + border: 1px solid var(--color-neutral-400); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); +} + +.search-actions-row { + display: flex; + gap: 12px; + align-items: center; + justify-content: flex-end; +} + +.global-search-field { + flex: 1; + max-width: none; + margin-right: auto; +} + +.btn-pindah-pasien { + text-transform: none !important; + font-weight: 600 !important; + font-size: 14px !important; + line-height: 20px !important; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important; + min-height: 40px !important; + padding: 8px 20px !important; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important; + transition: all 0.2s ease !important; + white-space: nowrap !important; + background-color: #FF9800 !important; + color: #FFFFFF !important; + border: none !important; +} + +.btn-pindah-pasien:hover { + transform: translateY(-1px) !important; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15) !important; + background-color: #F57C00 !important; +} + +.btn-pindah-pasien:active { + transform: translateY(0) !important; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) !important; + background-color: #E65100 !important; +} + +.btn-pindah-pasien .v-icon { + color: #FFFFFF !important; +} + +.sort-select { + font-size: 12px; } .room-card { border-radius: 12px; border: 1px solid var(--color-neutral-500); background: var(--color-neutral-100); + width: 100%; + height: fit-content; + box-sizing: border-box; + overflow: hidden; } .room-header { - background: linear-gradient(135deg, var(--color-warning-600) 0%, var(--color-warning-700) 100%); + background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-primary-700) 100%); color: var(--color-neutral-100); - padding: 16px; + padding: 16px 20px; box-shadow: 0 2px 8px rgba(255, 152, 0, 0.2); } @@ -1100,6 +1448,7 @@ onMounted(() => { background: linear-gradient(135deg, var(--color-primary-200) 0%, var(--color-primary-300) 100%); border-radius: 8px; padding: 16px; + border: 1px solid var(--color-primary-400); } .current-patient-info { @@ -1108,33 +1457,62 @@ onMounted(() => { .patient-number-large { font-size: 32px; - font-weight: 900; + line-height: 40px; + font-weight: 700; color: var(--color-neutral-900); - margin-bottom: 8px; + margin-bottom: 12px; } .patient-details { - font-size: 13px; + font-size: 14px; + line-height: 20px; color: var(--color-neutral-700); + margin-bottom: 4px; } -.action-buttons { - display: flex; - gap: 8px; - justify-content: center; - flex-wrap: wrap; +.action-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 12px; + margin-top: 16px; +} + +.action-grid .v-btn { + text-transform: none; + font-weight: 600; + font-size: 14px; + line-height: 20px; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + padding: 8px 12px; + min-height: 40px; + white-space: nowrap; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; +} + +.action-grid .v-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); +} + +.action-grid .v-btn:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } .empty-current { text-align: center; - padding: 16px; + padding: 24px 16px; background: var(--color-neutral-200); border-radius: 8px; + border: 1px solid var(--color-neutral-300); } .empty-text { - font-size: 12px; + font-size: 14px; + line-height: 20px; color: var(--color-neutral-600); + font-weight: 500; } .queue-sections { @@ -1157,7 +1535,8 @@ onMounted(() => { } .queue-section-title { - font-size: 13px; + font-size: 14px; + line-height: 20px; font-weight: 700; color: var(--color-neutral-900); flex: 1; @@ -1177,53 +1556,94 @@ onMounted(() => { } .empty-text-small { - font-size: 11px; + font-size: 12px; + line-height: 16px; color: var(--color-neutral-600); margin-top: 8px; } -.dialog-header { - display: flex; - justify-content: space-between; - align-items: center; - background: linear-gradient(135deg, var(--color-warning-600) 0%, var(--color-warning-700) 100%); - color: var(--color-neutral-100); - padding: 16px 20px; +.empty-filtered-state { + text-align: center; + padding: 40px 20px; + background: var(--color-neutral-200); + border-radius: 8px; + border: 1px dashed var(--color-neutral-400); } -/* Detail Dialog Styles */ -.detail-dialog-card { +/* Dialog Styles - Consistent with AdminLoket */ +.dialog-card { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; border-radius: 12px; overflow: hidden; } -.detail-dialog-header { +.dialog-header { + background: linear-gradient(135deg, var(--color-secondary-600) 0%, var(--color-secondary-700) 100%); + color: var(--color-neutral-100); + padding: 20px 24px; display: flex; justify-content: space-between; align-items: center; - background: var(--color-neutral-100); - color: var(--color-neutral-900); - padding: 20px 24px; - border-bottom: 1px solid var(--color-neutral-300); } -.detail-dialog-title { +.dialog-header-warning { + background: linear-gradient(135deg, var(--color-secondary-600) 0%, var(--color-secondary-700) 100%); +} + +.headline-4 { font-size: 20px; - font-weight: 700; - color: var(--color-neutral-900); + line-height: 28px; + font-weight: 600; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + margin: 0; + color: var(--color-neutral-100); } -.detail-close-btn { - color: var(--color-neutral-600) !important; +.btn-close { + color: var(--color-neutral-100) !important; + transition: all 0.2s ease; } -.detail-close-btn:hover { - background: var(--color-neutral-200) !important; +.btn-close:hover { + background: rgba(255, 255, 255, 0.2) !important; + transform: rotate(90deg); } -.detail-dialog-content { +.dialog-content { padding: 24px !important; - background: var(--color-neutral-50); + background: var(--color-neutral-300); +} + +.dialog-actions { + padding: 16px 24px; + background: var(--color-neutral-300); + border-top: 1px solid var(--color-neutral-400); +} + +.dialog-actions .v-btn { + text-transform: none; + font-weight: 600; + font-size: 16px; + line-height: 24px; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + min-width: 100px; +} + +.btn-cancel { + border-color: var(--color-neutral-600) !important; + color: var(--color-neutral-800) !important; +} + +.btn-submit { + background-color: var(--color-secondary-600) !important; + color: var(--color-neutral-100) !important; +} + +.patient-card { + background: var(--color-neutral-100); + border-radius: 12px; + padding: 20px; + border: 1px solid var(--color-neutral-400); } .detail-row { @@ -1237,7 +1657,7 @@ onMounted(() => { .detail-item { display: flex; flex-direction: column; - gap: 8px; + gap: 4px; } .detail-label { @@ -1252,7 +1672,7 @@ onMounted(() => { .detail-value { font-size: 16px; line-height: 24px; - font-weight: 700; + font-weight: 600; color: var(--color-neutral-900); } @@ -1294,46 +1714,6 @@ onMounted(() => { opacity: 0.6; } -.detail-dialog-actions { - padding: 16px 24px; - background: var(--color-neutral-100); - border-top: 1px solid var(--color-neutral-300); -} - -.detail-dialog-actions .v-btn { - min-width: 120px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.detail-chips-group { - display: flex; - gap: 8px; - flex-wrap: wrap; -} - -.detail-chip-clickable { - cursor: pointer; - transition: all 0.2s ease; - font-weight: 600; - text-transform: none; -} - -.detail-chip-clickable:hover { - transform: scale(1.05); - opacity: 0.9; -} - -.detail-chip-clickable.chip-active { - cursor: pointer; -} - -.detail-chip-clickable:not(.chip-active) { - cursor: not-allowed; - opacity: 0.6; -} - .body-2 { font-size: 16px; line-height: 24px; @@ -1353,47 +1733,62 @@ onMounted(() => { } .patient-list-section { - background: var(--color-warning-50); - border: 1px solid var(--color-warning-200); + background: var(--color-neutral-200); + border: 1px solid var(--color-neutral-400); border-radius: 8px; - padding: 12px; + padding: 16px; margin-bottom: 16px; + width: 100%; + box-sizing: border-box; + overflow-x: hidden; } .patient-queue-list { display: flex; flex-direction: column; gap: 6px; + width: 100%; + box-sizing: border-box; + overflow-x: hidden; } .patient-queue-item { display: flex; justify-content: space-between; - align-items: center; - padding: 10px 14px; + align-items: flex-start; + padding: 16px 20px; border-radius: 8px; transition: all 0.2s ease; - gap: 12px; - min-height: 56px; + gap: 24px; + min-height: auto; + width: 100%; + box-sizing: border-box; } -/* Pasien dengan status pending: warna merah */ +/* Pasien dengan status pending: warna merah soft */ .patient-queue-item-pending-status { - background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%); - border: 2px solid #ef5350; + 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 { - background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); - border: 1px solid #90caf9; + background: linear-gradient(135deg, var(--color-primary-200) 0%, var(--color-primary-300) 100%); + border: 1px solid var(--color-primary-400); } .patient-queue-item-processed:hover { - background: linear-gradient(135deg, #bbdefb 0%, #90caf9 100%); - border-color: #64b5f6; + background: linear-gradient(135deg, var(--color-primary-300) 0%, var(--color-primary-400) 100%); + border-color: var(--color-primary-500); } /* Pasien default */ @@ -1411,120 +1806,548 @@ onMounted(() => { .patient-card-left { display: flex; flex-direction: column; - gap: 6px; - min-width: 100px; + gap: 10px; + min-width: 160px; + max-width: 200px; flex-shrink: 0; + flex: 0 0 auto; } .patient-queue-number { font-size: 20px; + line-height: 28px; font-weight: 700; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: var(--color-neutral-900); - line-height: 1.2; letter-spacing: 0.5px; + word-break: break-word; + white-space: nowrap; } .patient-queue-status-chips { display: flex; - gap: 4px; + gap: 6px; align-items: center; flex-wrap: wrap; margin-top: 4px; + max-width: 100%; } .status-chip { - font-size: 10px !important; - font-weight: 700 !important; + font-size: 12px !important; + line-height: 16px !important; + font-weight: 600 !important; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important; height: 20px !important; padding: 0 6px !important; min-width: 60px !important; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08) !important; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08) !important; border: 1px solid transparent !important; letter-spacing: 0.1px !important; + transition: all 0.2s ease !important; } .status-chip-pawal { - background: #6366f1 !important; + background: var(--color-primary-600) !important; color: white !important; - border-color: #4f46e5 !important; + border-color: var(--color-primary-700) !important; } .status-chip-pawal:hover { - background: #4f46e5 !important; - box-shadow: 0 1px 3px rgba(99, 102, 241, 0.15) !important; + background: var(--color-primary-700) !important; + box-shadow: 0 2px 4px rgba(255, 165, 50, 0.2) !important; + transform: translateY(-1px); } .status-chip-tindakan { - background: #14b8a6 !important; + background: var(--color-secondary-600) !important; color: white !important; - border-color: #0d9488 !important; + border-color: var(--color-secondary-700) !important; } .status-chip-tindakan:hover { - background: #0d9488 !important; - box-shadow: 0 1px 3px rgba(20, 184, 166, 0.15) !important; + background: var(--color-secondary-700) !important; + box-shadow: 0 2px 4px rgba(6, 113, 224, 0.2) !important; + transform: translateY(-1px); } .status-chip .v-icon { - font-size: 11px !important; - margin-right: 2px !important; + font-size: 12px !important; + margin-right: 4px !important; color: white !important; } /* Right Section: Actions */ .patient-card-right { display: flex; - align-items: center; + align-items: flex-start; flex: 1; justify-content: flex-end; - min-width: 0; + min-width: 400px; + max-width: none; + padding-top: 2px; + box-sizing: border-box; } .patient-queue-actions { display: flex; - gap: 6px; + gap: 10px; align-items: center; flex-wrap: nowrap; + justify-content: flex-end; + min-width: fit-content; + max-width: 100%; + box-sizing: border-box; } .patient-queue-actions .v-btn { text-transform: none; font-weight: 600; + font-size: 13px; + line-height: 18px; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; flex-shrink: 0; + min-height: 38px; + padding: 8px 16px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; + white-space: nowrap; + max-width: 100%; + box-sizing: border-box; +} + +.patient-queue-actions .v-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); +} + +.patient-queue-actions .v-btn:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.patient-queue-actions .v-btn.variant--text { + box-shadow: none; + min-height: 38px; + padding: 8px; + flex-shrink: 0; + min-width: 38px; +} + +.patient-queue-actions .v-btn.variant--text:hover { + background: rgba(0, 0, 0, 0.05); + transform: scale(1.1); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.patient-queue-actions .v-btn.variant--text:active { + transform: scale(1.05); } .call-btn { - min-width: 130px; - font-size: 11px; + min-width: 160px; + font-size: 13px; + line-height: 18px; white-space: nowrap; + padding: 8px 18px; + max-width: fit-content; + box-sizing: border-box; } .call-btn .v-icon { - margin-right: 4px; + margin-right: 6px; + flex-shrink: 0; } /* Responsive untuk card */ @media (max-width: 1400px) { + .rooms-grid:not(.rooms-grid-scrollable) { + grid-template-columns: repeat(2, 1fr); + } + + .rooms-grid-scrollable .room-card { + min-width: 650px; + max-width: 650px; + } + + .patient-queue-item { + padding: 14px 16px; + gap: 20px; + } + + .patient-card-left { + min-width: 150px; + max-width: 180px; + } + + .patient-card-right { + min-width: 360px; + } + + .patient-queue-actions { + gap: 8px; + flex-wrap: nowrap; + } + + .patient-queue-actions .v-btn { + font-size: 12px; + line-height: 16px; + min-height: 36px; + padding: 7px 14px; + } + .call-btn { - min-width: 100px; - font-size: 10px; + min-width: 140px; + font-size: 12px; + line-height: 16px; + padding: 7px 16px; } .call-btn .v-icon { - margin-right: 2px; + margin-right: 4px; } -} - -@media (max-width: 1400px) { - .rooms-grid { - grid-template-columns: repeat(2, 1fr); + + .patient-queue-actions .v-btn.variant--text { + padding: 7px; + min-width: 36px; + } + + .action-grid { + grid-template-columns: repeat(3, 1fr); + gap: 8px; + } + + .action-grid .v-btn { + font-size: 12px; + padding: 6px 12px; + min-height: 36px; + } + + .action-grid .v-btn .v-icon { + font-size: 16px; } } @media (max-width: 960px) { - .rooms-grid { + .rooms-grid:not(.rooms-grid-scrollable) { grid-template-columns: 1fr; } + + .rooms-grid-scrollable .room-card { + min-width: 100%; + max-width: 100%; + } + + .patient-queue-item { + flex-direction: row; + align-items: flex-start; + gap: 12px; + } + + .patient-card-left { + min-width: 100px; + flex: 0 0 auto; + } + + .patient-card-right { + width: auto; + justify-content: flex-end; + padding-top: 2px; + flex: 1; + min-width: 300px; + max-width: 100%; + } + + .patient-queue-actions { + width: auto; + justify-content: flex-end; + flex-wrap: nowrap; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + } + + .patient-queue-actions::-webkit-scrollbar { + display: none; + } + + .global-search-field { + max-width: 100%; + } + + .sort-select { + max-width: 150px !important; + } + + .action-grid { + grid-template-columns: repeat(3, 1fr); + gap: 8px; + } + + .action-grid .v-btn { + font-size: 11px; + padding: 6px 8px; + min-height: 36px; + } + + .action-grid .v-btn .v-icon { + font-size: 14px; + } + + .patient-queue-actions { + gap: 4px; + flex-wrap: nowrap; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + } + + .patient-queue-actions::-webkit-scrollbar { + display: none; + } + + .patient-queue-actions .v-btn { + font-size: 10px; + line-height: 14px; + min-height: 32px; + padding: 6px 8px; + } + + .call-btn { + min-width: 100px; + font-size: 10px; + line-height: 14px; + padding: 6px 8px; + } + + .call-btn .v-icon { + margin-right: 2px; + font-size: 14px; + } + + .patient-queue-actions .v-btn.variant--text { + padding: 6px; + min-width: 32px; + } + + .patient-queue-actions .v-btn .v-icon { + font-size: 16px; + } + + .search-actions-row { + flex-direction: column; + align-items: stretch; + } + + .global-search-field { + margin-right: 0; + margin-bottom: 12px; + } + + .btn-pindah-pasien { + width: 100%; + } + + .ruang-selection-grid { + grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); + gap: 8px; + } + + .ruang-selection-card { + min-height: 100px; + padding: 12px 8px; + } +} + +/* Dialog Pindah Ruang Styles */ +.pindah-ruang-step { + width: 100%; +} + +.step-title { + display: flex; + align-items: center; + font-size: 18px; + line-height: 24px; + font-weight: 600; + color: var(--color-neutral-900); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; +} + +.headline-5 { + font-size: 18px; + line-height: 24px; + font-weight: 600; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; +} + +.patient-selection-list { + max-height: 400px; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 8px; +} + +.patient-selection-card { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 16px; + background: var(--color-neutral-100); + border: 2px solid var(--color-neutral-300); + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease; +} + +.patient-selection-card:hover { + background: var(--color-neutral-200); + border-color: var(--color-primary-400); + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.patient-selection-card-selected { + background: var(--color-primary-100); + border-color: var(--color-primary-600); + box-shadow: 0 2px 8px rgba(255, 152, 0, 0.2); +} + +.patient-selection-info { + flex: 1; +} + +.patient-selection-number { + font-size: 16px; + line-height: 24px; + font-weight: 700; + color: var(--color-neutral-900); + margin-bottom: 4px; +} + +.patient-selection-details { + font-size: 12px; + line-height: 16px; + color: var(--color-neutral-600); +} + +.patient-selection-room { + display: flex; + align-items: center; + font-size: 12px; + line-height: 16px; + color: var(--color-neutral-600); +} + +.empty-patient-list { + text-align: center; + padding: 40px 20px; + background: var(--color-neutral-200); + border-radius: 8px; + border: 1px dashed var(--color-neutral-400); +} + +.selected-patient-simple { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 16px; + background: var(--color-primary-100); + border: 1px solid var(--color-primary-300); + border-radius: 8px; + margin-bottom: 16px; +} + +.selected-patient-simple-text { + display: flex; + align-items: center; + gap: 8px; + flex: 1; +} + +.selected-patient-simple-label { + font-size: 12px; + line-height: 16px; + color: var(--color-neutral-600); + font-weight: 500; +} + +.selected-patient-simple-value { + font-size: 14px; + line-height: 20px; + font-weight: 600; + color: var(--color-neutral-900); +} + +.selected-patient-simple-room { + font-size: 12px; + line-height: 16px; + color: var(--color-neutral-600); +} + +.ruang-selection-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); + gap: 10px; + max-height: 400px; + overflow-y: auto; +} + +.ruang-selection-card { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 16px 12px; + background: var(--color-neutral-100); + border: 2px solid var(--color-neutral-300); + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease; + text-align: center; + min-height: 110px; +} + +.ruang-selection-card:hover:not(.ruang-selection-card-disabled) { + background: var(--color-primary-100); + border-color: var(--color-primary-400); + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +.ruang-selection-card-selected { + background: var(--color-primary-100); + border-color: var(--color-primary-600); + box-shadow: 0 2px 8px rgba(255, 152, 0, 0.2); +} + +.ruang-selection-card-disabled { + background: var(--color-neutral-200); + border-color: var(--color-neutral-400); + cursor: not-allowed; + opacity: 0.6; +} + +.ruang-selection-content { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; +} + +.ruang-selection-name { + font-size: 13px; + line-height: 18px; + font-weight: 600; + color: var(--color-neutral-900); + margin-bottom: 2px; +} + +.ruang-selection-number { + font-size: 11px; + line-height: 16px; + color: var(--color-neutral-600); } diff --git a/pages/AdminLoket.vue b/pages/AdminLoket.vue index 092c0cd..525ee39 100644 --- a/pages/AdminLoket.vue +++ b/pages/AdminLoket.vue @@ -563,10 +563,25 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => { .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 { @@ -638,7 +653,7 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => { } .dialog-header { - background: linear-gradient(135deg, var(--color-warning-600) 0%, var(--color-primary-700) 100%); + background: linear-gradient(135deg, var(--color-secondary-600) 0%, var(--color-secondary-700) 100%); color: var(--color-neutral-100); padding: 20px 24px; display: flex; @@ -647,7 +662,7 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => { } .dialog-header-warning { - background: linear-gradient(135deg, var(--color-warning-600) 0%, var(--color-primary-700) 100%); + background: linear-gradient(135deg, var(--color-secondary-600) 0%, var(--color-secondary-700) 100%); } .headline-4 { @@ -655,6 +670,7 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => { line-height: 28px; font-weight: 600; margin: 0; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; } .headline-5 { @@ -663,10 +679,17 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => { font-weight: 600; margin: 0; color: var(--color-neutral-900); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; } .btn-close { color: var(--color-neutral-100) !important; + transition: all 0.2s ease; +} + +.btn-close:hover { + background: rgba(255, 255, 255, 0.2) !important; + transform: rotate(90deg); } .dialog-content { @@ -674,6 +697,30 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => { background: var(--color-neutral-300); } +.dialog-actions { + padding: 16px 24px; + background: var(--color-neutral-300); +} + +.dialog-actions .v-btn { + text-transform: none; + font-weight: 600; + font-size: 16px; + line-height: 24px; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + min-width: 100px; +} + +.btn-cancel { + border-color: var(--color-neutral-600) !important; + color: var(--color-neutral-800) !important; +} + +.btn-submit { + background-color: var(--color-secondary-600) !important; + color: var(--color-neutral-100) !important; +} + .patient-card { background: var(--color-neutral-100); border-radius: 12px; @@ -756,11 +803,19 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => { border-radius: 8px; cursor: pointer; transition: all 0.2s ease; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .ruang-item:hover { border-color: var(--color-warning-600); background: rgba(255, 185, 95, 0.15); + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.ruang-item:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .ruang-info { diff --git a/pages/Anjungan/AdminAnjungan.vue b/pages/Anjungan/AdminAnjungan.vue index fc87043..eb6e028 100644 --- a/pages/Anjungan/AdminAnjungan.vue +++ b/pages/Anjungan/AdminAnjungan.vue @@ -4,7 +4,11 @@
- mdi-view-dashboard +

Admin Anjungan

@@ -215,11 +219,22 @@ const items = ref([ } .header-icon { - background: rgba(255, 255, 255, 0.2); + background: rgba(255, 255, 255, 0.95); border-radius: 16px; padding: 16px; margin-right: 20px; backdrop-filter: blur(10px); + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.header-logo { + width: 48px; + height: 48px; + object-fit: contain; + padding: 4px; } .page-title { diff --git a/pages/Anjungan/Anjungan/[id].vue b/pages/Anjungan/Anjungan/[id].vue index 50cf657..3e7dc9f 100644 --- a/pages/Anjungan/Anjungan/[id].vue +++ b/pages/Anjungan/Anjungan/[id].vue @@ -4,7 +4,11 @@
- mdi-hospital-building +

{{ anjunganData.namaAnjungan }}

@@ -1286,10 +1290,21 @@ watch(lastRegisteredPatient, (newVal) => { } .header-icon { - background: rgba(255, 255, 255, 0.2); + background: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 12px; backdrop-filter: blur(10px); + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.header-logo { + width: 48px; + height: 48px; + object-fit: contain; + padding: 4px; } .header-text { diff --git a/pages/Anjungan/Anjungan/index.vue b/pages/Anjungan/Anjungan/index.vue index cd5b9a7..60df0ae 100644 --- a/pages/Anjungan/Anjungan/index.vue +++ b/pages/Anjungan/Anjungan/index.vue @@ -3,7 +3,11 @@
- mdi-monitor-dashboard +

Pilih Anjungan

@@ -165,13 +169,21 @@ const navigateToSettings = () => { } .header-icon { - background: rgba(255, 255, 255, 0.15); + background: rgba(255, 255, 255, 0.95); border-radius: 20px; padding: 24px; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(10px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.header-logo { + width: 80px; + height: 80px; + object-fit: contain; + padding: 4px; } .header-content { diff --git a/pages/Anjungan/AntreanMasuk/[id].vue b/pages/Anjungan/AntreanMasuk/[id].vue index 1dfecf8..ef3b872 100644 --- a/pages/Anjungan/AntreanMasuk/[id].vue +++ b/pages/Anjungan/AntreanMasuk/[id].vue @@ -5,7 +5,11 @@
- mdi-door-open +

ANTREAN MASUK

@@ -250,11 +254,13 @@ const statistics = computed(() => { const updateTime = () => { const now = new Date() - currentTime.value = now.toLocaleTimeString('id-ID', { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = now.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit' }) + currentTime.value = timeString.replace(/\./g, ':') currentDate.value = now.toLocaleDateString('id-ID', { weekday: 'long', day: 'numeric', @@ -344,7 +350,7 @@ onUnmounted(() => { } .logo-circle { - background: rgba(255, 255, 255, 0.15); + background: rgba(255, 255, 255, 0.95); width: 80px; height: 80px; border-radius: 50%; @@ -352,6 +358,14 @@ onUnmounted(() => { align-items: center; justify-content: center; backdrop-filter: blur(10px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.header-logo { + width: 64px; + height: 64px; + object-fit: contain; + padding: 4px; } .header-text { diff --git a/pages/Anjungan/AntrianKlinik/[id].vue b/pages/Anjungan/AntrianKlinik/[id].vue index 677cf71..bca350b 100644 --- a/pages/Anjungan/AntrianKlinik/[id].vue +++ b/pages/Anjungan/AntrianKlinik/[id].vue @@ -5,7 +5,11 @@

ANTRIAN KLINIK

@@ -321,11 +325,13 @@ const statistics = computed(() => { const updateTime = () => { const now = new Date(); - currentTime.value = now.toLocaleTimeString("id-ID", { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = now.toLocaleTimeString("id-ID", { hour: "2-digit", minute: "2-digit", second: "2-digit", }); + currentTime.value = timeString.replace(/\./g, ':'); currentDate.value = now.toLocaleDateString("id-ID", { weekday: "long", year: "numeric", @@ -388,12 +394,20 @@ onUnmounted(() => { } .hospital-logo { - background: rgba(255, 255, 255, 0.15); + background: rgba(255, 255, 255, 0.95); border-radius: 16px; padding: 12px; display: flex; align-items: center; justify-content: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.header-logo { + width: 64px; + height: 64px; + object-fit: contain; + padding: 4px; } .display-title { diff --git a/pages/Anjungan/AntrianKlinikRuang/[kodeKlinik].vue b/pages/Anjungan/AntrianKlinikRuang/[kodeKlinik].vue index e8fd5d2..e813dca 100644 --- a/pages/Anjungan/AntrianKlinikRuang/[kodeKlinik].vue +++ b/pages/Anjungan/AntrianKlinikRuang/[kodeKlinik].vue @@ -5,13 +5,16 @@
- mdi-door-open +

ANTRIAN KLINIK RUANG

RSUD dr. Saiful Anwar Provinsi Jawa Timur

-

{{ klinikData.namaKlinik }} ({{ klinikData.kodeKlinik }})

-
+
@@ -354,11 +357,13 @@ const statistics = computed(() => { const updateTime = () => { const now = new Date() - currentTime.value = now.toLocaleTimeString('id-ID', { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = now.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit' }) + currentTime.value = timeString.replace(/\./g, ':') currentDate.value = now.toLocaleDateString('id-ID', { weekday: 'long', day: 'numeric', @@ -604,7 +609,7 @@ watch(anjunganClientId, (newClientId, oldClientId) => { margin: 0 auto; box-sizing: border-box; - // Responsive scaling menggunakan CSS variables dan JavaScript + /* Responsive scaling menggunakan CSS variables dan JavaScript */ transform-origin: top center; --scale-factor: 1; transform: scale(var(--scale-factor)); @@ -629,7 +634,7 @@ watch(anjunganClientId, (newClientId, oldClientId) => { } .logo-circle { - background: rgba(255, 255, 255, 0.15); + background: rgba(255, 255, 255, 0.95); width: 80px; height: 80px; border-radius: 50%; @@ -637,6 +642,14 @@ watch(anjunganClientId, (newClientId, oldClientId) => { align-items: center; justify-content: center; backdrop-filter: blur(10px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.header-logo { + width: 64px; + height: 64px; + object-fit: contain; + padding: 4px; } .hospital-name { diff --git a/pages/Anjungan/AntrianLoket/[id].vue b/pages/Anjungan/AntrianLoket/[id].vue index 0fd6ff5..4ef94a2 100644 --- a/pages/Anjungan/AntrianLoket/[id].vue +++ b/pages/Anjungan/AntrianLoket/[id].vue @@ -5,7 +5,11 @@
- mdi-view-dashboard +

ANTRIAN LOKET

@@ -838,11 +842,13 @@ const statistics = computed(() => { const updateTime = () => { const now = new Date() - currentTime.value = now.toLocaleTimeString('id-ID', { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = now.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit' }) + currentTime.value = timeString.replace(/\./g, ':') currentDate.value = now.toLocaleDateString('id-ID', { weekday: 'long', day: 'numeric', @@ -902,13 +908,21 @@ onUnmounted(() => { } .logo-circle { - background: rgba(255, 255, 255, 0.15); + background: rgba(255, 255, 255, 0.95); width: 80px; height: 80px; border-radius: 50%; display: flex; align-items: center; justify-content: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.header-logo { + width: 64px; + height: 64px; + object-fit: contain; + padding: 4px; backdrop-filter: blur(10px); } diff --git a/pages/Anjungan/AntrianPenunjang.vue b/pages/Anjungan/AntrianPenunjang.vue index 454bf7f..7354169 100644 --- a/pages/Anjungan/AntrianPenunjang.vue +++ b/pages/Anjungan/AntrianPenunjang.vue @@ -5,7 +5,11 @@
- mdi-clipboard-pulse +

RUMAH SAKIT

@@ -203,11 +207,13 @@ const statistics = computed(() => { const updateTime = () => { const now = new Date() - currentTime.value = now.toLocaleTimeString('id-ID', { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = now.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit' }) + currentTime.value = timeString.replace(/\./g, ':') currentDate.value = now.toLocaleDateString('id-ID', { weekday: 'long', day: 'numeric', @@ -252,7 +258,7 @@ onUnmounted(() => { } .logo-circle { - background: rgba(255, 255, 255, 0.2); + background: rgba(255, 255, 255, 0.95); width: 80px; height: 80px; border-radius: 50%; @@ -260,6 +266,16 @@ onUnmounted(() => { align-items: center; justify-content: center; backdrop-filter: blur(10px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.header-logo { + width: 64px; + height: 64px; + object-fit: contain; + padding: 4px; + justify-content: center; + backdrop-filter: blur(10px); } .hospital-name { diff --git a/pages/CheckInPasien/checkIn.vue b/pages/CheckInPasien/checkIn.vue index a66ce6a..563d280 100644 --- a/pages/CheckInPasien/checkIn.vue +++ b/pages/CheckInPasien/checkIn.vue @@ -795,7 +795,7 @@

Waktu Scan

-

{{ new Date().toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' }) }}

+

{{ getCurrentTime() }}

@@ -1962,7 +1962,7 @@ const saveScannedQRData = (qrData: string) => { data: qrData, timestamp: new Date().toISOString(), date: new Date().toLocaleDateString('id-ID'), - time: new Date().toLocaleTimeString('id-ID') + time: new Date().toLocaleTimeString('id-ID').replace(/\./g, ':') }); // Simpan maksimal 50 item @@ -3272,21 +3272,34 @@ const getStatusClass = (status: string) => { const formatDateTime = (dateString: string) => { const date = new Date(dateString); - return date.toLocaleTimeString('id-ID', { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = date.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); + return timeString.replace(/\./g, ':'); }; const formatTime = (dateString: string) => { const date = new Date(dateString); - // Format: HH.MM (menggunakan titik, bukan titik dua) + // Format: HH:MM:SS (menggunakan titik dua) const timeString = date.toLocaleTimeString('id-ID', { hour: '2-digit', - minute: '2-digit' + minute: '2-digit', + second: '2-digit' }); - return timeString.replace(':', '.'); + return timeString.replace(/\./g, ':'); +}; + +const getCurrentTime = () => { + // Format jam dengan titik dua (HH:MM:SS) + const timeString = new Date().toLocaleTimeString('id-ID', { + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }); + return timeString.replace(/\./g, ':'); }; const formatDate = (dateString: string) => { diff --git a/stores/klinikruangstore.js b/stores/klinikruangstore.js index 08075a3..6aecbdb 100644 --- a/stores/klinikruangstore.js +++ b/stores/klinikruangstore.js @@ -35,10 +35,14 @@ export const useKlinikRuangStore = defineStore('klinikRuang', () => { no: 2, kodeKlinik: 'AS', namaKlinik: 'ANESTESI', - namaRuang: 'Ruang 1, Ruang 2', + namaRuang: 'Ruang 1, Ruang 2, Ruang 3, Ruang 4, Ruang 5, Ruang 6', ruangList: [ { nomorRuang: '1', namaRuang: 'Ruang 1', nomorScreen: '201' }, - { nomorRuang: '2', namaRuang: 'Ruang 2', nomorScreen: '202' } + { nomorRuang: '2', namaRuang: 'Ruang 2', nomorScreen: '202' }, + { nomorRuang: '3', namaRuang: 'Ruang 3', nomorScreen: '203' }, + { nomorRuang: '4', namaRuang: 'Ruang 4', nomorScreen: '204' }, + { nomorRuang: '5', namaRuang: 'Ruang 5', nomorScreen: '205' }, + { nomorRuang: '6', namaRuang: 'Ruang 6', nomorScreen: '206' } ] }, { diff --git a/stores/ruangStore.js b/stores/ruangStore.js index aad7a2e..c0e9355 100644 --- a/stores/ruangStore.js +++ b/stores/ruangStore.js @@ -37,10 +37,14 @@ export const useRuangStore = defineStore('ruang', () => { no: 2, kodeKlinik: 'AS', namaKlinik: 'ANESTESI', - namaRuang: 'Ruang 1, Ruang 2', + namaRuang: 'Ruang 1, Ruang 2, Ruang 3, Ruang 4, Ruang 5, Ruang 6', ruangList: [ { nomorRuang: '1', namaRuang: 'Ruang 1', nomorScreen: '201' }, - { nomorRuang: '2', namaRuang: 'Ruang 2', nomorScreen: '202' } + { nomorRuang: '2', namaRuang: 'Ruang 2', nomorScreen: '202' }, + { nomorRuang: '3', namaRuang: 'Ruang 3', nomorScreen: '203' }, + { nomorRuang: '4', namaRuang: 'Ruang 4', nomorScreen: '204' }, + { nomorRuang: '5', namaRuang: 'Ruang 5', nomorScreen: '205' }, + { nomorRuang: '6', namaRuang: 'Ruang 6', nomorScreen: '206' } ] }, {