diff --git a/src/Pages/BookingScreen/Components/BSCombo/BSC1Search.jsx b/src/Pages/BookingScreen/Components/BSCombo/BSC1Search.jsx index ba57dd2..a567aa5 100644 --- a/src/Pages/BookingScreen/Components/BSCombo/BSC1Search.jsx +++ b/src/Pages/BookingScreen/Components/BSCombo/BSC1Search.jsx @@ -81,6 +81,7 @@ import { Global_PromoCodeOffers } from '../../../../Features/Offer/Offer.js'; import { validateOffers } from '../BSItemCards/ValidateOffer.jsx'; import { useSaleswiseOfferWatcher } from '../BSItemCards/SalesWiseOffer.jsx'; import ExpireConfirmModal from '../BookingFunctionality/ExpireConfirmModal.jsx'; +import BarCodeScan from '../../../../Services/BarCodeScan.jsx'; export default function BSC1Search(props) { const dispatch = useDispatch(); @@ -4567,10 +4568,15 @@ export default function BSC1Search(props) { {isMobile && screenWidth <= 768 && ( - handleQrcode()} - // onClick={() => OnfocusTrue()} + // handleQrcode()} + // // onClick={() => OnfocusTrue()} + // /> + { + ProductNameOnChange(value, true); + }} /> )} @@ -4821,7 +4827,7 @@ export default function BSC1Search(props) { - {isMobile && screenWidth <= 768 && ( + {/* {isMobile && screenWidth <= 768 && ( )} - )} + )} */} ); } diff --git a/src/Pages/BookingScreen/Components/BSNavbar/verfiedProduct/VerfiedProducts.jsx b/src/Pages/BookingScreen/Components/BSNavbar/verfiedProduct/VerfiedProducts.jsx index 0969a2a..6b5a781 100644 --- a/src/Pages/BookingScreen/Components/BSNavbar/verfiedProduct/VerfiedProducts.jsx +++ b/src/Pages/BookingScreen/Components/BSNavbar/verfiedProduct/VerfiedProducts.jsx @@ -19,6 +19,8 @@ import './Verfiedproduct.scss'; import { useSelector } from 'react-redux'; import { ApplicationPreferences } from '../../../../../Features/BrachLogin/BranchLogin.js'; import { changeOfferAppliedProductsForMembership } from '../../../../../Features/Offer/Offernew/BookingOffernew.js'; +import BarCodeScan from '../../../../../Services/BarCodeScan.jsx'; +import { isMobile } from 'react-device-detect'; const VerfiedProducts = ({ drawerOpen = false, setDrawerOpen = () => {} }) => { @@ -303,10 +305,16 @@ const VerfiedProducts = ({ drawerOpen = false, setDrawerOpen = () => {} }) => { > Clear - - + ) + : ( { + setScanValue(value); + fetchProductsByOrderId(value); + }} + />)} {message &&
{message}
} diff --git a/src/Pages/BookingScreen/Components/UtillComponents/BSNavBarComboSearch.jsx b/src/Pages/BookingScreen/Components/UtillComponents/BSNavBarComboSearch.jsx index 33a4909..507f21b 100644 --- a/src/Pages/BookingScreen/Components/UtillComponents/BSNavBarComboSearch.jsx +++ b/src/Pages/BookingScreen/Components/UtillComponents/BSNavBarComboSearch.jsx @@ -32,6 +32,7 @@ import BarcodeScanner from './BarcodeScanner'; import { isMobile } from 'react-device-detect'; import { BiBarcodeReader } from 'react-icons/bi'; import TooltipWrapper from '../../../../Components/Tooltip/Tooltip'; +import BarCodeScan from '../../../../Services/BarCodeScan.jsx'; const BSNavBarComboSearch = (props) => { @@ -1197,28 +1198,28 @@ const BSNavBarComboSearch = (props) => { : []; // }); }; - const stopScannerFromParent = () => { - if (scannerRef.current) { - scannerRef.current.stopScanner(); // Call stopScanner from the child component - } - }; + // const stopScannerFromParent = () => { + // if (scannerRef.current) { + // scannerRef.current.stopScanner(); // Call stopScanner from the child component + // } + // }; - const handleQrcode = () => { - setOpenScanner((prev) => !prev); - if (!openScanner && scannerRef.current) { - scannerRef.current.reinitializeCamera(); // Call the function to reinitialize the camera - } - }; + // const handleQrcode = () => { + // setOpenScanner((prev) => !prev); + // if (!openScanner && scannerRef.current) { + // scannerRef.current.reinitializeCamera(); // Call the function to reinitialize the camera + // } + // }; - const handleQrData = (decodedText, err) => { - onChangeprodFunction(decodedText); - setOpenScanner(false); // Close the modal after scanning - stopScannerFromParent(); - if (err && err?.error) { - setMessageData(err?.error); - setMessageType('error'); - } - }; + // const handleQrData = (decodedText, err) => { + // onChangeprodFunction(decodedText); + // setOpenScanner(false); // Close the modal after scanning + // stopScannerFromParent(); + // if (err && err?.error) { + // setMessageData(err?.error); + // setMessageType('error'); + // } + // }; return (
{ />
{isMobile && screenWidth <= 768 ? ( - handleQrcode()} - /> + // handleQrcode()} + // /> + { + onChangeprodFunction(value); + }} /> ) : ( )} @@ -1395,7 +1400,7 @@ const BSNavBarComboSearch = (props) => { )} - {isMobile && screenWidth <= 768 && ( + {/* {isMobile && screenWidth <= 768 && ( { /> )} - )} + )} */} ); }; diff --git a/src/Pages/BookingScreen/Components/UtillComponents/BSNavBarSearch.jsx b/src/Pages/BookingScreen/Components/UtillComponents/BSNavBarSearch.jsx index bc14ed7..1e56375 100644 --- a/src/Pages/BookingScreen/Components/UtillComponents/BSNavBarSearch.jsx +++ b/src/Pages/BookingScreen/Components/UtillComponents/BSNavBarSearch.jsx @@ -37,6 +37,7 @@ import { BiBarcodeReader } from 'react-icons/bi'; import { ApplicationPreferences } from '../../../../Features/BrachLogin/BranchLogin.js'; import { useDateStore } from '../../../../Features/BookingScreen/BookingData/DateStore.js'; import { Messages } from '../../../../../ownLib/my-ui-lib.js'; +import BarCodeScan from '../../../../Services/BarCodeScan.jsx'; const BSNavBarSearch = (props) => { const searchInputRef = useRef(null); @@ -362,28 +363,28 @@ const BSNavBarSearch = (props) => { await dispatch(getCardDataWithoutSub(data)); }; - const stopScannerFromParent = () => { - if (scannerRef?.current) { - scannerRef?.current?.stopScanner(); // Call stopScanner from the child component - } - }; + // const stopScannerFromParent = () => { + // if (scannerRef?.current) { + // scannerRef?.current?.stopScanner(); // Call stopScanner from the child component + // } + // }; - const handleQrcode = () => { - setOpenScanner((prev) => !prev); - if (!openScanner && scannerRef?.current) { - scannerRef?.current?.reinitializeCamera(); // Call the function to reinitialize the camera - } - }; + // const handleQrcode = () => { + // setOpenScanner((prev) => !prev); + // if (!openScanner && scannerRef?.current) { + // scannerRef?.current?.reinitializeCamera(); // Call the function to reinitialize the camera + // } + // }; - const handleQrData = async (value, err) => { - if (err && err?.error) { - setMessageData(err?.error); - setMessageType('error'); - } - await searchdata(value); - setOpenScanner(false); - stopScannerFromParent(); - }; + // const handleQrData = async (value, err) => { + // if (err && err?.error) { + // setMessageData(err?.error); + // setMessageType('error'); + // } + // await searchdata(value); + // setOpenScanner(false); + // stopScannerFromParent(); + // }; const onComplete = useCallback(() => { setMessageData(null); @@ -421,9 +422,14 @@ const BSNavBarSearch = (props) => { disabled={props.OrderType === 'Failed' ? true : false} /> {isMobile && screenWidth <= 768 ? ( - handleQrcode()} + // handleQrcode()} + // /> + { + searchdata(value); + }} /> ) : ( @@ -435,7 +441,7 @@ const BSNavBarSearch = (props) => { } */} - {isMobile && screenWidth <= 768 && ( + {/* {isMobile && screenWidth <= 768 && ( { /> )} - )} + )} */} ); }; diff --git a/src/Pages/BookingScreen/Components/UtillComponents/BSNavbarSearchStandard.jsx b/src/Pages/BookingScreen/Components/UtillComponents/BSNavbarSearchStandard.jsx index 35671ac..d072b60 100644 --- a/src/Pages/BookingScreen/Components/UtillComponents/BSNavbarSearchStandard.jsx +++ b/src/Pages/BookingScreen/Components/UtillComponents/BSNavbarSearchStandard.jsx @@ -19,6 +19,8 @@ import Search from "../../../../Components/Forms/Search"; import VoiceToTextItemCard from "../../../VoiceToText/VoiceToTextItemCard"; import { ApplicationPreferences } from "../../../../Features/BrachLogin/BranchLogin"; import { useDateStore } from "../../../../Features/BookingScreen/BookingData/DateStore"; +import BarCodeScan from "../../../../Services/BarCodeScan"; +import { isMobile } from "react-device-detect"; const BSNavbarSearchStandard = ({ inputRef }) => { const dispatch = useDispatch(); @@ -147,6 +149,9 @@ const BSNavbarSearchStandard = ({ inputRef }) => { const handleSearch = (e) => { dispatch(changeSearchedData(e?.target?.value)); }; + const handleScan = (e) => { + dispatch(changeSearchedData(e)); + }; const HandleVoiceSearch = () => { setVoiceSearch(!voiceSearch); }; @@ -159,6 +164,13 @@ const BSNavbarSearchStandard = ({ inputRef }) => { ref={inputRef} value={ProdName} /> + {isMobile && screenWidth <= 768 && ( + { + handleScan(value); + }} + /> + )} ); }; diff --git a/src/Pages/PurchaseOrder/PurchaseOrder.jsx b/src/Pages/PurchaseOrder/PurchaseOrder.jsx index b3f8be0..b43eb50 100644 --- a/src/Pages/PurchaseOrder/PurchaseOrder.jsx +++ b/src/Pages/PurchaseOrder/PurchaseOrder.jsx @@ -52,6 +52,7 @@ import { PrintStyleFunction } from '../paymentpdfPage/PrintStyleFunction.js'; import { PurchaseOrderMobilePrint } from './PurchsasePrintStyle/PurchaseOrderMobilePrint.js'; import { isMobile } from 'react-device-detect'; import { CiEdit } from 'react-icons/ci'; +import BarCodeScan from '../../Services/BarCodeScan.jsx'; const subDirectory = import.meta.env.BASE_URL; const stylesMap = { @@ -1628,6 +1629,7 @@ const PurchaseOrder = () => { }} > + {!isMobile && ( { onClick={handleScanSearch} /> + )} + {isMobile && ( +
+ { + debouncedScannerSearch(value); + }} + /> +
+ )} { style={{ width: '250px' }} > + {/* + + */} + {isMobile ? ( +
+ { + debouncedScannerSearch(value); + }} + /> +
+ ) : ( { onClick={handleScanSearch} /> + )} { disabled={isProcessing} /> - + {isMobile ? ( +
+ { + debouncedScannerSearch(value); + }} + /> +
+ ) : ( + )}
diff --git a/src/Services/BarCodeScan.jsx b/src/Services/BarCodeScan.jsx new file mode 100644 index 0000000..4e2c71c --- /dev/null +++ b/src/Services/BarCodeScan.jsx @@ -0,0 +1,419 @@ +// import React, { useRef, useState, useEffect } from "react"; +// import { BarcodeScanner } from "@capacitor-mlkit/barcode-scanning"; +// import { BsUpcScan } from "react-icons/bs"; +// import { BrowserMultiFormatReader } from "@zxing/library"; +// import { Capacitor } from "@capacitor/core"; +// import { DefaultModal } from "../Components/Modal/DefaultModal"; + +// export default function BarCodeScan({ onScan }) { +// const isMobileApp = Capacitor.getPlatform() !== "web"; +// const [scanning, setScanning] = useState(false); +// const [modalOpen, setModalOpen] = useState(false); +// const videoRef = useRef(null); +// const codeReaderRef = useRef(null); +// const streamRef = useRef(null); + +// const startScan = async () => { +// if (scanning) return; +// setScanning(true); + +// if (isMobileApp) { +// // Mobile: MLKit scanner +// try { +// const perm = await BarcodeScanner.requestPermissions(); +// if (perm.camera !== "granted") { +// alert("Camera permission not granted"); +// setScanning(false); +// return; +// } + +// const { barcodes } = await BarcodeScanner.scan(); +// if (barcodes && barcodes.length > 0) { +// onScan(barcodes[0].rawValue); +// } +// } catch (err) { +// alert("Error scanning barcode: " + err.message); +// } finally { +// setScanning(false); +// } +// } else { +// // Web: open modal and start camera +// setModalOpen(true); +// setTimeout(() => startWebScan(), 50); // wait for modal DOM +// } +// }; + +// const startWebScan = async () => { +// try { +// codeReaderRef.current = new BrowserMultiFormatReader(); +// streamRef.current = await navigator.mediaDevices.getUserMedia({ +// video: { facingMode: "environment" }, +// }); +// if (videoRef.current) { +// videoRef.current.srcObject = streamRef.current; +// videoRef.current.play(); +// } + +// codeReaderRef.current.decodeFromVideoDevice( +// null, +// videoRef.current, +// (result) => { +// if (result) { +// onScan(result.getText()); +// stopWebScan(); +// setModalOpen(false); +// } +// } +// ); +// } catch (err) { +// alert("Error accessing camera: " + err.message); +// setScanning(false); +// setModalOpen(false); +// } +// }; + +// const stopWebScan = () => { +// if (streamRef.current) { +// streamRef.current.getTracks().forEach((track) => track.stop()); +// streamRef.current = null; +// } +// if (codeReaderRef.current) { +// codeReaderRef.current.reset(); +// codeReaderRef.current = null; +// } +// setScanning(false); +// }; + +// const closeModal = () => { +// stopWebScan(); +// setModalOpen(false); +// }; + +// // Stop camera if component unmounts +// useEffect(() => () => stopWebScan(), []); + +// return ( +//
+// {!scanning && ( +// +// )} + +// { +// closeModal(); +// }} +// > +//
+//
+//
+ +//
+// ); +// } + +import React, { useRef, useState, useEffect } from "react"; +import { BarcodeScanner } from "@capacitor-mlkit/barcode-scanning"; +import { BsUpcScan } from "react-icons/bs"; +import { Capacitor } from "@capacitor/core"; +import { DefaultModal } from "../Components/Modal/DefaultModal"; +import QrScanner from "qr-scanner/qr-scanner.min.js"; +import { + BrowserMultiFormatReader, + BarcodeFormat, +} from "@zxing/library"; + +QrScanner.WORKER_PATH = new URL( + "qr-scanner/qr-scanner-worker.min.js", + import.meta.url +).toString(); + +export default function BarCodeScan({ onScan }) { + const isMobileApp = Capacitor.getPlatform() !== "web"; + const [scanning, setScanning] = useState(false); + const [modalOpen, setModalOpen] = useState(false); + + const videoRef = useRef(null); + const qrScannerRef = useRef(null); + const barcodeReaderRef = useRef(null); + + // ------------------------- + // START SCAN + // ------------------------- + const startScan = async () => { + if (scanning) return; + setScanning(true); + + if (isMobileApp) { + try { + const perm = await BarcodeScanner.requestPermissions(); + if (perm.camera !== "granted") { + alert("Camera permission not granted"); + setScanning(false); + return; + } + + const { barcodes } = await BarcodeScanner.scan(); + if (barcodes?.length > 0) { + onScan(barcodes[0].rawValue); + } + } catch (err) { + console.error(err); + } finally { + setScanning(false); + } + } else { + setModalOpen(true); + } + }; + + // ------------------------- + // START WEB SCAN (HYBRID) + // ------------------------- + const startWebScan = async () => { + if (!videoRef.current) return; + + // Start QR scanner (fast) + qrScannerRef.current = new QrScanner( + videoRef.current, + (result) => { + stopWebScan(); + onScan(result.data); + setModalOpen(false); + }, + { + maxScansPerSecond: 25, + } + ); + + await qrScannerRef.current.start(); + + // Start Barcode scanner (ZXing) + barcodeReaderRef.current = new BrowserMultiFormatReader(undefined, { + possibleFormats: [ + BarcodeFormat.CODE_128, + BarcodeFormat.EAN_13, + BarcodeFormat.UPC_A, + BarcodeFormat.UPC_E, + ], + }); + + barcodeReaderRef.current.timeBetweenDecodingAttempts = 50; + + barcodeReaderRef.current.decodeFromVideoDevice( + null, + videoRef.current, + (result) => { + if (result) { + stopWebScan(); + onScan(result.getText()); + setModalOpen(false); + } + } + ); + }; + + const stopWebScan = () => { + if (qrScannerRef.current) { + qrScannerRef.current.stop(); + qrScannerRef.current.destroy(); + qrScannerRef.current = null; + } + + if (barcodeReaderRef.current) { + barcodeReaderRef.current.reset(); + barcodeReaderRef.current = null; + } + + setScanning(false); + }; + + const closeModal = () => { + stopWebScan(); + setModalOpen(false); + }; + + useEffect(() => { + if (modalOpen) { + startWebScan(); + } + }, [modalOpen]); + + useEffect(() => { + return () => stopWebScan(); + }, []); + + return ( +
+ {!scanning && ( + + )} + + {/* +
+
+ + +
*/} + +
+ {/* VIDEO */} +