130 lines
4.5 KiB
JavaScript
130 lines
4.5 KiB
JavaScript
import React, {
|
|
useEffect,
|
|
useRef,
|
|
useState,
|
|
forwardRef,
|
|
useImperativeHandle,
|
|
} from 'react';
|
|
import { Html5Qrcode } from 'html5-qrcode';
|
|
import { useDispatch } from 'react-redux';
|
|
import { changeSearchedData } from '../../../../Features/BookingScreen/BookingData/BookingData.js';
|
|
import '../../../../Styles/BookingScreen/Components/UtillComponents/BarcodeScanner.scss';
|
|
|
|
const BarcodeScanner = forwardRef(
|
|
({ handleQrData, openScanner, setOpenScanner, type }, ref) => {
|
|
const dispatch = useDispatch();
|
|
const html5QrCode = useRef(null); // Ref to hold the scanner instance
|
|
const [isScannerActive, setIsScannerActive] = useState(false); // Track scanner status
|
|
|
|
useImperativeHandle(ref, () => ({
|
|
stopScanner, // Expose the stopScanner function to the parent
|
|
reinitializeCamera, // Expose the reinitializeCamera function to the parent
|
|
}));
|
|
|
|
useEffect(() => {
|
|
if (openScanner) {
|
|
initializeScanner(); // Initialize scanner when modal opens
|
|
} else {
|
|
stopScanner(); // Stop the scanner when modal closes
|
|
}
|
|
|
|
return () => {
|
|
stopScanner(); // Cleanup scanner when component unmounts
|
|
};
|
|
}, [openScanner]);
|
|
|
|
const initializeScanner = () => {
|
|
if (!isScannerActive) {
|
|
console.log('Initializing scanner...');
|
|
html5QrCode.current = new Html5Qrcode('qr-reader');
|
|
const config = {
|
|
fps: 10,
|
|
qrbox: { width: 250, height: 250 },
|
|
};
|
|
|
|
html5QrCode.current
|
|
.start(
|
|
{ facingMode: 'environment' }, // Use environment (back) camera
|
|
config,
|
|
(decodedText) => {
|
|
console.log('Scanned Barcode:', decodedText);
|
|
if (type === 'Search') {
|
|
dispatch(changeSearchedData(decodedText)); // Dispatch the scanned data
|
|
}
|
|
handleQrData(decodedText); // Trigger the action after scan
|
|
setOpenScanner(false); // Close modal after successful scan
|
|
},
|
|
(errorMessage) => {
|
|
console.error('Scanning error:', errorMessage);
|
|
}
|
|
)
|
|
.then(() => {
|
|
setIsScannerActive(true); // Mark scanner as active
|
|
})
|
|
.catch((err) => {
|
|
console.error('Unable to start scanning:', err);
|
|
// Handle specific error types
|
|
if (err.name === 'NotAllowedError' || err?.includes('Permission denied')) {
|
|
// Camera permission denied
|
|
handleQrData('', { error: 'Camera permission denied. Please allow camera access and try again.' });
|
|
} else if (err.name === 'NotFoundError' || err?.includes('NotFoundError')) {
|
|
// No camera found
|
|
handleQrData('', { error: 'No camera found on this device.' });
|
|
} else if (err.name === 'NotReadableError' || err?.includes('NotReadableError')) {
|
|
// Camera already in use
|
|
handleQrData('', { error: 'Camera is already in use by another application.' });
|
|
} else {
|
|
// Generic error
|
|
handleQrData('', { error: 'Failed to initialize camera scanner.' });
|
|
}
|
|
|
|
setOpenScanner(false); // Close scanner on error
|
|
});
|
|
}
|
|
};
|
|
|
|
// Function to reinitialize the camera (can be called from parent)
|
|
const reinitializeCamera = async () => {
|
|
if (isScannerActive) {
|
|
await stopScanner(); // Wait for scanner to stop if it's active
|
|
}
|
|
initializeScanner(); // Reinitialize scanner
|
|
};
|
|
|
|
const stopScanner = () => {
|
|
return new Promise((resolve) => {
|
|
if (html5QrCode.current && isScannerActive) {
|
|
html5QrCode.current
|
|
.stop()
|
|
.then(() => {
|
|
setIsScannerActive(false); // Mark scanner as inactive
|
|
html5QrCode.current.clear(); // Clear the scanner UI
|
|
html5QrCode.current = null; // Reset the instance
|
|
console.log('Scanner stopped.');
|
|
resolve();
|
|
})
|
|
.catch((err) => {
|
|
console.error('Failed to stop scanning:', err);
|
|
setIsScannerActive(false);
|
|
html5QrCode.current = null;
|
|
resolve();
|
|
});
|
|
} else {
|
|
resolve(); // Resolve immediately if scanner is not active
|
|
}
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div style={{ textAlign: 'center', marginTop: '50px' }}>
|
|
<div
|
|
id="qr-reader"
|
|
style={{ width: '300px', height: 'auto', margin: '0 auto' }}
|
|
></div>
|
|
</div>
|
|
);
|
|
}
|
|
);
|
|
|
|
export default BarcodeScanner;
|