Files
web-antrean/components/checkin/CheckInDialog.vue
2026-01-14 08:25:47 +07:00

182 lines
7.4 KiB
Vue

<template>
<v-dialog
:model-value="modelValue"
@update:model-value="$emit('update:modelValue', $event)"
max-width="500"
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-8" :class="lastCheckInResult?.success && infoAction === 'checkin' ? 'success-header' : lastCheckInResult?.status === 'NOT_ALLOWED' ? 'warning-header' : 'error-header'">
<div class="decorative-circles">
<div class="circle circle-1"></div>
<div class="circle circle-2"></div>
<div class="circle circle-3"></div>
</div>
<div class="icon-wrapper mb-4">
<div class="icon-bg" :class="lastCheckInResult?.success && infoAction === 'checkin' ? 'icon-bg-success' : lastCheckInResult?.status === 'NOT_ALLOWED' ? 'icon-bg-warning' : 'icon-bg-error'">
<v-icon size="64" color="white" class="dialog-icon">
{{ lastCheckInResult?.success && infoAction === 'checkin' ? 'mdi-check-circle' : lastCheckInResult?.status === 'NOT_ALLOWED' ? 'mdi-alert-circle' : 'mdi-close-circle' }}
</v-icon>
</div>
</div>
<h2 class="text-h4 font-weight-bold text-white mb-2">
{{ lastCheckInResult?.success && infoAction === 'checkin'
? 'Check-in Berhasil!'
: lastCheckInResult?.status === 'NOT_ALLOWED'
? 'Belum Diizinkan'
: 'Check-in Gagal' }}
</h2>
<div class="status-badge mt-3">
<v-chip
:color="lastCheckInResult?.success && infoAction === 'checkin' ? 'white' : 'white'"
:text-color="lastCheckInResult?.success && infoAction === 'checkin' ? 'success' : lastCheckInResult?.status === 'NOT_ALLOWED' ? 'orange' : 'error'"
size="small"
class="font-weight-bold"
>
<v-icon start size="16">
{{ lastCheckInResult?.success && infoAction === 'checkin' ? 'mdi-check' : lastCheckInResult?.status === 'NOT_ALLOWED' ? 'mdi-clock-alert' : 'mdi-close-circle' }}
</v-icon>
{{ lastCheckInResult?.success && infoAction === 'checkin'
? 'Berhasil'
: lastCheckInResult?.status === 'NOT_ALLOWED'
? 'Menunggu'
: 'Gagal' }}
</v-chip>
</div>
</div>
<v-card-text class="pa-8">
<div class="message-container">
<div class="message-icon mb-4">
<v-icon :color="lastCheckInResult?.success && infoAction === 'checkin' ? 'success' : lastCheckInResult?.status === 'NOT_ALLOWED' ? 'orange' : 'error'" size="32">
{{ lastCheckInResult?.success && infoAction === 'checkin' ? 'mdi-check-circle' : lastCheckInResult?.status === 'NOT_ALLOWED' ? 'mdi-clock-alert' : 'mdi-close-circle' }}
</v-icon>
</div>
<div class="text-h6 font-weight-bold mb-3 text-center" style="white-space: pre-line;">{{ infoMessage }}</div>
<v-divider class="my-4"></v-divider>
<div v-if="lastCheckInResult" class="instruction-box pa-4 rounded-lg" :class="lastCheckInResult.success && infoAction === 'checkin' ? 'instruction-success' : 'instruction-warning'">
<div class="d-flex align-start">
<v-icon :color="lastCheckInResult.success && infoAction === 'checkin' ? 'success' : 'orange'" class="mr-3 mt-1">
{{ lastCheckInResult.success && infoAction === 'checkin' ? 'mdi-check-circle' : 'mdi-timer-sand' }}
</v-icon>
<div>
<p class="text-body-1 font-weight-medium mb-1">
{{ lastCheckInResult.success && infoAction === 'checkin' ? 'Status Check-in:' : 'Status:' }}
</p>
<p class="text-body-2 text-grey-darken-1">
{{ lastCheckInResult.success && infoAction === 'checkin'
? 'Check-in telah berhasil dilakukan. Pasien dapat melanjutkan ke tahap selanjutnya.'
: lastCheckInResult.status === 'NOT_ALLOWED'
? 'Mohon menunggu hingga antrean Anda dipanggil oleh petugas'
: 'Proses check-in gagal. Silakan coba lagi atau hubungi petugas.' }}
</p>
</div>
</div>
</div>
<!-- Patient Info Card -->
<v-card variant="outlined" class="mt-4 patient-info-card" color="grey-lighten-4">
<v-card-text class="py-3">
<div class="d-flex justify-space-between align-center">
<div class="d-flex align-center">
<v-icon color="primary" class="mr-2 patient-info-icon">mdi-account-circle</v-icon>
<div>
<p class="text-caption patient-info-label mb-0">ID Pasien</p>
<p class="text-body-1 patient-info-value mb-0">{{ scannedData?.split('|')[0] || 'N/A' }}</p>
</div>
</div>
<div class="text-right">
<p class="text-caption patient-info-label mb-0">Waktu Scan</p>
<p class="text-body-2 patient-info-value mb-0">{{ getCurrentTime() }}</p>
</div>
</div>
</v-card-text>
</v-card>
</div>
</v-card-text>
<v-card-actions class="pa-6 pt-0">
<v-row dense>
<v-col v-if="infoAction === 'kembali'" cols="12">
<v-btn
color="grey-darken-1"
class="text-white font-weight-bold text-none dialog-button"
size="x-large"
block
variant="flat"
@click="handleClose"
elevation="0"
prepend-icon="mdi-arrow-left"
>
Kembali
</v-btn>
</v-col>
<template v-else>
<v-col cols="12">
<v-btn
:color="lastCheckInResult?.success && infoAction === 'checkin' ? 'success' : 'primary'"
class="text-white font-weight-bold text-none dialog-button"
size="x-large"
block
variant="flat"
@click="handleClose"
elevation="4"
:prepend-icon="lastCheckInResult?.success && infoAction === 'checkin' ? 'mdi-check' : 'mdi-close'"
>
{{ lastCheckInResult?.success && infoAction === 'checkin' ? 'Tutup' : 'Tutup' }}
</v-btn>
</v-col>
</template>
</v-row>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
import type { CheckInResult, InfoAction } from '~/types/checkin'
interface Props {
modelValue: boolean
lastCheckInResult: CheckInResult | null
infoMessage: string
infoAction: InfoAction
scannedData: string | null
}
const props = defineProps<Props>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
'close': []
}>()
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, ':')
}
</script>
<style scoped lang="scss">
@import '~/assets/scss/checkin/dialogs';
</style>