Files
front-Censo/src/components/BarcodeScanner.tsx
T

117 lines
2.6 KiB
TypeScript
Raw Normal View History

2025-10-27 17:41:24 -06:00
// components/BarcodeScanner.tsx
2025-10-23 14:12:18 -06:00
"use client";
2025-10-27 17:41:24 -06:00
import React, { useEffect, useRef } from "react";
import Quagga from "@ericblade/quagga2";
2025-10-23 14:12:18 -06:00
2025-10-27 17:41:24 -06:00
// Tipos mínimos para el resultado de Quagga
interface CodeResult {
code: string;
format: string;
}
interface QuaggaResult {
codeResult: CodeResult | null;
}
2025-10-23 14:12:18 -06:00
2025-10-27 17:41:24 -06:00
// Tipos para la configuración (opcional, pero mejora legibilidad)
interface QuaggaConfig {
inputStream: {
name: string;
type: string;
target: HTMLElement;
constraints: MediaTrackConstraints;
};
decoder: {
readers: string[];
};
locate: boolean;
}
interface BarcodeScannerProps {
onScan: (code: string) => void;
}
export default function BarcodeScanner({ onScan }: BarcodeScannerProps) {
const scannerRef = useRef<HTMLDivElement>(null);
2025-10-23 14:12:18 -06:00
useEffect(() => {
2025-10-27 17:41:24 -06:00
if (!scannerRef.current) return;
// ✅ Sin `any`: usamos un objeto literal tipado implícitamente
const config: QuaggaConfig = {
inputStream: {
name: "Live",
type: "LiveStream",
target: scannerRef.current,
constraints: {
width: 640,
height: 480,
facingMode: "environment",
},
},
decoder: {
readers: [
"code_128_reader",
"ean_reader",
"ean_8_reader",
"code_39_reader",
"upc_reader",
],
},
locate: true,
};
// 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();
};
2025-10-23 14:12:18 -06:00
2025-10-27 17:41:24 -06:00
Quagga.init(config as unknown as Record<string, unknown>, initCallback);
2025-10-23 14:12:18 -06:00
2025-10-27 17:41:24 -06:00
// 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
}
}
};
2025-10-23 14:12:18 -06:00
2025-10-27 17:41:24 -06:00
Quagga.onDetected(handleDetected);
return () => {
Quagga.offDetected(handleDetected);
Quagga.stop();
};
}, [onScan]);
2025-10-23 14:12:18 -06:00
return (
2025-10-27 17:41:24 -06:00
<div
ref={scannerRef}
2025-10-23 14:12:18 -06:00
style={{
width: "100%",
2025-10-27 17:41:24 -06:00
maxWidth: "500px",
height: "300px",
borderRadius: "12px",
overflow: "hidden",
border: "2px solid #0056b3",
2025-10-23 14:12:18 -06:00
}}
/>
);
2025-10-27 17:41:24 -06:00
}