import React, { useCallback, useEffect, useMemo, useState, } from 'react'; import { useDispatch, useSelector, } from 'react-redux'; import Spotlight from '@enact/spotlight'; import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; import { setHidePopup, setShowPopup, } from '../../../actions/commonActions'; import { sendLogTotalRecommend } from '../../../actions/logActions'; import { popPanel } from '../../../actions/panelActions'; import TButton from '../../../components/TButton/TButton'; import TPopUp from '../../../components/TPopUp/TPopUp'; import TQRCode from '../../../components/TQRCode/TQRCode'; import useScrollTo from '../../../hooks/useScrollTo'; import useScrollTopByDistance from '../../../hooks/useScrollTopByDistance'; import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig'; import * as Config from '../../../utils/Config'; import { $L, getQRCodeUrl, } from '../../../utils/helperMethods'; import BillingAddressCard from '../components/BillingAddressCard'; import PaymentCard from '../components/PaymentCard'; import ShippingAddressCard from '../components/ShippingAddressCard'; import Subject from '../components/Subject'; import css from './InformationContainer.module.less'; const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); const BtnSpot = Spottable('p'); const getBtnNmByIndex = (index) => { switch (index) { case 0: return 'SHIPPING ADDRESS'; case 1: return 'BILLING ADDRESS'; case 2: return 'PATMENT METHOD'; default: return ''; } }; export default function InformationContainer({ toggleOfferSideBar, toggleOrderSideBar, scrollTopBody, doSendLogMyInfoEdit, }) { const dispatch = useDispatch(); // All useSelector calls must be at the top - before any conditional logic const reduxCheckoutData = useSelector((state) => state.checkout?.checkoutData); const { cursorVisible } = useSelector((state) => state.common.appStatus); const { popupVisible, activePopup } = useSelector((state) => state.common.popup); const auctProdYn = useSelector( (state) => state.checkout?.checkoutData?.productList?.[0].auctProdYn ); const auctFinalPriceChgDt = useSelector( (state) => state.checkout?.checkoutData?.productList?.[0].auctFinalPriceChgDt ); const totDcAmt = useSelector((state) => state.checkout?.checkoutTotalData?.totDcAmt); const reduxServerHOST = useSelector((state) => state.common.appStatus.serverHOST); const reduxServerType = useSelector((state) => state.localSettings.serverType); const reduxNowMenu = useSelector((state) => state.common.menu.nowMenu); const reduxEntryMenu = useSelector((state) => state.common.menu.entryMenu); const reduxDeviceInfo = useSelector((state) => state.device.deviceInfo); // Mock Mode: Provide fallback values for Redux selectors const serverHOST = BUYNOW_CONFIG.isMockMode() ? reduxServerHOST || 'sdp-us.shoptime.com' : reduxServerHOST; const serverType = BUYNOW_CONFIG.isMockMode() ? reduxServerType || 'system' : reduxServerType; const nowMenu = BUYNOW_CONFIG.isMockMode() ? reduxNowMenu || 'MOCK_NOW_MENU' : reduxNowMenu; const entryMenu = BUYNOW_CONFIG.isMockMode() ? reduxEntryMenu || 'MOCK_ENTRY_MENU' : reduxEntryMenu; const deviceInfo = BUYNOW_CONFIG.isMockMode() ? reduxDeviceInfo || { dvcIndex: 1 } : reduxDeviceInfo; // Check if reduxCheckoutData has actual data (productList) const hasValidCheckoutData = reduxCheckoutData?.productList && Array.isArray(reduxCheckoutData.productList) && reduxCheckoutData.productList.length > 0; const checkoutData = hasValidCheckoutData ? reduxCheckoutData : BUYNOW_CONFIG.isMockMode() ? { productList: [ { prdtId: 'MOCK_PRODUCT_1', prdtNm: 'Mock Product', patnrId: '1', prodQty: 1, prdtOpt: [{ prodOptCdCval: 'MOCK_OPT_1' }], auctProdYn: 'N', auctFinalPriceChgDt: null, }, ], shippingAddressList: [ { dlvrAddrSno: 'MOCK_ADDR_1', dlvrOdrFnm: 'Mock', dlvrOdrLnm: 'Receiver', dlvrZpcd: '12345', dlvrStatNm: 'CA', dlvrCityNm: 'Los Angeles', dlvrDtlAddr: '123 Mock Street, Suite 100', dlvrCtpt: '555-1234', dlvrEmalAddr: 'mock@example.com', }, ], billingAddressList: [ { bilAddrSno: 'MOCK_ADDR_2', bilOdrFnm: 'Mock', bilOdrLnm: 'Payer', bilZpcd: '12346', bilStatNm: 'CA', bilCityNm: 'Los Angeles', bilDtlAddr: '456 Mock Avenue, Suite 200', bilCtpt: '5555678', bilEmalAddr: 'payer@example.com', }, ], cardInfo: [ { cardSno: 'MOCK_CARD_1', cardNm: 'Mock Card', cardNo: '****-****-****-1234', cardType: 'CREDIT', }, ], } : null; const [_, setTab] = useState(0); const [prdtData, setPrdtData] = useState({}); const { getScrollTo } = useScrollTo(); const { scrollTopByDistance } = useScrollTopByDistance(); // Use effect to handle missing checkoutData (only in API mode without mock fallback) useEffect(() => { if (!checkoutData) { dispatch(popPanel()); } }, [checkoutData, dispatch]); useEffect(() => { if (checkoutData && checkoutData.productList) { try { const { patnrId, prdtId, prodQty } = checkoutData.productList[0]; const prdtOpt = checkoutData.productList[0].prdtOpt; const prodOptCdCval = Array.isArray(prdtOpt) && prdtOpt.length > 0 ? prdtOpt[0].prodOptCdCval : ''; const params = { patnrId: patnrId, prdtId: prdtId, prodOptCdCval: prodOptCdCval || '', prodQty: prodQty, }; setPrdtData(params); } catch (error) { console.error('[CheckOutPanel] InformationContainer prdtData useEffect - ERROR:', error); } } }, [checkoutData]); const checkoutUrlObj = useMemo(() => { try { // Guard: ensure checkoutData and productList exist if (!checkoutData?.productList?.[0]) { console.error('[CheckOutPanel] InformationContainer checkoutUrl useMemo - No product data'); return null; } const { patnrId, prdtId } = checkoutData.productList[0]; const url = getQRCodeUrl({ serverHOST, serverType, prdtData, entryMenu, nowMenu, prdtId, patnrId, index: deviceInfo?.dvcIndex, }); return url; } catch (error) { console.error('[CheckOutPanel] InformationContainer checkoutUrl useMemo - ERROR:', error); return null; } }, [serverHOST, serverType, entryMenu, nowMenu, deviceInfo]); // Extract the actual URL string from the URL object const checkoutUrl = checkoutUrlObj?.checkoutUrl || null; const handleFocus = useCallback(() => { const c = Spotlight.getCurrent(); const target = c.getAttribute('data-spotlight-id'); const targetValue = '[data-spotlight-id="' + target + '"]'; if (cursorVisible) { return; } scrollTopByDistance(`[data-marker="scroll-marker"]`, targetValue, scrollTopBody, 100); }, []); const handleButtonClick = useCallback( (index) => { const btnNm = getBtnNmByIndex(index); if (btnNm && doSendLogMyInfoEdit) { doSendLogMyInfoEdit(btnNm); } setTab(index); dispatch(setShowPopup(Config.ACTIVE_POPUP.qrPopup)); dispatch( sendLogTotalRecommend({ buttonTitle: `${btnNm} ADD/EDIT`, buttonId: `checkout_info_${btnNm.toLowerCase().replace(/\s+/g, '_')}`, contextName: Config.LOG_CONTEXT_NAME.CHECKOUT, messageId: Config.LOG_MESSAGE_ID.BUTTONCLICK, }) ); }, [dispatch, doSendLogMyInfoEdit] ); const handleCancel = useCallback(() => { dispatch(setHidePopup()); }, [dispatch]); const handleDone = useCallback(() => { dispatch(setHidePopup()); dispatch(popPanel()); }, [dispatch]); return ( <>
{checkoutData?.productList?.length || 0} ITEMS
handleButtonClick(0)} > ADD/EDIT {checkoutData?.shippingAddressList && ( )}
handleButtonClick(1)} > ADD/EDIT {/* BillingAddressCard disabled due to infinite render loop in Mock Mode */} {/*
Mock Billing Address
*/} {checkoutData?.billingAddressList && ( )}
handleButtonClick(2)} > ADD/EDIT {checkoutData?.cardInfo && }
{auctProdYn === 'Y' && !auctFinalPriceChgDt ? ' - ' : totDcAmt ? totDcAmt : '-'}
{/* QR Code */} {activePopup === Config.ACTIVE_POPUP.qrPopup && (

{$L('QR CODE')}

{checkoutUrl && (
)}

{$L( 'Please update your information and complete the payment on your mobile. By clicking the OK button, you will be redirected to the product details page' )}

{$L('OK')}
)} ); }