diff --git a/package-lock.json b/package-lock.json index dd11af5..473c15c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "html-to-image": "^1.11.11", "html2canvas": "^1.4.1", "jsqr": "^1.4.0", + "qr-scanner": "^1.4.2", "qrcode.react": "^3.1.0", "react": "^18.3.1", "react-apexcharts": "^1.7.0", @@ -5112,6 +5113,12 @@ "@types/node": "*" } }, + "node_modules/@types/offscreencanvas": { + "version": "2019.7.3", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz", + "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==", + "license": "MIT" + }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -5639,31 +5646,6 @@ "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==", "peer": true }, - "node_modules/@zxing/browser": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@zxing/browser/-/browser-0.0.7.tgz", - "integrity": "sha512-AepzMgDnD6EjxewqmXpHJsi4S3Gw9ilZJLIbTf6fWuWySEcHBodnGu3p7FWlgq1Sd5QyfPhTum5z3CBkkhMVng==", - "optionalDependencies": { - "@zxing/text-encoding": "^0.9.0" - }, - "peerDependencies": { - "@zxing/library": "^0.18.3" - } - }, - "node_modules/@zxing/library": { - "version": "0.18.6", - "resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.18.6.tgz", - "integrity": "sha512-bulZ9JHoLFd9W36pi+7e7DnEYNJhljYjZ1UTsKPOoLMU3qtC+REHITeCRNx40zTRJZx18W5TBRXt5pq2Uopjsw==", - "dependencies": { - "ts-custom-error": "^3.0.0" - }, - "engines": { - "node": ">= 10.4.0" - }, - "optionalDependencies": { - "@zxing/text-encoding": "~0.9.0" - } - }, "node_modules/@zxing/text-encoding": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", @@ -15768,6 +15750,15 @@ "teleport": ">=0.2.0" } }, + "node_modules/qr-scanner": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/qr-scanner/-/qr-scanner-1.4.2.tgz", + "integrity": "sha512-kV1yQUe2FENvn59tMZW6mOVfpq9mGxGf8l6+EGaXUOd4RBOLg7tRC83OrirM5AtDvZRpdjdlXURsHreAOSPOUw==", + "license": "MIT", + "dependencies": { + "@types/offscreencanvas": "^2019.6.4" + } + }, "node_modules/qrcode.react": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz", @@ -16189,6 +16180,33 @@ "react-dom": "^16.8.0 || ^17.0.0" } }, + "node_modules/react-qr-reader/node_modules/@zxing/browser": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zxing/browser/-/browser-0.0.7.tgz", + "integrity": "sha512-AepzMgDnD6EjxewqmXpHJsi4S3Gw9ilZJLIbTf6fWuWySEcHBodnGu3p7FWlgq1Sd5QyfPhTum5z3CBkkhMVng==", + "license": "MIT", + "optionalDependencies": { + "@zxing/text-encoding": "^0.9.0" + }, + "peerDependencies": { + "@zxing/library": "^0.18.3" + } + }, + "node_modules/react-qr-reader/node_modules/@zxing/library": { + "version": "0.18.6", + "resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.18.6.tgz", + "integrity": "sha512-bulZ9JHoLFd9W36pi+7e7DnEYNJhljYjZ1UTsKPOoLMU3qtC+REHITeCRNx40zTRJZx18W5TBRXt5pq2Uopjsw==", + "license": "MIT", + "dependencies": { + "ts-custom-error": "^3.0.0" + }, + "engines": { + "node": ">= 10.4.0" + }, + "optionalDependencies": { + "@zxing/text-encoding": "~0.9.0" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", diff --git a/package.json b/package.json index 3576ac4..fe2433e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "html-to-image": "^1.11.11", "html2canvas": "^1.4.1", "jsqr": "^1.4.0", + "qr-scanner": "^1.4.2", "qrcode.react": "^3.1.0", "react": "^18.3.1", "react-apexcharts": "^1.7.0", diff --git a/src/App.js b/src/App.js index 240c678..8ac0fb9 100644 --- a/src/App.js +++ b/src/App.js @@ -394,14 +394,14 @@ function App() { console.log(transaction_info); // Log the updated transaction_info - const depthh = transactionList.current.findIndex( + let depthh = transactionList.current.findIndex( item => item.transactionId.toString() === transaction_info.toString() ); - + if(depthh == 0 && transaction_info.toString() != '') depthh = 1; setDepth(depthh); console.log(transaction_info == response[0].transactionId) // If transaction_info is an empty string, set the modal - if (transaction_info == '' || transaction_info == response[0].transactionId) return false; + if (transaction_info.toString() == '' || transaction_info.toString() == response[0].transactionId) return false; else return true; } diff --git a/src/components/PaymentOptions.js b/src/components/PaymentOptions.js index 972c230..e324cb2 100644 --- a/src/components/PaymentOptions.js +++ b/src/components/PaymentOptions.js @@ -1,5 +1,5 @@ import React, { useState, useRef, useEffect } from "react"; -import jsQR from "jsqr"; +import QrScanner from "qr-scanner"; // Import qr-scanner import { getImageUrl } from "../helpers/itemHelper"; import { getCafe, @@ -20,6 +20,8 @@ const SetPaymentQr = ({ shopId, const [isQRISavailable, setIsQRISavailable] = useState(0); const qrPaymentInputRef = useRef(null); const qrCodeContainerRef = useRef(null); + + const [qrCodeData, setQrCodeData] = useState(null); const [cafe, setCafe] = useState({}); const [isConfigQRIS, setIsConfigQRIS] = useState(false); @@ -45,12 +47,6 @@ const SetPaymentQr = ({ shopId, fetchCafe(); }, [shopId]); - // Detect QR code when qrPayment updates - useEffect(() => { - if (qrPayment && isConfigQRIS) { - detectQRCodeFromContainer(); - } - }, [qrPayment, isConfigQRIS]); // Handle file input change const handleFileChange = (e) => { @@ -62,25 +58,48 @@ const SetPaymentQr = ({ shopId, } }; - // Detect QR code from the container + useEffect(() => { + if (qrPayment && isConfigQRIS) { + detectQRCodeFromContainer(); + } + }, [qrPayment, isConfigQRIS]); + const detectQRCodeFromContainer = () => { const container = qrCodeContainerRef.current; - const canvas = document.createElement("canvas"); - const context = canvas.getContext("2d"); + if (!container) return; + const img = new Image(); img.crossOrigin = "Anonymous"; - img.onload = () => { - canvas.width = container.offsetWidth; - canvas.height = container.offsetHeight; - context.drawImage(img, 0, 0, canvas.width, canvas.height); - const imageData = context.getImageData(0, 0, canvas.width, canvas.height); - const qrCode = jsQR(imageData.data, canvas.width, canvas.height); - setQrCodeDetected(!!qrCode); - if (qrCode) { - console.log("QR Code detected:", qrCode.data); - } - }; img.src = qrPayment; + + img.onload = () => { + // Buat canvas dari image + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); + canvas.width = img.width; + canvas.height = img.height; + context.drawImage(img, 0, 0); + + // Ambil data URL dari canvas (png) + const imageDataUrl = canvas.toDataURL(); + + QrScanner.scanImage(imageDataUrl, { returnDetailedScanResult: true }) + .then(result => { + setQrCodeDetected(true); + setQrCodeData(result.data); + console.log("QR Code detected:", result.data); + }) + .catch(() => { + setQrCodeDetected(false); + setQrCodeData(null); + console.log("QR Code not detected"); + }); + }; + + img.onerror = () => { + setQrCodeDetected(false); + setQrCodeData(null); + }; }; // Save cafe details diff --git a/src/pages/Cart.js b/src/pages/Cart.js index 494cee6..1b95853 100644 --- a/src/pages/Cart.js +++ b/src/pages/Cart.js @@ -272,6 +272,8 @@ export default function Invoice({ shopId, setModal, table, sendParam, deviceType socketId ); localStorage.removeItem('lastTransaction') + // Dispatch the custom event + window.dispatchEvent(new Event("localStorageUpdated")); } else