[JustForYou] 저스트 포유 테스트

1. Config 파일에 저스트포유테스트 추가.
	2. THeaderCustom부분에 kind 추가하여 없을경우 로고 나오지 않도록 처리.
	3. 저스트 포유배너에서 링크 테스트로 갈수있도록 변경.
	4. 테스트 파일 추가. Jsx,less파일

Etc) 서브카테고리에 들어있는 console 제거.
This commit is contained in:
junghoon86.park
2025-09-16 13:33:29 +09:00
parent 584d17a784
commit 1ae19abbea
8 changed files with 387 additions and 22 deletions

View File

@@ -32,6 +32,7 @@ export const panel_names = {
SERVICE_UNAVAILABLE: "servicepanel",
OPTIONAL_TERMS_PANEL: "optionaltermspanel", // 선택약관 Intro Panel
JUST_FOR_YOU_PANEL: "justforyoupanel", //justforyou
JUST_FOR_YOU_TEST_PANEL: "justforyoutestpanel", //justforyoutest
// error
ERROR_PANEL: "errorpanel",

View File

@@ -1,15 +1,20 @@
import React, { useCallback, useMemo } from "react";
import React, {
useCallback,
useMemo,
} from 'react';
import classNames from "classnames";
import classNames from 'classnames';
import { Marquee } from "@enact/sandstone/Marquee";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import { Marquee } from '@enact/sandstone/Marquee';
import SpotlightContainerDecorator
from '@enact/spotlight/SpotlightContainerDecorator';
import Spottable from '@enact/spotlight/Spottable';
import { $L } from "../../../utils/helperMethods";
import defaultLogoImg from "../../../../assets/images/ic-tab-partners-default@3x.png";
import qvcLogoImg from "../../../../assets/images/icons/ic-partners-qvc@3x.png";
import css from "./THeaderCustom.module.less";
import defaultLogoImg
from '../../../../assets/images/ic-tab-partners-default@3x.png';
import qvcLogoImg from '../../../../assets/images/icons/ic-partners-qvc@3x.png';
import { $L } from '../../../utils/helperMethods';
import css from './THeaderCustom.module.less';
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
@@ -27,14 +32,15 @@ export default function THeaderCustom({
onClick,
ariaLabel,
children,
kind,
...rest
}) {
const convertedTitle = useMemo(() => {
if (title && typeof title === 'string') {
if (title && typeof title === "string") {
const cleanedTitle = title.replace(/(\r\n|\n)/g, "");
return $L(marqueeDisabled ? title : cleanedTitle);
}
return '';
return "";
}, [marqueeDisabled, title]);
const _onClick = useCallback(
@@ -71,12 +77,16 @@ export default function THeaderCustom({
role="button"
/>
)}
<div
className={css.centerImage}
style={{
backgroundImage: `url("${qvcLogoImg}")`
}}
/>
{kind ? (
""
) : (
<div
className={css.centerImage}
style={{
backgroundImage: `url("${qvcLogoImg}")`,
}}
/>
)}
<Marquee
marqueeOn="render"
className={css.title}
@@ -90,4 +100,4 @@ export default function THeaderCustom({
{children}
</Container>
);
}
}

View File

@@ -191,7 +191,9 @@ export default function HomeBanner({
const termsLoading = useSelector((state) => state.common.termsLoading);
const isGnbOpened = useSelector((state) => state.common.isGnbOpened);
// 선택약관 동의여부
const introTermsAgree = useSelector((state) => state.common.introTermsAgree);
const introTermsAgree = useSelector(
(state) => state.common.termsFlag.optionalTerms
);
// 새로운 Redux 상태: 선택약관 팝업 플로우 관리
const optionalTermsPopupFlow = useSelector(
@@ -314,11 +316,13 @@ export default function HomeBanner({
dispatch(updateOptionalTermsAgreement(true));
// 로컬 상태도 업데이트 (기존 로직 유지)
setOptionalTermsAgreed(true);
console.log("###test pjh ___ 2");
} else {
if (process.env.NODE_ENV === "development") {
console.error("[HomeBanner] 약관 동의 실패:", response);
}
}
console.log("###test pjh ___ 1", introTermsAgree);
};
if (process.env.NODE_ENV === "development") {
@@ -651,6 +655,10 @@ export default function HomeBanner({
[_handleShelfFocus]
);
useEffect(() => {
console.log("####introTermsAgree", introTermsAgree);
}, [introTermsAgree]);
const renderLayout = useCallback(() => {
switch (selectTemplate) {
case "DSP00201": {
@@ -662,7 +670,7 @@ export default function HomeBanner({
</ContainerBasic>
{renderItem(2, false)}
{/* //NOTE - 약관 동의 여부 & 추후 API 따라 팝업 표시 여부 결정 */}
{introTermsAgree ? (
{introTermsAgree === "Y" ? (
<div className={css.imgBox}>
<JustForSwitchBanner
renderItem={renderItem}

View File

@@ -187,7 +187,7 @@ export default function JustForSwitchBanner({
const shelfFocus = useCallback(() => {
dispatch(
pushPanel({
name: panel_names.JUST_FOR_YOU_PANEL,
name: panel_names.JUST_FOR_YOU_TEST_PANEL,
})
);
}, []);

View File

@@ -218,7 +218,7 @@ export default memo(function SubCategory({
handleShelfFocus();
}
}, [handleShelfFocus]);
console.log("###test pjh");
return (
<Container
spotlightId={spotlightId}

View File

@@ -0,0 +1,258 @@
import React, {
useCallback,
useRef,
useState,
} from 'react';
import classNames from 'classnames';
import {
useDispatch,
useSelector,
} from 'react-redux';
import Spotlight from '@enact/spotlight';
import SpotlightContainerDecorator
from '@enact/spotlight/SpotlightContainerDecorator';
import { setContainerLastFocusedElement } from '@enact/spotlight/src/container';
import background
from '../../../assets/images/JustForYouPanel/background_new.png';
import {
sendLogGNB,
sendLogTotalRecommend,
} from '../../actions/logActions';
import {
popPanel,
pushPanel,
updatePanel,
} from '../../actions/panelActions';
import CustomImage from '../../components/CustomImage/CustomImage';
import SectionTitle from '../../components/SectionTitle/SectionTitle';
import TBody from '../../components/TBody/TBody';
import TButton, { TYPES } from '../../components/TButton/TButton';
import TItemCard, {
removeDotAndColon,
} from '../../components/TItemCard/TItemCard';
import TPanel from '../../components/TPanel/TPanel';
import TVerticalPagenator
from '../../components/TVerticalPagenator/TVerticalPagenator';
import TVirtualGridList
from '../../components/TVirtualGridList/TVirtualGridList';
import useScrollTo from '../../hooks/useScrollTo';
import {
LOG_CONTEXT_NAME,
LOG_MENU,
LOG_MESSAGE_ID,
panel_names,
} from '../../utils/Config';
import { $L } from '../../utils/helperMethods';
import { SpotlightIds } from '../../utils/SpotlightIds';
import THeaderCustom from '../DetailPanel/components/THeaderCustom';
import css from './JustForYouTestPanel.module.less';
const ListContainer = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
);
const STRING_CONF_TITLE = {
LIKE_ITEMS: "Like items you recently saw",
LIKE_BRANDS: "Liked Brand Products",
MORE_PRICE: "More to Consider at This Price",
};
const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
const dispatch = useDispatch();
const [showButton, setShowButton] = useState("showButton", true);
const cbChangePageRef = useRef(null);
const currentSentMenuRef = useRef(null);
const focusedContainerIdRef = useRef(panelInfo?.focusedContainerId);
const { getScrollTo } = useScrollTo();
const STRING_CONF = {
LIKE_ITEMS: "Like items you recently saw",
LIKE_BRANDS: "Liked Brand Products",
MORE_PRICE: "More to Consider at This Price",
};
const recentItems = useSelector(
(state) => state.product?.bestSellerData?.bestSeller
);
const onClick = useCallback(() => {
dispatch(popPanel(panel_names.JUST_FOR_YOU_TEST_PANEL));
}, [dispatch]);
const handleScroll = useCallback((e) => {
setShowButton(e.scrollTop === 0);
}, []);
const handleTopButtonClick = useCallback(() => {
if (cbChangePageRef.current) {
cbChangePageRef.current(0, true);
}
if (recentItems && recentItems.length > 0) {
const target = `spotlightId-recentItem-${recentItems[0]?.prdtId}`;
Spotlight.focus(target);
setContainerLastFocusedElement(null, [SpotlightIds.JUST_FOR_YOU_ITEMS]);
}
}, [recentItems]);
const renderItem = useCallback(
({ index, ...rest }) => {
const {
imgUrl,
offerInfo,
prdtId,
lgCatNm,
patncNm,
patnrId,
brndNm,
prdtNm,
priceInfo,
} = recentItems[index];
const handleItemClick = () => {
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: { patnrId, prdtId },
})
);
};
return (
<TItemCard
key={prdtId}
catNm={lgCatNm}
patnerName={patncNm}
brandName={brndNm}
data-wheel-point={index >= 5}
imageAlt={prdtId}
imageSource={imgUrl}
label={index * 1 + 1 + " of " + recentItems.length}
lastLabel=" go to detail, button"
offerInfo={offerInfo}
priceInfo={priceInfo}
productName={prdtNm}
productId={prdtId}
onClick={handleItemClick}
spotlightId={"spotlightId-recentItem-" + removeDotAndColon(prdtId)}
{...rest}
/>
);
},
[recentItems]
);
return (
<div className={css.container}>
<TPanel isTabActivated={false}>
<TBody className={css.justForYou} isDefaultContainer={true}>
<TVerticalPagenator
className={css.tVerticalPagenator}
spotlightId={"justforyouspotlight"}
topMargin={470}
>
<div className={css.background}>
<THeaderCustom
className={css.header}
title={"Just For You"}
onBackButton
onClick={onClick}
kind="justforyou"
/>
<CustomImage src={background} animationSpeed="none" />
</div>
{recentItems && recentItems?.length > 0 && (
<ListContainer
className={classNames(
css.itemsContainer,
css.itemsContinerFirst
)}
spotlightId={SpotlightIds.JUST_FOR_YOU_ITEMS}
data-wheel-point
>
<SectionTitle
title={`${$L(STRING_CONF.LIKE_ITEMS)} (${recentItems.length})`}
data-title-index="JFYTitle"
/>
<div className={css.itemList}>
<TVirtualGridList
dataSize={recentItems.length}
itemWidth={324}
itemHeight={438}
spacing={18}
renderItem={renderItem}
direction="horizontal"
/>
</div>
</ListContainer>
)}
{recentItems && recentItems?.length > 0 && (
<ListContainer
className={classNames(css.itemsContainer)}
spotlightId={SpotlightIds.JUST_FOR_YOU_ITEMS}
data-wheel-point
>
<SectionTitle
title={`${$L(STRING_CONF.LIKE_BRANDS)} (${recentItems.length})`}
data-title-index="JFYTitle"
/>
<div className={css.itemList}>
<TVirtualGridList
dataSize={recentItems.length}
itemWidth={324}
itemHeight={438}
spacing={18}
renderItem={renderItem}
direction="horizontal"
/>
</div>
</ListContainer>
)}
{recentItems && recentItems?.length > 0 && (
<ListContainer
className={classNames(css.itemsContainer)}
spotlightId={SpotlightIds.JUST_FOR_YOU_ITEMS}
data-wheel-point
>
<SectionTitle
title={`${$L(STRING_CONF.MORE_PRICE)} (${recentItems.length})`}
data-title-index="JFYTitle"
/>
<div className={css.itemList}>
<TVirtualGridList
dataSize={recentItems.length}
itemWidth={324}
itemHeight={438}
spacing={18}
renderItem={renderItem}
direction="horizontal"
/>
</div>
</ListContainer>
)}
<ListContainer>
<TButton
onClick={handleTopButtonClick}
size={null}
spotlightId={SpotlightIds.JUST_FOR_YOU_TOP_BUTTON}
ariaLabel="Move to Top"
data-wheel-point
type={TYPES.topButton}
/>
</ListContainer>
</TVerticalPagenator>
</TBody>
</TPanel>
</div>
);
};
export default JustForYouTestPanel;

View File

@@ -0,0 +1,86 @@
@import "../../style/CommonStyle.module.less";
@import "../../style/utils.module.less";
.container {
width: 100%;
height: 100%;
.justForYou {
position: relative;
background: @COLOR_WHITE;
overflow: auto;
height: @globalHeight;
.tVerticalPagenator {
height: 100% !important;
.itemsContainer {
width: calc(100% - 60px);
padding: 0 0 0 60px;
margin-top: 30px;
&.itemsContinerFirst {
margin-top: 470px;
}
.itemList {
.size(@w: 100%, @h: 438px);
margin-top: 24px;
padding-right: 18px;
display: flex;
flex-direction: row;
overflow: initial;
width: 100%;
> div:nth-child(1) {
.size(@w: 100%, @h: 438px);
&.tVirtualGridList {
padding-left: 60px;
}
}
}
}
.background {
position: absolute;
top: 0;
left: 0;
max-width: 1920px;
max-height: 650px;
.header {
width: 100%;
height: 60px;
background-color: transparent;
align-items: center;
color: rgba(238, 238, 238, 1);
padding: 0 0 0 60px;
position: relative;
left: 0;
top: 0;
z-index: 1;
> div {
font-weight: bold !important;
font-size: 30px !important;
.elip(@clamp: 1);
padding-left: 12px !important;
text-transform: none !important;
letter-spacing: 0 !important;
}
> button {
background-image: url("../../../assets/images/btn/btn-60-wh-back-nor@3x.png");
&:focus {
border: 4px solid @PRIMARY_COLOR_RED;
box-shadow: 0 0 22px 0 rgba(0, 0, 0, 0.5);
border-radius: 0px;
}
}
}
img {
max-width: 1920px;
max-height: 650px;
object-fit: cover;
position: absolute;
left: 0;
top: 0;
}
}
}
}
}

View File

@@ -96,6 +96,7 @@ import HotPicksPanel from '../HotPicksPanel/HotPicksPanel';
import ImagePanel from '../ImagePanel/ImagePanel';
import IntroPanel from '../IntroPanel/IntroPanel.new';
import JustForYouPanel from '../JustForYouPanel/JustForYouPanel';
import JustForYouTestPanel from '../JustForYouTestPanel/JustForYouTestPanel';
import LoadingPanel from '../LoadingPanel/LoadingPanel';
import MyPagePanel from '../MyPagePanel/MyPagePanel';
import OnSalePanel from '../OnSalePanel/OnSalePanel';
@@ -140,6 +141,7 @@ const panelMap = {
[Config.panel_names.CONFIRM_PANEL]: ConfirmPanel,
[Config.panel_names.USER_REVIEW_PANEL]: UserReviewPanel,
[Config.panel_names.JUST_FOR_YOU_PANEL]: JustForYouPanel,
[Config.panel_names.JUST_FOR_YOU_TEST_PANEL]: JustForYouTestPanel,
// [Config.panel_names.OPTIONAL_TERMS_PANEL]: TermsOfOptional,
};