215 lines
7.3 KiB
Vue
215 lines
7.3 KiB
Vue
<template>
|
|
<v-dialog
|
|
:model-value="modelValue"
|
|
@update:model-value="$emit('update:modelValue', $event)"
|
|
max-width="800"
|
|
persistent
|
|
transition="dialog-transition"
|
|
scrim="rgba(0, 0, 0, 0.5)"
|
|
class="blur-dialog"
|
|
>
|
|
<v-card class="rounded-xl dialog-card" elevation="24">
|
|
<div class="dialog-header text-center pa-6" style="background: linear-gradient(135deg, #1565C0 0%, #0D47A1 100%);">
|
|
<h2 class="text-h5 font-weight-bold text-white mb-2">
|
|
<v-icon color="white" class="mr-2">mdi-history</v-icon>
|
|
Riwayat Check-in
|
|
</h2>
|
|
<p class="text-body-2 text-white opacity-90">Daftar check-in yang telah dilakukan</p>
|
|
</div>
|
|
|
|
<v-card-text class="pa-6">
|
|
<!-- Filter dan Search -->
|
|
<div class="mb-4">
|
|
<v-row dense>
|
|
<v-col cols="12" md="4">
|
|
<v-text-field
|
|
:model-value="search"
|
|
@update:model-value="$emit('update:search', $event)"
|
|
label="Cari ID Pasien atau Nomor Antrean"
|
|
prepend-inner-icon="mdi-magnify"
|
|
variant="outlined"
|
|
density="comfortable"
|
|
clearable
|
|
hide-details
|
|
></v-text-field>
|
|
</v-col>
|
|
<v-col cols="12" md="3">
|
|
<v-text-field
|
|
:model-value="dateFilter"
|
|
@update:model-value="$emit('update:dateFilter', $event || '')"
|
|
type="date"
|
|
label="Filter Tanggal"
|
|
variant="outlined"
|
|
density="comfortable"
|
|
clearable
|
|
hide-details
|
|
class="date-picker-field"
|
|
></v-text-field>
|
|
</v-col>
|
|
<v-col cols="12" md="2">
|
|
<v-select
|
|
:model-value="statusFilter"
|
|
@update:model-value="$emit('update:statusFilter', $event)"
|
|
label="Filter Status"
|
|
:items="statusOptions"
|
|
variant="outlined"
|
|
density="comfortable"
|
|
hide-details
|
|
clearable
|
|
></v-select>
|
|
</v-col>
|
|
<v-col cols="12" md="3">
|
|
<v-btn
|
|
color="error"
|
|
variant="outlined"
|
|
block
|
|
@click="$emit('clear')"
|
|
:disabled="history.length === 0"
|
|
>
|
|
<v-icon start>mdi-delete</v-icon>
|
|
Hapus Semua
|
|
</v-btn>
|
|
</v-col>
|
|
</v-row>
|
|
</div>
|
|
|
|
<!-- History List -->
|
|
<div v-if="filteredHistory.length > 0" class="history-list">
|
|
<v-card
|
|
v-for="(item, index) in filteredHistory"
|
|
:key="index"
|
|
variant="outlined"
|
|
class="mb-3 history-item"
|
|
:class="getStatusClass(item.status)"
|
|
>
|
|
<v-card-text class="pa-4">
|
|
<div class="d-flex justify-space-between align-start">
|
|
<div class="flex-grow-1">
|
|
<div class="d-flex align-center mb-2">
|
|
<v-chip
|
|
:color="getStatusColor(item.status)"
|
|
size="small"
|
|
class="mr-2"
|
|
>
|
|
<v-icon start size="16">{{ getStatusIcon(item.status) }}</v-icon>
|
|
{{ getStatusText(item.status) }}
|
|
</v-chip>
|
|
<v-chip
|
|
color="grey-lighten-1"
|
|
size="x-small"
|
|
variant="text"
|
|
>
|
|
{{ item.method }}
|
|
</v-chip>
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<p class="text-body-1 font-weight-bold mb-1">
|
|
<v-icon size="18" class="mr-1" :color="primaryColor">mdi-account-circle</v-icon>
|
|
ID Pasien: {{ item.patientId }}
|
|
</p>
|
|
<p v-if="item.queueNumber" class="text-body-2 text-grey mb-1">
|
|
<v-icon size="16" class="mr-1">mdi-ticket</v-icon>
|
|
Nomor Antrean: {{ item.queueNumber }}
|
|
</p>
|
|
</div>
|
|
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<v-chip
|
|
size="x-small"
|
|
variant="outlined"
|
|
color="grey-darken-1"
|
|
>
|
|
<v-icon start size="14">mdi-clock-outline</v-icon>
|
|
{{ formatDateTime(item.checkInTime) }}
|
|
</v-chip>
|
|
<v-chip
|
|
v-if="item.checkInDate"
|
|
size="x-small"
|
|
variant="outlined"
|
|
color="grey-darken-1"
|
|
>
|
|
<v-icon start size="14">mdi-calendar</v-icon>
|
|
{{ formatDate(item.checkInDate) }}
|
|
</v-chip>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ml-4">
|
|
<v-btn
|
|
icon
|
|
size="small"
|
|
variant="text"
|
|
color="error"
|
|
@click="$emit('delete-item', index)"
|
|
>
|
|
<v-icon>mdi-delete-outline</v-icon>
|
|
</v-btn>
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div v-else class="text-center py-12">
|
|
<v-icon size="64" color="grey-lighten-1" class="mb-4">mdi-history</v-icon>
|
|
<p class="text-h6 text-grey mb-2">Belum ada riwayat check-in</p>
|
|
<p class="text-body-2 text-grey">Riwayat check-in akan muncul di sini setelah Anda melakukan check-in</p>
|
|
</div>
|
|
</v-card-text>
|
|
|
|
<v-card-actions class="pa-6 pt-0">
|
|
<v-spacer></v-spacer>
|
|
<v-btn
|
|
color="primary"
|
|
class="text-white font-weight-bold text-none"
|
|
size="large"
|
|
variant="flat"
|
|
@click="$emit('update:modelValue', false)"
|
|
prepend-icon="mdi-close"
|
|
>
|
|
Tutup
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</v-dialog>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { CheckInHistoryItem, HistoryStatus } from '~/types/checkin'
|
|
|
|
interface Props {
|
|
modelValue: boolean
|
|
search: string
|
|
dateFilter: string
|
|
statusFilter: HistoryStatus | ''
|
|
filteredHistory: CheckInHistoryItem[]
|
|
history: CheckInHistoryItem[] | ReadonlyArray<CheckInHistoryItem>
|
|
statusOptions: Array<{ title: string; value: string }>
|
|
primaryColor: string
|
|
getStatusColor: (status: string) => string
|
|
getStatusIcon: (status: string) => string
|
|
getStatusText: (status: string) => string
|
|
getStatusClass: (status: string) => string
|
|
formatDateTime: (dateString: string) => string
|
|
formatDate: (dateString: string) => string
|
|
}
|
|
|
|
defineProps<Props>()
|
|
|
|
defineEmits<{
|
|
'update:modelValue': [value: boolean]
|
|
'update:search': [value: string]
|
|
'update:dateFilter': [value: string]
|
|
'update:statusFilter': [value: HistoryStatus | '']
|
|
'delete-item': [index: number]
|
|
'clear': []
|
|
}>()
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import '~/assets/scss/checkin/components';
|
|
@import '~/assets/scss/checkin/dialogs';
|
|
</style>
|