perubahan update sidebar dashboard monitoring dan antrean loket verifikasi
This commit is contained in:
@@ -334,6 +334,7 @@ onMounted(async () => {
|
||||
|
||||
.sidebar-logo-container {
|
||||
overflow: visible !important;
|
||||
height: 80px !important;
|
||||
|
||||
:deep(.v-list-item__content) {
|
||||
overflow: visible !important;
|
||||
|
||||
+25
-165
@@ -468,13 +468,11 @@ const visitTrendData = ref({
|
||||
borderWidth: 3,
|
||||
fill: true,
|
||||
tension: 0.4,
|
||||
pointRadius: 5,
|
||||
pointHoverRadius: 8,
|
||||
pointRadius: 4,
|
||||
pointHoverRadius: 6,
|
||||
pointBackgroundColor: colors.primary[600],
|
||||
pointBorderColor: '#fff',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 3,
|
||||
pointHoverBorderColor: colors.primary[900],
|
||||
},
|
||||
{
|
||||
label: 'Pasien BPJS',
|
||||
@@ -484,13 +482,11 @@ const visitTrendData = ref({
|
||||
borderWidth: 3,
|
||||
fill: true,
|
||||
tension: 0.4,
|
||||
pointRadius: 5,
|
||||
pointHoverRadius: 8,
|
||||
pointRadius: 4,
|
||||
pointHoverRadius: 6,
|
||||
pointBackgroundColor: colors.secondary[600],
|
||||
pointBorderColor: '#fff',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 3,
|
||||
pointHoverBorderColor: colors.secondary[900],
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -509,9 +505,7 @@ const paymentStatusData = ref({
|
||||
],
|
||||
borderColor: '#fff',
|
||||
borderWidth: 3,
|
||||
hoverOffset: 20,
|
||||
hoverBorderWidth: 4,
|
||||
hoverBorderColor: '#000',
|
||||
hoverOffset: 15,
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -531,14 +525,6 @@ const waitingTimeData = ref({
|
||||
colors.secondary[500],
|
||||
colors.success[500],
|
||||
],
|
||||
hoverBackgroundColor: [
|
||||
colors.primary[600],
|
||||
colors.secondary[600],
|
||||
colors.success[600],
|
||||
colors.primary[700],
|
||||
colors.secondary[700],
|
||||
colors.success[700],
|
||||
],
|
||||
borderColor: [
|
||||
colors.primary[600],
|
||||
colors.secondary[600],
|
||||
@@ -549,7 +535,6 @@ const waitingTimeData = ref({
|
||||
],
|
||||
borderWidth: 2,
|
||||
borderRadius: 8,
|
||||
hoverBorderWidth: 3,
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -567,16 +552,8 @@ const attendanceData = ref({
|
||||
colors.neutral[500],
|
||||
colors.primary[300],
|
||||
],
|
||||
hoverBackgroundColor: [
|
||||
colors.success[600],
|
||||
colors.primary[600],
|
||||
colors.secondary[600],
|
||||
colors.neutral[700],
|
||||
colors.primary[500],
|
||||
],
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2,
|
||||
hoverBorderWidth: 3,
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -589,11 +566,6 @@ const areaChartOptions = ref({
|
||||
duration: 1000,
|
||||
easing: 'easeInOutQuart'
|
||||
},
|
||||
onHover: (event, activeElements) => {
|
||||
if (event.native) {
|
||||
event.native.target.style.cursor = activeElements.length > 0 ? 'pointer' : 'default';
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: true,
|
||||
@@ -615,43 +587,14 @@ const areaChartOptions = ref({
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||
titleColor: colors.neutral[900],
|
||||
bodyColor: colors.neutral[700],
|
||||
borderColor: colors.primary,
|
||||
borderWidth: 2,
|
||||
padding: 16,
|
||||
boxPadding: 8,
|
||||
displayColors: true,
|
||||
borderColor: colors.neutral[400],
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
boxPadding: 6,
|
||||
usePointStyle: true,
|
||||
caretPadding: 15,
|
||||
cornerRadius: 8,
|
||||
xAlign: 'center',
|
||||
yAlign: 'top',
|
||||
animation: {
|
||||
duration: 200,
|
||||
easing: 'easeInOutQuart'
|
||||
},
|
||||
titleFont: {
|
||||
size: 13,
|
||||
weight: 'bold',
|
||||
family: "'Inter', sans-serif"
|
||||
},
|
||||
bodyFont: {
|
||||
size: 12,
|
||||
family: "'Inter', sans-serif"
|
||||
},
|
||||
callbacks: {
|
||||
title: function(context) {
|
||||
return `📈 ${context[0].label}`;
|
||||
},
|
||||
label: function(context) {
|
||||
const value = context.parsed.y.toLocaleString('id-ID');
|
||||
const percentage = ((context.parsed.y / Math.max(...context.dataset.data)) * 100).toFixed(0);
|
||||
return [
|
||||
`${context.dataset.label}: ${value} pasien`,
|
||||
`Persentase: ${percentage}%`
|
||||
];
|
||||
},
|
||||
afterLabel: function(context) {
|
||||
return `Dataset: ${context.dataset.label}`;
|
||||
return `${context.dataset.label}: ${context.parsed.y.toLocaleString('id-ID')} pasien`;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -741,43 +684,18 @@ const doughnutOptions = ref({
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||
titleColor: colors.neutral[900],
|
||||
bodyColor: colors.neutral[700],
|
||||
borderColor: colors.success,
|
||||
borderWidth: 2,
|
||||
padding: 16,
|
||||
boxPadding: 8,
|
||||
displayColors: true,
|
||||
borderColor: colors.neutral[400],
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
boxPadding: 6,
|
||||
usePointStyle: true,
|
||||
caretPadding: 15,
|
||||
cornerRadius: 8,
|
||||
xAlign: 'center',
|
||||
yAlign: 'top',
|
||||
animation: {
|
||||
duration: 200,
|
||||
easing: 'easeInOutQuart'
|
||||
},
|
||||
titleFont: {
|
||||
size: 13,
|
||||
weight: 'bold',
|
||||
family: "'Inter', sans-serif"
|
||||
},
|
||||
bodyFont: {
|
||||
size: 12,
|
||||
family: "'Inter', sans-serif"
|
||||
},
|
||||
callbacks: {
|
||||
title: function(context) {
|
||||
return `💳 Status Pembayaran`;
|
||||
},
|
||||
label: function(context) {
|
||||
const label = context.label || '';
|
||||
const value = context.parsed;
|
||||
const total = context.dataset.data.reduce((a, b) => a + b, 0);
|
||||
const percentage = ((value / total) * 100).toFixed(1);
|
||||
return [
|
||||
`${label}: ${value.toLocaleString('id-ID')}`,
|
||||
`Persentase: ${percentage}%`,
|
||||
`Total: ${total.toLocaleString('id-ID')}`
|
||||
];
|
||||
return `${label}: ${value.toLocaleString('id-ID')} (${percentage}%)`;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -793,11 +711,6 @@ const horizontalBarOptions = ref({
|
||||
duration: 1000,
|
||||
easing: 'easeInOutQuart'
|
||||
},
|
||||
onHover: (event, activeElements) => {
|
||||
if (event.native) {
|
||||
event.native.target.style.cursor = activeElements.length > 0 ? 'pointer' : 'default';
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
@@ -807,42 +720,14 @@ const horizontalBarOptions = ref({
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||
titleColor: colors.neutral[900],
|
||||
bodyColor: colors.neutral[700],
|
||||
borderColor: colors.secondary,
|
||||
borderWidth: 2,
|
||||
padding: 16,
|
||||
boxPadding: 8,
|
||||
displayColors: true,
|
||||
borderColor: colors.neutral[400],
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
boxPadding: 6,
|
||||
usePointStyle: true,
|
||||
caretPadding: 15,
|
||||
cornerRadius: 8,
|
||||
xAlign: 'center',
|
||||
yAlign: 'top',
|
||||
animation: {
|
||||
duration: 200,
|
||||
easing: 'easeInOutQuart'
|
||||
},
|
||||
titleFont: {
|
||||
size: 13,
|
||||
weight: 'bold',
|
||||
family: "'Inter', sans-serif"
|
||||
},
|
||||
bodyFont: {
|
||||
size: 12,
|
||||
family: "'Inter', sans-serif"
|
||||
},
|
||||
callbacks: {
|
||||
title: function(context) {
|
||||
return `⏱️ ${context[0].label}`;
|
||||
},
|
||||
label: function(context) {
|
||||
const waitTime = context.parsed.x;
|
||||
let status = '✅ Cepat';
|
||||
if (waitTime > 30) status = '⚠️ Sedang';
|
||||
if (waitTime > 60) status = '🔴 Lama';
|
||||
return [
|
||||
`Waktu tunggu: ${waitTime} menit`,
|
||||
`Status: ${status}`
|
||||
];
|
||||
return `Waktu tunggu: ${context.parsed.x} menit`;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -910,43 +795,18 @@ const polarAreaOptions = ref({
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||
titleColor: colors.neutral[900],
|
||||
bodyColor: colors.neutral[700],
|
||||
borderColor: colors.primary,
|
||||
borderWidth: 2,
|
||||
padding: 16,
|
||||
boxPadding: 8,
|
||||
displayColors: true,
|
||||
borderColor: colors.neutral[400],
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
boxPadding: 6,
|
||||
usePointStyle: true,
|
||||
caretPadding: 15,
|
||||
cornerRadius: 8,
|
||||
xAlign: 'center',
|
||||
yAlign: 'top',
|
||||
animation: {
|
||||
duration: 200,
|
||||
easing: 'easeInOutQuart'
|
||||
},
|
||||
titleFont: {
|
||||
size: 13,
|
||||
weight: 'bold',
|
||||
family: "'Inter', sans-serif"
|
||||
},
|
||||
bodyFont: {
|
||||
size: 12,
|
||||
family: "'Inter', sans-serif"
|
||||
},
|
||||
callbacks: {
|
||||
title: function(context) {
|
||||
return `👤 Tingkat Kehadiran`;
|
||||
},
|
||||
label: function(context) {
|
||||
const label = context.label || '';
|
||||
const value = context.parsed.r;
|
||||
const total = context.dataset.data.reduce((a, b) => a + b, 0);
|
||||
const percentage = ((value / total) * 100).toFixed(1);
|
||||
return [
|
||||
`${label}: ${value.toLocaleString('id-ID')}`,
|
||||
`Persentase: ${percentage}%`,
|
||||
`Total: ${total.toLocaleString('id-ID')}`
|
||||
];
|
||||
return `${label}: ${value.toLocaleString('id-ID')} (${percentage}%)`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +410,8 @@ $font-weight-semibold: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32px;
|
||||
padding: 16px 28px;
|
||||
height: 80px;
|
||||
color: $neutral-100;
|
||||
}
|
||||
|
||||
@@ -421,15 +422,18 @@ $font-weight-semibold: 600;
|
||||
|
||||
.header-icon {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
margin-right: 20px;
|
||||
border-radius: 12px;
|
||||
padding: 12px;
|
||||
margin-right: 16px;
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 36px;
|
||||
line-height: 44px;
|
||||
font-size: 32px;
|
||||
line-height: 40px;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin: 0;
|
||||
color: $neutral-100;
|
||||
@@ -437,10 +441,10 @@ $font-weight-semibold: 600;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
margin: 4px 0 0 0;
|
||||
margin: 2px 0 0 0;
|
||||
opacity: 0.9;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: $font-weight-regular;
|
||||
color: $neutral-100;
|
||||
}
|
||||
|
||||
@@ -1,43 +1,19 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<v-card>
|
||||
<!-- Header -->
|
||||
<div class="page-header">
|
||||
<div class="header-content">
|
||||
<div class="header-left">
|
||||
<div class="header-icon">
|
||||
<v-icon size="32" color="white">mdi-account-details</v-icon>
|
||||
</div>
|
||||
<div class="header-text">
|
||||
<h2 class="page-title">Informasi Pasien</h2>
|
||||
<p class="page-subtitle">{{ currentDate }} - Detail Data Pasien</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-stats">
|
||||
<v-chip
|
||||
v-if="patient.status"
|
||||
color="white"
|
||||
variant="flat"
|
||||
class="stat-chip mr-2"
|
||||
>
|
||||
<v-icon start size="16">mdi-progress-check</v-icon>
|
||||
{{ patient.status }}
|
||||
</v-chip>
|
||||
<v-btn
|
||||
color="white"
|
||||
elevation="0"
|
||||
class="btn-back"
|
||||
@click="$router.go(-1)"
|
||||
>
|
||||
<v-icon left size="20">mdi-arrow-left</v-icon>
|
||||
Kembali
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- Compact Header -->
|
||||
<PageHeader
|
||||
icon="mdi-account-details"
|
||||
title="Informasi Pasien"
|
||||
:subtitle="currentDate"
|
||||
:show-add-button="false"
|
||||
theme="primary"
|
||||
/>
|
||||
|
||||
<!-- Content -->
|
||||
<v-card-text class="content-section">
|
||||
<div class="monitoring-detail-container">
|
||||
<!-- Main Content -->
|
||||
<v-card class="detail-card" elevation="0">
|
||||
<!-- Content -->
|
||||
<v-card-text class="content-section pa-4">
|
||||
<v-card class="mb-6 patient-info-card" elevation="0">
|
||||
<v-row class="align-center mb-4">
|
||||
<v-col cols="12" md="8">
|
||||
@@ -122,12 +98,14 @@
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import PageHeader from '@/components/common/PageHeader.vue';
|
||||
|
||||
definePageMeta({
|
||||
middleware:['auth']
|
||||
@@ -289,79 +267,25 @@ $font-weight-semibold: 600;
|
||||
// ============================================
|
||||
// PAGE HEADER
|
||||
// ============================================
|
||||
.page-header {
|
||||
background: linear-gradient(135deg, $primary-600 0%, $primary-700 100%);
|
||||
border-radius: 16px 16px 0 0;
|
||||
box-shadow: 0 4px 16px rgba(58, 97, 201, 0.2);
|
||||
}
|
||||
/* Header styles are now handled by PageHeader component */
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32px;
|
||||
color: $neutral-100;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
.monitoring-detail-container {
|
||||
background: var(--color-neutral-300);
|
||||
min-height: 100vh;
|
||||
padding: 16px;
|
||||
margin-right: 20px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 36px;
|
||||
line-height: 44px;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin: 0;
|
||||
color: $neutral-100;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
margin: 4px 0 0 0;
|
||||
opacity: 0.9;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: $font-weight-regular;
|
||||
color: $neutral-100;
|
||||
}
|
||||
|
||||
.header-stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.stat-chip {
|
||||
color: $primary-600 !important;
|
||||
font-weight: $font-weight-semibold;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
font-weight: $font-weight-semibold;
|
||||
text-transform: none;
|
||||
letter-spacing: 0.5px;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: $primary-600 !important;
|
||||
.detail-card {
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--color-neutral-500);
|
||||
background: var(--color-neutral-100);
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// CONTENT SECTION
|
||||
// ============================================
|
||||
.content-section {
|
||||
padding: 24px !important;
|
||||
background: $neutral-100;
|
||||
background: var(--color-neutral-100);
|
||||
}
|
||||
|
||||
.patient-info-card {
|
||||
|
||||
@@ -1,37 +1,19 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<v-card>
|
||||
<!-- Header -->
|
||||
<div class="page-header">
|
||||
<div class="header-content">
|
||||
<div class="header-left">
|
||||
<div class="header-icon">
|
||||
<v-icon size="32" color="white">mdi-shield-check</v-icon>
|
||||
</div>
|
||||
<div class="header-text">
|
||||
<h2 class="page-title">Verifikasi Akun</h2>
|
||||
<p class="page-subtitle">{{ currentDate }} - Manajemen Pasien Digital</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-stats">
|
||||
<v-chip color="white" variant="flat" class="stat-chip mr-2">
|
||||
<v-icon start size="16">mdi-account-group</v-icon>
|
||||
{{ patients.length }} User
|
||||
</v-chip>
|
||||
<v-chip color="white" variant="flat" class="stat-chip mr-2">
|
||||
<v-icon start size="16">mdi-clock-alert</v-icon>
|
||||
{{ unverifiedPatients.length }} Pending
|
||||
</v-chip>
|
||||
<v-chip color="white" variant="flat" class="stat-chip">
|
||||
<v-icon start size="16">mdi-check-decagram</v-icon>
|
||||
{{ verifiedPatients.length }} Terverifikasi
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- Compact Header -->
|
||||
<PageHeader
|
||||
icon="mdi-shield-check"
|
||||
title="Verifikasi Akun"
|
||||
:subtitle="currentDate"
|
||||
:show-add-button="false"
|
||||
theme="primary"
|
||||
/>
|
||||
|
||||
<!-- Search & Content -->
|
||||
<v-card-text>
|
||||
<div class="verification-container">
|
||||
<!-- Main Content -->
|
||||
<v-card class="verification-card" elevation="0">
|
||||
<!-- Search & Content -->
|
||||
<v-card-text class="pa-4">
|
||||
<!-- Search & Filter -->
|
||||
<div class="search-filter-section">
|
||||
<div class="section-label">DATA PASIEN</div>
|
||||
@@ -147,13 +129,15 @@
|
||||
/>
|
||||
</template>
|
||||
</QRVerificationDialog>
|
||||
</v-container>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { useDisplay } from 'vuetify';
|
||||
import QrcodeVue from 'qrcode.vue';
|
||||
import PageHeader from '@/components/common/PageHeader.vue';
|
||||
import QRVerificationDialog from '@/components/verification/QRVerificationDialog.vue';
|
||||
|
||||
definePageMeta({
|
||||
@@ -323,62 +307,18 @@ $font-weight-semibold: 600;
|
||||
// ============================================
|
||||
// PAGE HEADER
|
||||
// ============================================
|
||||
.page-header {
|
||||
background: linear-gradient(135deg, $primary-600 0%, $primary-700 100%);
|
||||
border-radius: 16px 16px 0 0;
|
||||
box-shadow: 0 4px 16px rgba(58, 97, 201, 0.2);
|
||||
}
|
||||
/* Header styles are now handled by PageHeader component */
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32px;
|
||||
color: $neutral-100;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
.verification-container {
|
||||
background: var(--color-neutral-300);
|
||||
min-height: 100vh;
|
||||
padding: 16px;
|
||||
margin-right: 20px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 36px;
|
||||
line-height: 44px;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin: 0;
|
||||
color: $neutral-100;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
margin: 4px 0 0 0;
|
||||
opacity: 0.9;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: $font-weight-regular;
|
||||
color: $neutral-100;
|
||||
}
|
||||
|
||||
.header-stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.stat-chip {
|
||||
color: $primary-600 !important;
|
||||
font-weight: $font-weight-semibold;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
.verification-card {
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--color-neutral-500);
|
||||
background: var(--color-neutral-100);
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
|
||||
Reference in New Issue
Block a user