Lectura qr
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
'use client';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { Modal as BootstrapModal } from 'bootstrap';
|
||||
|
||||
interface ModalProps {
|
||||
children?: React.ReactNode;
|
||||
isVisible: boolean;
|
||||
closeButton?: boolean;
|
||||
size: 'sm' | 'md' | 'lg' | 'xl';
|
||||
className?: {
|
||||
dialog?: string;
|
||||
content?: string;
|
||||
body?: string;
|
||||
};
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function Modal({
|
||||
children,
|
||||
isVisible,
|
||||
size,
|
||||
className,
|
||||
closeButton = true,
|
||||
onClose,
|
||||
}: ModalProps) {
|
||||
const ref = useRef<HTMLDivElement | null>(null);
|
||||
const modalInstance = useRef<BootstrapModal | null>(null);
|
||||
const modalSizeClass = size ? `modal-${size}` : '';
|
||||
|
||||
useEffect(() => {
|
||||
const node = ref.current;
|
||||
|
||||
if (node) {
|
||||
modalInstance.current = new BootstrapModal(node);
|
||||
|
||||
const handleClose = () => {
|
||||
const elements = document.querySelectorAll<HTMLDivElement>(
|
||||
'.modal-backdrop.fade.show'
|
||||
);
|
||||
if (elements.length > 0) {
|
||||
elements.forEach((element) => {
|
||||
element.remove();
|
||||
});
|
||||
document.body.removeAttribute('style');
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
node.addEventListener('hidden.bs.modal', handleClose);
|
||||
|
||||
return () => {
|
||||
if (node) {
|
||||
node.removeEventListener('hidden.bs.modal', handleClose);
|
||||
}
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisible) {
|
||||
modalInstance.current?.show();
|
||||
} else {
|
||||
modalInstance.current?.hide();
|
||||
}
|
||||
}, [isVisible]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="modal fade"
|
||||
tabIndex={-1}
|
||||
aria-labelledby="modal"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
className={`modal-dialog modal-dialog-centered ${className?.dialog ?? ''} ${modalSizeClass}`}
|
||||
>
|
||||
<div className={`modal-content ${className?.content}`}>
|
||||
{closeButton && (
|
||||
<div className="position-relative">
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close position-absolute top-0 end-0 m-2"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
style={{
|
||||
zIndex: 999,
|
||||
}}
|
||||
></button>
|
||||
</div>
|
||||
)}
|
||||
<div className={`modal-body ${className?.body}`}>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// components/QrScanner.tsx
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { Html5Qrcode } from 'html5-qrcode';
|
||||
|
||||
interface Props {
|
||||
onScan: (text: string) => void;
|
||||
}
|
||||
|
||||
export default function QrScanner({ onScan }: Props) {
|
||||
useEffect(() => {
|
||||
const scanner = new Html5Qrcode('qr-reader');
|
||||
|
||||
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));
|
||||
|
||||
return () => {
|
||||
scanner.stop().then(() => scanner.clear());
|
||||
};
|
||||
}, [onScan]);
|
||||
|
||||
return (
|
||||
<div
|
||||
id='qr-reader'
|
||||
style={{ width: '100%', maxWidth: 400, margin: '0 auto' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user