Files
web-antrean/components/verification/PatientVerificationList.vue
T
2026-01-06 14:26:19 +07:00

365 lines
8.0 KiB
Vue

<template>
<v-card-text class="pa-0 bg-white">
<v-table class="patient-table">
<!-- Table Body -->
<tbody>
<tr
v-for="patient in patients"
:key="patient.rm"
class="table-row"
:class="{ 'verified-row': patient.status === 'Terverifikasi' }"
>
<!-- Status Avatar -->
<td class="table-cell status-cell">
<div class="status-wrapper">
<v-avatar
:color="patient.status === 'Terverifikasi' ? 'secondary-600' : 'primary-600'"
size="48"
class="patient-avatar"
>
<v-icon size="24" color="white">
{{ patient.status === 'Terverifikasi' ? 'mdi-check-decagram' : 'mdi-clock-alert' }}
</v-icon>
</v-avatar>
</div>
</td>
<!-- Nama -->
<td class="table-cell">
<span class="patient-name">{{ patient.nama }}</span>
</td>
<!-- RM -->
<td class="table-cell">
<v-chip size="small" color="primary-200" class="chip-rm" variant="flat">
<v-icon start size="14" color="secondary-600">mdi-file-document</v-icon>
<span class="chip-rm-text">{{ patient.rm }}</span>
</v-chip>
</td>
<!-- Alamat -->
<td class="table-cell">
<div class="info-item">
<v-icon size="14" class="mr-2" color="neutral-600">mdi-map-marker</v-icon>
<span>{{ patient.alamat }}</span>
</div>
</td>
<!-- Nomor Telepon -->
<td class="table-cell">
<div class="info-item">
<v-icon size="14" class="mr-2" color="neutral-600">mdi-phone</v-icon>
<span>{{ patient.telepon || 'Belum diisi' }}</span>
</div>
</td>
<!-- Aksi -->
<td class="table-cell action-col">
<div class="action-wrapper">
<v-btn
v-if="patient.status === 'Belum Terverifikasi'"
variant="flat"
class="action-btn"
@click="$emit('verify', patient)"
>
<v-icon start size="16">mdi-qrcode-scan</v-icon>
VERIFIKASI
</v-btn>
<v-btn
v-else
color="secondary-600"
variant="flat"
class="verified-btn"
disabled
>
<v-icon start size="16">mdi-shield-check</v-icon>
VERIFIED
</v-btn>
</div>
</td>
</tr>
<!-- Empty State -->
<tr v-if="patients.length === 0">
<td colspan="6" class="empty-state-cell">
<div class="empty-state">{{ emptyMessage }}</div>
</td>
</tr>
</tbody>
</v-table>
</v-card-text>
</template>
<script setup>
defineProps({
patients: {
type: Array,
required: true
},
emptyMessage: {
type: String,
default: 'Tidak ada data pasien'
}
});
defineEmits(['verify']);
</script>
<style scoped lang="scss">
$neutral-100: #FFFFFF;
$neutral-400: #E5F7FA;
$neutral-500: #ABBED1;
$neutral-600: #89939E;
$neutral-700: #717171;
$neutral-900: #212121;
$primary-100: #FFE8CC;
$primary-200: #FFDCAF;
$primary-600: #FFA532;
$primary-700: #FF9B1B;
$secondary-200: #EDF5FF;
$secondary-300: #DBEDFF;
$secondary-400: #B3D9FF;
$secondary-600: #0671E0;
$secondary-700: #0053AD;
$font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
$font-weight-regular: 400;
$font-weight-semibold: 600;
$font-weight-bold: 700;
$font-weight-extra-bold: 800;
.patient-table {
font-family: $font-family-base;
width: 100%;
border-collapse: collapse;
table-layout: auto;
:deep(thead),
:deep(tbody),
:deep(tr) {
margin: 0;
padding: 0;
}
}
// ============================================
// TABLE HEADER
// ============================================
.table-header {
background-color: $neutral-400;
}
.header-cell {
padding: 16px 24px !important;
text-align: left;
font-weight: $font-weight-bold;
font-size: 14px;
color: $neutral-900;
text-transform: uppercase;
letter-spacing: 0.5px;
font-family: $font-family-base;
border-bottom: 2px solid $neutral-500;
vertical-align: middle;
&.status-header-hidden {
padding: 16px 24px !important;
width: 96px;
min-width: 96px;
max-width: 96px;
}
&.action-col {
text-align: right;
padding-right: 24px !important;
}
}
// ============================================
// TABLE BODY
// ============================================
.table-row {
transition: all 0.3s ease;
position: relative;
&:hover {
background-color: $primary-100 !important;
&::before {
transform: scaleY(1);
}
}
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 4px;
background: $primary-600;
transform: scaleY(0);
transition: transform 0.3s ease;
}
}
.verified-row {
background-color: $secondary-200 !important;
&::before {
background: $secondary-600 !important;
}
&:hover {
background-color: $secondary-300 !important;
}
}
.table-cell {
padding: 16px 24px !important;
vertical-align: middle;
font-family: $font-family-base;
border-bottom: 1px solid $neutral-400;
&.status-cell {
text-align: center;
padding: 16px 24px !important;
width: 96px;
min-width: 96px;
max-width: 96px;
}
&.action-col {
text-align: right;
padding-right: 24px !important;
}
}
.status-wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}
.patient-avatar {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
border: 3px solid $neutral-100;
margin: 0 auto;
}
.patient-name {
font-size: 18px;
font-weight: $font-weight-extra-bold;
color: $neutral-900;
font-family: $font-family-base;
}
.chip-rm {
border: 1px solid $secondary-400;
font-weight: $font-weight-bold;
}
.chip-rm-text {
color: $secondary-700;
font-weight: $font-weight-bold;
font-family: $font-family-base;
}
.info-item {
color: $neutral-700;
display: flex;
align-items: center;
font-size: 14px;
font-family: $font-family-base;
}
.action-wrapper {
display: flex;
align-items: center;
justify-content: flex-end;
}
.action-btn {
background-color: $primary-700 !important;
text-transform: none;
letter-spacing: 0.5px;
font-weight: $font-weight-extra-bold;
font-size: 14px;
color: $neutral-100 !important;
padding: 8px 24px !important;
height: 40px !important;
min-width: 150px;
box-shadow: 0 4px 12px rgba(255, 155, 27, 0.4), 0 2px 6px rgba(255, 155, 27, 0.3);
font-family: $font-family-base;
transition: all 0.3s ease;
}
.action-btn:hover {
background-color: #E68A00 !important;
box-shadow: 0 6px 16px rgba(255, 155, 27, 0.5), 0 3px 8px rgba(255, 155, 27, 0.4);
transform: translateY(-2px);
}
.verified-btn {
text-transform: none;
letter-spacing: 0.5px;
font-weight: $font-weight-extra-bold;
font-size: 14px;
color: $neutral-100 !important;
padding: 8px 24px !important;
height: 40px !important;
min-width: 150px;
font-family: $font-family-base;
opacity: 1 !important;
}
.empty-state-cell {
padding: 40px 24px;
text-align: center;
}
.empty-state {
font-size: 18px;
color: $neutral-600;
font-weight: $font-weight-semibold;
font-family: $font-family-base;
}
// ============================================
// RESPONSIVE
// ============================================
@media (max-width: 960px) {
.patient-table {
display: block;
overflow-x: auto;
}
.table-cell {
padding: 20px 16px;
white-space: nowrap;
}
.header-cell {
padding: 12px 16px;
font-size: 12px;
}
.action-btn,
.verified-btn {
font-size: 12px;
}
.patient-avatar {
width: 44px !important;
height: 44px !important;
}
.patient-name {
font-size: 16px;
}
.info-item {
font-size: 12px;
}
}
</style>