[MobileSendPopUp]

- google-libphonenumber 라이브러리 추가
- 국가별 포맷팅,maxNum 적용
This commit is contained in:
jiwon93.son
2024-05-07 14:18:13 +09:00
parent 0ab9109833
commit 78a291900f
2 changed files with 105 additions and 36 deletions

View File

@@ -40,6 +40,7 @@
"@enact/ui": "^3.3.0", "@enact/ui": "^3.3.0",
"@enact/webos": "^3.3.0", "@enact/webos": "^3.3.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"google-libphonenumber": "^3.2.34",
"ilib": "^14.3.0", "ilib": "^14.3.0",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
"qrcode": "^1.5.3", "qrcode": "^1.5.3",

View File

@@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { PhoneNumberFormat, PhoneNumberUtil } from "google-libphonenumber";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { off, on } from "@enact/core/dispatcher"; import { off, on } from "@enact/core/dispatcher";
@@ -18,7 +19,6 @@ import TPopUp from "../TPopUp/TPopUp";
import css from "./MobileSendPopUp.module.less"; import css from "./MobileSendPopUp.module.less";
import SMSNumKeyPad from "./SMSNumKeyPad"; import SMSNumKeyPad from "./SMSNumKeyPad";
const MAX_NUMBER = 10;
const instruction = $L(` const instruction = $L(`
<span>By clicking "Agree and Send" button below, I agree that LGE may collect and store my mobile number to send text messages as I requested, for data analysis, and for feature-enhancement purposes. </span> <span>By clicking "Agree and Send" button below, I agree that LGE may collect and store my mobile number to send text messages as I requested, for data analysis, and for feature-enhancement purposes. </span>
<br/> <br/>
@@ -47,31 +47,83 @@ export default function MobileSendPopUp({
}) { }) {
const deviceInfo = useSelector((state) => state.device.deviceInfo); const deviceInfo = useSelector((state) => state.device.deviceInfo);
const [mobileNumber, setMobileNumber] = useState(""); const [mobileNumber, setMobileNumber] = useState("");
const [viewNumber, setViewNumber] = useState(""); const [recentSentNumber, setRecentSentNumber] = useState([]);
const [keyPadOff, setKeyPadOff] = useState(true);
const { httpHeader } = useSelector((state) => state.common);
const info = useSelector((state) => state.common.appStatus);
const sendSmsSuccess = useSelector((state) => state.appData.sendSms);
const deviceCountryCode = httpHeader["X-Device-Country"];
const dispatch = useDispatch(); const dispatch = useDispatch();
const handleKeydown = useCallback((ev) => { const getMaxNum = (_deviceCountryCode) => {
if (ev && ev.key >= 0 && ev.key <= 9) { if (_deviceCountryCode === "DE" || _deviceCountryCode === "GB") {
setMobileNumber((num) => (num.length >= MAX_NUMBER ? num : num + ev.key)); return 11;
} else if (ev.key === "Backspace") { } else if (_deviceCountryCode === "KR") {
setMobileNumber((num) => num.slice(0, -1)); return 12;
} else return 10;
};
const getRawPhoneNumber = useCallback(
(key) => {
let rawPhoneNumber = `${mobileNumber}${key}`.replace(/\D/g, "");
if (rawPhoneNumber.length > getMaxNum(deviceCountryCode)) {
return;
} }
}, []); const phoneUtil = PhoneNumberUtil.getInstance();
useEffect(() => {
if (mobileNumber.length === 10) { try {
setViewNumber( let numberProto = phoneUtil.parse(rawPhoneNumber, deviceCountryCode);
mobileNumber.replace(/^(\d{3})(\d{3})(\d{4})$/, `($1) $2-$3`) if (
phoneUtil.isValidNumber(numberProto) &&
phoneUtil.isValidNumberForRegion(numberProto, deviceCountryCode)
) {
rawPhoneNumber = phoneUtil.format(
numberProto,
PhoneNumberFormat.NATIONAL
); );
} else {
setViewNumber(mobileNumber);
} }
}, [mobileNumber]); } catch (e) {
useEffect(() => { rawPhoneNumber = `${mobileNumber}${key}`;
if (!open) { } finally {
setMobileNumber(""); setMobileNumber(rawPhoneNumber);
} }
}, [open]); },
[mobileNumber, deviceCountryCode]
);
const getBackspaceRawNumber = useCallback(() => {
let rawPhoneNumber = mobileNumber.replace(/\D/g, "").slice(0, -1);
const phoneUtil = PhoneNumberUtil.getInstance();
try {
let numberProto = phoneUtil.parse(rawPhoneNumber, deviceCountryCode);
if (
phoneUtil.isValidNumber(numberProto) &&
phoneUtil.isValidNumberForRegion(numberProto, deviceCountryCode)
) {
rawPhoneNumber = phoneUtil.format(
numberProto,
PhoneNumberFormat.NATIONAL
);
}
} catch (e) {
rawPhoneNumber = mobileNumber.slice(0, -1);
} finally {
setMobileNumber(rawPhoneNumber);
}
}, [mobileNumber, deviceCountryCode]);
const handleKeydown = useCallback(
(ev) => {
if (ev && ev.key >= 0 && ev.key <= 9) {
getRawPhoneNumber(ev.key);
} else if (ev.key === "Backspace") {
getBackspaceRawNumber();
}
},
[mobileNumber]
);
useEffect(() => { useEffect(() => {
on("keydown", handleKeydown); on("keydown", handleKeydown);
return () => { return () => {
@@ -83,38 +135,52 @@ export default function MobileSendPopUp({
dispatch(getDeviceAdditionInfo()); dispatch(getDeviceAdditionInfo());
}, [dispatch]); }, [dispatch]);
// useEffect(() => {
// if (sendSmsSuccess?.retCode === 0) {
// console.log("#### 성공");
// }
// }, [sendSmsSuccess]);
const numKeypadClicked = useCallback( const numKeypadClicked = useCallback(
(key) => { (key) => {
if (key === "clear") { if (key === "clear") {
setMobileNumber(""); setMobileNumber("");
} else if (key == "backspace") { } else if (key == "backspace") {
setMobileNumber((num) => num.slice(0, -1)); getBackspaceRawNumber();
} else } else {
setMobileNumber((num) => (num.length >= MAX_NUMBER ? num : num + key)); getRawPhoneNumber(key);
}
}, },
[mobileNumber] [deviceCountryCode, mobileNumber]
); );
const handleAgreeSendClick = useCallback(() => { const handleAgreeSendClick = useCallback(() => {
// EVT00101 & APP00207(welcome) EVT00103 & APP00209 (welcome+Prizes) : smsTpCd 값을 받지 않음
if (!mobileNumber) return; if (!mobileNumber) return;
let naturalNumber = mobileNumber.replace(/\D/g, "");
// TODO(jw) : RUSIA Check
// if (deviceCountryCode === "RU") {
// naturalNumber = "7" + naturalNumber;
// }
if (isCurationEvnt) { if (isCurationEvnt) {
// EVT00102 CURATION EVENT : 원하는 페이지로 이동(앱 내 모든 페이지) 미완 // EVT00102 CURATION EVENT : 원하는 페이지로 이동(앱 내 모든 페이지) 미완
dispatch( dispatch(
setEventIssueReq({ setEventIssueReq({
evntTpCd,
evntId, evntId,
mbphNo: mobileNumber, mbphNo: naturalNumber,
}) })
); );
} }
if (deviceInfo && smsTpCd) { if (deviceInfo && smsTpCd) {
let params = { let params = {
dvcIndex: deviceInfo.dvcIndex, dvcIndex: deviceInfo.dvcIndex,
mbphNo: mobileNumber, mbphNo: naturalNumber,
smsTpCd, smsTpCd,
patnrId, patnrId,
evntId, evntId,
curationId,
smsText, smsText,
prdtId, prdtId,
}; };
@@ -123,23 +189,25 @@ export default function MobileSendPopUp({
if (smsTpCd === "APP00205") { if (smsTpCd === "APP00205") {
params = { ...params, hotelId, hotelNm, hotelDtlUrl, curationId }; params = { ...params, hotelId, hotelNm, hotelDtlUrl, curationId };
} }
if (smsTpCd === "APP00204" || smsTpCd === "APP00211") { if (smsTpCd === "APP00204") {
params = { ...params, curationId }; params = { ...params, curationId };
} }
dispatch(sendSms(params)); dispatch(sendSms(params));
} else { }
// EVT00101 & APP00207(welcome) EVT00103 & APP00209 (welcome+Prizes) : smsTpCd 값을 받지 않음
if (evntTpCd === "EVT00101" || evntTpCd === "EVT00103") {
dispatch( dispatch(
registerDeviceInfo({ registerDeviceInfo({
evntTpCd, evntTpCd,
evntId, evntId,
evntApplcnFlag: "Y", evntApplcnFlag: "Y",
entryMenu: "TermsPop", entryMenu: "TermsPop",
mbphNo: mobileNumber, mbphNo: naturalNumber,
}) })
); );
dispatch(setHidePopup()); // dispatch(setHidePopup());
} }
}, [dispatch, mobileNumber, smsTpCd]); }, [dispatch, mobileNumber, smsTpCd, evntTpCd]);
return ( return (
<TPopUp <TPopUp
@@ -175,7 +243,7 @@ export default function MobileSendPopUp({
<div className={css.smsArea}> <div className={css.smsArea}>
<div className={css.smsContainer}> <div className={css.smsContainer}>
<div className={css.smsNumLayer}> <div className={css.smsNumLayer}>
<div className={css.inputNum}>{viewNumber}</div> <div className={css.inputNum}>{mobileNumber}</div>
<SMSNumKeyPad onKeyDown={numKeypadClicked} /> <SMSNumKeyPad onKeyDown={numKeypadClicked} />
</div> </div>
</div> </div>