diff --git a/com.twin.app.shoptime/src/components/TQRCode/TQRCodeNew.jsx b/com.twin.app.shoptime/src/components/TQRCode/TQRCodeNew.jsx new file mode 100644 index 00000000..1f7738fb --- /dev/null +++ b/com.twin.app.shoptime/src/components/TQRCode/TQRCodeNew.jsx @@ -0,0 +1,93 @@ +import React, { useEffect, useMemo, useRef, useState } from "react"; + +import { useDispatch, useSelector } from "react-redux"; + +import { getDeviceAdditionInfo } from "../../actions/deviceActions"; +import { scaleH, scaleW } from "../../utils/helperMethods"; + +export default function TQRCodeNew({ + isBillingProductVisible, + ariaLabel, + text, + width = "128", + height = "128", +}) { + const qrcodeRef = useRef(null); + const deviceInfo = useSelector((state) => state.device.deviceInfo); + const { entryMenu, nowMenu } = useSelector((state) => state.common.menu); + const dispatch = useDispatch(); + + useEffect(() => { + if (!deviceInfo) { + dispatch(getDeviceAdditionInfo()); + } + }, [deviceInfo, dispatch]); + + const applyCircularMask = (scaledWidth, scaledHeight) => { + if (!qrcodeRef.current) return; + + const canvas = qrcodeRef.current.querySelector('canvas'); + if (!canvas) return; + + const radius = scaledWidth / 2; + + // 원본 canvas 저장 + const tempCanvas = document.createElement('canvas'); + tempCanvas.width = scaledWidth; + tempCanvas.height = scaledHeight; + const tempCtx = tempCanvas.getContext('2d'); + tempCtx.drawImage(canvas, 0, 0); + + // 원본 canvas 초기화 + const ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, scaledWidth, scaledHeight); + + // 원형 마스크 적용 + ctx.beginPath(); + ctx.arc(radius, radius, radius, 0, Math.PI * 2); + ctx.clip(); + + // 이미지 다시 그리기 + ctx.drawImage(tempCanvas, 0, 0); + }; + + useEffect(() => { + if (typeof window === "object" && entryMenu && nowMenu) { + if (qrcodeRef.current) { + while (qrcodeRef.current.firstChild) { + qrcodeRef.current.removeChild(qrcodeRef.current.firstChild); + } + } + // nowMenu 데이터를 Base64로 인코딩 + const encodedNowMenu = encodeURIComponent(nowMenu); + const encodeEntryMenu = encodeURIComponent(entryMenu); + + let idx; + + if (deviceInfo === null || !deviceInfo) { + idx = 0; + } else { + idx = deviceInfo?.dvcIndex; + } + + const scaledWidth = scaleW(width); + const scaledHeight = scaleH(height); + + const qrcode = new window.QRCode(qrcodeRef.current, { + text: isBillingProductVisible + ? text + : `${text}&entryMenu=${encodeEntryMenu}&nowMenu=${encodedNowMenu}&idx=${idx}`, + width: scaledWidth, + height: scaledHeight, + correctLevel: window.QRCode.CorrectLevel.L, + }); + + // QR코드 생성 완료 후 원형 마스킹 적용 + setTimeout(() => { + applyCircularMask(scaledWidth, scaledHeight); + }, 100); + } + }, [text, deviceInfo, entryMenu, nowMenu, isBillingProductVisible, width, height]); + + return
; +} diff --git a/com.twin.app.shoptime/src/components/TQRCode/TQRCodeNew.module.less b/com.twin.app.shoptime/src/components/TQRCode/TQRCodeNew.module.less new file mode 100644 index 00000000..e69de29b diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx index 4b6b0978..c35283d9 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx @@ -570,6 +570,21 @@ export default function ProductAllSection({ [productType, themeProductInfo, themeProducts, selectedIndex, productInfo] ); + // 🆕 [251211] patnrId=21인 경우 QR 데이터 확인 + useEffect(() => { + if (productData?.patnrId === 21 || productData?.patnrId === "21") { + console.log('[QR-Data] patnrId=21 QR 데이터 확인:', { + patnrId: productData?.patnrId, + prdtId: productData?.prdtId, + qrImgUrl: productData?.qrImgUrl, + qrCodeUrl: productData?.qrCodeUrl, + hasQrImgUrl: !!productData?.qrImgUrl, + hasQrCodeUrl: !!productData?.qrCodeUrl, + allData: productData, + }); + } + }, [productData]); + // 단품(결제 가능 상품) - DetailPanel.backup.jsx와 동일한 로직 const isBillingProductVisible = useMemo(() => { // API Mode: 기존 로직 100% 유지 (절대 수정 안 함) diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductInfoSection/QRCode/QRCode.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductInfoSection/QRCode/QRCode.jsx index 35f1f1c6..9da15d9d 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductInfoSection/QRCode/QRCode.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductInfoSection/QRCode/QRCode.jsx @@ -4,6 +4,7 @@ import classNames from 'classnames'; import { useSelector } from 'react-redux'; import TQRCode from '../../../../components/TQRCode/TQRCode'; +import TQRCodeNew from '../../../../components/TQRCode/TQRCodeNew'; import { getQRCodeUrl } from '../../../../utils/helperMethods'; import css from './QRCode.module.less'; @@ -56,13 +57,26 @@ export default function QRCode({ return detailUrl; }, [productInfo, isShopByMobile, detailUrl]); + // patnrId === 21인 경우 TQRCodeNew 사용 (원형 QR코드) + const isPatnrId21 = productInfo?.patnrId === 21 || productInfo?.patnrId === "21"; + return (