Android_Retail/src/Pages/BookingScreen/Components/UtillComponents/BarcodeScanner.jsx

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;