import React, { useState, useRef, useEffect } from "react"; import QrScanner from "qr-scanner"; // Import qr-scanner import { getImageUrl } from "../helpers/itemHelper"; import { getCafe, saveCafeDetails } from "../helpers/cafeHelpers"; import Switch from "react-switch"; // Import the Switch component import styles from "./PaymentOptions.module.css"; const SetPaymentQr = ({ shopId, qrCodeUrl }) => { const [qrPosition, setQrPosition] = useState([50, 50]); // legacy kept for API compatibility const [qrSize, setQrSize] = useState(50); // legacy kept for API compatibility const [qrPayment, setQrPayment] = useState(); const [qrPaymentFile, setQrPaymentFile] = useState(); const [qrCodeDetected, setQrCodeDetected] = useState(false); const [isNeedConfirmationState, setIsNeedConfirmationState] = useState(0); 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); const [isOpenBillAvailable, setIsOpenBillAvailable] = useState(false); const [saving, setSaving] = useState(false); const [saveStatus, setSaveStatus] = useState(null); // 'success' | 'error' const [copied, setCopied] = useState(false); useEffect(() => { const fetchCafe = async () => { try { const response = await getCafe(shopId); setCafe(response); setQrPayment(getImageUrl(response.qrPayment)); console.log(response.needsConfirmation); setIsNeedConfirmationState(response.needsConfirmation === true ? 1 : 0); // Set state based on fetched data setIsQRISavailable(response.isQRISavailable === true ? 1 : 0); // Set state based on fetched data setIsOpenBillAvailable(response.isOpenBillAvailable === true ? 1 : 0); // Set state based on fetched data setQrPosition([response.xposition, response.yposition]); setQrSize(response.scale); } catch (error) { console.error("Error fetching cafe:", error); } }; fetchCafe(); }, [shopId]); // Handle file input change const handleFileChange = (e) => { const file = e.target.files[0]; if (file) { const newqrPayment = URL.createObjectURL(file); setQrPayment(newqrPayment); setQrPaymentFile(file); } }; useEffect(() => { if (qrPayment && isConfigQRIS) { detectQRCodeFromContainer(); } }, [qrPayment, isConfigQRIS]); const detectQRCodeFromContainer = () => { const container = qrCodeContainerRef.current; if (!container) return; const img = new Image(); img.crossOrigin = "Anonymous"; 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 const handleSave = async () => { setSaving(true); setSaveStatus(null); let qrPaymentFileCache; console.log(qrPaymentFile) if(qrPaymentFile != null) qrPaymentFileCache = qrPaymentFile; const details = { qrPosition, qrSize, qrPaymentFile: qrPaymentFileCache, isQRISavailable: isQRISavailable === 1, isOpenBillAvailable: isOpenBillAvailable === 1, isNeedConfirmationState: isNeedConfirmationState === 1 }; try { const response = await saveCafeDetails(cafe.cafeId, details); setIsNeedConfirmationState(response.needsConfirmation ? 1 : 0); setIsQRISavailable(response.isQRISavailable ? 1 : 0); setIsOpenBillAvailable(response.isOpenBillAvailable ? 1 : 0); setSaveStatus('success'); console.log("Cafe details saved:", response); } catch (error) { console.error("Error saving cafe details:", error); setSaveStatus('error'); } finally { setSaving(false); } }; const copyQrData = async () => { if (!qrCodeData) return; try { await navigator.clipboard.writeText(qrCodeData); setCopied(true); setTimeout(()=>setCopied(false), 1200); } catch {} }; return (

Konfigurasi pembayaran

Pembayaran QRIS
Aktifkan agar pelanggan dapat membayar via QRIS. Kasir tetap perlu verifikasi rekening.
setIsQRISavailable(checked ? 1 : 0)} checked={isQRISavailable === 1} offColor="#888" onColor="#4CAF50" uncheckedIcon={false} checkedIcon={false} height={25} width={50} />
{isConfigQRIS && ( <>
qrPaymentInputRef.current.click()} style={{ backgroundImage: `url(${qrPayment})` }} >
Klik area untuk unggah/ganti gambar QR
{qrCodeDetected && qrPayment !== 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPsNr0TPq8dHT3nBwDQ6OHQQTrqzVFoeBOmuWfgyErrLbJi6f6CnnYhpNHEvkJ_2X-kyI&usqp=CAU' ? 'QR terdeteksi' : 'Tidak ada QR terdeteksi'}
{qrCodeDetected && (
)}
)}
Open bill
Izinkan pelanggan menambah pesanan dalam satu sesi dan bayar di akhir.
setIsOpenBillAvailable(checked ? 1 : 0)} checked={isOpenBillAvailable === 1} offColor="#888" onColor="#4CAF50" uncheckedIcon={false} checkedIcon={false} height={25} width={50} />
Pengecekan ganda
Kasir memeriksa kembali ketersediaan item sebelum pembayaran.
setIsNeedConfirmationState(checked ? 1 : 0)} checked={isNeedConfirmationState === 1} offColor="#888" onColor="#4CAF50" uncheckedIcon={false} checkedIcon={false} height={25} width={50} />
{saveStatus === 'success' && Simpan berhasil} {saveStatus === 'error' && Gagal menyimpan}
); }; export default SetPaymentQr;