[myPage] myInfo 데이터 추가

This commit is contained in:
hyunwoo93.cha
2024-03-04 22:35:15 +09:00
parent e341493292
commit 8dcbf72ed3
28 changed files with 717 additions and 129 deletions

View File

@@ -18,6 +18,7 @@
"axios": "^0.21.1", "axios": "^0.21.1",
"ilib": "^14.3.0", "ilib": "^14.3.0",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
"qrcode.react": "^3.1.0",
"react": "^16.7.0", "react": "^16.7.0",
"react-dom": "^16.7.0", "react-dom": "^16.7.0",
"react-redux": "^7.2.3", "react-redux": "^7.2.3",
@@ -443,6 +444,14 @@
"react-is": "^16.13.1" "react-is": "^16.13.1"
} }
}, },
"node_modules/qrcode.react": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz",
"integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/ramda": { "node_modules/ramda": {
"version": "0.24.1", "version": "0.24.1",
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz",
@@ -1012,6 +1021,12 @@
"react-is": "^16.13.1" "react-is": "^16.13.1"
} }
}, },
"qrcode.react": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz",
"integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==",
"requires": {}
},
"ramda": { "ramda": {
"version": "0.24.1", "version": "0.24.1",
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz",

View File

@@ -19,9 +19,15 @@ export const types = {
SET_EXIT_APP: "SET_EXIT_APP", SET_EXIT_APP: "SET_EXIT_APP",
GET_LOGIN_USER_DATA: "GET_LOGIN_USER_DATA", GET_LOGIN_USER_DATA: "GET_LOGIN_USER_DATA",
// billing actions
GET_MY_INFO_BILLING_SEARCH: "GET_MY_INFO_BILLING_SEARCH",
// card actions // card actions
GET_MY_INFO_CARD_SEARCH: "GET_MY_INFO_CARD_SEARCH", GET_MY_INFO_CARD_SEARCH: "GET_MY_INFO_CARD_SEARCH",
// shipping actions
GET_MY_INFO_SHIPPING_SEARCH: "GET_MY_INFO_SHIPPING_SEARCH",
// appData actions // appData actions
ADD_MAIN_INDEX: "ADD_MAIN_INDEX", ADD_MAIN_INDEX: "ADD_MAIN_INDEX",

View File

@@ -0,0 +1,32 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// IF-LGSP-328 : 회원 Billing Address 조회
export const getMyInfoBillingSearch = (props) => (dispatch, getState) => {
const { mbrNo } = props;
const onSuccess = (response) => {
console.log("getMyInfoBillingSearch onSuccess: ", response.data);
dispatch({
type: types.GET_MY_INFO_BILLING_SEARCH,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getMyInfoBillingSearch onFail: ", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_MY_INFO_BILLING_SEARCH,
{ mbrNo },
{},
onSuccess,
onFail
);
};

View File

@@ -0,0 +1,32 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { types } from "./actionTypes";
// IF-LGSP-324 회원 Shipping Address 조회
export const getMyInfoShippingSearch = (props) => (dispatch, getState) => {
const { mbrNo } = props;
const onSuccess = (response) => {
console.log("getmyInfoShippingSearch OnSuccess: ", response.data);
dispatch({
type: types.GET_MY_INFO_SHIPPING_SEARCH,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getmyInfoShippingSearch onFail: ", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_MY_INFO_SHIPPING_SEARCH,
{ mbrNo },
{},
onSuccess,
onFail
);
};

View File

@@ -11,9 +11,15 @@ export const URLS = {
REGISTER_DEVICE: "/lgsp/v1/device/register.lge", REGISTER_DEVICE: "/lgsp/v1/device/register.lge",
REGISTER_DEVICE_INFO: "/lgsp/v1/device/register/info.lge", REGISTER_DEVICE_INFO: "/lgsp/v1/device/register/info.lge",
// billing controller
GET_MY_INFO_BILLING_SEARCH: "/lgsp/v1/myinfo/address/billing/search.lge",
// card controller // card controller
GET_MY_INFO_CARD_SEARCH: "/lgsp/v1/myinfo/card/search.lge", GET_MY_INFO_CARD_SEARCH: "/lgsp/v1/myinfo/card/search.lge",
// shipping controller
GET_MY_INFO_SHIPPING_SEARCH: "/lgsp/v1/myinfo/address/shipping/search.lge",
//home controller //home controller
GET_HOME_TERMS: "/lgsp/v1/home/terms.lge", GET_HOME_TERMS: "/lgsp/v1/home/terms.lge",
GET_HOME_MENU: "/lgsp/v1/home/menu.lge", GET_HOME_MENU: "/lgsp/v1/home/menu.lge",

View File

@@ -108,13 +108,41 @@ export const getLoginUserData = (
} else { } else {
onSuccess({ onSuccess({
userId: "twin", userId: "twin",
userInfo: "US2401051532595", userInfo: "US2308020104782",
email: "twin@t-win.kr", email: "twin@t-win.kr",
returnValue: true, returnValue: true,
}); });
} }
}; };
export const logoutAccount = (
parameters,
{ onSuccess, onFailure, onComplete }
) => {
if (typeof window === "object" && window.PalmSystem) {
if (process.env.REACT_APP_MODE === "DEBUG") {
console.log("logoutAccount");
return "Mock Data";
} else {
return new LS2Request().send({
service: "luna://com.webos.service.accountmanager",
method: "logoutAccount",
parameters: parameters,
onSuccess,
onFailure,
onComplete,
});
}
} else {
onSuccess({
useId: null,
userInfo: null,
email: null,
returnValue: true,
});
}
};
export const launchMembershipApp = ({ onSuccess, onFailure, onComplete }) => { export const launchMembershipApp = ({ onSuccess, onFailure, onComplete }) => {
if (typeof window === "object" && window.PalmSystem) { if (typeof window === "object" && window.PalmSystem) {
if (process.env.REACT_APP_MODE === "DEBUG") { if (process.env.REACT_APP_MODE === "DEBUG") {

View File

@@ -67,7 +67,7 @@ export const getHttpHeaderForServiceRequest = ({
} else { } else {
onSuccess({ onSuccess({
HOST: "US.nextlgsdp.com", HOST: "US.nextlgsdp.com",
"X-User-Number": "US2401051532595", "X-User-Number": "US2308020104782",
Authorization: Authorization:
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuZXh0bGdzZHAuY29tIiwiYXVkIjoibmV4dGxnc2RwLmNvbSIsImlhdCI6MTcwNzc4NTUyNSwiZXhwIjoxNzA3NzkyNzI1LCJtYWNBZGRyZXNzIjoiZWVkMDQ2NjdiNjUzOWU3YmQxMDA1OTljYjBkYTI5ZjRjZTgyZGZlOGZkNzIzMDAxZGVmMjg4NWRkNWZiODRmNWNiMzZlM2QwNzYzNWZjZGJjYWNjNGVjMzI5NWIwNjZjOTMwNmNmNDI1ZGQzMmQ2MDMxMjc1NWNkOTIyNjEwMzcifQ.vqPdYGnN46diesDBLzA4UhACCJVdIycLs7wZu9M55Hc", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuZXh0bGdzZHAuY29tIiwiYXVkIjoibmV4dGxnc2RwLmNvbSIsImlhdCI6MTcwNzc4NTUyNSwiZXhwIjoxNzA3NzkyNzI1LCJtYWNBZGRyZXNzIjoiZWVkMDQ2NjdiNjUzOWU3YmQxMDA1OTljYjBkYTI5ZjRjZTgyZGZlOGZkNzIzMDAxZGVmMjg4NWRkNWZiODRmNWNiMzZlM2QwNzYzNWZjZGJjYWNjNGVjMzI5NWIwNjZjOTMwNmNmNDI1ZGQzMmQ2MDMxMjc1NWNkOTIyNjEwMzcifQ.vqPdYGnN46diesDBLzA4UhACCJVdIycLs7wZu9M55Hc",
"X-Authentication": "MkOLvUocrJ69RH/iV1ZABJhjR2g=", "X-Authentication": "MkOLvUocrJ69RH/iV1ZABJhjR2g=",

View File

@@ -0,0 +1,18 @@
import { types } from "../actions/actionTypes";
const initialState = {
billingData: null,
};
export const billingReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_MY_INFO_BILLING_SEARCH:
return {
...state,
billingData: action.payload,
};
default:
return state;
}
};

View File

@@ -0,0 +1,18 @@
import { types } from "../actions/actionTypes";
const initialState = {
shippingData: null,
};
export const shippingReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_MY_INFO_SHIPPING_SEARCH:
return {
...state,
shippingData: action.payload,
};
default:
return state;
}
};

View File

@@ -2,6 +2,7 @@ import { applyMiddleware, combineReducers, createStore } from "redux";
import thunk from "redux-thunk"; import thunk from "redux-thunk";
import { appDataReducer } from "../reducers/appDataReducer"; import { appDataReducer } from "../reducers/appDataReducer";
import { billingReducer } from "../reducers/billingReducer";
import { brandReducer } from "../reducers/brandReducer"; import { brandReducer } from "../reducers/brandReducer";
import { cardReducer } from "../reducers/cardReducer"; import { cardReducer } from "../reducers/cardReducer";
import { commonReducer } from "../reducers/commonReducer"; import { commonReducer } from "../reducers/commonReducer";
@@ -16,6 +17,7 @@ import { onSaleReducer } from "../reducers/onSaleReducer";
import { panelsReducer } from "../reducers/panelReducer"; import { panelsReducer } from "../reducers/panelReducer";
import { productReducer } from "../reducers/productReducer"; import { productReducer } from "../reducers/productReducer";
import { searchReducer } from "../reducers/searchReducer"; import { searchReducer } from "../reducers/searchReducer";
import { shippingReducer } from "../reducers/shippingReducer";
const rootReducer = combineReducers({ const rootReducer = combineReducers({
panels: panelsReducer, panels: panelsReducer,
@@ -33,6 +35,8 @@ const rootReducer = combineReducers({
event: eventReducer, event: eventReducer,
coupon: couponReducer, coupon: couponReducer,
card: cardReducer, card: cardReducer,
billing: billingReducer,
shipping: shippingReducer,
}); });
export const store = createStore(rootReducer, applyMiddleware(thunk)); export const store = createStore(rootReducer, applyMiddleware(thunk));

View File

@@ -50,6 +50,7 @@
@BG_COLOR_02: #f2f2f2; @BG_COLOR_02: #f2f2f2;
@BG_COLOR_03: #f2f6fb; @BG_COLOR_03: #f2f6fb;
@BG_COLOR_04: #f5f5f5; @BG_COLOR_04: #f5f5f5;
@BG_COLOR_05: #fcfcfc;
/* MAIN COLOR */ /* MAIN COLOR */
@PRIMARY_COLOR_RED: #c70850; @PRIMARY_COLOR_RED: #c70850;
@@ -66,6 +67,7 @@
@COLOR_GRAY07: #222222; @COLOR_GRAY07: #222222;
@COLOR_GRAY08: #1a1a1a; @COLOR_GRAY08: #1a1a1a;
@COLOR_GRAY09: #999999; @COLOR_GRAY09: #999999;
@COLOR_GRAY10: #a3a3a3;
@COLOR_BLACK: #000000; @COLOR_BLACK: #000000;
@COLOR_NAVY: #2c343f; @COLOR_NAVY: #2c343f;

View File

@@ -45,6 +45,7 @@ export const ACTIVE_POPUP = {
couponPopup: "couponPopup", couponPopup: "couponPopup",
favoritePopup: "favoritePopup", favoritePopup: "favoritePopup",
loginPopup: "loginPopup", loginPopup: "loginPopup",
logoutPopup: "logoutPopup",
}; };
export const AUTO_SCROLL_DELAY = 600; export const AUTO_SCROLL_DELAY = 600;

View File

@@ -7,11 +7,17 @@ import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDeco
import ic_profile from "../../../../../assets/images/icons/ic-profile.svg"; import ic_profile from "../../../../../assets/images/icons/ic-profile.svg";
import myinfo_login from "../../../../../assets/images/img-banner-myinfo-login@3x.png"; import myinfo_login from "../../../../../assets/images/img-banner-myinfo-login@3x.png";
import { getMyInfoBillingSearch } from "../../../../actions/billingActions";
import { getMyInfoCardSearch } from "../../../../actions/cardActions"; import { getMyInfoCardSearch } from "../../../../actions/cardActions";
import { setHidePopup, setShowPopup } from "../../../../actions/commonActions";
import { getProductCouponInfo } from "../../../../actions/couponActions";
import { getMyInfoShippingSearch } from "../../../../actions/shippingActions";
import TButton, { SIZES, TYPES } from "../../../../components/TButton/TButton"; import TButton, { SIZES, TYPES } from "../../../../components/TButton/TButton";
import TButtonTab, { import TButtonTab, {
LIST_TYPE, LIST_TYPE,
} from "../../../../components/TButtonTab/TButtonTab"; } from "../../../../components/TButtonTab/TButtonTab";
import TPopUp from "../../../../components/TPopUp/TPopUp";
import * as Config from "../../../../utils/Config";
import { $L } from "../../../../utils/helperMethods"; import { $L } from "../../../../utils/helperMethods";
import css from "../MyInfo/MyInfo.module.less"; import css from "../MyInfo/MyInfo.module.less";
import BillingAddressTab from "./MyInfoTabContents/BillingAddressTab/BillingAddressTab"; import BillingAddressTab from "./MyInfoTabContents/BillingAddressTab/BillingAddressTab";
@@ -52,6 +58,9 @@ export default function MyInfo() {
const { userId, userInfo, email } = useSelector( const { userId, userInfo, email } = useSelector(
(state) => state.common.appStatus.loginUserData (state) => state.common.appStatus.loginUserData
); );
const { popupVisible, activePopup } = useSelector(
(state) => state.common.popup
);
const [tab, setTab] = useState(0); const [tab, setTab] = useState(0);
@@ -69,7 +78,12 @@ export default function MyInfo() {
useEffect(() => { useEffect(() => {
setTab(0); setTab(0);
dispatch(getMyInfoCardSearch(userInfo)); if (userInfo) {
dispatch(getMyInfoCardSearch({ mbrNo: userInfo }));
dispatch(getMyInfoBillingSearch({ mbrNo: userInfo }));
dispatch(getMyInfoShippingSearch({ mbrNo: userInfo }));
dispatch(getProductCouponInfo({ mbrNo: userInfo }));
}
}, [userInfo, dispatch]); }, [userInfo, dispatch]);
const handleItemClick = useCallback( const handleItemClick = useCallback(
@@ -99,7 +113,20 @@ export default function MyInfo() {
}; };
}, []); }, []);
const handleLogoutButtonClick = useCallback(() => {
dispatch(setShowPopup(Config.ACTIVE_POPUP.logoutPopup));
}, [dispatch]);
const handleCancel = useCallback(() => {
dispatch(setHidePopup());
}, [dispatch]);
useEffect(() => {
Spotlight.focus();
}, [popupVisible]);
return ( return (
<>
<Container className={css.myInfoContainer}> <Container className={css.myInfoContainer}>
<div className={css.contentsBox}> <div className={css.contentsBox}>
<div className={css.infoBox}> <div className={css.infoBox}>
@@ -119,7 +146,11 @@ export default function MyInfo() {
<div className={css.email}>{userInfo ? email : "-"}</div> <div className={css.email}>{userInfo ? email : "-"}</div>
</div> </div>
{userInfo ? ( {userInfo ? (
<TButton type={TYPES.normal} className={css.logoutButton}> <TButton
type={TYPES.normal}
className={css.logoutButton}
onClick={handleLogoutButtonClick}
>
{$L("LOG OUT")} {$L("LOG OUT")}
</TButton> </TButton>
) : ( ) : (
@@ -157,5 +188,20 @@ export default function MyInfo() {
)} )}
</div> </div>
</Container> </Container>
{/* logout */}
{activePopup === Config.ACTIVE_POPUP.logoutPopup && (
<TPopUp
kind="textPopup"
open={popupVisible}
hasButton
button1Text={$L("OK")}
button2Text={$L("Cancel")}
hasText
text={$L("Do you want to logout?")}
onClose={handleCancel}
/>
)}
</>
); );
} }

View File

@@ -0,0 +1,43 @@
import React, { memo } from "react";
import Spottable from "@enact/spotlight/Spottable";
import css from "./BillingAddressItem.module.less";
const ItemContainer = Spottable("div");
export default memo(function BillingAddressItem({
bilOdrFnm,
bilOdrLnm,
bilZpcd,
bilStatNm,
bilCityNm,
bilDtlAddr,
bilCtpt,
bilEmalAddr,
}) {
return (
<ItemContainer className={css.itemContainer}>
<h2 className={css.title}>
{bilOdrFnm} {bilOdrLnm}
</h2>
<div className={css.addressWrap}>
<p>
{bilZpcd} {bilStatNm}, <br />
{bilCityNm} <br />
{bilDtlAddr}
</p>
</div>
<div className={css.cardFooter}>
<p className={css.callNumber}>
<span />
{bilCtpt.replace(/^(\d{2,3})(\d{3,4})(\d{4})$/, `$1-$2-$3`)}
</p>
<p className={css.email}>
<span />
{bilEmalAddr}
</p>
</div>
</ItemContainer>
);
});

View File

@@ -0,0 +1,63 @@
@import "../../../../../../style/CommonStyle.module.less";
@import "../../../../../../style/utils.module.less";
.itemContainer {
.size(@w: 444px, @h: 348px);
background-color: @BG_COLOR_05;
border-radius: 12px;
padding: 32px 30px;
position: relative;
.title {
color: @COLOR_GRAY06;
.font(@fontFamily: @baseFontBold, @fontSize: 36px);
margin-bottom: 19px;
}
.addressWrap {
color: @COLOR_GRAY03;
line-height: 1.33;
margin-bottom: 37px;
font-size: 24px;
}
.cardFooter {
.font(@fontFamily: @baseFontBold, @fontSize: 24px);
color: @COLOR_GRAY03;
.callNumber {
padding-left: 42px;
margin-bottom: 6px;
> span {
background-image: url("../../../../../../../assets/images/icons/ic-gr-call.svg");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
.size(@w: 36px, @h: 36px);
position: absolute;
left: 30px;
}
}
.email {
padding-left: 42px;
> span {
background-image: url("../../../../../../../assets/images/icons/ic-gr-mail-36.svg");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
.size(@w: 36px, @h: 36px);
position: absolute;
left: 30px;
}
}
}
&:focus {
&::after {
.focused(@boxShadow: 22px, @borderRadius: 12px);
}
}
}

View File

@@ -1,9 +1,80 @@
import React from "react"; import React, { useCallback } from "react";
import { useSelector } from "react-redux";
import TVirtualGridList from "../../../../../../components/TVirtualGridList/TVirtualGridList";
import useScrollTo from "../../../../../../hooks/useScrollTo";
import MyInfoNoResults from "../MyInfoNoResults/MyInfoNoResults";
import MyInfoTabContentsContainer from "../MyInfoTabContentsContainer"; import MyInfoTabContentsContainer from "../MyInfoTabContentsContainer";
import BillingAddressItem from "./BillingAddressItem";
import css from "./BillingAddressTab.module.less";
export const ITEM_SIZE = {
itemWidth: 444,
itemHeight: 348,
spacing: 18,
};
export default function BillingAddressTab() { export default function BillingAddressTab() {
const billingDatas = useSelector((state) => state.billing.billingData);
const { billingInfo } = billingDatas || {};
const { getScrollTo, scrollLeft } = useScrollTo();
const renderItem = useCallback(
({ index, ...rest }) => {
const {
bilAddrSno,
bilCityNm,
bilCtpt,
bilDtlAddr,
bilEmalAddr,
bilOdrFnm,
bilOdrLnm,
bilStatNm,
bilStatPvc,
bilZpcd,
chgDt,
cntryCd,
cntryNm,
mbrNo,
regDt,
useFlag,
} = billingInfo[index];
return ( return (
<MyInfoTabContentsContainer>BillingAddressTab</MyInfoTabContentsContainer> <BillingAddressItem
key={index}
bilOdrFnm={bilOdrFnm}
bilOdrLnm={bilOdrLnm}
bilZpcd={bilZpcd}
bilStatNm={bilStatNm}
bilCityNm={bilCityNm}
bilDtlAddr={bilDtlAddr}
bilCtpt={bilCtpt}
bilEmalAddr={bilEmalAddr}
/>
);
},
[billingInfo]
);
return (
<MyInfoTabContentsContainer>
{billingDatas && billingInfo && billingInfo.length > 0 ? (
<TVirtualGridList
cbScrollTo={getScrollTo}
className={css.grid}
dataSize={billingInfo.length}
renderItem={renderItem}
direction="horizontal"
itemWidth={ITEM_SIZE.itemWidth}
itemHeight={ITEM_SIZE.itemHeight}
spacing={ITEM_SIZE.spacing}
/>
) : (
<MyInfoNoResults type="BILLING ADDRESS" />
)}
</MyInfoTabContentsContainer>
); );
} }

View File

@@ -1,7 +1,13 @@
import React from "react"; import React from "react";
import { useSelector } from "react-redux";
import MyInfoTabContentsContainer from "../MyInfoTabContentsContainer"; import MyInfoTabContentsContainer from "../MyInfoTabContentsContainer";
export default function CouponTab() { export default function CouponTab() {
const couponDatas = useSelector(
(state) => state.coupon.productCouponInfoData
);
return <MyInfoTabContentsContainer>Coupon</MyInfoTabContentsContainer>; return <MyInfoTabContentsContainer>Coupon</MyInfoTabContentsContainer>;
} }

View File

@@ -0,0 +1,26 @@
import React from "react";
import NoResultsImgBilling from "../../../../../../../assets/images/img-my-info-billing@3x.png";
import NoResultsImgCoupon from "../../../../../../../assets/images/img-myinfo-coupon@3x.png";
import NoResultsImgPayment from "../../../../../../../assets/images/img-myinfo-payment@3x.png";
import NoResultsImgShipping from "../../../../../../../assets/images/img-myinfo-shipping@3x.png";
import { $L } from "../../../../../../utils/helperMethods";
import css from "./MyInfoNoResults.module.less";
const NO_RESULTS_IMAGE = {
PAYMENT: NoResultsImgPayment,
"BILLING ADDRESS": NoResultsImgBilling,
"SHIPPING ADDRESS": NoResultsImgShipping,
COUPON: NoResultsImgCoupon,
};
export default function MyInfoNoResults({ type }) {
return (
<div className={css.container}>
<img src={NO_RESULTS_IMAGE[type]} alt="No Results" />
<p>
{$L("There is No Registered")} {$L(type)}
</p>
</div>
);
}

View File

@@ -0,0 +1,20 @@
@import "../../../../../../style/CommonStyle.module.less";
@import "../../../../../../style/utils.module.less";
.container {
.size(@w: 100%, @h: 390px);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
> img {
.size(@w: 360px, @h: 180px);
}
> p {
.font(@fontFamily: @baseFontBold, @fontSize: 36px);
margin-top: 10px;
color: @COLOR_GRAY10;
}
}

View File

@@ -1,5 +1,7 @@
import React from "react"; import React from "react";
import classNames from "classnames";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import css from "./MyInfoTabContentsContainer.module.less"; import css from "./MyInfoTabContentsContainer.module.less";
@@ -10,5 +12,7 @@ const Container = SpotlightContainerDecorator(
); );
export default function MyInfoTabContentsContainer({ children }) { export default function MyInfoTabContentsContainer({ children }) {
return <Container className={css.container}>{children}</Container>; return (
<Container className={classNames(css.container)}>{children}</Container>
);
} }

View File

@@ -1,48 +1,22 @@
import React, { useCallback } from "react"; import React, { memo } from "react";
import { useDispatch, useSelector } from "react-redux"; import Spottable from "@enact/spotlight/Spottable";
import {
alertToast,
changeAppStatus,
} from "../../../../../../actions/commonActions";
import TButton, {
SIZES,
TYPES,
} from "../../../../../../components/TButton/TButton";
import TToast from "../../../../../../components/TToast/TToast";
import { $L } from "../../../../../../utils/helperMethods";
import css from "./PaymentItem.module.less"; import css from "./PaymentItem.module.less";
export default function PaymentItem({ easyPmtSeq, cardKnd, cardNo }) { const CardItem = Spottable("div");
const dispatch = useDispatch();
export default memo(function PaymentItem({ easyPmtSeq, cardKnd, cardNo }) {
const getFormattingCardNo = (cardNumber) => { const getFormattingCardNo = (cardNumber) => {
return `${"*".repeat(12)}${cardNumber.slice(-4)}` return `${"*".repeat(12)}${cardNumber.slice(-4)}`
.replace(/(.{4})/g, "$1-") .replace(/(.{4})/g, "$1-")
.slice(0, -1); .slice(0, -1);
}; };
const handleClick = useCallback(() => {
dispatch(alertToast($L("Deleted a Payment Method")));
}, [dispatch]);
return ( return (
<> <CardItem className={css.card}>
<div className={css.itemContainer}>
<div className={css.card}>
<h2 className={css.cardKnd}>{cardKnd.toUpperCase()}</h2> <h2 className={css.cardKnd}>{cardKnd.toUpperCase()}</h2>
<p className={css.cardNo}>{getFormattingCardNo(cardNo)}</p> <p className={css.cardNo}>{getFormattingCardNo(cardNo)}</p>
</div> </CardItem>
<TButton
type={TYPES.mypage}
size={SIZES.small}
className={css.deleteBtn}
onClick={handleClick}
>
{$L("DELETE")}
</TButton>
</div>
</>
); );
} });

View File

@@ -1,11 +1,8 @@
@import "../../../../../../style/CommonStyle.module.less"; @import "../../../../../../style/CommonStyle.module.less";
@import "../../../../../../style/utils.module.less"; @import "../../../../../../style/utils.module.less";
.itemContainer {
.size(@w: 402px, @h: 354px);
.card { .card {
.size(@w: 100%, @h: 270px); .size(@w: 402px, @h: 270px);
background-image: url("../../../../../../../assets/images/mypagepanel/img-card-bg.png"); background-image: url("../../../../../../../assets/images/mypagepanel/img-card-bg.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
@@ -14,6 +11,8 @@
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
color: @COLOR_WHITE; color: @COLOR_WHITE;
border-radius: 12px;
position: relative;
.cardKnd { .cardKnd {
.font(@fontFamily: @baseFontBold, @fontSize: 36px); .font(@fontFamily: @baseFontBold, @fontSize: 36px);
@@ -22,11 +21,10 @@
.cardNo { .cardNo {
font-size: 24px; font-size: 24px;
} }
}
.deleteBtn { &:focus {
margin: 12px auto 0; &::after {
.size(@w: 138px, @h: 60px); .focused(@boxShadow: 22px, @borderRadius: 12px);
font-size: 24px; }
} }
} }

View File

@@ -2,30 +2,23 @@ import React from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import MyInfoNoResults from "../MyInfoNoResults/MyInfoNoResults";
import MyInfoTabContentsContainer from "../MyInfoTabContentsContainer"; import MyInfoTabContentsContainer from "../MyInfoTabContentsContainer";
import PaymentItem from "./PaymentItem"; import PaymentItem from "./PaymentItem";
const mockData = {
easyPmtSeq: "202306290001561",
cardKnd: "Visa",
cardNo: "4111111111111234",
};
export default function PaymentTab() { export default function PaymentTab() {
const cardDatas = useSelector((state) => state.card.cardData); const cardDatas = useSelector((state) => state.card.cardData);
const { easyPmtSeq, cardKnd, cardNo } = mockData;
return ( return (
<MyInfoTabContentsContainer> <MyInfoTabContentsContainer>
{mockData ? ( {cardDatas ? (
<PaymentItem <PaymentItem
easyPmtSeq={easyPmtSeq} easyPmtSeq={cardDatas.cardInfo.easyPmtSeq}
cardKnd={cardKnd} cardKnd={cardDatas.cardInfo.cardKnd}
cardNo={cardNo} cardNo={cardDatas.cardInfo.cardNo}
/> />
) : ( ) : (
<p>no card</p> <MyInfoNoResults type="PAYMENT" />
)} )}
</MyInfoTabContentsContainer> </MyInfoTabContentsContainer>
); );

View File

@@ -0,0 +1,43 @@
import React, { memo } from "react";
import Spottable from "@enact/spotlight/Spottable";
import css from "./ShippingAddressItem.module.less";
const ItemContainer = Spottable("div");
export default memo(function ShippingAddressItem({
dlvrOdrFnm,
dlvrOdrLnm,
dlvrZpcd,
dlvrStatNm,
dlvrCityNm,
dlvrDtlAddr,
dlvrCtpt,
dlvrEmalAddr,
}) {
return (
<ItemContainer className={css.itemContainer}>
<h2 className={css.title}>
{dlvrOdrFnm} {dlvrOdrLnm}
</h2>
<div className={css.addressWrap}>
<p>
{dlvrZpcd} {dlvrStatNm}, <br />
{dlvrCityNm} <br />
{dlvrDtlAddr}
</p>
</div>
<div className={css.cardFooter}>
<p className={css.callNumber}>
<span />
{dlvrCtpt.replace(/^(\d{2,3})(\d{3,4})(\d{4})$/, `$1-$2-$3`)}
</p>
<p className={css.email}>
<span />
{dlvrEmalAddr}
</p>
</div>
</ItemContainer>
);
});

View File

@@ -0,0 +1,63 @@
@import "../../../../../../style/CommonStyle.module.less";
@import "../../../../../../style/utils.module.less";
.itemContainer {
.size(@w: 444px, @h: 348px);
background-color: @BG_COLOR_05;
border-radius: 12px;
padding: 32px 30px;
position: relative;
.title {
color: @COLOR_GRAY06;
.font(@fontFamily: @baseFontBold, @fontSize: 36px);
margin-bottom: 19px;
}
.addressWrap {
color: @COLOR_GRAY03;
line-height: 1.33;
margin-bottom: 37px;
font-size: 24px;
}
.cardFooter {
.font(@fontFamily: @baseFontBold, @fontSize: 24px);
color: @COLOR_GRAY03;
.callNumber {
padding-left: 42px;
margin-bottom: 6px;
> span {
background-image: url("../../../../../../../assets/images/icons/ic-gr-call.svg");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
.size(@w: 36px, @h: 36px);
position: absolute;
left: 30px;
}
}
.email {
padding-left: 42px;
> span {
background-image: url("../../../../../../../assets/images/icons/ic-gr-mail-36.svg");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
.size(@w: 36px, @h: 36px);
position: absolute;
left: 30px;
}
}
}
&:focus {
&::after {
.focused(@boxShadow: 22px, @borderRadius: 12px);
}
}
}

View File

@@ -1,9 +1,75 @@
import React from "react"; import React, { useCallback } from "react";
import { useSelector } from "react-redux";
import TVirtualGridList from "../../../../../../components/TVirtualGridList/TVirtualGridList";
import useScrollTo from "../../../../../../hooks/useScrollTo";
import { ITEM_SIZE } from "../BillingAddressTab/BillingAddressTab";
import MyInfoNoResults from "../MyInfoNoResults/MyInfoNoResults";
import MyInfoTabContentsContainer from "../MyInfoTabContentsContainer"; import MyInfoTabContentsContainer from "../MyInfoTabContentsContainer";
import ShippingAddressItem from "./ShippingAddressItem";
import css from "./ShippingAddressTab.module.less";
export default function ShippingAddressTab() { export default function ShippingAddressTab() {
const shippingDatas = useSelector((state) => state.shipping.shippingData);
const { dlvrInfo } = shippingDatas || {};
const { getScrollTo, scrollLeft } = useScrollTo();
const renderItem = useCallback(
({ index, ...rest }) => {
const {
chgDt,
cntryCd,
cntryNm,
dlvrAddSno,
dlvrCityNm,
dlvrCtpt,
dlvrDtlAddr,
dlvrEmalAddr,
dlvrOdrFnm,
dlvrOdrLnm,
dlvrStatNm,
dlvrStatPvc,
dlvrZpcd,
mbrNo,
regDt,
useFlag,
} = dlvrInfo[index];
return ( return (
<MyInfoTabContentsContainer>Shipping Address</MyInfoTabContentsContainer> <ShippingAddressItem
key={index}
dlvrOdrFnm={dlvrOdrFnm}
dlvrOdrLnm={dlvrOdrLnm}
dlvrZpcd={dlvrZpcd}
dlvrStatNm={dlvrStatNm}
dlvrCityNm={dlvrCityNm}
dlvrDtlAddr={dlvrDtlAddr}
dlvrCtpt={dlvrCtpt}
dlvrEmalAddr={dlvrEmalAddr}
/>
);
},
[shippingDatas]
);
return (
<MyInfoTabContentsContainer>
{shippingDatas && dlvrInfo && dlvrInfo.length > 0 ? (
<TVirtualGridList
cbScrollTo={getScrollTo}
className={css.grid}
dataSize={dlvrInfo.length}
renderItem={renderItem}
direction="horizontal"
itemWidth={ITEM_SIZE.itemWidth}
itemHeight={ITEM_SIZE.itemHeight}
spacing={ITEM_SIZE.spacing}
/>
) : (
<MyInfoNoResults type="SHIPPING ADDRESS" />
)}
</MyInfoTabContentsContainer>
); );
} }