219 lines
6.3 KiB
Vue
219 lines
6.3 KiB
Vue
<script setup lang="ts">
|
|
const props = defineProps<{
|
|
isScanning: boolean;
|
|
hasCamera: boolean;
|
|
cameraChecking: boolean;
|
|
cameraReady: boolean;
|
|
primaryColor: string;
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
'start-scanning': [];
|
|
'stop-scanning': [];
|
|
'test-camera': [];
|
|
'open-history': [];
|
|
'open-qr-history': [];
|
|
}>();
|
|
|
|
const handleStartScanning = () => {
|
|
emit('start-scanning');
|
|
};
|
|
|
|
const handleStopScanning = () => {
|
|
emit('stop-scanning');
|
|
};
|
|
|
|
const handleTestCamera = () => {
|
|
emit('test-camera');
|
|
};
|
|
|
|
const handleOpenHistory = () => {
|
|
emit('open-history');
|
|
};
|
|
|
|
const handleOpenQRHistory = () => {
|
|
emit('open-qr-history');
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="tab-content">
|
|
<!-- Status Header -->
|
|
<div class="status-header mb-3">
|
|
<div class="status-icon-wrapper">
|
|
<v-icon :color="primaryColor" size="24">mdi-qrcode-scan</v-icon>
|
|
</div>
|
|
<div class="status-text">
|
|
<h3 class="status-title">
|
|
{{ isScanning ? 'Arahkan Kamera ke QR Code' : 'Siap untuk Scan QR Code' }}
|
|
</h3>
|
|
<p class="status-subtitle">
|
|
{{ isScanning ? 'Pastikan QR code terlihat jelas dan tidak terpotong' : 'Klik tombol di bawah untuk memulai scan' }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Camera Status Check -->
|
|
<div v-if="cameraChecking" class="text-center mb-4">
|
|
<v-progress-circular
|
|
indeterminate
|
|
:color="primaryColor"
|
|
size="24"
|
|
class="mr-2"
|
|
></v-progress-circular>
|
|
<span class="text-body-2 text-grey">Memeriksa ketersediaan kamera...</span>
|
|
</div>
|
|
|
|
<!-- Camera Not Available Warning -->
|
|
<v-alert
|
|
v-else-if="!hasCamera && !isScanning"
|
|
type="warning"
|
|
variant="tonal"
|
|
class="mb-4"
|
|
>
|
|
<template #prepend>
|
|
<v-icon>mdi-camera-off</v-icon>
|
|
</template>
|
|
<div>
|
|
<p class="font-weight-bold mb-1">Kamera tidak terdeteksi</p>
|
|
<p class="text-body-2 mb-0">
|
|
Perangkat Anda tidak memiliki kamera atau kamera tidak dapat diakses.
|
|
Silakan gunakan tab <strong>Manual</strong> untuk input data secara manual.
|
|
</p>
|
|
</div>
|
|
</v-alert>
|
|
|
|
<!-- QR Scanner Area dengan webcam -->
|
|
<div class="qr-scanner-container mb-4">
|
|
<div v-if="!isScanning" class="qr-placeholder">
|
|
<div class="scanner-overlay">
|
|
<div class="corner corner-tl"></div>
|
|
<div class="corner corner-tr"></div>
|
|
<div class="corner corner-bl"></div>
|
|
<div class="corner corner-br"></div>
|
|
<div class="scan-line"></div>
|
|
</div>
|
|
<v-icon size="64" :color="primaryColor" class="qr-icon">mdi-qrcode-scan</v-icon>
|
|
</div>
|
|
<div v-else class="qr-reader-container">
|
|
<div class="scanner-status mb-2">
|
|
<v-chip color="success" size="small" class="mr-2">
|
|
<v-icon start size="16">mdi-camera</v-icon>
|
|
Kamera Aktif
|
|
</v-chip>
|
|
<span class="text-caption text-grey">Preview kamera sedang berjalan</span>
|
|
</div>
|
|
<div id="qr-reader" class="qr-reader-wrapper">
|
|
<div v-if="!cameraReady" class="scanner-loading-overlay">
|
|
<v-progress-circular
|
|
indeterminate
|
|
color="white"
|
|
size="48"
|
|
></v-progress-circular>
|
|
<p class="text-white mt-4">Memuat kamera...</p>
|
|
</div>
|
|
</div>
|
|
<div class="scanner-instruction">
|
|
<v-icon :color="primaryColor" size="20" class="mr-2">mdi-information</v-icon>
|
|
<span class="text-body-2">Arahkan kamera ke QR code. Pastikan QR code berada dalam kotak pemindaian.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Action Button Minimalis -->
|
|
<div class="action-buttons">
|
|
<v-btn
|
|
v-if="!isScanning"
|
|
class="btn-primary-modern btn-centered"
|
|
size="large"
|
|
elevation="0"
|
|
@click="handleStartScanning"
|
|
:disabled="!hasCamera && !cameraChecking"
|
|
>
|
|
<v-icon start size="20">mdi-camera</v-icon>
|
|
{{ hasCamera ? 'Mulai Scan QR' : 'Kamera Tidak Tersedia' }}
|
|
</v-btn>
|
|
<v-btn
|
|
v-else
|
|
class="btn-stop-modern btn-centered"
|
|
size="large"
|
|
elevation="0"
|
|
@click="handleStopScanning"
|
|
>
|
|
<v-icon start size="20">mdi-camera-off</v-icon>
|
|
Stop Scan
|
|
</v-btn>
|
|
</div>
|
|
|
|
<!-- Info tambahan -->
|
|
<div class="info-card mt-3">
|
|
<v-alert
|
|
type="info"
|
|
variant="tonal"
|
|
:color="primaryColor"
|
|
class="text-body-2 info-alert-centered"
|
|
density="compact"
|
|
>
|
|
<div class="d-flex align-center justify-center">
|
|
<v-icon size="16" class="mr-2">mdi-lightbulb-outline</v-icon>
|
|
<span style="font-size: 12px;">Tips: Pastikan pencahayaan cukup untuk hasil scan optimal</span>
|
|
</div>
|
|
</v-alert>
|
|
</div>
|
|
|
|
<!-- Test Camera Button (Debug) -->
|
|
<div class="test-camera-section mt-2 mb-2">
|
|
<v-btn
|
|
variant="outlined"
|
|
color="primary"
|
|
size="small"
|
|
class="text-none btn-centered-small btn-test-camera"
|
|
@click="handleTestCamera"
|
|
>
|
|
<v-icon start size="18" color="#1565C0">mdi-camera</v-icon>
|
|
Test Kamera
|
|
</v-btn>
|
|
<p class="text-caption text-grey text-center mt-1" style="font-size: 11px;">
|
|
Klik untuk menguji apakah browser dapat mengakses kamera
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Quick Access Buttons -->
|
|
<div class="quick-actions mt-4">
|
|
<p class="text-caption text-grey text-center mb-3">Akses Cepat</p>
|
|
<v-row dense>
|
|
<v-col cols="12">
|
|
<v-btn
|
|
variant="outlined"
|
|
:color="primaryColor"
|
|
block
|
|
size="small"
|
|
class="text-none"
|
|
@click="handleOpenHistory"
|
|
>
|
|
<v-icon start size="18">mdi-history</v-icon>
|
|
Riwayat Check-in
|
|
</v-btn>
|
|
</v-col>
|
|
<v-col cols="12">
|
|
<v-btn
|
|
variant="outlined"
|
|
color="primary"
|
|
block
|
|
size="small"
|
|
class="text-none"
|
|
@click="handleOpenQRHistory"
|
|
>
|
|
<v-icon start size="18" color="#1565C0">mdi-qrcode-scan</v-icon>
|
|
Riwayat QR Scan
|
|
</v-btn>
|
|
</v-col>
|
|
</v-row>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
@import '~/assets/scss/checkin/components';
|
|
</style>
|