update sidebar checkin dan antrian loket
This commit is contained in:
+4
-4
@@ -35,17 +35,17 @@ KEYCLOAK_ISSUER="https://auth.rssa.top/realms/sandbox"
|
||||
|
||||
#AUTH ORIGIN UNTUK ACCESS APLIKASI login dari KEYCLOAK
|
||||
# AUTH_ORIGIN="http://10.10.150.175:3000"
|
||||
AUTH_ORIGIN="0.0.0.0"
|
||||
# AUTH_ORIGIN="0.0.0.0"
|
||||
# AUTH_ORIGIN="http://localhost:3000"
|
||||
# AUTH_ORIGIN="https://antrean.dev.rssa.id"
|
||||
AUTH_ORIGIN="https://antrean.dev.rssa.id"
|
||||
# AUTH_ORIGIN="https://antrean.rssa.id"
|
||||
|
||||
#HOST UNTUK ACCESS APLIKASI
|
||||
# HOST="http://localhost:3000"
|
||||
# HOST="http://10.10.150.175:3000"
|
||||
# HOST="https://antrean.rssa.id"
|
||||
HOST="https://antrean.dev.rssa.id"
|
||||
# HOST=
|
||||
# HOST="https://antrean.dev.rssa.id"
|
||||
HOST="0.0.0.0"
|
||||
# HOST=
|
||||
|
||||
# Custom Keycloak logout endpoint UBAH SESUAI REALM DAN DOMAIN KEYCLOAK ANDA
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
# Dashboard Dummy Data Documentation
|
||||
|
||||
Dokumentasi lengkap data dummy yang digunakan di `pages/Dashboard.vue`
|
||||
|
||||
## 📊 Statistics Cards (Header Mini Stats)
|
||||
|
||||
Data statistik mini yang ditampilkan di header:
|
||||
|
||||
```javascript
|
||||
{
|
||||
pasienHariIni: 324,
|
||||
antreanAktif: 47
|
||||
}
|
||||
```
|
||||
|
||||
## 📈 Main Statistics Cards
|
||||
|
||||
Data untuk 4 kartu statistik utama:
|
||||
|
||||
### 1. Pasien Hari Ini
|
||||
|
||||
```javascript
|
||||
{
|
||||
label: 'Pasien Hari Ini',
|
||||
value: '324',
|
||||
icon: 'mdi-account-heart',
|
||||
iconColor: 'white',
|
||||
color: 'primary',
|
||||
change: '+18.2%',
|
||||
changeType: 'positive',
|
||||
changeIcon: 'mdi-trending-up'
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Antrean Aktif
|
||||
|
||||
```javascript
|
||||
{
|
||||
label: 'Antrean Aktif',
|
||||
value: '47',
|
||||
icon: 'mdi-clock-fast',
|
||||
iconColor: 'white',
|
||||
color: 'secondary',
|
||||
change: '+5',
|
||||
changeType: 'positive',
|
||||
changeIcon: 'mdi-arrow-up'
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Rata-rata Tunggu
|
||||
|
||||
```javascript
|
||||
{
|
||||
label: 'Rata-rata Tunggu',
|
||||
value: '12 min',
|
||||
icon: 'mdi-timer-outline',
|
||||
iconColor: 'white',
|
||||
color: 'success',
|
||||
change: '-3 min',
|
||||
changeType: 'positive',
|
||||
changeIcon: 'mdi-trending-down'
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Tingkat Kehadiran
|
||||
|
||||
```javascript
|
||||
{
|
||||
label: 'Tingkat Kehadiran',
|
||||
value: '89.5%',
|
||||
icon: 'mdi-check-circle',
|
||||
iconColor: 'white',
|
||||
color: 'primary',
|
||||
change: '+2.3%',
|
||||
changeType: 'positive',
|
||||
changeIcon: 'mdi-trending-up'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Chart 1: Tren Kunjungan Pasien (Line/Area Chart)
|
||||
|
||||
Chart yang menampilkan tren kunjungan pasien bulanan untuk tahun 2025.
|
||||
|
||||
### Labels (Bulan)
|
||||
|
||||
```javascript
|
||||
[
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"Mei",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Ags",
|
||||
"Sep",
|
||||
"Okt",
|
||||
"Nov",
|
||||
"Des",
|
||||
];
|
||||
```
|
||||
|
||||
### Dataset 1: Pasien Umum
|
||||
|
||||
```javascript
|
||||
{
|
||||
label: 'Pasien Umum',
|
||||
data: [850, 920, 880, 1050, 1120, 1080, 1200, 1150, 1080, 1190, 1250, 1300],
|
||||
backgroundColor: 'rgba(86, 126, 231, 0.2)',
|
||||
borderColor: '#567EE7' // primary-500
|
||||
}
|
||||
```
|
||||
|
||||
**Total Pasien Umum 2025**: 13,070 pasien
|
||||
|
||||
### Dataset 2: Pasien BPJS
|
||||
|
||||
```javascript
|
||||
{
|
||||
label: 'Pasien BPJS',
|
||||
data: [1200, 1350, 1280, 1480, 1550, 1620, 1700, 1650, 1590, 1720, 1800, 1850],
|
||||
backgroundColor: 'rgba(255, 132, 65, 0.2)',
|
||||
borderColor: '#FF8441' // secondary-500
|
||||
}
|
||||
```
|
||||
|
||||
**Total Pasien BPJS 2025**: 18,790 pasien
|
||||
|
||||
**Grand Total**: 31,860 pasien sepanjang tahun 2025
|
||||
|
||||
---
|
||||
|
||||
## 💰 Chart 2: Status Pembayaran (Doughnut Chart)
|
||||
|
||||
Distribusi metode pembayaran pasien.
|
||||
|
||||
### Data
|
||||
|
||||
```javascript
|
||||
{
|
||||
labels: ['BPJS Kesehatan', 'Umum/Tunai', 'Asuransi Swasta', 'Corporate'],
|
||||
datasets: [{
|
||||
data: [1850, 680, 320, 280]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### Breakdown Persentase
|
||||
|
||||
| Metode Pembayaran | Jumlah | Persentase |
|
||||
| ----------------- | --------- | ---------- |
|
||||
| BPJS Kesehatan | 1,850 | 58.6% |
|
||||
| Umum/Tunai | 680 | 21.5% |
|
||||
| Asuransi Swasta | 320 | 10.1% |
|
||||
| Corporate | 280 | 8.9% |
|
||||
| **Total** | **3,130** | **100%** |
|
||||
|
||||
---
|
||||
|
||||
## ⏱️ Chart 3: Waktu Tunggu per Poli (Horizontal Bar Chart)
|
||||
|
||||
Rata-rata waktu tunggu untuk setiap poliklinik (dalam menit).
|
||||
|
||||
### Data
|
||||
|
||||
```javascript
|
||||
{
|
||||
labels: ['Poli Umum', 'Poli Anak', 'Poli Gigi', 'Poli Mata', 'Poli THT', 'Poli Jantung'],
|
||||
datasets: [{
|
||||
label: 'Waktu Tunggu (menit)',
|
||||
data: [15, 12, 8, 18, 10, 22]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### Ranking Waktu Tunggu
|
||||
|
||||
| Rank | Poliklinik | Waktu Tunggu |
|
||||
| ---- | ------------ | ------------ |
|
||||
| 1 | Poli Gigi | 8 menit ⚡ |
|
||||
| 2 | Poli THT | 10 menit |
|
||||
| 3 | Poli Anak | 12 menit |
|
||||
| 4 | Poli Umum | 15 menit |
|
||||
| 5 | Poli Mata | 18 menit |
|
||||
| 6 | Poli Jantung | 22 menit 🐌 |
|
||||
|
||||
**Rata-rata Total**: 14.17 menit
|
||||
|
||||
---
|
||||
|
||||
## ✅ Chart 4: Tingkat Kehadiran (Polar Area Chart)
|
||||
|
||||
Status kehadiran pasien dalam seminggu.
|
||||
|
||||
### Data
|
||||
|
||||
```javascript
|
||||
{
|
||||
labels: ['Hadir Tepat Waktu', 'Hadir Terlambat', 'Tidak Hadir', 'Batal', 'Reschedule'],
|
||||
datasets: [{
|
||||
data: [1850, 420, 280, 150, 230]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### Breakdown Persentase
|
||||
|
||||
| Status | Jumlah | Persentase |
|
||||
| -------------------- | --------- | ---------- |
|
||||
| Hadir Tepat Waktu ✅ | 1,850 | 62.6% |
|
||||
| Hadir Terlambat ⏰ | 420 | 14.2% |
|
||||
| Tidak Hadir ❌ | 280 | 9.5% |
|
||||
| Batal 🚫 | 150 | 5.1% |
|
||||
| Reschedule 📅 | 230 | 7.8% |
|
||||
| **Total** | **2,960** | **100%** |
|
||||
|
||||
**Tingkat Kehadiran Total** (Hadir Tepat Waktu + Hadir Terlambat): 76.8%
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Color Palette
|
||||
|
||||
Palet warna yang digunakan dalam dashboard:
|
||||
|
||||
### Primary Colors
|
||||
|
||||
```javascript
|
||||
{
|
||||
700: '#3556AE',
|
||||
600: '#3A61C9',
|
||||
500: '#567EE7',
|
||||
400: '#7898EC',
|
||||
300: '#9AB2F1',
|
||||
200: '#BBCBF5'
|
||||
}
|
||||
```
|
||||
|
||||
### Secondary Colors
|
||||
|
||||
```javascript
|
||||
{
|
||||
700: '#E65A0D',
|
||||
600: '#F16F29',
|
||||
500: '#FF8441',
|
||||
400: '#FF9D67',
|
||||
300: '#FFB58D'
|
||||
}
|
||||
```
|
||||
|
||||
### Success Colors
|
||||
|
||||
```javascript
|
||||
{
|
||||
700: '#008D65',
|
||||
600: '#33A484',
|
||||
500: '#59B59B',
|
||||
400: '#80C6B2'
|
||||
}
|
||||
```
|
||||
|
||||
### Neutral Colors
|
||||
|
||||
```javascript
|
||||
{
|
||||
100: '#FFFFFF',
|
||||
300: '#F5F7FA',
|
||||
500: '#CDD4DC',
|
||||
700: '#717171',
|
||||
900: '#212121'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📤 Export Options
|
||||
|
||||
Menu export data yang tersedia:
|
||||
|
||||
```javascript
|
||||
[
|
||||
{ title: "JSON (.json)", type: "json", icon: "mdi-code-json" },
|
||||
{ title: "CSV (.csv)", type: "csv", icon: "mdi-file-delimited" },
|
||||
{
|
||||
title: "Excel (.xlsx) - Server Only",
|
||||
type: "excel",
|
||||
icon: "mdi-file-excel",
|
||||
},
|
||||
{ title: "PDF (.pdf) - Placeholder", type: "pdf", icon: "mdi-file-pdf" },
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Summary Insights
|
||||
|
||||
### Total Visitors
|
||||
|
||||
- **Hari Ini**: 324 pasien (+18.2%)
|
||||
- **Bulan Ini** (estimasi): ~2,617 pasien
|
||||
- **Tahun 2025** (dari chart): 31,860 pasien
|
||||
|
||||
### Performance Metrics
|
||||
|
||||
- **Antrean Aktif**: 47 (+5)
|
||||
- **Rata-rata Waktu Tunggu**: 12 menit (-3 min improvement)
|
||||
- **Tingkat Kehadiran**: 89.5% (+2.3%)
|
||||
- **Kehadiran Tepat Waktu**: 62.6%
|
||||
|
||||
### Top Performing Clinic
|
||||
|
||||
- **Tercepat**: Poli Gigi (8 menit)
|
||||
- **Terlambat**: Poli Jantung (22 menit)
|
||||
|
||||
### Payment Distribution
|
||||
|
||||
- **BPJS dominan**: 58.6% dari total transaksi
|
||||
- **Non-BPJS**: 41.4% (Umum + Asuransi + Corporate)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Usage Notes
|
||||
|
||||
File ini mendokumentasikan semua data dummy yang digunakan dalam komponen Dashboard.vue. Data ini dapat digunakan sebagai:
|
||||
|
||||
1. **Reference** untuk struktur data API
|
||||
2. **Testing data** untuk pengembangan
|
||||
3. **Template** untuk implementasi data real dari backend
|
||||
4. **Documentation** untuk tim pengembang
|
||||
|
||||
Semua data bersifat **dummy/sample** dan harus diganti dengan data real dari API/backend saat production.
|
||||
@@ -58,8 +58,6 @@
|
||||
|
||||
<div class="footer">
|
||||
<div class="footer-text">Tunjukkan tiket ini saat check-in</div>
|
||||
<div class="footer-text">QR Code digunakan untuk check-in pasien</div>
|
||||
<div class="footer-text">Terima kasih</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -245,7 +243,7 @@ const {
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 6mm;
|
||||
border-top: 2px solid #000;
|
||||
font-size: 9px;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: 1.0;
|
||||
|
||||
+148
-120
@@ -46,7 +46,6 @@
|
||||
>
|
||||
<template #activator="{ props: menuProps }">
|
||||
<v-tooltip
|
||||
:disabled="!rail"
|
||||
open-on-hover
|
||||
location="end"
|
||||
:text="item.name"
|
||||
@@ -63,17 +62,26 @@
|
||||
</v-tooltip>
|
||||
</template>
|
||||
<v-list density="compact" class="sidebar-popup-menu">
|
||||
<v-list-item
|
||||
<v-tooltip
|
||||
v-for="child in item.children"
|
||||
:key="child.name"
|
||||
:to="child.path"
|
||||
:title="child.name"
|
||||
:prepend-icon="child.icon"
|
||||
link
|
||||
class="sidebar-nav-item"
|
||||
active-class="sidebar-nav-item-active"
|
||||
@click="closePopup"
|
||||
></v-list-item>
|
||||
open-on-hover
|
||||
location="end"
|
||||
:text="child.name"
|
||||
>
|
||||
<template #activator="{ props: tooltipProps }">
|
||||
<v-list-item
|
||||
v-bind="tooltipProps"
|
||||
:to="child.path"
|
||||
:title="child.name"
|
||||
:prepend-icon="child.icon"
|
||||
link
|
||||
class="sidebar-nav-item"
|
||||
active-class="sidebar-nav-item-active"
|
||||
@click="closePopup"
|
||||
></v-list-item>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
|
||||
@@ -93,21 +101,29 @@
|
||||
></v-list-item>
|
||||
</template>
|
||||
|
||||
<v-list-item
|
||||
<v-tooltip
|
||||
v-for="child in item.children"
|
||||
:key="child.name"
|
||||
:to="child.path"
|
||||
:title="child.name"
|
||||
:prepend-icon="child.icon"
|
||||
link
|
||||
class="pl-8 sidebar-nav-item"
|
||||
active-class="sidebar-nav-item-active"
|
||||
></v-list-item>
|
||||
open-on-hover
|
||||
location="end"
|
||||
:text="child.name"
|
||||
>
|
||||
<template #activator="{ props: tooltipProps }">
|
||||
<v-list-item
|
||||
v-bind="tooltipProps"
|
||||
:to="child.path"
|
||||
:title="child.name"
|
||||
:prepend-icon="child.icon"
|
||||
link
|
||||
class="pl-8 sidebar-nav-item"
|
||||
active-class="sidebar-nav-item-active"
|
||||
></v-list-item>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</v-list-group>
|
||||
|
||||
<v-tooltip
|
||||
v-else
|
||||
:disabled="!rail"
|
||||
open-on-hover
|
||||
location="end"
|
||||
:text="item.name"
|
||||
@@ -129,104 +145,106 @@
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-list v-if="user" nav density="compact" class="pa-2 flex-shrink-0">
|
||||
<ProfilePopup :user="user" @logout="handleLogout" :rail="rail" />
|
||||
</v-list>
|
||||
<v-list v-else nav density="compact" class="flex-shrink-0">
|
||||
<v-list-item
|
||||
@click="redirectToLogin"
|
||||
prepend-icon="mdi-login"
|
||||
title="Login"
|
||||
link
|
||||
class="sidebar-login-item"
|
||||
></v-list-item>
|
||||
</v-list>
|
||||
<!-- Bottom section wrapper for profile and lock button -->
|
||||
<div class="sidebar-bottom-section">
|
||||
<v-list v-if="user" nav density="compact" class="pa-2">
|
||||
<ProfilePopup :user="user" @logout="handleLogout" :rail="rail" />
|
||||
</v-list>
|
||||
<v-list v-else nav density="compact">
|
||||
<v-list-item
|
||||
@click="redirectToLogin"
|
||||
prepend-icon="mdi-login"
|
||||
title="Login"
|
||||
link
|
||||
class="sidebar-login-item"
|
||||
></v-list-item>
|
||||
</v-list>
|
||||
|
||||
<!-- Lock Sidebar Toggle - Positioned at bottom left -->
|
||||
<div class="sidebar-lock-container">
|
||||
<v-tooltip
|
||||
:disabled="!rail"
|
||||
open-on-hover
|
||||
location="end"
|
||||
:text="isLocked ? 'Buka Sidebar' : 'Kunci Sidebar'"
|
||||
>
|
||||
<template #activator="{ props: tooltipProps }">
|
||||
<v-btn
|
||||
v-bind="tooltipProps"
|
||||
:class="['sidebar-lock-btn', { 'sidebar-lock-btn-locked': isLocked }]"
|
||||
variant="text"
|
||||
size="small"
|
||||
@click="handleLockToggle(!isLocked)"
|
||||
>
|
||||
<!-- Icon Collapsed Sidebar (sidebar collapsed/locked) -->
|
||||
<svg
|
||||
v-if="isLocked"
|
||||
class="sidebar-toggle-icon"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<!-- Lock Sidebar Toggle -->
|
||||
<div class="sidebar-lock-container">
|
||||
<v-tooltip
|
||||
open-on-hover
|
||||
location="end"
|
||||
:text="isLocked ? 'Buka Sidebar' : 'Kunci Sidebar'"
|
||||
>
|
||||
<template #activator="{ props: tooltipProps }">
|
||||
<v-btn
|
||||
v-bind="tooltipProps"
|
||||
:class="['sidebar-lock-btn', { 'sidebar-lock-btn-locked': isLocked }]"
|
||||
variant="text"
|
||||
size="small"
|
||||
@click="handleLockToggle(!isLocked)"
|
||||
>
|
||||
<!-- Rounded rectangle container -->
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="16"
|
||||
height="16"
|
||||
rx="3"
|
||||
fill="var(--color-primary-100)"
|
||||
/>
|
||||
<!-- Sidebar area (kiri, narrow ~30%, biru gelap) -->
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="6"
|
||||
height="16"
|
||||
rx="3"
|
||||
fill="var(--color-primary-600)"
|
||||
/>
|
||||
</svg>
|
||||
<!-- Icon Expanded Sidebar (sidebar expanded/unlocked) -->
|
||||
<svg
|
||||
v-else
|
||||
class="sidebar-toggle-icon"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!-- Rounded rectangle container -->
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="16"
|
||||
height="16"
|
||||
rx="3"
|
||||
fill="var(--color-primary-100)"
|
||||
/>
|
||||
<!-- Sidebar area (kiri, wider ~55%, biru gelap) -->
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="11"
|
||||
height="16"
|
||||
rx="3"
|
||||
fill="var(--color-primary-600)"
|
||||
/>
|
||||
<!-- Left-pointing arrow in the white area -->
|
||||
<path
|
||||
d="M 15.5 10 L 13.5 8 M 15.5 10 L 13.5 12"
|
||||
stroke="var(--color-primary-600)"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<!-- Icon Collapsed Sidebar (sidebar collapsed/locked) -->
|
||||
<svg
|
||||
v-if="isLocked"
|
||||
class="sidebar-toggle-icon"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!-- Rounded rectangle container -->
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="16"
|
||||
height="16"
|
||||
rx="3"
|
||||
fill="var(--color-primary-100)"
|
||||
/>
|
||||
<!-- Sidebar area (kiri, narrow ~30%, biru gelap) -->
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="6"
|
||||
height="16"
|
||||
rx="3"
|
||||
fill="var(--color-primary-600)"
|
||||
/>
|
||||
</svg>
|
||||
<!-- Icon Expanded Sidebar (sidebar expanded/unlocked) -->
|
||||
<svg
|
||||
v-else
|
||||
class="sidebar-toggle-icon"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!-- Rounded rectangle container -->
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="16"
|
||||
height="16"
|
||||
rx="3"
|
||||
fill="var(--color-primary-100)"
|
||||
/>
|
||||
<!-- Sidebar area (kiri, wider ~55%, biru gelap) -->
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="11"
|
||||
height="16"
|
||||
rx="3"
|
||||
fill="var(--color-primary-600)"
|
||||
/>
|
||||
<!-- Left-pointing arrow in the white area -->
|
||||
<path
|
||||
d="M 15.5 10 L 13.5 8 M 15.5 10 L 13.5 12"
|
||||
stroke="var(--color-primary-600)"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</v-navigation-drawer>
|
||||
</template>
|
||||
@@ -329,7 +347,17 @@ onMounted(async () => {
|
||||
@use '~/assets/scss/_colors.scss' as *;
|
||||
|
||||
:deep(.v-navigation-drawer) {
|
||||
position: relative;
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
height: 100vh !important;
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
.sidebar-bottom-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-logo-container {
|
||||
@@ -472,10 +500,10 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.sidebar-lock-container {
|
||||
position: absolute;
|
||||
bottom: 16px;
|
||||
left: 8px;
|
||||
z-index: 10;
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sidebar-lock-btn {
|
||||
|
||||
@@ -329,7 +329,7 @@ export const useThermalPrint = () => {
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 6mm;
|
||||
border-top: 2px solid #000;
|
||||
font-size: 9px;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: 1.0;
|
||||
@@ -462,8 +462,6 @@ export const useThermalPrint = () => {
|
||||
|
||||
<div class="footer">
|
||||
<div class="footer-text">Tunjukkan tiket ini saat check-in</div>
|
||||
<div class="footer-text">QR Code digunakan untuk check-in pasien</div>
|
||||
<div class="footer-text">Terima kasih</div>
|
||||
</div>
|
||||
|
||||
<!-- Feed lines untuk auto cutter (space setelah footer untuk cutter) -->
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="header-content">
|
||||
<h1 class="main-title">Pilih Layar Antrian Loket</h1>
|
||||
<p class="subtitle">RSUD dr. Saiful Anwar Provinsi Jawa Timur</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="loket-selection-container">
|
||||
|
||||
+404
-217
@@ -15,10 +15,10 @@
|
||||
<!-- Main Content Grid - Same pattern as AdminLoket.vue -->
|
||||
<v-row class="content-grid" dense>
|
||||
<!-- Left Column: QR Scan Card -->
|
||||
<v-col cols="12" md="6" lg="5" class="sticky-column">
|
||||
<div class="sticky-wrapper">
|
||||
<v-card class="qr-scan-card" elevation="0">
|
||||
<v-card-text class="pa-4">
|
||||
<v-col cols="12" md="6" lg="5" class="sticky-column d-flex">
|
||||
<div class="sticky-wrapper" style="width: 100%;">
|
||||
<v-card class="qr-scan-card" elevation="0" style="height: 100%;">
|
||||
<v-card-text class="pa-4 d-flex flex-column" style="height: 100%;">
|
||||
<!-- Status Header -->
|
||||
<div class="status-header mb-3">
|
||||
<div class="status-icon-wrapper">
|
||||
@@ -50,7 +50,8 @@
|
||||
v-else-if="!hasCamera && !isScanning"
|
||||
type="warning"
|
||||
variant="tonal"
|
||||
class="mb-4"
|
||||
class="mb-3 compact-alert"
|
||||
density="compact"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<v-icon>mdi-camera-off</v-icon>
|
||||
@@ -210,9 +211,9 @@
|
||||
</v-col>
|
||||
|
||||
<!-- Right Column: Manual Input Card -->
|
||||
<v-col cols="12" md="6" lg="5" class="manual-input-column">
|
||||
<v-card class="manual-input-card" elevation="0">
|
||||
<v-card-text class="pa-4">
|
||||
<v-col cols="12" md="6" lg="4" class="manual-input-column d-flex">
|
||||
<v-card class="manual-input-card" elevation="0" style="height: 100%; width: 100%;">
|
||||
<v-card-text class="pa-4 d-flex flex-column" style="height: 100%;">
|
||||
<!-- Status Header -->
|
||||
<div class="status-header mb-3">
|
||||
<div class="status-icon-wrapper">
|
||||
@@ -395,74 +396,62 @@
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- Enhanced Stats Sidebar - Right Side -->
|
||||
<v-col cols="12" lg="auto" class="stats-sidebar-right" style="order: 3; flex-shrink: 0;">
|
||||
<div class="sticky-wrapper">
|
||||
<div class="stats-sidebar-enhanced">
|
||||
<!-- Sidebar Header -->
|
||||
<div class="sidebar-header">
|
||||
<v-icon :color="primaryColor" size="14" class="mr-1">mdi-chart-box-outline</v-icon>
|
||||
<span class="sidebar-title">Statistik</span>
|
||||
<!-- Stats Footer (Horizontal) - Permanent Footer for All Screens -->
|
||||
<v-row class="stats-footer-row" dense>
|
||||
<v-col cols="12">
|
||||
<div class="stats-footer-horizontal">
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-primary" :title="`Total Check-in Hari Ini: ${todayStats.total}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon :color="primaryColor" size="18">mdi-calendar-today</v-icon>
|
||||
</div>
|
||||
|
||||
<!-- Stats Items -->
|
||||
<div class="stats-container">
|
||||
<div class="stat-item-enhanced stat-item-primary" :title="`Total Check-in Hari Ini: ${todayStats.total}`">
|
||||
<div class="stat-icon-enhanced">
|
||||
<v-icon :color="primaryColor" size="18">mdi-calendar-today</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-enhanced">
|
||||
<div class="stat-value-enhanced">{{ todayStats.total }}</div>
|
||||
<div class="stat-label-enhanced">Hari Ini</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-item-enhanced stat-item-success" :title="`Check-in Berhasil: ${todayStats.success}`">
|
||||
<div class="stat-icon-enhanced">
|
||||
<v-icon color="success" size="18">mdi-check-circle</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-enhanced">
|
||||
<div class="stat-value-enhanced">{{ todayStats.success }}</div>
|
||||
<div class="stat-label-enhanced">Berhasil</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-item-enhanced stat-item-error" :title="`Check-in Gagal: ${todayStats.failed}`">
|
||||
<div class="stat-icon-enhanced">
|
||||
<v-icon color="error" size="18">mdi-close-circle</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-enhanced">
|
||||
<div class="stat-value-enhanced">{{ todayStats.failed }}</div>
|
||||
<div class="stat-label-enhanced">Gagal</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-item-enhanced stat-item-info" :title="`Check-in via QR: ${todayStats.qr}`">
|
||||
<div class="stat-icon-enhanced">
|
||||
<v-icon color="info" size="18">mdi-qrcode-scan</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-enhanced">
|
||||
<div class="stat-value-enhanced">{{ todayStats.qr }}</div>
|
||||
<div class="stat-label-enhanced">QR Scan</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-item-enhanced stat-item-warning" :title="`Check-in Manual: ${todayStats.manual}`">
|
||||
<div class="stat-icon-enhanced">
|
||||
<v-icon color="warning" size="18">mdi-keyboard</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-enhanced">
|
||||
<div class="stat-value-enhanced">{{ todayStats.manual }}</div>
|
||||
<div class="stat-label-enhanced">Manual</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.total }}</div>
|
||||
<div class="stat-label-footer-enhanced">Hari Ini</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-success" :title="`Check-in Berhasil: ${todayStats.success}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon color="success" size="18">mdi-check-circle</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.success }}</div>
|
||||
<div class="stat-label-footer-enhanced">Berhasil</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-error" :title="`Check-in Gagal: ${todayStats.failed}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon color="error" size="18">mdi-close-circle</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.failed }}</div>
|
||||
<div class="stat-label-footer-enhanced">Gagal</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-info" :title="`Check-in via QR: ${todayStats.qr}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon color="info" size="18">mdi-qrcode-scan</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.qr }}</div>
|
||||
<div class="stat-label-footer-enhanced">QR Scan</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-warning" :title="`Check-in Manual: ${todayStats.manual}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon color="warning" size="18">mdi-keyboard</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.manual }}</div>
|
||||
<div class="stat-label-footer-enhanced">Manual</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
||||
<!-- Generate QR Dialog -->
|
||||
<v-dialog v-model="showGenerateQRDialog" max-width="600px" scrollable>
|
||||
<v-card>
|
||||
@@ -675,54 +664,7 @@
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<!-- Stats Footer (Horizontal) - For Small Screens - Match Sidebar Design -->
|
||||
<div class="stats-footer-horizontal mt-3">
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-primary" :title="`Total Check-in Hari Ini: ${todayStats.total}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon :color="primaryColor" size="18">mdi-calendar-today</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.total }}</div>
|
||||
<div class="stat-label-footer-enhanced">Hari Ini</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-success" :title="`Check-in Berhasil: ${todayStats.success}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon color="success" size="18">mdi-check-circle</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.success }}</div>
|
||||
<div class="stat-label-footer-enhanced">Berhasil</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-error" :title="`Check-in Gagal: ${todayStats.failed}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon color="error" size="18">mdi-close-circle</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.failed }}</div>
|
||||
<div class="stat-label-footer-enhanced">Gagal</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-info" :title="`Check-in via QR: ${todayStats.qr}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon color="info" size="18">mdi-qrcode-scan</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.qr }}</div>
|
||||
<div class="stat-label-footer-enhanced">QR Scan</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item-footer-enhanced stat-item-footer-warning" :title="`Check-in Manual: ${todayStats.manual}`">
|
||||
<div class="stat-icon-footer-enhanced">
|
||||
<v-icon color="warning" size="18">mdi-keyboard</v-icon>
|
||||
</div>
|
||||
<div class="stat-content-footer-enhanced">
|
||||
<div class="stat-value-footer-enhanced">{{ todayStats.manual }}</div>
|
||||
<div class="stat-label-footer-enhanced">Manual</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Enhanced Dialog with Blur -->
|
||||
<v-dialog
|
||||
@@ -3645,18 +3587,22 @@ onUnmounted(() => {
|
||||
.checkin-page-container {
|
||||
background: $neutral-100;
|
||||
min-height: 100vh;
|
||||
padding: 0 8px 16px 8px;
|
||||
max-height: 100vh;
|
||||
padding: 0 4px 0 4px;
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Header Full Width - No padding from edges */
|
||||
.checkin-page-container :deep(.page-header) {
|
||||
margin-left: -8px;
|
||||
margin-right: -8px;
|
||||
margin-left: -4px;
|
||||
margin-right: -4px;
|
||||
border-radius: 0 !important;
|
||||
width: calc(100% + 16px);
|
||||
width: calc(100% + 8px);
|
||||
}
|
||||
|
||||
.checkin-page-container::before {
|
||||
@@ -4098,16 +4044,19 @@ onUnmounted(() => {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 16px;
|
||||
padding: 20px 24px;
|
||||
gap: 12px;
|
||||
padding: 14px 16px;
|
||||
background: linear-gradient(135deg, rgba($primary-50, 0.8) 0%, rgba($primary-100, 0.6) 100%);
|
||||
border-radius: 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba($primary-600, 0.12);
|
||||
box-shadow: 0 4px 12px rgba($primary-600, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||
text-align: left;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
min-height: 72px;
|
||||
max-height: 72px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-header::before {
|
||||
@@ -4127,9 +4076,13 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.status-icon-wrapper {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 12px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
min-width: 40px;
|
||||
min-height: 40px;
|
||||
max-width: 40px;
|
||||
max-height: 40px;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(135deg, $primary-600 0%, $primary-700 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -4162,12 +4115,12 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.status-title {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: $neutral-900;
|
||||
margin: 0 0 4px;
|
||||
letter-spacing: -0.2px;
|
||||
line-height: 1.3;
|
||||
font-size: 15px !important;
|
||||
font-weight: 700 !important;
|
||||
color: $neutral-900 !important;
|
||||
margin: 0 0 2px !important;
|
||||
letter-spacing: -0.2px !important;
|
||||
line-height: 1.3 !important;
|
||||
}
|
||||
|
||||
.status-subtitle {
|
||||
@@ -4183,8 +4136,8 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 32px 0;
|
||||
padding: 8px;
|
||||
margin: 24px 0;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.qr-placeholder {
|
||||
@@ -4432,9 +4385,9 @@ onUnmounted(() => {
|
||||
font-weight: 600;
|
||||
text-transform: none;
|
||||
letter-spacing: 0.5px;
|
||||
border-radius: 14px !important;
|
||||
padding: 16px 32px !important;
|
||||
min-height: 56px !important;
|
||||
border-radius: 12px !important;
|
||||
padding: 14px 28px !important;
|
||||
min-height: 50px !important;
|
||||
min-width: 44px !important;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 6px 20px rgba($primary-600, 0.35), 0 2px 8px rgba($primary-600, 0.2) !important;
|
||||
@@ -4486,9 +4439,9 @@ onUnmounted(() => {
|
||||
font-weight: 600;
|
||||
text-transform: none;
|
||||
letter-spacing: 0.5px;
|
||||
border-radius: 14px !important;
|
||||
padding: 16px 32px !important;
|
||||
min-height: 56px !important;
|
||||
border-radius: 12px !important;
|
||||
padding: 14px 28px !important;
|
||||
min-height: 50px !important;
|
||||
min-width: 44px !important;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 6px 20px rgba($danger-500, 0.35), 0 2px 8px rgba($danger-500, 0.2) !important;
|
||||
@@ -4828,10 +4781,11 @@ onUnmounted(() => {
|
||||
|
||||
/* Content Grid - Same pattern as AdminLoket.vue */
|
||||
.content-grid {
|
||||
margin: 0 20px;
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
margin: 0 8px;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: visible;
|
||||
align-items: stretch;
|
||||
flex-wrap: nowrap !important;
|
||||
}
|
||||
|
||||
@@ -4842,15 +4796,15 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.content-grid > .v-col {
|
||||
padding: 8px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.content-grid > .v-col:first-child {
|
||||
padding-left: 8px;
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.content-grid > .v-col:last-child {
|
||||
padding-right: 8px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
/* Ensure proper column order */
|
||||
@@ -4882,8 +4836,10 @@ onUnmounted(() => {
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba($primary-300, 0.2);
|
||||
border-radius: 16px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -4893,28 +4849,37 @@ onUnmounted(() => {
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba($primary-300, 0.2);
|
||||
border-radius: 16px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Removed main-content-col - now using content-grid pattern */
|
||||
/* Column classes for equal height */
|
||||
.sticky-column,
|
||||
.manual-input-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sticky-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Hide right sidebar on all screens */
|
||||
.stats-sidebar-right {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
min-width: 160px;
|
||||
max-width: 180px;
|
||||
width: auto;
|
||||
display: none;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
flex-shrink: 0 !important;
|
||||
flex-grow: 0 !important;
|
||||
position: relative;
|
||||
height: auto;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Content Grid */
|
||||
.content-grid {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: visible;
|
||||
order: 3 !important;
|
||||
}
|
||||
|
||||
:deep(.stats-sidebar-right) {
|
||||
@@ -4926,20 +4891,22 @@ onUnmounted(() => {
|
||||
display: flex !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0 !important;
|
||||
flex-grow: 0 !important;
|
||||
width: auto !important;
|
||||
max-width: 180px !important;
|
||||
min-width: 160px !important;
|
||||
max-width: 160px !important;
|
||||
min-width: 140px !important;
|
||||
z-index: 10;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.stats-sidebar-enhanced {
|
||||
display: flex !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4966,26 +4933,123 @@ onUnmounted(() => {
|
||||
.sticky-wrapper {
|
||||
top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compact Alert for Camera Warning */
|
||||
.compact-alert {
|
||||
padding: 4px 8px !important;
|
||||
font-size: 10px !important;
|
||||
min-height: 48px !important;
|
||||
max-height: 48px !important;
|
||||
border-radius: 8px !important;
|
||||
|
||||
.checkin-page-container {
|
||||
padding-right: 0;
|
||||
:deep(.v-alert__prepend) {
|
||||
margin-right: 4px !important;
|
||||
}
|
||||
|
||||
.checkin-page-container :deep(.page-header) {
|
||||
margin-right: 0;
|
||||
width: calc(100% + 8px);
|
||||
:deep(.v-icon) {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
:deep(p) {
|
||||
font-size: 9px !important;
|
||||
line-height: 1.2 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.font-weight-bold) {
|
||||
font-size: 11px !important;
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
|
||||
:deep(.text-body-2) {
|
||||
font-size: 9px !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert__content) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.checkin-page-container {
|
||||
padding: 0 12px 12px 12px;
|
||||
padding: 0 8px 8px 8px;
|
||||
max-height: none !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
.checkin-page-container :deep(.page-header) {
|
||||
margin-left: -12px;
|
||||
margin-right: -12px;
|
||||
width: calc(100% + 24px);
|
||||
margin-left: -8px;
|
||||
margin-right: -8px;
|
||||
width: calc(100% + 16px);
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
flex-direction: column !important;
|
||||
margin: 0 4px !important;
|
||||
}
|
||||
|
||||
.sticky-column,
|
||||
.manual-input-column {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.qr-scan-card,
|
||||
.manual-input-card {
|
||||
max-height: 40vh !important;
|
||||
overflow-y: auto !important;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* Alert box mobile styles */
|
||||
:deep(.v-alert) {
|
||||
font-size: 12px !important;
|
||||
padding: 10px 12px !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert .v-alert__prepend) {
|
||||
margin-right: 8px !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert .v-icon) {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert p) {
|
||||
font-size: 11px !important;
|
||||
line-height: 1.4 !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert .font-weight-bold) {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
/* QR Scanner mobile */
|
||||
.qr-scanner-container {
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.qr-placeholder {
|
||||
max-width: 280px !important;
|
||||
min-height: 180px !important;
|
||||
}
|
||||
|
||||
/* Buttons mobile */
|
||||
:deep(.v-btn) {
|
||||
font-size: 13px !important;
|
||||
min-height: 44px !important;
|
||||
}
|
||||
|
||||
/* Input fields mobile */
|
||||
:deep(.v-text-field) {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
:deep(.v-text-field .v-field__input) {
|
||||
min-height: 44px !important;
|
||||
padding: 8px 12px !important;
|
||||
}
|
||||
|
||||
.sticky-wrapper {
|
||||
@@ -4993,6 +5057,30 @@ onUnmounted(() => {
|
||||
top: 0;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.stats-footer-horizontal {
|
||||
flex-wrap: wrap !important;
|
||||
gap: 6px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.stat-item-footer-enhanced {
|
||||
min-width: calc(50% - 6px);
|
||||
flex: 1 1 calc(50% - 6px);
|
||||
padding: 8px 6px;
|
||||
}
|
||||
|
||||
.stat-value-footer-enhanced {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.stat-label-footer-enhanced {
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.stat-icon-footer-enhanced .v-icon {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enhanced Sidebar Design */
|
||||
@@ -6121,13 +6209,20 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop - Large screens */
|
||||
@media (min-width: 1264px) {
|
||||
.content-grid {
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap !important;
|
||||
}
|
||||
|
||||
.qr-scan-card,
|
||||
.manual-input-card {
|
||||
max-height: calc(100vh - 240px) !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.stats-sidebar-right {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
@@ -6143,16 +6238,120 @@ onUnmounted(() => {
|
||||
.sticky-column {
|
||||
order: 1 !important;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.content-grid > .v-col:nth-child(2) {
|
||||
order: 2 !important;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.stats-sidebar-enhanced,
|
||||
.stats-sidebar-discord {
|
||||
margin: 0 auto;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet - Medium screens (961px to 1263px) */
|
||||
@media (min-width: 961px) and (max-width: 1263px) {
|
||||
.qr-scan-card,
|
||||
.manual-input-card {
|
||||
max-height: calc(100vh - 220px) !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
/* Small tablets and large phones (721px to 960px) */
|
||||
@media (min-width: 721px) and (max-width: 960px) {
|
||||
.qr-scan-card,
|
||||
.manual-input-card {
|
||||
max-height: calc(50vh - 100px) !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* Very small screens (up to 720px) */
|
||||
@media (max-width: 720px) {
|
||||
.qr-scan-card,
|
||||
.manual-input-card {
|
||||
max-height: calc(45vh - 70px) !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.stats-footer-horizontal {
|
||||
padding: 6px 8px;
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extra small screens (phones in portrait, up to 480px) */
|
||||
@media (max-width: 480px) {
|
||||
.checkin-page-container {
|
||||
padding: 0 4px 4px 4px !important;
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
margin: 0 2px !important;
|
||||
}
|
||||
|
||||
.qr-scan-card,
|
||||
.manual-input-card {
|
||||
max-height: 38vh !important;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
/* Alert box extra small */
|
||||
:deep(.v-alert) {
|
||||
font-size: 11px !important;
|
||||
padding: 8px 10px !important;
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert .v-alert__prepend) {
|
||||
margin-right: 6px !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert .v-icon) {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert p) {
|
||||
font-size: 10px !important;
|
||||
}
|
||||
|
||||
:deep(.v-alert .font-weight-bold) {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.stats-footer-horizontal {
|
||||
padding: 4px 6px;
|
||||
gap: 3px;
|
||||
border-radius: 8px;
|
||||
max-width: calc(100vw - 12px) !important;
|
||||
}
|
||||
|
||||
.stat-item-footer-enhanced {
|
||||
min-width: calc(50% - 3px);
|
||||
flex: 1 1 calc(50% - 3px);
|
||||
padding: 6px 4px;
|
||||
}
|
||||
|
||||
.stat-value-footer-enhanced {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.stat-label-footer-enhanced {
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
.stat-icon-footer-enhanced .v-icon {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6174,18 +6373,32 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
/* Stats Footer Horizontal - For Small Screens - Match Sidebar Design */
|
||||
.stats-footer-horizontal {
|
||||
/* Stats Footer Horizontal - Permanent Footer for All Screens */
|
||||
.stats-footer-row {
|
||||
margin-top: 4px !important;
|
||||
margin-bottom: 4px !important;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.stats-footer-horizontal {
|
||||
display: flex !important;
|
||||
width: 100%;
|
||||
max-width: calc(100vw - 32px);
|
||||
gap: 5px;
|
||||
padding: 8px;
|
||||
padding: 6px 8px;
|
||||
background: linear-gradient(180deg, rgba($primary-50, 0.98) 0%, rgba($primary-100, 0.92) 100%);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
border: 1px solid rgba($primary-300, 0.2);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.stat-item-footer-enhanced {
|
||||
@@ -6197,11 +6410,11 @@ onUnmounted(() => {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
padding: 6px 4px;
|
||||
border-radius: 10px;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border: 1px solid rgba($primary-300, 0.25);
|
||||
overflow: hidden;
|
||||
padding: 5px 4px;
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
min-width: 65px;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.stat-item-footer-enhanced:hover {
|
||||
@@ -6222,7 +6435,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.stat-value-footer-enhanced {
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: $primary-700;
|
||||
line-height: 1.2;
|
||||
@@ -6304,34 +6517,8 @@ onUnmounted(() => {
|
||||
border-color: rgba($secondary-500, 0.5);
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.stats-footer-horizontal {
|
||||
gap: 4px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.stat-item-footer-enhanced {
|
||||
padding: 5px 3px;
|
||||
}
|
||||
|
||||
.stat-value-footer-enhanced {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.stat-label-footer-enhanced {
|
||||
font-size: 6px;
|
||||
}
|
||||
|
||||
.stat-icon-footer-enhanced .v-icon {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1264px) {
|
||||
.stats-footer-horizontal {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Mobile Landscape */
|
||||
@media (max-width: 900px) and (orientation: landscape) {
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ const defaultNavItems: NavItem[] = [
|
||||
{ id: 4, name: "Admin Loket", icon: "mdi-account-supervisor-outline", path: "/AdminLoket" },
|
||||
{ id: 6, name: "Admin Klinik Ruang", icon: "mdi-door-open", path: "/AdminKlinikRuang" },
|
||||
// { id: 7, name: "Admin Penunjang", icon: "mdi-plus-box-outline", path: "/AdminPenunjang" },
|
||||
{ id: 8, name: "Buat Antrean", icon: "mdi-account-multiple-plus-outline", path: "/BuatAntrean" },
|
||||
// { id: 8, name: "Buat Antrean", icon: "mdi-account-multiple-plus-outline", path: "/BuatAntrean" },
|
||||
{ id: 9, name: "Monitoring Pasien", icon: "mdi-account-group-outline", path: "/MonitoringPasien/monitoringPasien" },
|
||||
{
|
||||
id: 10,
|
||||
|
||||
Reference in New Issue
Block a user