Rebasing
This commit is contained in:
@@ -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<string | null>(null);
|
||||
const [mostrarModal, setMostrarModal] = useState(false);
|
||||
const [enviando, setEnviando] = useState(false);
|
||||
const [mensaje, setMensaje] = useState<string | null>(null);
|
||||
const [text, setText] = React.useState<string>('');
|
||||
const [showModal, setShowModal] = React.useState<boolean>(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() {
|
||||
<main className='py-3'>
|
||||
<div className='container text-center'>
|
||||
<h1 className='mb-4'>Lectura de QRs</h1>
|
||||
{!resultado && <QrScanner onScan={handleScan} />}
|
||||
|
||||
<Modal
|
||||
isVisible={mostrarModal}
|
||||
onClose={() => setMostrarModal(false)}
|
||||
size='md'
|
||||
>
|
||||
<h5 className='mb-3'>Resultado del QR</h5>
|
||||
<pre className='bg-light p-2 rounded'>{resultado}</pre>
|
||||
{mensaje && <p className='mt-2'>{mensaje}</p>}
|
||||
<button
|
||||
className='btn btn-primary mt-3'
|
||||
onClick={handleConfirm}
|
||||
disabled={enviando}
|
||||
>
|
||||
Confirmar
|
||||
</button>
|
||||
</Modal>
|
||||
<div className='mb-4'>
|
||||
<Html5QrcodePlugin
|
||||
fps={10}
|
||||
qrbox={500}
|
||||
qrCodeSuccessCallback={onScanSuccess}
|
||||
qrCodeErrorCallback={onScanError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className='mt-4'>
|
||||
{text
|
||||
? `Texto escaneado: ${text}`
|
||||
: 'Escanea un código QR para ver el texto aquí.'}
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Modal
|
||||
isVisible={showModal}
|
||||
size='md'
|
||||
onClose={handleCloseModal}
|
||||
closeButton
|
||||
className={{
|
||||
content: 'p-3',
|
||||
body: 'text-center',
|
||||
}}
|
||||
>
|
||||
<h5 className='mb-3'>Texto escaneado</h5>
|
||||
<p>{text}</p>
|
||||
|
||||
<Button variant='success' onClick={handleCloseModal}>
|
||||
Confirmar lectura
|
||||
</Button>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<Html5QrcodeCameraScanConfig> {
|
||||
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<Html5QrcodePluginProps> = (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 (
|
||||
<div
|
||||
id='qr-reader'
|
||||
style={{ width: '100%', maxWidth: 400, margin: '0 auto' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <div id={qrcodeRegionId} />;
|
||||
};
|
||||
|
||||
export default Html5QrcodePlugin;
|
||||
|
||||
Reference in New Issue
Block a user