315 lines
6.8 KiB
Vue
315 lines
6.8 KiB
Vue
<template>
|
|
<v-dialog
|
|
:model-value="modelValue"
|
|
@update:model-value="$emit('update:modelValue', $event)"
|
|
max-width="600"
|
|
transition="dialog-bottom-transition"
|
|
scrollable
|
|
>
|
|
<v-card class="modal-card">
|
|
<!-- Modal Header -->
|
|
<div class="modal-header">
|
|
<v-icon size="72" color="white" class="mb-3">mdi-qrcode-scan</v-icon>
|
|
<h2 class="modal-title">Aktivasi Akun</h2>
|
|
<p class="modal-subtitle">{{ patient.nama }}</p>
|
|
<v-chip color="white" class="modal-chip" variant="flat" size="default">
|
|
<span class="modal-chip-text">RM: {{ patient.rm }}</span>
|
|
</v-chip>
|
|
</div>
|
|
|
|
<!-- Modal Content -->
|
|
<v-card-text class="pa-7">
|
|
<v-text-field
|
|
:model-value="phoneNumber"
|
|
@update:model-value="$emit('update:phoneNumber', $event)"
|
|
:disabled="qrGenerated"
|
|
label="Nomor Telepon Pasien"
|
|
placeholder="08xxxxxxxxxx"
|
|
variant="outlined"
|
|
density="comfortable"
|
|
:color="qrGenerated ? 'grey' : 'primary-600'"
|
|
:rules="[v => v.length >= 8 || 'Min. 8 digit']"
|
|
prepend-inner-icon="mdi-phone"
|
|
class="mb-3 phone-field"
|
|
base-color="grey-darken-1"
|
|
/>
|
|
|
|
<!-- Generate Button -->
|
|
<v-btn
|
|
v-if="!qrGenerated"
|
|
:disabled="!isPhoneValid"
|
|
color="secondary-600"
|
|
block
|
|
size="x-large"
|
|
class="generate-btn"
|
|
@click="$emit('generate')"
|
|
rounded="xl"
|
|
>
|
|
<v-icon left size="32">mdi-qrcode-plus</v-icon>
|
|
Generate QR Code
|
|
</v-btn>
|
|
|
|
<!-- QR Code Container -->
|
|
<div v-else class="qr-container">
|
|
<div class="pulse-icon">
|
|
<v-icon color="secondary-600" :size="isMobile ? 48 : 64">
|
|
mdi-cellphone-check
|
|
</v-icon>
|
|
</div>
|
|
|
|
<h3 class="qr-title">Pindai QR Code</h3>
|
|
<p class="qr-subtitle">Arahkan kamera smartphone ke QR code</p>
|
|
|
|
<div class="d-flex justify-center mb-3 mb-sm-4">
|
|
<div class="qr-frame">
|
|
<slot name="qr-code" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
|
|
<!-- Modal Actions -->
|
|
<v-card-actions v-if="qrGenerated" class="modal-actions">
|
|
<v-btn
|
|
color="secondary-600"
|
|
variant="outlined"
|
|
@click="$emit('reload')"
|
|
prepend-icon="mdi-reload"
|
|
size="x-large"
|
|
class="modal-action-btn"
|
|
rounded="xl"
|
|
>
|
|
Reload QR
|
|
</v-btn>
|
|
|
|
<v-btn
|
|
color="primary-600"
|
|
variant="flat"
|
|
@click="$emit('complete')"
|
|
prepend-icon="mdi-check-circle"
|
|
size="x-large"
|
|
class="modal-action-btn-primary"
|
|
rounded="xl"
|
|
>
|
|
Selesai
|
|
</v-btn>
|
|
</v-card-actions>
|
|
|
|
<v-card-actions v-else class="modal-actions">
|
|
<v-btn
|
|
color="neutral-600"
|
|
variant="text"
|
|
@click="$emit('close')"
|
|
size="x-large"
|
|
block
|
|
rounded="xl"
|
|
class="modal-cancel-btn"
|
|
>
|
|
Batal
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</v-dialog>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue';
|
|
|
|
const props = defineProps({
|
|
modelValue: {
|
|
type: Boolean,
|
|
required: true
|
|
},
|
|
patient: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
phoneNumber: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
qrGenerated: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
isMobile: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
});
|
|
|
|
const emit = defineEmits([
|
|
'update:modelValue',
|
|
'update:phoneNumber',
|
|
'generate',
|
|
'reload',
|
|
'complete',
|
|
'close'
|
|
]);
|
|
|
|
const isPhoneValid = computed(() => props.phoneNumber.length >= 8);
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
$neutral-100: #FFFFFF;
|
|
$neutral-600: #89939E;
|
|
$neutral-700: #717171;
|
|
$primary-600: #FFA532;
|
|
$secondary-200: #EDF5FF;
|
|
$secondary-600: #0671E0;
|
|
$secondary-700: #0053AD;
|
|
$font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
$font-weight-semibold: 600;
|
|
$font-weight-bold: 700;
|
|
$font-weight-extra-bold: 800;
|
|
$font-weight-black: 900;
|
|
|
|
.modal-card {
|
|
border-radius: 16px;
|
|
overflow: hidden;
|
|
padding: 0;
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
.modal-header {
|
|
background: linear-gradient(135deg, $secondary-600 0%, $secondary-700 100%);
|
|
text-align: center;
|
|
padding: 28px;
|
|
box-shadow: 0 4px 12px rgba(6, 99, 199, 0.2);
|
|
}
|
|
|
|
.modal-title {
|
|
font-size: 32px;
|
|
font-weight: $font-weight-black;
|
|
color: $neutral-100;
|
|
margin: 8px 0;
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
.modal-subtitle {
|
|
font-size: 20px;
|
|
color: $neutral-100;
|
|
opacity: 0.95;
|
|
font-weight: $font-weight-semibold;
|
|
margin: 0;
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
.modal-chip {
|
|
margin-top: 8px;
|
|
font-weight: $font-weight-bold;
|
|
}
|
|
|
|
.modal-chip-text {
|
|
color: $primary-600;
|
|
font-weight: $font-weight-bold;
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
.phone-field {
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
.generate-btn {
|
|
margin-top: 12px;
|
|
font-weight: $font-weight-extra-bold;
|
|
font-size: 18px;
|
|
color: $neutral-100;
|
|
box-shadow: 0 2px 8px rgba(6, 99, 199, 0.25);
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
.qr-container {
|
|
background: $secondary-200;
|
|
border: 3px solid $secondary-600;
|
|
border-radius: 16px;
|
|
padding: 28px 16px;
|
|
margin-top: 24px;
|
|
box-shadow: 0 6px 20px rgba(6, 99, 199, 0.15);
|
|
text-align: center;
|
|
}
|
|
|
|
@media (min-width: 600px) {
|
|
.qr-container {
|
|
padding: 28px;
|
|
}
|
|
}
|
|
|
|
.pulse-icon {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.qr-title {
|
|
font-size: 24px;
|
|
font-weight: $font-weight-black;
|
|
color: $secondary-700;
|
|
margin-bottom: 8px;
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
@media (min-width: 600px) {
|
|
.qr-title {
|
|
font-size: 28px;
|
|
margin-bottom: 12px;
|
|
}
|
|
}
|
|
|
|
.qr-subtitle {
|
|
font-size: 13px;
|
|
color: $neutral-700;
|
|
margin-bottom: 16px;
|
|
font-weight: $font-weight-semibold;
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
@media (min-width: 600px) {
|
|
.qr-subtitle {
|
|
font-size: 14px;
|
|
margin-bottom: 24px;
|
|
}
|
|
}
|
|
|
|
.qr-frame {
|
|
padding: 16px;
|
|
background: $neutral-100;
|
|
border-radius: 12px;
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
display: inline-block;
|
|
border: 3px solid $secondary-600;
|
|
}
|
|
|
|
@media (min-width: 600px) {
|
|
.qr-frame {
|
|
padding: 24px;
|
|
border-radius: 16px;
|
|
border: 4px solid $secondary-600;
|
|
}
|
|
}
|
|
|
|
.modal-actions {
|
|
padding: 28px;
|
|
padding-top: 0;
|
|
}
|
|
|
|
.modal-action-btn,
|
|
.modal-action-btn-primary {
|
|
font-weight: $font-weight-bold;
|
|
font-size: 14px;
|
|
text-transform: none;
|
|
flex-grow: 1;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
font-family: $font-family-base;
|
|
}
|
|
|
|
.modal-action-btn-primary {
|
|
color: $neutral-100;
|
|
font-weight: $font-weight-extra-bold;
|
|
}
|
|
|
|
.modal-cancel-btn {
|
|
font-weight: $font-weight-bold;
|
|
font-size: 14px;
|
|
text-transform: none;
|
|
font-family: $font-family-base;
|
|
}
|
|
</style> |