player tab featured livechannel 구현
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import React, { memo, useCallback } from "react";
|
||||
|
||||
import classNames from "classnames";
|
||||
|
||||
import Spottable from "@enact/spotlight/Spottable";
|
||||
|
||||
import CustomImage from "../../../components/CustomImage/CustomImage";
|
||||
import { $L } from "../../../utils/helperMethods";
|
||||
import css from "./PlayerItemCard.module.less";
|
||||
|
||||
const SpottableComponent = Spottable("div");
|
||||
|
||||
const TYPES = {
|
||||
liveHorizontal: "liveHorizontal",
|
||||
featuredHorizontal: "featuredHorizontal",
|
||||
};
|
||||
|
||||
const IMAGETYPES = {
|
||||
imgHorizontal: "imgHorizontal",
|
||||
imgVertical: "imgVertical",
|
||||
};
|
||||
|
||||
// @@pyh Todo, 추후 다국어 resource 추가
|
||||
const STRING_CONF = {
|
||||
SOLD_OUT: $L("SOLD OUT"),
|
||||
TOP: $L("TOP"),
|
||||
};
|
||||
|
||||
export const removeDotAndColon = (string) => {
|
||||
return /[.:]/.test(string) ? string.replace(/[.:]/g, "") : string;
|
||||
};
|
||||
|
||||
export default memo(function TItemCard({
|
||||
children,
|
||||
disabled,
|
||||
imageAlt,
|
||||
imageSource,
|
||||
imgType = IMAGETYPES.imgHorizontal,
|
||||
logo,
|
||||
onBlur,
|
||||
onClick,
|
||||
onFocus,
|
||||
productId,
|
||||
productName,
|
||||
soldoutFlag,
|
||||
spotlightId,
|
||||
patnerName,
|
||||
type = TYPES.liveHorizontal,
|
||||
...rest
|
||||
}) {
|
||||
const _onBlur = useCallback(() => {
|
||||
if (onBlur) {
|
||||
onBlur();
|
||||
}
|
||||
}, [onBlur]);
|
||||
|
||||
const _onClick = useCallback(
|
||||
(e) => {
|
||||
if (disabled) {
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (onClick) {
|
||||
onClick(e);
|
||||
}
|
||||
},
|
||||
[onClick, disabled]
|
||||
);
|
||||
const _onFocus = useCallback(() => {
|
||||
if (onFocus) {
|
||||
onFocus();
|
||||
}
|
||||
}, [onFocus]);
|
||||
|
||||
return (
|
||||
<SpottableComponent
|
||||
className={classNames(css[type])}
|
||||
onBlur={_onBlur}
|
||||
onClick={_onClick}
|
||||
onFocus={_onFocus}
|
||||
spotlightId={
|
||||
productId ? "spotlightId-" + removeDotAndColon(productId) : spotlightId
|
||||
}
|
||||
{...rest}
|
||||
>
|
||||
<div className={css.imageWrap}>
|
||||
<CustomImage alt={imageAlt} delay={0} src={imageSource} />
|
||||
{soldoutFlag && soldoutFlag === "Y" && (
|
||||
<div>{STRING_CONF.SOLD_OUT}</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={css.descWrap}>
|
||||
<div className={css.patnerWrap}>
|
||||
<img className={css.logo} src={logo} alt="" />
|
||||
<h3 className={css.brandName}>{patnerName}</h3>
|
||||
</div>
|
||||
<h3 className={css.title}>{productName}</h3>
|
||||
</div>
|
||||
</SpottableComponent>
|
||||
);
|
||||
});
|
||||
|
||||
export { IMAGETYPES, TYPES };
|
||||
@@ -0,0 +1,144 @@
|
||||
@import "../../../style/CommonStyle.module.less";
|
||||
@import "../../../style/utils.module.less";
|
||||
|
||||
/* liveHorizontal */
|
||||
.liveHorizontal {
|
||||
display: flex;
|
||||
.size(@w: 600px, @h: 236px);
|
||||
padding: 18px;
|
||||
border-radius: 12px;
|
||||
border: solid 1px @COLOR_GRAY02;
|
||||
background-color: @COLOR_WHITE;
|
||||
|
||||
.imageWrap {
|
||||
position: relative;
|
||||
.size(@w: 200px, @h: 200px);
|
||||
margin-right: 20px;
|
||||
color: @COLOR_WHITE;
|
||||
|
||||
> img {
|
||||
.size(@w: inherit, @h: inherit);
|
||||
object-fit: cover;
|
||||
border: solid 1px #f0f0f0;
|
||||
}
|
||||
|
||||
// sold out
|
||||
> div {
|
||||
.position(@position: absolute, @top: 0, @right: 0);
|
||||
.flex();
|
||||
.size(@w: 200px, @h: 200px);
|
||||
background-color: rgba(26, 26, 26, 0.6);
|
||||
font-weight: bold;
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.descWrap {
|
||||
.flex(@direction: column, @justifyCenter: space-between, @alignCenter: flex-start);
|
||||
width: 404px;
|
||||
padding: 12px 0;
|
||||
|
||||
.patnerWrap {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
> img {
|
||||
.size(@w: 42px , @h: 42px);
|
||||
margin-right: 11px;
|
||||
}
|
||||
|
||||
> h3 {
|
||||
font-size: 30px;
|
||||
color: #767676;
|
||||
font-weight: 600;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
> h3 {
|
||||
font-weight: bold;
|
||||
font-size: 24px;
|
||||
color: @COLOR_GRAY06;
|
||||
.elip(@clamp:2);
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// focused
|
||||
&:focus {
|
||||
&::after {
|
||||
.focused(@boxShadow:22px, @borderRadius:12px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// featuredHorizontal
|
||||
.featuredHorizontal {
|
||||
display: flex;
|
||||
.size(@w: 600px, @h: 176px);
|
||||
padding: 18px;
|
||||
border-radius: 12px;
|
||||
border: solid 1px @COLOR_GRAY02;
|
||||
background-color: @COLOR_WHITE;
|
||||
|
||||
.imageWrap {
|
||||
position: relative;
|
||||
.size(@w: 248px, @h: 140px);
|
||||
margin-right: 20px;
|
||||
color: @COLOR_WHITE;
|
||||
|
||||
> img {
|
||||
.size(@w: inherit, @h: inherit);
|
||||
object-fit: cover;
|
||||
border: solid 1px #f0f0f0;
|
||||
}
|
||||
|
||||
// sold out
|
||||
> div {
|
||||
.position(@position: absolute, @top: 0, @right: 0);
|
||||
.flex();
|
||||
.size(@w: 200px, @h: 200px);
|
||||
background-color: rgba(26, 26, 26, 0.6);
|
||||
font-weight: bold;
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.descWrap {
|
||||
.flex(@direction: column, @justifyCenter: space-between, @alignCenter: flex-start);
|
||||
width: 404px;
|
||||
padding: 12px 0;
|
||||
|
||||
.patnerWrap {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
> img {
|
||||
.size(@w: 42px , @h: 42px);
|
||||
margin-right: 11px;
|
||||
}
|
||||
|
||||
> h3 {
|
||||
font-size: 30px;
|
||||
color: #767676;
|
||||
font-weight: 600;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
> h3 {
|
||||
font-weight: bold;
|
||||
font-size: 24px;
|
||||
color: @COLOR_GRAY06;
|
||||
.elip(@clamp:2);
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// focused
|
||||
&:focus {
|
||||
&::after {
|
||||
.focused(@boxShadow:22px, @borderRadius:12px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,9 @@ import { VideoPlayer } from "../../components/VideoPlayer/VideoPlayer";
|
||||
import { panel_names } from "../../utils/Config";
|
||||
import { $L } from "../../utils/helperMethods";
|
||||
import css from "./PlayerPanel.module.less";
|
||||
import PlayerTabLiveContents from "./PlayerTabContents/PlayerTabLiveContents";
|
||||
import FeaturedShowContents from "./PlayerTabContents/FeaturedShowContents";
|
||||
import LiveChannelContents from "./PlayerTabContents/LiveChannelContents";
|
||||
import ShopNowContents from "./PlayerTabContents/ShopNowContents";
|
||||
import YouMayLikeContents from "./PlayerTabContents/YouMayLikeContents";
|
||||
|
||||
const SpottableBtn = Spottable("button");
|
||||
@@ -44,7 +46,6 @@ const Container = SpotlightContainerDecorator(
|
||||
const unableToPlay = new Job((callback) => {
|
||||
// callback();
|
||||
}, 5000);
|
||||
const tabList = [$L("SHOP NOW"), $L("LIVE CHANNEL")];
|
||||
|
||||
const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -54,14 +55,14 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
|
||||
const [showItem, setShowItem] = useState(true);
|
||||
const [sideOpen, setSideOpen] = useState(false);
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
const liveChannelInfos = useSelector((state) => state.main.liveChannelInfos);
|
||||
const featuredShowsInfos = useSelector(
|
||||
(state) => state.main.featuredShowsInfos
|
||||
);
|
||||
|
||||
const showNowProduct = useSelector((state) => state.main.showNowProduct);
|
||||
const fullVideoData = useSelector((state) => state.main.fullVideoData);
|
||||
const panels = useSelector((state) => state.panels.panels);
|
||||
|
||||
const tabList = [
|
||||
$L("SHOP NOW"),
|
||||
$L(panelInfo.type === "LIVE" ? "LIVE CHANNEL" : "FEATURED SHOWS"),
|
||||
];
|
||||
const onClickBack = useCallback(
|
||||
(ev) => {
|
||||
console.log("onClickBack ev...", ev);
|
||||
@@ -242,10 +243,12 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
|
||||
listType={LIST_TYPE.small}
|
||||
/>
|
||||
|
||||
{panelInfo.type === "LIVE" && tab === 0 && <PlayerTabLiveContents />}
|
||||
{showNowProduct && showNowProduct.length < 3 && (
|
||||
{tab === 0 && <ShopNowContents />}
|
||||
{showNowProduct && showNowProduct.length < 3 && tab === 0 && (
|
||||
<YouMayLikeContents />
|
||||
)}
|
||||
{panelInfo.type === "LIVE" && tab === 1 && <LiveChannelContents />}
|
||||
{panelInfo.type === "VOD" && tab === 1 && <FeaturedShowContents />}
|
||||
</Container>
|
||||
)}
|
||||
</TPanel>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import { pushPanel } from "../../../actions/panelActions";
|
||||
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList";
|
||||
import { panel_names } from "../../../utils/Config";
|
||||
import PlayerItemCard, { TYPES } from "../PlayerItemCard/PlayerItemCard";
|
||||
import css from "./LiveChannelContents.module.less";
|
||||
|
||||
export default function FeaturedShowContents() {
|
||||
const dispatch = useDispatch();
|
||||
const featuredShowsInfos = useSelector(
|
||||
(state) => state.main.featuredShowsInfos
|
||||
);
|
||||
|
||||
console.log("#featuredShowsInfos", featuredShowsInfos);
|
||||
const renderItem = useCallback(
|
||||
({ index, ...rest }) => {
|
||||
const { thumbnailUrl, patncLogoPath, patnrId, prdtId, patncNm, showNm } =
|
||||
featuredShowsInfos[index];
|
||||
|
||||
const handleItemClick = () => {};
|
||||
|
||||
return (
|
||||
<PlayerItemCard
|
||||
{...rest}
|
||||
key={prdtId}
|
||||
imageAlt={prdtId}
|
||||
logo={patncLogoPath}
|
||||
imageSource={thumbnailUrl}
|
||||
productName={showNm}
|
||||
patnerName={patncNm}
|
||||
onClick={handleItemClick}
|
||||
type={TYPES.featuredHorizontal}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[featuredShowsInfos]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<div className={css.container}>
|
||||
{featuredShowsInfos && featuredShowsInfos.length > 0 && (
|
||||
<TVirtualGridList
|
||||
dataSize={featuredShowsInfos.length}
|
||||
direction="vertical"
|
||||
renderItem={renderItem}
|
||||
itemWidth={600}
|
||||
itemHeight={176}
|
||||
spacing={12}
|
||||
className={css.itemList}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
@import "../../../style/utils.module.less";
|
||||
|
||||
.container {
|
||||
height: 956px;
|
||||
overflow: hidden;
|
||||
|
||||
> div:nth-child(1) {
|
||||
.size(@w: 100%, @h: inherit);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import { pushPanel } from "../../../actions/panelActions";
|
||||
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList";
|
||||
import { panel_names } from "../../../utils/Config";
|
||||
import PlayerItemCard, { TYPES } from "../PlayerItemCard/PlayerItemCard";
|
||||
import css from "./LiveChannelContents.module.less";
|
||||
|
||||
export default function LiveChannelContents() {
|
||||
const dispatch = useDispatch();
|
||||
const liveChannelInfos = useSelector((state) => state.main.liveChannelInfos);
|
||||
|
||||
console.log("#liveChannelInfos", liveChannelInfos);
|
||||
const renderItem = useCallback(
|
||||
({ index, ...rest }) => {
|
||||
const {
|
||||
dfltThumbnailImgPath,
|
||||
patncLogoPath,
|
||||
patnrId,
|
||||
prdtId,
|
||||
prdtNm,
|
||||
priceInfo,
|
||||
offerInfo,
|
||||
patncNm,
|
||||
} = liveChannelInfos[index];
|
||||
|
||||
const handleItemClick = () => {};
|
||||
|
||||
return (
|
||||
<PlayerItemCard
|
||||
{...rest}
|
||||
key={prdtId}
|
||||
imageAlt={prdtId}
|
||||
logo={patncLogoPath}
|
||||
imageSource={dfltThumbnailImgPath}
|
||||
productName={prdtNm}
|
||||
patnerName={patncNm}
|
||||
onClick={handleItemClick}
|
||||
type={TYPES.liveHorizontal}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[liveChannelInfos]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<div className={css.container}>
|
||||
{liveChannelInfos && liveChannelInfos.length > 0 && (
|
||||
<TVirtualGridList
|
||||
dataSize={liveChannelInfos.length}
|
||||
direction="vertical"
|
||||
renderItem={renderItem}
|
||||
itemWidth={600}
|
||||
itemHeight={236}
|
||||
spacing={12}
|
||||
className={css.itemList}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
@import "../../../style/utils.module.less";
|
||||
|
||||
.container {
|
||||
height: 956px;
|
||||
overflow: hidden;
|
||||
|
||||
> div:nth-child(1) {
|
||||
.size(@w: 100%, @h: inherit);
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,14 @@ import { pushPanel } from "../../../actions/panelActions";
|
||||
import TItemCard, { TYPES } from "../../../components/TItemCard/TItemCard";
|
||||
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList";
|
||||
import { panel_names } from "../../../utils/Config";
|
||||
import css from "./PlayerTabLiveContents.module.less";
|
||||
import css from "./ShopNowContents.module.less";
|
||||
|
||||
export default function PlayerTabContents() {
|
||||
export default function ShopNowContents() {
|
||||
const dispatch = useDispatch();
|
||||
const showNowProduct = useSelector((state) => state.main.showNowProduct);
|
||||
const [height, setHeight] = useState();
|
||||
|
||||
console.log("#showNowProduct", showNowProduct);
|
||||
const gridStyle = useMemo(() => ({ height: `${height}px` }), [height]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -27,7 +28,7 @@ export default function PlayerTabContents() {
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ index, ...rest }) => {
|
||||
const { thumbnailUrl, patnrId, prdtId, prdtNm, priceInfo, offerInfo } =
|
||||
const { imgUrls600, patnrId, prdtId, prdtNm, priceInfo, offerInfo } =
|
||||
showNowProduct[index];
|
||||
|
||||
const handleItemClick = () => {
|
||||
@@ -47,7 +48,7 @@ export default function PlayerTabContents() {
|
||||
{...rest}
|
||||
key={prdtId}
|
||||
imageAlt={prdtId}
|
||||
imageSource={thumbnailUrl}
|
||||
imageSource={imgUrls600[0]}
|
||||
priceInfo={priceInfo}
|
||||
offerInfo={offerInfo}
|
||||
productName={prdtNm}
|
||||
Reference in New Issue
Block a user