diff --git a/src/app/(admins)/staff/page.tsx b/src/app/(admins)/staff/page.tsx index 6c492c0..f0e1915 100644 --- a/src/app/(admins)/staff/page.tsx +++ b/src/app/(admins)/staff/page.tsx @@ -1,55 +1,33 @@ 'use client'; import Header from '@/components/layout/header'; -import QrScanner from '@/components/qr-scanner'; +import React from 'react'; import dynamic from 'next/dynamic'; -import React, { useState } from 'react'; -import axiosInstance from '@/utils/api-config'; +import Button from '@/components/button'; + +const Html5QrcodePlugin = dynamic(() => import('@/components/qr-scanner'), { + ssr: false, +}); const Modal = dynamic(() => import('@/components/modal'), { ssr: false, }); export default function Page() { - const [resultado, setResultado] = useState(null); - const [mostrarModal, setMostrarModal] = useState(false); - const [enviando, setEnviando] = useState(false); - const [mensaje, setMensaje] = useState(null); + const [text, setText] = React.useState(''); + const [showModal, setShowModal] = React.useState(false); - const handleScan = (text: string) => { - setResultado(text); - setMostrarModal(true); + const onScanSuccess = (decodedText: string) => { + setText(decodedText); + setShowModal(true); // Muestra el modal al escanear }; - const handleConfirm = async () => { - if (!resultado) return; + const onScanError = (errorMessage: string) => { + console.warn('QR Error:', errorMessage); + }; - try { - setEnviando(true); - const parsed = JSON.parse(resultado); - const { idParticipante, idEvento } = parsed; - - if (!idParticipante || !idEvento) { - setMensaje('El código QR no contiene los datos necesarios.'); - return; - } - - const res = await axiosInstance.post( - `/participante-evento/asistencia/${idParticipante}/${idEvento}` - ); - - console.log('Respuesta del servidor:', res.data); - } catch (error) { - console.error('Error registrando asistencia:', error); - setMensaje('Error al registrar asistencia.'); - } finally { - setEnviando(false); - setTimeout(() => { - setMostrarModal(false); - setResultado(null); - setMensaje(null); - }, 2500); - } + const handleCloseModal = () => { + setShowModal(false); }; return ( @@ -58,26 +36,41 @@ export default function Page() {

Lectura de QRs

- {!resultado && } - setMostrarModal(false)} - size='md' - > -
Resultado del QR
-
{resultado}
- {mensaje &&

{mensaje}

} - -
+
+ +
+ +

+ {text + ? `Texto escaneado: ${text}` + : 'Escanea un código QR para ver el texto aquí.'} +

+ + +
Texto escaneado
+

{text}

+ + +
); } diff --git a/src/components/qr-scanner.tsx b/src/components/qr-scanner.tsx index ea0d39d..cfadffd 100644 --- a/src/components/qr-scanner.tsx +++ b/src/components/qr-scanner.tsx @@ -1,41 +1,70 @@ -// components/QrScanner.tsx +// file: Html5QrcodePlugin.tsx 'use client'; +import { Html5QrcodeScanner, Html5QrcodeCameraScanConfig } from 'html5-qrcode'; import { useEffect } from 'react'; -import { Html5Qrcode } from 'html5-qrcode'; -interface Props { - onScan: (text: string) => void; +const qrcodeRegionId = 'html5qr-code-full-region'; + +interface Html5QrcodePluginProps extends Partial { + verbose?: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + qrCodeSuccessCallback: (decodedText: string, decodedResult: any) => void; + qrCodeErrorCallback?: (errorMessage: string) => void; } -export default function QrScanner({ onScan }: Props) { - useEffect(() => { - const scanner = new Html5Qrcode('qr-reader'); +const createConfig = ( + props: Html5QrcodePluginProps +): Html5QrcodeCameraScanConfig => { + const config: Html5QrcodeCameraScanConfig = { fps: 10 }; // Default fps value set to 10 - scanner - .start( - { facingMode: 'environment' }, - { fps: 10, qrbox: 250 }, - (decodedText) => { - onScan(decodedText); - scanner.stop().then(() => scanner.clear()); - }, - (error) => { - // puedes ignorar errores de escaneo frecuentes - console.error('Error de escaneo:', error); - } - ) - .catch((err) => console.error('Error al iniciar el lector QR:', err)); + if (props.fps !== undefined) { + config.fps = props.fps; + } + if (props.qrbox !== undefined) { + config.qrbox = props.qrbox; + } + if (props.aspectRatio !== undefined) { + config.aspectRatio = props.aspectRatio; + } + if (props.disableFlip !== undefined) { + config.disableFlip = props.disableFlip; + } + + return config; +}; + +const Html5QrcodePlugin: React.FC = (props) => { + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(() => { + // Previene ejecución en SSR + if (typeof window === 'undefined') return; + + const config = createConfig(props); + const verbose = props.verbose === true; + + if (!props.qrCodeSuccessCallback) { + throw new Error('qrCodeSuccessCallback is required.'); + } + + const html5QrcodeScanner = new Html5QrcodeScanner( + qrcodeRegionId, + config, + verbose + ); + html5QrcodeScanner.render( + props.qrCodeSuccessCallback, + props.qrCodeErrorCallback + ); return () => { - scanner.stop().then(() => scanner.clear()); + html5QrcodeScanner.clear().catch((error) => { + console.error('Failed to clear html5QrcodeScanner: ', error); + }); }; - }, [onScan]); + }, []); - return ( -
- ); -} + return
; +}; + +export default Html5QrcodePlugin;