From 9db0d1b65b1f74076b972dd31bbad224441b301c Mon Sep 17 00:00:00 2001 From: IO <320154041@pcpuma.acatlan.unam.mx> Date: Wed, 12 Nov 2025 17:05:47 -0600 Subject: [PATCH] new barcodeScanner and fixed error scss --- src/app/(Operador)/escaner/page.tsx | 5 +- src/app/styles/base/globales.scss | 2 +- src/components/BarcodeScanner.tsx | 151 ++++++++++++++++------------ 3 files changed, 91 insertions(+), 67 deletions(-) diff --git a/src/app/(Operador)/escaner/page.tsx b/src/app/(Operador)/escaner/page.tsx index 3860d17..bc1b1df 100644 --- a/src/app/(Operador)/escaner/page.tsx +++ b/src/app/(Operador)/escaner/page.tsx @@ -67,7 +67,10 @@ export default function Page() {

Escanear Inventario

{isScanning ? ( - + ) : (
; + static getSupportedFormats(): Promise; + } } +export {}; interface BarcodeScannerProps { onScan: (code: string) => void; } export default function BarcodeScanner({ onScan }: BarcodeScannerProps) { - const scannerRef = useRef(null); + const videoRef = useRef(null); + const lastScan = useRef(null); + + // 🔹 Verifica soporte antes de montar el componente + if (typeof window !== "undefined" && !("BarcodeDetector" in window)) { + toast.error("BarcodeDetector API no soportada en este navegador"); + return null; + } useEffect(() => { - if (!scannerRef.current) return; + let stream: MediaStream | null = null; + let detector: BarcodeDetector | null = null; + let animationFrame: number; - const config: QuaggaConfig = { - inputStream: { - name: "Live", - type: "LiveStream", - target: scannerRef.current, - constraints: { - width: 300, - height: 500, - facingMode: "environment", - }, - }, - decoder: { - readers: ["code_128_reader"], - }, - locate: true, - }; + const startCamera = async () => { + try { + stream = await navigator.mediaDevices.getUserMedia({ + video: { facingMode: "environment" }, + }); - // El callback de error: tipamos `err` como `unknown` - const initCallback = (err: unknown) => { - if (err) { - console.error("Error al iniciar el escáner:", err); - return; - } - Quagga.start(); - }; + if (!videoRef.current) return; - Quagga.init(config as unknown as Record, initCallback); + videoRef.current.srcObject = stream; - // Handler de detección: `data` es `unknown`, lo validamos - const handleDetected = (data: unknown) => { - // Validación segura - if ( - data != null && - typeof data === "object" && - "codeResult" in data && - data.codeResult != null && - typeof data.codeResult === "object" && - "code" in data.codeResult && - typeof data.codeResult.code === "string" - ) { - const code = data.codeResult.code.trim(); - if (code !== "") { - onScan(code); - Quagga.stop(); // Opcional + // Esperar a que el video esté listo antes de reproducirlo + await new Promise((resolve) => { + videoRef.current!.onloadedmetadata = () => resolve(true); + }); + + await videoRef.current.play().catch((err) => { + console.warn("No se pudo reproducir automáticamente:", err); + }); + + if (!("BarcodeDetector" in window)) { + console.error("BarcodeDetector API no soportada en este navegador"); + return; } + + detector = new BarcodeDetector({ formats: ["code_128", "ean_13"] }); + + const detect = async () => { + if (!videoRef.current || !detector) return; + try { + const barcodes = await detector.detect(videoRef.current); + if (barcodes.length > 0) { + const rawValue = barcodes[0].rawValue.trim(); + if (rawValue && rawValue !== lastScan.current) { + lastScan.current = rawValue; + const processed = rawValue.startsWith("0") + ? rawValue.slice(1) + : rawValue; + onScan(processed); + } + } + } catch (err) { + console.error(err); + } + animationFrame = requestAnimationFrame(detect); + }; + + detect(); + } catch (err) { + console.error("Error al iniciar cámara:", err); + toast.error("No se pudo acceder a la cámara"); } }; - Quagga.onDetected(handleDetected); + startCamera(); return () => { - Quagga.offDetected(handleDetected); - Quagga.stop(); + if (animationFrame) cancelAnimationFrame(animationFrame); + if (stream) stream.getTracks().forEach((t) => t.stop()); }; }, [onScan]); return ( -
);