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 (
-
);