diff --git a/com.twin.app.shoptime/assets/images/icons/ico-del-keyword.png b/com.twin.app.shoptime/assets/images/icons/ico-del-keyword.png new file mode 100644 index 00000000..aef4e938 Binary files /dev/null and b/com.twin.app.shoptime/assets/images/icons/ico-del-keyword.png differ diff --git a/com.twin.app.shoptime/src/actions/actionTypes.js b/com.twin.app.shoptime/src/actions/actionTypes.js index 1df8cfcd..73b45844 100644 --- a/com.twin.app.shoptime/src/actions/actionTypes.js +++ b/com.twin.app.shoptime/src/actions/actionTypes.js @@ -36,6 +36,7 @@ export const types = { // appData actions ADD_MAIN_INDEX: "ADD_MAIN_INDEX", SEND_SMS: "SEND_SMS", + CLEAR_SMS: "CLEAR_SMS", // home actions GET_HOME_TERMS: "GET_HOME_TERMS", diff --git a/com.twin.app.shoptime/src/actions/appDataActions.js b/com.twin.app.shoptime/src/actions/appDataActions.js index 5836d19e..b7e75fa9 100644 --- a/com.twin.app.shoptime/src/actions/appDataActions.js +++ b/com.twin.app.shoptime/src/actions/appDataActions.js @@ -62,3 +62,7 @@ export const sendSms = (params) => (dispatch, getState) => { onFail ); }; + +export const clearSMS = () => ({ + type: types.CLEAR_SMS, +}); diff --git a/com.twin.app.shoptime/src/components/MobileSend/HistoryPhoneNumber/HistoryPhoneNumber.jsx b/com.twin.app.shoptime/src/components/MobileSend/HistoryPhoneNumber/HistoryPhoneNumber.jsx new file mode 100644 index 00000000..3e9fe36c --- /dev/null +++ b/com.twin.app.shoptime/src/components/MobileSend/HistoryPhoneNumber/HistoryPhoneNumber.jsx @@ -0,0 +1,48 @@ +import React, { useEffect } from "react"; + +import { Spottable } from "@enact/spotlight/Spottable"; + +import TButton from "../../TButton/TButton"; +import css from "./HistoryPhoneNumber.module.less"; + +const SpottableComponent = Spottable("div"); + +export default function HistoryPhoneNumber({ + handleClickSelect, + recentSentNumber, + handleDelete, +}) { + const handleClickNumber = (number) => { + handleClickSelect(number); + }; + + return ( + <> + {recentSentNumber && + recentSentNumber.length > 0 && + recentSentNumber.map((number, index) => { + return ( +
+ { + handleClickNumber(number); + }} + className={css.phoneNumberList} + > + {number} + + { + handleDelete(index); + }} + /> +
+ ); + })} + + ); +} diff --git a/com.twin.app.shoptime/src/components/MobileSend/HistoryPhoneNumber/HistoryPhoneNumber.module.less b/com.twin.app.shoptime/src/components/MobileSend/HistoryPhoneNumber/HistoryPhoneNumber.module.less new file mode 100644 index 00000000..f7ef3f51 --- /dev/null +++ b/com.twin.app.shoptime/src/components/MobileSend/HistoryPhoneNumber/HistoryPhoneNumber.module.less @@ -0,0 +1,43 @@ +@import "../../../style/CommonStyle.module.less"; +@import "../../../style/utils.module.less"; + +.container { + width: 492px; + height: 68px; + display: flex; + align-items: center; + + .phoneNumberList { + width: 437px; + height: 68px; + background-color: #434040; + .border-solid(@size:1px,@color:#cccccc); + color: @COLOR_WHITE; + padding: 18px 5px 18px 20px; + position: relative; + + &:focus { + &::after { + .focused(); + } + } + p { + color: @COLOR_WHITE; + } + } + .deleteButton { + background-image: url("../../../../assets/images/icons/ico-del-keyword.png"); + min-width: 40px; + height: 40px; + background-color: transparent; + background-position: -4px -4px; + transition: none; + border-radius: 50%; + + margin-left: 10px; + + &:focus { + background-position: -4px -100px; + } + } +} diff --git a/com.twin.app.shoptime/src/components/MobileSend/MobileSendPopUp.jsx b/com.twin.app.shoptime/src/components/MobileSend/MobileSendPopUp.jsx index 07241476..2a34ad1a 100644 --- a/com.twin.app.shoptime/src/components/MobileSend/MobileSendPopUp.jsx +++ b/com.twin.app.shoptime/src/components/MobileSend/MobileSendPopUp.jsx @@ -5,9 +5,10 @@ import { PhoneNumberFormat, PhoneNumberUtil } from "google-libphonenumber"; import { useDispatch, useSelector } from "react-redux"; import { off, on } from "@enact/core/dispatcher"; +import { Spottable } from "@enact/spotlight/Spottable"; -import { sendSms } from "../../actions/appDataActions"; -import { setHidePopup } from "../../actions/commonActions"; +import { clearSMS, sendSms } from "../../actions/appDataActions"; +import { changeLocalSettings, setHidePopup } from "../../actions/commonActions"; import { getDeviceAdditionInfo, registerDeviceInfo, @@ -16,6 +17,7 @@ import { setEventIssueReq } from "../../actions/eventActions"; import { $L } from "../../utils/helperMethods"; import TButton from "../TButton/TButton"; import TPopUp from "../TPopUp/TPopUp"; +import HistoryPhoneNumber from "./HistoryPhoneNumber/HistoryPhoneNumber"; import css from "./MobileSendPopUp.module.less"; import SMSNumKeyPad from "./SMSNumKeyPad"; @@ -26,6 +28,8 @@ const instruction = $L(` By entering my mobile number, I agree to receive messages from LGE with information on how to purchase the product I selected. Message and data rates may apply. `); +const SpottableComponent = Spottable("div"); + export default function MobileSendPopUp({ open, onClose, @@ -48,10 +52,14 @@ export default function MobileSendPopUp({ const deviceInfo = useSelector((state) => state.device.deviceInfo); const [mobileNumber, setMobileNumber] = useState(""); const [recentSentNumber, setRecentSentNumber] = useState([]); - const [keyPadOff, setKeyPadOff] = useState(true); + const [keyPadOff, setKeyPadOff] = useState(false); + const [SMSRetCode, setSMSRetCode] = useState(); const { httpHeader } = useSelector((state) => state.common); - const info = useSelector((state) => state.common.appStatus); const sendSmsSuccess = useSelector((state) => state.appData.sendSms); + const smsRetCode = useSelector((state) => state.appData.sendSms?.retCode); + const { phoneNumberList } = useSelector( + (state) => state.localSettings.phoneNumbers + ); const deviceCountryCode = httpHeader["X-Device-Country"]; const dispatch = useDispatch(); @@ -63,6 +71,16 @@ export default function MobileSendPopUp({ } else return 10; }; + const handleClickSelect = (_phoneNumber) => { + setKeyPadOff((state) => !state); + setMobileNumber(_phoneNumber); + }; + + const handleInputClick = () => { + setKeyPadOff(false); + if (recentSentNumber) setMobileNumber(recentSentNumber[0]); + }; + const getRawPhoneNumber = useCallback( (key) => { let rawPhoneNumber = `${mobileNumber}${key}`.replace(/\D/g, ""); @@ -135,11 +153,16 @@ export default function MobileSendPopUp({ dispatch(getDeviceAdditionInfo()); }, [dispatch]); - // useEffect(() => { - // if (sendSmsSuccess?.retCode === 0) { - // console.log("#### 성공"); - // } - // }, [sendSmsSuccess]); + useEffect(() => { + if (phoneNumberList) setRecentSentNumber(phoneNumberList); + }, []); + + useEffect(() => { + if (recentSentNumber && recentSentNumber.length > 0) { + setKeyPadOff(true); + setMobileNumber(recentSentNumber[0]); + } else setKeyPadOff(false); + }, [recentSentNumber]); const numKeypadClicked = useCallback( (key) => { @@ -154,14 +177,66 @@ export default function MobileSendPopUp({ [deviceCountryCode, mobileNumber] ); + const handleDelete = (selectedIndex) => { + if (recentSentNumber) { + const updateItems = recentSentNumber.filter( + (_, index) => index !== selectedIndex + ); + setRecentSentNumber(updateItems); + dispatch( + changeLocalSettings({ + phoneNumbers: { + phoneNumberList: updateItems, + }, + }) + ); + } + }; + const handleAgreeSendClick = useCallback(() => { if (!mobileNumber) return; + let naturalNumber = mobileNumber.replace(/\D/g, ""); - // TODO(jw) : RUSIA Check - // if (deviceCountryCode === "RU") { - // naturalNumber = "7" + naturalNumber; - // } + if (deviceCountryCode === "KR") { + naturalNumber = "82" + naturalNumber; + } + + if (recentSentNumber && recentSentNumber.length > 0) { + const updatedNumbers = [...recentSentNumber]; + + const existingNumberIndex = updatedNumbers.findIndex( + (existingNum) => existingNum === mobileNumber + ); + if (existingNumberIndex !== -1) { + updatedNumbers.splice(existingNumberIndex, 1); + } + + if (updatedNumbers.length >= 5) { + updatedNumbers.pop(); + } + + updatedNumbers.unshift(mobileNumber); + + setRecentSentNumber(updatedNumbers); + + dispatch( + changeLocalSettings({ + phoneNumbers: { + phoneNumberList: updatedNumbers, + }, + }) + ); + } else { + setRecentSentNumber([mobileNumber]); + dispatch( + changeLocalSettings({ + phoneNumbers: { + phoneNumberList: [mobileNumber], + }, + }) + ); + } if (isCurationEvnt) { // EVT00102 CURATION EVENT : 원하는 페이지로 이동(앱 내 모든 페이지) 미완 @@ -205,57 +280,126 @@ export default function MobileSendPopUp({ mbphNo: naturalNumber, }) ); - // dispatch(setHidePopup()); } - }, [dispatch, mobileNumber, smsTpCd, evntTpCd]); + }, [dispatch, mobileNumber, smsTpCd, evntTpCd, sendSmsSuccess]); + + const _onClose = (e) => { + if (e.target) { + setSMSRetCode(undefined); + } + onClose(); + }; + + useEffect(() => { + setSMSRetCode(smsRetCode); + + if (smsRetCode === 0) { + setTimeout(() => { + dispatch(setHidePopup()); + }, 3000); + } + }, [smsRetCode]); + + useEffect(() => { + // smsRetCode initialize + return () => { + dispatch(clearSMS()); + }; + }, [dispatch]); return ( - -
- {productImg && ( -

- alt -

- )} -
+ {SMSRetCode === undefined && open && ( + - {title &&
{title}
} - {subTitle && ( +
+ {productImg && ( +

+ alt +

+ )}
- {subTitle} + {title &&
{title}
} + {subTitle && ( +
+ {subTitle} +
+ )} + {productPrice &&
{productPrice}
}
- )} - {productPrice &&
{productPrice}
} -
-
-
-
-
-
{mobileNumber}
-
-
-
-
-
- {$L("Agree and Send")} - {$L("Cancel")} -
- +
+
+
+ + {mobileNumber} + + {keyPadOff ? ( + + ) : ( + + )} +
+
+
+
+
+ + {$L("Agree and Send")} + + {$L("Cancel")} +
+ + )} + {SMSRetCode === 907 || + (SMSRetCode === 900 && ( + + ))} + {SMSRetCode === 0 && ( + + )} + ); } diff --git a/com.twin.app.shoptime/src/components/MobileSend/MobileSendPopUp.module.less b/com.twin.app.shoptime/src/components/MobileSend/MobileSendPopUp.module.less index e0d56855..4df4f316 100644 --- a/com.twin.app.shoptime/src/components/MobileSend/MobileSendPopUp.module.less +++ b/com.twin.app.shoptime/src/components/MobileSend/MobileSendPopUp.module.less @@ -79,6 +79,7 @@ .flex(@justifyCenter: space-between, @alignCenter: flex-start); .smsNumLayer { .inputNum { + position: relative; padding: 18px 5px 18px 20px; width: 437px; .border-solid(@size:1px,#cccccc); @@ -86,10 +87,11 @@ cursor: text; font-weight: normal; font-size: 28px; - &::after { - content: ""; - width: 2px; - height: 100%; + + &:focus { + &::after { + .focused(); + } } } min-width: 437px; diff --git a/com.twin.app.shoptime/src/reducers/appDataReducer.js b/com.twin.app.shoptime/src/reducers/appDataReducer.js index 63a8d04a..82bf1a85 100644 --- a/com.twin.app.shoptime/src/reducers/appDataReducer.js +++ b/com.twin.app.shoptime/src/reducers/appDataReducer.js @@ -2,6 +2,7 @@ import { types } from "../actions/actionTypes"; const initialState = { mainIndex: null, + sendSms: {}, }; export const appDataReducer = (state = initialState, action) => { @@ -10,9 +11,17 @@ export const appDataReducer = (state = initialState, action) => { return { ...state, mainIndex: action.payload, - retCode: action.retCode, }; - + case types.SEND_SMS: + return { + ...state, + sendSms: { retCode: action.retCode }, + }; + case types.CLEAR_SMS: + return { + ...state, + sendSms: { retCode: undefined }, + }; default: return state; } diff --git a/com.twin.app.shoptime/src/reducers/localSettingsReducer.js b/com.twin.app.shoptime/src/reducers/localSettingsReducer.js index ede96ed9..b83f6964 100644 --- a/com.twin.app.shoptime/src/reducers/localSettingsReducer.js +++ b/com.twin.app.shoptime/src/reducers/localSettingsReducer.js @@ -6,6 +6,7 @@ const initialLocalSettings = { serverType: Config.DEFAULT_SERVERTYPE, ricCodeSetting: Config.DEFAULT_RIC_CODE, accessToken: null, + phoneNumbers: {}, }; const updateInitialLocalSettings = () => {