96 lines
4.7 KiB
PHP
96 lines
4.7 KiB
PHP
<div
|
|
class="rounded-2xl border border-amber-200 bg-gradient-to-r from-amber-50 via-white to-sky-50 p-4"
|
|
x-data="{
|
|
scannerActive: false,
|
|
scannerError: '',
|
|
stream: null,
|
|
detector: null,
|
|
rafId: null,
|
|
baseUrl: '/admin-filament/strumenti/documenti?tab=lettore-codici',
|
|
openReader(rawValue) {
|
|
const value = (rawValue || this.$refs.archiveCode?.value || '').trim();
|
|
if (value === '') {
|
|
return;
|
|
}
|
|
window.location.href = `${this.baseUrl}&code=${encodeURIComponent(value)}`;
|
|
},
|
|
async startScanner() {
|
|
this.scannerError = '';
|
|
if (!('BarcodeDetector' in window)) {
|
|
this.scannerError = 'BarcodeDetector non disponibile in questo browser. Usa il lettore esterno, il telefono o un tag NFC in input testo.';
|
|
return;
|
|
}
|
|
try {
|
|
this.detector = new BarcodeDetector({ formats: ['qr_code'] });
|
|
this.stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } });
|
|
this.$refs.video.srcObject = this.stream;
|
|
await this.$refs.video.play();
|
|
this.scannerActive = true;
|
|
this.scanFrame();
|
|
} catch (error) {
|
|
this.scannerError = 'Impossibile avviare la camera: ' + (error?.message || 'permesso negato');
|
|
}
|
|
},
|
|
stopScanner() {
|
|
this.scannerActive = false;
|
|
if (this.rafId) {
|
|
cancelAnimationFrame(this.rafId);
|
|
this.rafId = null;
|
|
}
|
|
if (this.stream) {
|
|
this.stream.getTracks().forEach((track) => track.stop());
|
|
this.stream = null;
|
|
}
|
|
if (this.$refs.video) {
|
|
this.$refs.video.srcObject = null;
|
|
}
|
|
},
|
|
async scanFrame() {
|
|
if (!this.scannerActive || !this.detector || !this.$refs.video) {
|
|
return;
|
|
}
|
|
try {
|
|
const codes = await this.detector.detect(this.$refs.video);
|
|
if (codes.length > 0 && (codes[0]?.rawValue || '') !== '') {
|
|
this.$refs.archiveCode.value = codes[0].rawValue;
|
|
this.openReader(codes[0].rawValue);
|
|
this.stopScanner();
|
|
return;
|
|
}
|
|
} catch (error) {
|
|
this.scannerError = 'Errore lettura QR: ' + (error?.message || 'lettura non disponibile');
|
|
this.stopScanner();
|
|
return;
|
|
}
|
|
this.rafId = requestAnimationFrame(() => this.scanFrame());
|
|
},
|
|
}"
|
|
>
|
|
<div class="flex flex-col gap-3 xl:flex-row xl:items-start xl:justify-between">
|
|
<div>
|
|
<div class="text-sm font-semibold text-slate-900">{{ $title ?? 'Lettore QR archivio' }}</div>
|
|
<div class="mt-1 text-xs text-slate-600">{{ $description ?? 'Scansiona un QR archivio e apri subito il contenuto del nodo selezionato.' }}</div>
|
|
</div>
|
|
<div class="rounded-full bg-white px-3 py-1 text-xs font-semibold text-slate-700 shadow-sm">Visualizza contenuto senza aprire il contenitore</div>
|
|
</div>
|
|
|
|
<div class="mt-4 grid gap-3 md:grid-cols-[minmax(0,1fr)_auto_auto]">
|
|
<div>
|
|
<label class="mb-1 block text-xs font-semibold uppercase tracking-wide text-slate-500">Codice archivio / payload QR / NFC</label>
|
|
<input x-ref="archiveCode" type="text" class="w-full rounded-lg border-slate-200 bg-white text-sm shadow-sm" placeholder="Es. AF-20-0001 oppure NGDOC|AF:AF-20-0001|..." x-on:keydown.enter.prevent="openReader()" />
|
|
</div>
|
|
<button type="button" class="inline-flex items-center self-end rounded-lg border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50" x-on:click="openReader()">Apri lettore</button>
|
|
<button type="button" class="inline-flex items-center self-end rounded-lg bg-slate-900 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-slate-800" x-on:click="scannerActive ? stopScanner() : startScanner()">
|
|
<span x-text="scannerActive ? 'Ferma camera' : 'Leggi QR'"></span>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="mt-3 rounded-lg border border-dashed border-slate-300 bg-white/80 p-3" x-show="scannerActive || scannerError !== ''" x-cloak>
|
|
<template x-if="scannerActive">
|
|
<video x-ref="video" class="aspect-video w-full rounded-lg border border-slate-300 bg-slate-900" playsinline muted></video>
|
|
</template>
|
|
<template x-if="scannerError !== ''">
|
|
<div class="text-xs text-amber-800" x-text="scannerError"></div>
|
|
</template>
|
|
</div>
|
|
</div> |