diff --git a/com.twin.app.shoptime/src/actions/actionTypes.js b/com.twin.app.shoptime/src/actions/actionTypes.js index 8aa0640e..2319d8f1 100644 --- a/com.twin.app.shoptime/src/actions/actionTypes.js +++ b/com.twin.app.shoptime/src/actions/actionTypes.js @@ -158,4 +158,7 @@ export const types = { // emp actions GET_SHOPTIME_TERMS: "GET_SHOPTIME_TERMS", + + // pinCode actions + GET_MY_INFO_CARD_PINCODE_CHECK: "GET_MY_INFO_CARD_PINCODE_CHECK", }; diff --git a/com.twin.app.shoptime/src/actions/pinCodeActions.js b/com.twin.app.shoptime/src/actions/pinCodeActions.js new file mode 100644 index 00000000..6b04c849 --- /dev/null +++ b/com.twin.app.shoptime/src/actions/pinCodeActions.js @@ -0,0 +1,32 @@ +import { URLS } from '../api/apiConfig'; +import { TAxios } from '../api/TAxios'; +import { types } from './actionTypes'; + +// 회원 등록카드 PIN CODE 입력 체크 IF-LGSP-336 +export const getMyInfoCardPincodeCheck = (params) => (dispatch, getState) => { + const { mbrNo, pinCd } = params; + + const onSuccess = (response) => { + console.log("getMyInfoCardPincodeCheck onSuccess ", response.data); + + dispatch({ + type: types.GET_MY_INFO_CARD_PINCODE_CHECK, + payload: response.data.data, + }); + }; + + const onFail = (error) => { + console.error("getMyInfoCardPincodeCheck onFail ", error); + }; + + TAxios( + dispatch, + getState, + "get", + URLS.GET_MY_INFO_CARD_PINCODE_CHECK, + { mbrNo, pinCd }, + {}, + onSuccess, + onFail + ); +}; diff --git a/com.twin.app.shoptime/src/api/apiConfig.js b/com.twin.app.shoptime/src/api/apiConfig.js index a4feee95..f35f7ad4 100644 --- a/com.twin.app.shoptime/src/api/apiConfig.js +++ b/com.twin.app.shoptime/src/api/apiConfig.js @@ -128,6 +128,9 @@ export const URLS = { // emp controller GET_SHOPTIME_TERMS: "/lgsp/m/v1/emp/shoptime/terms.lge", + // pinCode controller + GET_MY_INFO_CARD_PINCODE_CHECK: "/lgsp/v1/myinfo/card/pincode/check.lge", + // IF-LGSP-LOG-001 log live controller LOG_LIVE: "/lgsp/v1/log/live.lge", diff --git a/com.twin.app.shoptime/src/components/CustomImage/CustomImage.jsx b/com.twin.app.shoptime/src/components/CustomImage/CustomImage.jsx index 0dc7b5e6..85b97ddb 100644 --- a/com.twin.app.shoptime/src/components/CustomImage/CustomImage.jsx +++ b/com.twin.app.shoptime/src/components/CustomImage/CustomImage.jsx @@ -3,13 +3,19 @@ * * @module CustomImage */ -import React, { memo, useCallback, useEffect, useRef, useState } from "react"; +import React, { + memo, + useCallback, + useEffect, + useRef, + useState, +} from 'react'; -import classNames from "classnames"; +import classNames from 'classnames'; -import { Job } from "@enact/core/util"; +import { Job } from '@enact/core/util'; -import css from "./CustomImage.module.less"; +import css from './CustomImage.module.less'; //animationSpeed : "slow", "normal", "fast", ==> 500ms, 250ms, 10ms export default memo(function CustomImage({ @@ -34,14 +40,17 @@ export default memo(function CustomImage({ useEffect(() => { setImageLoaded(false); + setImgSrc(src); setError(false); showImageJob.current.stop(); + }, [src]); + useEffect(() => { return () => { showImageJob.current.stop(); }; - }, [src]); + }, []); const _onLoad = useCallback(() => { showImageJob.current.start(setImageLoaded); diff --git a/com.twin.app.shoptime/src/components/TFullPopup/TFullPopup.jsx b/com.twin.app.shoptime/src/components/TFullPopup/TFullPopup.jsx new file mode 100644 index 00000000..6559ee4a --- /dev/null +++ b/com.twin.app.shoptime/src/components/TFullPopup/TFullPopup.jsx @@ -0,0 +1,48 @@ +import React, { useCallback } from 'react'; + +import classNames from 'classnames'; + +import Popup from '@enact/sandstone/Popup'; + +import css from './TFullPopup.module.less'; + +export default function TFullPopup({ + noAnimation = false, + noAutoDismiss = false, + onClose, + onHide, + open, + position = "fullscreen", + scrimType = "translucent", + spotlightRestrict, + className, + children, +}) { + const _onClose = useCallback(() => { + if (onClose) { + onClose(); + } + }, [onClose]); + + const _onHide = useCallback(() => { + if (onHide) { + onHide(); + } + }, [onHide]); + + return ( + + {children} + + ); +} diff --git a/com.twin.app.shoptime/src/components/TFullPopup/TFullPopup.module.less b/com.twin.app.shoptime/src/components/TFullPopup/TFullPopup.module.less new file mode 100644 index 00000000..a803ee1e --- /dev/null +++ b/com.twin.app.shoptime/src/components/TFullPopup/TFullPopup.module.less @@ -0,0 +1,10 @@ +@import "../../style/CommonStyle.module.less"; +@import "../../style/utils.module.less"; + +.tFullPopup { + > div { + font-family: @baseFont !important; + font-size: unset !important; + padding: 0 !important; + } +} diff --git a/com.twin.app.shoptime/src/lunaSend/account.js b/com.twin.app.shoptime/src/lunaSend/account.js index 9bad7d1d..c7703301 100644 --- a/com.twin.app.shoptime/src/lunaSend/account.js +++ b/com.twin.app.shoptime/src/lunaSend/account.js @@ -64,7 +64,7 @@ export const getLoginUserData = ( } else { return new LS2Request().send({ service: "luna://com.webos.service.accountmanager", - method: "getLoginUserData", + method: "getLoginID", subscribe: false, parameters: parameters, onSuccess, diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx index 41dc8503..ae92634a 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx @@ -17,13 +17,16 @@ import { changeAppStatus } from '../../actions/commonActions'; import { getShoptimeTerms } from '../../actions/empActions'; import { popPanel } from '../../actions/panelActions'; import TBody from '../../components/TBody/TBody'; +import TFullPopup from '../../components/TFullPopup/TFullPopup'; import THeader from '../../components/THeader/THeader'; import TPanel from '../../components/TPanel/TPanel'; import TScroller from '../../components/TScroller/TScroller'; +import { $L } from '../../utils/helperMethods'; import css from './CheckOutPanel.module.less'; import CheckoutQRCode from './components/CheckoutQRCode'; import CheckOutTerms from './components/CheckOutTerms'; import PinCode from './components/PinCode'; +import PinCodeInput from './components/PinCodeInput'; import FixedSideBar from './container/FixedSideBar'; import InformationContainer from './container/InformationContainer'; import OrderItemsSideBar from './container/OrderItemsSideBar'; @@ -44,8 +47,13 @@ export default function CheckOutPanel() { const infoForCheckoutData = useSelector( (state) => state.checkout?.infoForCheckoutData ); + const cardInfo = useSelector( + (state) => state.checkout?.checkoutData.cardInfo + ); + const [orderSideBarOpen, setOrderSideBarOpen] = useState(false); const [offerSideBarOpen, setOfferSideBarOpen] = useState(false); + const [placeOrderPopup, setPlaceOrderPopup] = useState(false); useEffect(() => { dispatch(getShoptimeTerms()); @@ -114,7 +122,7 @@ export default function CheckOutPanel() { onClick={onBackClick} />
- + )} {offerSideBarOpen && } + + + + ); } diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.module.less b/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.module.less index 16662067..29bc19ba 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.module.less +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.module.less @@ -16,6 +16,10 @@ } } +.pinCodePopup { + background-color: #000 !important; +} + .fixedSideBar { position: fixed; background-color: rgba(0, 0, 0, 0.3); diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCode.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCode.jsx index c767ba5e..5f40c6c2 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCode.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCode.jsx @@ -1,11 +1,12 @@ -import React, { useState } from "react"; +import React, { useState } from 'react'; -import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; -import Spottable from "@enact/spotlight/Spottable"; +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; +import Spottable from '@enact/spotlight/Spottable'; -import TButton from "../../../components/TButton/TButton"; -import { $L } from "../../../utils/helperMethods"; -import css from "./PinCode.module.less"; +import TButton from '../../../components/TButton/TButton'; +import { $L } from '../../../utils/helperMethods'; +import css from './PinCode.module.less'; const Container = SpotlightContainerDecorator( { enterTo: "last-focused" }, diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCodeInput.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCodeInput.jsx new file mode 100644 index 00000000..5211be65 --- /dev/null +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCodeInput.jsx @@ -0,0 +1,93 @@ +import React, { + useCallback, + useState, +} from 'react'; + +import classNames from 'classnames'; + +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; +import Spottable from '@enact/spotlight/Spottable'; + +import TButton from '../../../components/TButton/TButton'; +import { $L } from '../../../utils/helperMethods'; +import css from './PinCodeInput.module.less'; + +const PinCodeContainer = SpotlightContainerDecorator("div"); + +const SpottableButton = Spottable("div"); + +export default function PinCodeInput({ setPlaceOrderPopup }) { + const [pin, setPin] = useState(["", "", "", ""]); + + const handleDigitClick = useCallback( + (digit) => { + const newPin = [...pin]; + const nextIndex = pin.findIndex((p) => p === ""); + + if (nextIndex !== -1) { + newPin[nextIndex] = digit; + setPin(newPin); + + if (nextIndex === 3) { + console.log("chw", newPin.join("")); + } + } + }, + [pin] + ); + + const handleBackspace = useCallback(() => { + const newPin = [...pin]; + const lastIndex = pin.lastIndexOf(""); + const index = lastIndex === -1 ? 3 : lastIndex - 1; + + if (index >= 0) { + newPin[index] = ""; + setPin(newPin); + } + }, [pin]); + + const onClickCancel = useCallback(() => { + setPin(["", "", "", ""]); + setPlaceOrderPopup(false); + }, [setPlaceOrderPopup]); + + return ( + +

{$L("Enter PIN CODE")}

+
+ {pin.map((digit, index) => ( +
p === "") === index, + })} + > + {digit ? "*" : ""} +
+ ))} +
+
+ {[...Array(10).keys()].map((digit) => ( + handleDigitClick(digit.toString())} + > + {digit} + + ))} + +
+
+ {$L("Cancel")} + {$L("OK")} +
+
+ ); +} diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCodeInput.module.less b/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCodeInput.module.less new file mode 100644 index 00000000..d839487e --- /dev/null +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/components/PinCodeInput.module.less @@ -0,0 +1,109 @@ +@import "../../../style/CommonStyle.module.less"; +@import "../../../style/utils.module.less"; + +.pinCodeContainer { + width: 100%; + height: 100%; + padding: 120px 0; + + .pinCodeTitle { + text-align: center; + font-size: 72px; + color: #e6e6e6; + } + + .pinCodeBoxes { + margin-top: 162px; + display: flex; + justify-content: center; + + .pinCodeBox { + width: 120px; + height: 144px; + border-radius: 6px; + background-color: #e6e6e6; + margin-right: 18px; + opacity: 0.15; + color: #000; // 검은색 * 표시 + display: flex; + justify-content: center; + align-items: center; + font-size: 48px; + + &.focused { + background-color: #fff; + opacity: 1; + } + + &.filled { + opacity: 1; + } + + &:last-child { + margin-right: 0; + } + } + } + + .pinCodeDigits { + margin: 150px auto 0; + display: flex; + justify-content: center; + + .pinCodeDigit { + width: 84px; + height: 84px; + line-height: 84px; + text-align: center; + color: #e6e6e6; + font-size: 42px; + font-weight: bold; + + &:focus { + background-color: #fff; + color: #4c5059; + border-radius: 6px; + font-weight: bold; + } + } + + .deleteKey { + background: url("../../../../assets/images/icons/ic-delete-nor@3x.png"); + background-size: contain; + + &:focus { + background: url("../../../../assets/images/icons/ic-delete-foc@3x.png"); + background-size: contain; + } + } + } + + .buttonContainer { + display: flex; + justify-content: center; + margin-top: 168px; + + > div { + width: 270px; + height: 72px; + line-height: 72px; + font-weight: 200; + margin: 0 10px; + background: @COLOR_GRAY09; + &:focus { + box-shadow: 0px 18px 28.2px 1.8px rgba(62, 59, 59, 0.4); + background-color: @PRIMARY_COLOR_RED; + color: @COLOR_WHITE; + transform: translateY(3%) translateX(-3%) scale(1.1); + } + &:last-child { + &:focus { + box-shadow: 0px 18px 28.2px 1.8px rgba(62, 59, 59, 0.4); + background-color: @PRIMARY_COLOR_RED; + color: @COLOR_WHITE; + transform: translateY(3%) translateX(3%) scale(1.1); + } + } + } + } +} diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/container/SummaryCotainer.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/container/SummaryCotainer.jsx index a3acb895..b799a79e 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/container/SummaryCotainer.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/container/SummaryCotainer.jsx @@ -37,7 +37,7 @@ const DEFAULT_SUMMARY = { currSignLoc: "", }; -export default function SummaryContainer({ userInfo }) { +export default function SummaryContainer({ setPlaceOrderPopup }) { const dispatch = useDispatch(); const { productList } = useSelector((state) => state.checkout.checkoutData); @@ -126,7 +126,7 @@ export default function SummaryContainer({ userInfo }) { ]; const handleClickOrder = useCallback(() => { - console.log("success"); + setPlaceOrderPopup(true); }, []); return (