일반상품 인디게이터 수정 및 플레이패널 css 및 구조변경

This commit is contained in:
고동영
2024-04-03 11:01:01 +09:00
parent b52b7936d4
commit b0ec4220cb
23 changed files with 518 additions and 230 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

View File

@@ -66,6 +66,7 @@ export const types = {
SET_MAIN_LIKE_CATEGORY: "SET_MAIN_LIKE_CATEGORY",
SET_MAIN_LIVE_UPCOMING_ALARM: "SET_MAIN_LIVE_UPCOMING_ALARM",
GET_MAIN_LIVE_SHOW_NOW_PRODUCT: "GET_MAIN_LIVE_SHOW_NOW_PRODUCT",
GET_MAIN_CATEGORY_SHOW_DETAIL: "GET_MAIN_CATEGORY_SHOW_DETAIL",
// myPage actions
GET_MY_RECOMMANDED_KEYWORD: "GET_MY_RECOMMANDED_KEYWORD",

View File

@@ -1,8 +1,8 @@
import { URLS } from "../api/apiConfig";
import { TAxios } from "../api/TAxios";
import { CATEGORY_DATA_MAX_RESULTS_LIMIT } from "../utils/Config";
import * as HelperMethods from "../utils/helperMethods";
import { types } from "./actionTypes";
import { URLS } from '../api/apiConfig';
import { TAxios } from '../api/TAxios';
import { CATEGORY_DATA_MAX_RESULTS_LIMIT } from '../utils/Config';
import * as HelperMethods from '../utils/helperMethods';
import { types } from './actionTypes';
// Live 알람 설정/해제 IF-LGSP-012
export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => {
@@ -56,6 +56,34 @@ export const getMainCategoryDetail = (props) => (dispatch, getState) => {
);
};
// 영상 상세 보기 조회 LF-LGSP-047
export const getMainCategoryShowDetail = (props) => (dispatch, getState) => {
const { patnrId, showId } = props;
const onSuccess = (response) => {
console.log("getMainCategoryShowDetail onSuccess ", response.data);
dispatch({
type: types.GET_MAIN_CATEGORY_SHOW_DETAIL,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error("getMainCategoryShowDetail onFail", error);
};
TAxios(
dispatch,
getState,
"get",
URLS.GET_MAIN_CATEGORY_SHOW_DETAIL,
{ patnrId, showId },
{},
onSuccess,
onFail
);
};
// 서브카테고리 조회 IF-LGSP-051
let getSubCategoryKey = null;
export const getSubCategory =

View File

@@ -79,6 +79,7 @@ export const URLS = {
SET_MAIN_LIKE_CATEGORY: "/lgsp/v1/main/category/like.lge",
SET_MAIN_LIVE_UPCOMING_ALARM: "/lgsp/v1/main/live/upcoming/alarm.lge",
GET_MAIN_LIVE_SHOW_NOW_PRODUCT: "/lgsp/v1/main/live/show/nowproduct.lge",
GET_MAIN_CATEGORY_SHOW_DETAIL: "/lgsp/v1/main/category/show/detail.lge",
//event controller
GET_WELCOME_EVENT_INFO: "/lgsp/v1/event/event.lge",

View File

@@ -80,6 +80,13 @@ export const mainReducer = (state = initialState, action) => {
};
}
case types.GET_MAIN_CATEGORY_SHOW_DETAIL: {
return {
...state,
showDetailInfo: action.payload.showInfos,
};
}
default:
return state;
}

View File

@@ -119,6 +119,8 @@ export default function ItemDetail() {
<SingleProduct
selectedPatnrId={selectedPatnrId}
selectedPrdtId={selectedPrdtId}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
/>
)}
{/* 그룹상품 영역 */}
@@ -128,6 +130,8 @@ export default function ItemDetail() {
<GroupProduct
selectedPatnrId={selectedPatnrId}
selectedPrdtId={selectedPrdtId}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
/>
)}
{/* 구매불가상품 영역 */}
@@ -135,6 +139,8 @@ export default function ItemDetail() {
<UnableProduct
selectedPatnrId={selectedPatnrId}
selectedPrdtId={selectedPrdtId}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
/>
)}

View File

@@ -1,14 +1,33 @@
import React from 'react';
import { useSelector } from 'react-redux';
import ProductOption from '../components/ProductOption';
import ProductThumbnail from '../components/ProductThumbnail';
import GroupOption from './GroupOption';
import css from './GroupProduct.module.less';
export default function GroupProduct({ selectedPatnrId, selectedPrdtId }) {
export default function GroupProduct({
selectedPatnrId,
selectedPrdtId,
selectedIndex,
setSelectedIndex,
}) {
const productData = useSelector((state) => state.main.productData);
return (
<div className={css.container}>
<ProductThumbnail />
<div>
<Indicator
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
productInfo={productData}
/>
<IndicatorOptions
productInfo={productData}
thumbnailUrl={productData.imgUrls600[0]}
isFullOption
/>
</div>
<div>
<ProductOption />
<GroupOption

View File

@@ -1,26 +1,38 @@
import React, { useCallback, useEffect, useState } from "react";
import React, {
useCallback,
useEffect,
useState,
} from 'react';
import classNames from "classnames";
import { useDispatch, useSelector } from "react-redux";
import classNames from 'classnames';
import {
useDispatch,
useSelector,
} from 'react-redux';
import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import Spotlight from '@enact/spotlight';
import SpotlightContainerDecorator
from '@enact/spotlight/SpotlightContainerDecorator';
import Spottable from '@enact/spotlight/Spottable';
import { setHidePopup, setShowPopup } from "../../../actions/commonActions";
import { getProductCouponSearch } from "../../../actions/couponActions";
import { pushPanel } from "../../../actions/panelActions";
import { getProductOption } from "../../../actions/productActions";
import TButton from "../../../components/TButton/TButton";
import TPopUp from "../../../components/TPopUp/TPopUp";
import TScroller from "../../../components/TScroller/TScroller";
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList";
import usePriceInfo from "../../../hooks/usePriceInfo";
import * as Config from "../../../utils/Config";
import { $L } from "../../../utils/helperMethods";
import { SpotlightIds } from "../../../utils/SpotlightIds";
import FavoriteBtn from "../components/common/FavoriteBtn";
import css from "./SingleOption.module.less";
import {
setHidePopup,
setShowPopup,
} from '../../../actions/commonActions';
import { getProductCouponSearch } from '../../../actions/couponActions';
import { pushPanel } from '../../../actions/panelActions';
import { getProductOption } from '../../../actions/productActions';
import TButton from '../../../components/TButton/TButton';
import TPopUp from '../../../components/TPopUp/TPopUp';
import TScroller from '../../../components/TScroller/TScroller';
import TVirtualGridList
from '../../../components/TVirtualGridList/TVirtualGridList';
import usePriceInfo from '../../../hooks/usePriceInfo';
import * as Config from '../../../utils/Config';
import { $L } from '../../../utils/helperMethods';
import { SpotlightIds } from '../../../utils/SpotlightIds';
import FavoriteBtn from '../components/common/FavoriteBtn';
import css from './SingleOption.module.less';
const Container = SpotlightContainerDecorator(
{ enterTo: "default-element", preserveId: true },
@@ -113,10 +125,6 @@ export default function SingleOption({
return updatedOptions;
});
}
console.log("#selectedoptions", selectedOptions);
console.log("#selectedoptionIdx", selectedOptionIdx);
console.log("#discountedPrice", discountedPrice);
}, [selectedOptions]);
const handleIncrement = useCallback(() => {

View File

@@ -2,20 +2,34 @@ import React from 'react';
import { useSelector } from 'react-redux';
import Indicator from '../components/common/Indicator';
import ProductOption from '../components/ProductOption';
import ThemeIndicator from '../ThemeProduct/indicator/ThemeIndicator';
import IndicatorOptions from '../ThemeProduct/indicator/IndicatorOptions';
import SingleOption from './SingleOption';
import css from './SingleProduct.module.less';
export default function SingleProduct({ selectedPatnrId, selectedPrdtId }) {
export default function SingleProduct({
selectedPatnrId,
selectedPrdtId,
selectedIndex,
setSelectedIndex,
}) {
const productData = useSelector((state) => state.main.productData);
return (
<div className={css.container}>
<ThemeIndicator
productInfo={productData}
generalThumbnail={productData?.imgUrls600}
/>
<div>
<Indicator
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
productInfo={productData}
/>
<IndicatorOptions
productInfo={productData}
thumbnailUrl={productData.imgUrls600[0]}
isFullOption
/>
</div>
<div>
<ProductOption>
<SingleOption

View File

@@ -6,7 +6,7 @@
.size(@w: 100% , @h: 990px);
background-color: @BG_COLOR_01;
padding: 30px 120px 60px 60px;
margin-left: 61px;
.topLayer {
width: 846px;
.flex(@direction:row ,@justifyCenter:flex-start);

View File

@@ -1,12 +1,12 @@
import React, { useState } from "react";
import React, { useState } from 'react';
import { useSelector } from "react-redux";
import { useSelector } from 'react-redux';
import ProductOption from "../components/ProductOption";
import SingleOption from "../SingleProduct/SingleOption";
import IndicatorOptions from "./indicator/IndicatorOptions";
import ThemeIndicator from "./indicator/ThemeIndicator";
import css from "./ThemeOption.module.less";
import ProductOption from '../components/ProductOption';
import SingleOption from '../SingleProduct/SingleOption';
import IndicatorOptions from './indicator/IndicatorOptions';
import ThemeIndicator from './indicator/ThemeIndicator';
import css from './ThemeOption.module.less';
export default function ThemeOption({ selectedIndex, setSelectedIndex }) {
const productInfo = useSelector(
@@ -31,8 +31,11 @@ export default function ThemeOption({ selectedIndex, setSelectedIndex }) {
productInfo={productInfo[selectedIndex]}
/>
</div>
<div>
<ProductOption productInfo={productInfo[selectedIndex]}>
<div className={css.optionContainer}>
<ProductOption
productInfo={productInfo[selectedIndex]}
thumbnailUrls={productInfo?.thumbnailUrl}
>
<SingleOption
selectedPatnrId={productData?.themeInfo[0]?.patnrId}
selectedPrdtId={productInfo[selectedIndex]?.prdtId}

View File

@@ -4,3 +4,7 @@
.indicatorContainer {
.size(@w: 834px, @h: 930px);
}
.optionContainer {
margin-left: 61px;
}

View File

@@ -1,22 +1,32 @@
import React, { useCallback, useState } from "react";
import React, {
useCallback,
useState,
} from 'react';
import { useDispatch, useSelector } from "react-redux";
import {
useDispatch,
useSelector,
} from 'react-redux';
import Spottable from "@enact/spotlight/Spottable";
import Spottable from '@enact/spotlight/Spottable';
import { setHidePopup, setShowPopup } from "../../../../actions/commonActions";
import MobileSendPopUp from "../../../../components/MobileSend/MobileSendPopUp";
import TButtonScroller from "../../../../components/TButtonScroller/TButtonScroller";
import TButtonTab from "../../../../components/TButtonTab/TButtonTab";
import TPopUp from "../../../../components/TPopUp/TPopUp";
import TQRCode from "../../../../components/TQRCode/TQRCode";
import TScroller from "../../../../components/TScroller/TScroller";
import useScrollTo from "../../../../hooks/useScrollTo";
import * as Config from "../../../../utils/Config";
import { $L } from "../../../../utils/helperMethods";
import ProductTag from "../../components/common/ProductTag";
import StarRating from "../../components/common/StarRating";
import css from "./IndicatorOptions.module.less";
import {
setHidePopup,
setShowPopup,
} from '../../../../actions/commonActions';
import MobileSendPopUp from '../../../../components/MobileSend/MobileSendPopUp';
import TButtonScroller
from '../../../../components/TButtonScroller/TButtonScroller';
import TButtonTab from '../../../../components/TButtonTab/TButtonTab';
import TPopUp from '../../../../components/TPopUp/TPopUp';
import TQRCode from '../../../../components/TQRCode/TQRCode';
import TScroller from '../../../../components/TScroller/TScroller';
import useScrollTo from '../../../../hooks/useScrollTo';
import * as Config from '../../../../utils/Config';
import { $L } from '../../../../utils/helperMethods';
import ProductTag from '../../components/common/ProductTag';
import StarRating from '../../components/common/StarRating';
import css from './IndicatorOptions.module.less';
const SpottableComponent = Spottable("div");
@@ -24,6 +34,7 @@ export default function IndicatorOptions({
isFullOption,
address,
productInfo,
thumbnailUrl,
}) {
const [opened, setOpened] = useState(false);
const [tabLabel, setTabLabel] = useState("");
@@ -33,6 +44,7 @@ export default function IndicatorOptions({
(state) => state.common.popup
);
console.log("#productInfo", productInfo);
const dispatch = useDispatch();
const handlePopUpClick = (label, description) => {
@@ -70,7 +82,7 @@ export default function IndicatorOptions({
>
<div className={css.popUpContainer}>
<div className={css.popUpHeader}>
<img src={productInfo?.thumbnailUrl} />
<img src={thumbnailUrl} />
<div className={css.path}>
<div>
<img src={productInfo?.patncLogoPath} alt="" />

View File

@@ -1,14 +1,36 @@
import React from 'react';
import { useSelector } from 'react-redux';
import Indicator from '../components/common/Indicator';
import ProductOption from '../components/ProductOption';
import ProductThumbnail from '../components/ProductThumbnail';
import IndicatorOptions from '../ThemeProduct/indicator/IndicatorOptions';
import UnableOption from './UnableOption';
import css from './UnableProduct.module.less';
export default function UnableProduct({ selectedPatnrId, selectedPrdtId }) {
export default function UnableProduct({
selectedPatnrId,
selectedPrdtId,
selectedIndex,
setSelectedIndex,
}) {
const productData = useSelector((state) => state.main.productData);
return (
<div className={css.container}>
<ProductThumbnail />
<div>
<Indicator
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
productInfo={productData}
/>
<IndicatorOptions
productInfo={productData}
thumbnailUrl={productData.imgUrls600[0]}
isFullOption
/>
</div>
<div>
<ProductOption>
<UnableOption

View File

@@ -6,7 +6,7 @@
.size(@w: 1026px, @h: 930px);
background-color: @BG_COLOR_01;
padding: 30px 120px 60px 60px;
margin-left: 61px;
.topLayer {
width: 100%;
.flex(@direction:row ,@justifyCenter:flex-start);

View File

@@ -1,72 +1,105 @@
import React, { useCallback, useEffect, useState } from "react";
import React, {
useCallback,
useEffect,
useState,
} from 'react';
import classNames from "classnames";
import { useSelector } from "react-redux";
import classNames from 'classnames';
import { useSelector } from 'react-redux';
import Image from "@enact/sandstone/Image";
import Spottable from "@enact/spotlight/Spottable";
import Image from '@enact/sandstone/Image';
import SpotlightContainerDecorator
from '@enact/spotlight/SpotlightContainerDecorator';
import Spottable from '@enact/spotlight/Spottable';
import css from "./Indicator.module.less";
import TVirtualGridList
from '../../../../components/TVirtualGridList/TVirtualGridList';
import useScrollTo from '../../../../hooks/useScrollTo';
import css from './Indicator.module.less';
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused", preserveld: true },
"div"
);
const SpottableComponent = Spottable("div");
const SpottableImage = Spottable(Image);
export default function Indicator() {
const productImages = useSelector((state) => state.main.productImages);
const images = productImages?.images || [];
//const media = productImages?.media;
const IMAGE_WIDTH = 152;
export default function Indicator({
selectedIndex,
setSelectedIndex,
productInfo,
thumbnailUrls,
}) {
const [selectedImage, setSelectedImage] = useState(null);
const [selectedIndex, setSelectedIndex] = useState(0);
const [visibleImages, setVisibleImages] = useState([]);
const { cursorVisible } = useSelector((state) => state.common.appStatus);
const { getScrollTo, scrollTop } = useScrollTo();
let imagePosition = IMAGE_WIDTH * selectedIndex - IMAGE_WIDTH;
useEffect(() => {
if (images && images.length > 0) {
setSelectedImage(images[0]);
setVisibleImages(images.slice(0, 3));
setSelectedImage(productInfo.imgUrls600[selectedIndex]);
}, [selectedIndex, productInfo]);
const handleUpClick = useCallback(() => {
if (selectedIndex === 0) {
return;
}
setSelectedIndex((prev) => prev - 1);
if (productInfo.imgUrls600.length - 1 !== selectedIndex) {
scrollTop({ y: imagePosition - IMAGE_WIDTH, animate: true });
}
}, [selectedIndex]);
const handleDownClick = useCallback(() => {
if (productInfo.imgUrls600.length - 1 === selectedIndex) {
return;
}
const thumbnail = document.querySelector(`.${css.thumbnail}`);
if (thumbnail) {
thumbnail.focus();
setSelectedIndex((prev) => prev + 1);
if (selectedIndex > 1) {
scrollTop({
y: imagePosition,
animate: true,
});
}
}, [images]);
}, [selectedIndex]);
const handleUpClick = () => {
setSelectedImage((prevSelectedImage) => {
const currentIndex = images.indexOf(prevSelectedImage);
const prevIndex = currentIndex === 0 ? 0 : currentIndex - 1;
if (prevIndex >= 0 && prevIndex <= images.length - 3) {
setVisibleImages(images.slice(prevIndex, prevIndex + 3));
}
setSelectedIndex(prevIndex);
return images[prevIndex];
});
};
const renderItem = useCallback(
({ index, ...rest }) => {
const image = productInfo.imgUrls600[index];
const handleDownClick = () => {
setSelectedImage((prevSelectedImage) => {
const currentIndex = images.indexOf(prevSelectedImage);
const nextIndex =
currentIndex === images.length - 1 ? currentIndex : currentIndex + 1;
if (nextIndex >= 2 && nextIndex <= images.length - 1) {
setVisibleImages(images.slice(nextIndex - 2, nextIndex + 1));
}
setSelectedIndex(nextIndex);
return images[nextIndex];
});
};
const handleItemClick = () => {
setSelectedIndex(index);
};
const handleItemClick = (image) => {
const globalIndex = images.indexOf(image);
setSelectedImage(image);
setSelectedIndex(globalIndex);
};
return (
<>
<SpottableImage
src={image}
alt=""
className={classNames(
css.image,
selectedIndex === index && css.selected
)}
onClick={handleItemClick}
spotlightId={`indicator-image-${index}`}
{...rest}
>
<span
className={
selectedIndex === index && css.selected && css.checkIcon
}
/>
</SpottableImage>
</>
);
},
[productInfo, selectedIndex]
);
return (
<div className={css.Wrap}>
<Container className={css.indicatorContainer}>
<div>
{selectedImage && (
{productInfo && (
<SpottableImage
src={selectedImage}
alt=""
@@ -74,32 +107,37 @@ export default function Indicator() {
/>
)}
</div>
<div className={css.indicator}>
<SpottableComponent onClick={handleUpClick} className={css.upButton} />
{visibleImages &&
visibleImages.map((image, index) => (
<SpottableImage
key={index}
src={image}
alt=""
onClick={() => handleItemClick(image, index)}
className={classNames(
css.image,
selectedIndex === images.indexOf(image) && css.selected
)}
>
<span
className={
selectedIndex === images.indexOf(image) && css.checkIcon
}
/>
</SpottableImage>
))}
<div>
<SpottableComponent
onClick={handleUpClick}
spotlightDisabled={!cursorVisible}
className={classNames(
css.upButton,
selectedIndex === 0 && css.disable
)}
/>
<Container className={css.tVirtualGridListContainer}>
{productInfo && (
<TVirtualGridList
cbScrollTo={getScrollTo}
className={css.tVirtualGridList}
dataSize={productInfo.imgUrls600.length}
itemWidth={144}
itemHeight={144}
spacing={8}
renderItem={renderItem}
/>
)}
</Container>
<SpottableComponent
className={css.downButton}
onClick={handleDownClick}
spotlightDisabled={!cursorVisible}
className={classNames(
css.downButton,
productInfo.imgUrls600.length - 1 === selectedIndex && css.disable
)}
/>
</div>
</div>
</Container>
);
}

View File

@@ -1,29 +1,88 @@
@import "../../../../style/CommonStyle.module.less";
@import "../../../../style/utils.module.less";
.Wrap {
margin: 30px 0 0 10px;
.indicatorContainer {
margin-top: 30px;
width: 714px;
height: 560px;
display: flex;
.thumbnail {
.size(@w: 560px, @h: 560px);
border: solid 1px #dadada;
background-color: #fff;
margin: 0 10px 10px 0;
position: relative;
display: flex;
justify-content: center;
&:focus {
&::after {
.focused(@boxShadow: 22px, @borderRadius:0px);
}
}
.thumbnailIndicator {
margin-top: auto;
position: relative;
margin-bottom: 30px;
z-index: 1;
.prevButton {
.size(@w:42px, @h: 42px);
.position(@position: absolute, @right: 70px, @bottom: 0 , @top: 0);
background-image: url("../../../../../assets/images/btn/btn-prev-thumb-nor.svg");
background-position: center;
background-size: cover;
&:focus {
background-image: url("../../../../../assets/images/btn/btn-prev-thumb-foc.svg");
}
&.disable {
opacity: 0.1;
background-image: url("../../../../../assets/images/btn/btn-prev-thumb-nor.svg");
}
}
.nextButton {
.size(@w:42px, @h: 42px);
.position(@position: absolute, @left: 70px, @bottom: 0 , @top: 0);
background-image: url("../../../../../assets/images/btn/btn-next-thumb-nor.svg");
background-position: center;
background-size: cover;
&:focus {
background-image: url("../../../../../assets/images/btn/btn-next-thumb-foc.svg");
}
&.disable {
opacity: 0.1;
background-image: url("../../../../../assets/images/btn/btn-next-thumb-nor.svg");
}
}
> span {
// .size(@w: 51px , @h: 21px);
-webkit-text-stroke: 1px rgba(255, 255, 255, 0.7);
color: #222222;
font-size: 24px;
font-weight: bold;
line-height: 1.33;
}
}
}
.tVirtualGridListContainer {
overflow: hidden;
.size(@w: 144px , @h: 447px);
> div:nth-child(1) {
.size(@w: inherit, @h: 447px);
}
}
.upButton {
.size(@w: 144px , @h: 48px);
border: none;
margin-bottom: 4px;
margin-bottom: 10px;
background-position: center;
background-size: cover;
background-image: url("../../../../../assets/images/btn/btn-bk-up-nor.svg");
@@ -31,12 +90,16 @@
&:focus {
background-image: url("../../../../../assets/images/btn/btn-bk-up-foc.svg");
}
&.disable {
opacity: 0.1;
background-image: url("../../../../../assets/images/btn/btn-bk-up-nor.svg");
}
}
.downButton {
.size(@w: 144px , @h: 48px);
border: none;
margin-top: 4px;
margin-top: 10px;
background-position: center;
background-size: cover;
background-image: url("../../../../../assets/images/btn/btn-bk-down-nor.svg");
@@ -44,6 +107,10 @@
&:focus {
background-image: url("../../../../../assets/images/btn/btn-bk-down-foc.svg");
}
&.disable {
opacity: 0.1;
background-image: url("../../../../../assets/images/btn/btn-bk-down-nor.svg");
}
}
.image {
@@ -80,4 +147,6 @@
z-index: 20;
}
//isOptions
}

View File

@@ -21,6 +21,9 @@ import css from './PlayerOverlayChat.module.less';
const SpottableBtn = Spottable("button");
export default function PlayerOverlayChat() {
const dispatch = useDispatch();
const chatData = useSelector((state) => state.play.chatData);
console.log("#chatData", chatData);
const { popupVisible, activePopup } = useSelector(
(state) => state.common.popup
);
@@ -35,11 +38,27 @@ export default function PlayerOverlayChat() {
return (
<>
<div className={css.chatContainer}>
<div className={css.chatHeader} />
<div className={css.contents} />
<div className={css.chatHeader}>LIVE CHAT</div>
<div className={css.contents}>
채팅 내용 입력
<br />
채팅 내용 입력
<br />
채팅 내용 입력
<br />
채팅 내용 입력
<br />
채팅 내용 입력
<br />
채팅 내용 입력
<br />
채팅 내용 입력
<br />
</div>
<TButton className={css.messageBtn} onClick={handleQRCodeClick}>
{"TYPE A MESSAGE"}
</TButton>
<p className={css.chatclose}>X</p>
</div>
{activePopup === ACTIVE_POPUP.qrPopup && (

View File

@@ -2,28 +2,54 @@
@import "../../../style/utils.module.less";
.chatContainer {
.size(@w: 402px , @h: 640px);
.position(@position: absolute, @top: auto, @right: auto, @bottom: 220px, @left: 60px);
padding: 21px 18px 18px 18px;
.size(@w: 406px , @h: 490px);
.position(@position: absolute, @top: 198px, @left: 78px);
padding: 25px 20px 20px;
background-color: #1e1e1e;
border-radius: 10px;
.flex(@display: flex, @justifyCenter: space-between, @alignCenter: "", @direction: column);
.chatHeader {
height: 54px;
font-size: 24px;
font-weight: bold;
line-height: 1.35;
color: @COLOR_WHITE;
position: relative;
z-index: 2;
&::after {
.size(@w:100%, @h:135px);
.position(@position: absolute, @top: 54px, @left: 0);
background-image: linear-gradient(
to bottom,
#1e1e1e,
rgba(30, 30, 30, 0.15)
);
content: "";
z-index: 1;
}
}
.contents {
height: 326px;
// align-items: flex-start;
color: #fff;
}
.messageBtn {
.size(@w: 366px , @h: 60px);
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: auto;
font-size: 24px;
font-weight: bold;
line-height: 1.33;
line-height: 1.35;
text-align: center;
padding: 14px 0;
&:focus {
background-color: #c70850;
}
}
.chatclose {
.position(@position: absolute, @top: 20px, @right: 20px);
}
}
.popupContainer {
.header {

View File

@@ -24,11 +24,17 @@ export default function PlayerOverlayHeader({
<div className={classNames(css.overIcon, css.backLiveicon)}>
<SpottableBtn onClick={onClickBack} className={css.backIcon} />
<div className={panelInfo?.type === "LIVE" && css.liveIcon} />
<img src={playListInfo[selectedIndex]?.patncLogoPath} alt="" />
<h2 className={css.patnerName}>
{playListInfo[selectedIndex]?.patncNm}
</h2>
<h3 className={css.title}>{playListInfo[selectedIndex]?.showNm}</h3>
{playListInfo && (
<img src={playListInfo[selectedIndex]?.patncLogoPath} alt="" />
)}
{playListInfo && (
<>
<h2 className={css.patnerName}>
{playListInfo[selectedIndex]?.patncNm}
</h2>
<h3 className={css.title}>{playListInfo[selectedIndex]?.showNm}</h3>
</>
)}
</div>
{playListInfo && (
<div className={css.disclaimer}>

View File

@@ -21,6 +21,7 @@ import Spottable from '@enact/spotlight/Spottable';
import * as CommonActions from '../../actions/commonActions';
import {
getHomeFullVideoInfo,
getMainCategoryShowDetail,
getMainLiveShowNowProduct,
} from '../../actions/mainActions';
import * as PanelActions from '../../actions/panelActions';
@@ -57,24 +58,42 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
const [playListInfo, setPlayListInfo] = useState("");
const [panelInfo, setPaneInfo] = useState([]);
const [tab, setTab] = useState(0);
const [showItem, setShowItem] = useState(true);
const [sideOpen, setSideOpen] = useState(false);
const [selectedIndex, setSelectedIndex] = useState(0);
const showNowInfos = useSelector((state) => state.main.data);
const panels = useSelector((state) => state.panels.panels);
//VOD
const showDetailInfo = useSelector((state) => state.main.showDetailInfo);
const featuredShowsInfos = useSelector(
(state) => state.main.featuredShowsInfos
);
//라이브
const liveChannelInfos = useSelector((state) => state.main.liveChannelInfos);
const showNowProduct = useSelector((state) => state.main.showNowProduct);
const data = useSelector((state) => state.main.data);
const fullVideoData = useSelector((state) => state.main.fullVideoData);
const panels = useSelector((state) => state.panels.panels);
console.log("#data", data);
console.log("#panels", panels);
console.log("#showDetailInfo", showNowProduct);
console.log("#playListInfo", playListInfo);
const tabList = [
$L("SHOP NOW"),
$L(panelInfo.type === "LIVE" ? "LIVE CHANNEL" : "FEATURED SHOWS"),
];
// 패널 정보 받기
const getPanelInfo = useCallback(() => {
if (panels) {
for (let i = 0; i < panels.length; i++) {
if (panels[i].name === "playerpanel") {
setPaneInfo(panels[i].panelInfo.playInfo);
}
}
}
}, [panelInfo]);
const onClickBack = useCallback(
(ev) => {
dispatch(PanelActions.popPanel());
@@ -121,17 +140,6 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
onClickBack();
}, [dispatch, onClickBack]);
// 패널 정보 받기
const getPanelInfo = useCallback(() => {
if (panels) {
for (let i = 0; i < panels.length; i++) {
if (panels[i].name === "playerpanel") {
setPaneInfo(panels[i].panelInfo.playInfo);
}
}
}
}, [panelInfo]);
const handleUpClick = () => {
if (selectedIndex !== 0) {
setSelectedIndex((prev) => prev + 1);
@@ -145,18 +153,20 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
setSelectedIndex((prev) => prev + 1);
};
console.log("#fullVideoData", fullVideoData);
useEffect(() => {
getPanelInfo();
}, [panels, panelInfo, dispatch]);
useEffect(() => {
if (panelInfo) {
dispatch(
getHomeFullVideoInfo({
lgCatCd: panelInfo.lgCatCd,
})
);
if (panelInfo.type === "VOD") {
dispatch(
getMainCategoryShowDetail({
patnrId: panelInfo.patnrId,
showId: panelInfo.showId,
})
);
}
dispatch(
getMainLiveShowNowProduct({
@@ -165,6 +175,11 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
})
);
dispatch(
getHomeFullVideoInfo({
lgCatCd: panelInfo.lgCatCd,
})
);
dispatch(
getChatLog({ patnrId: panelInfo.patnrId, showId: panelInfo.showId })
);
@@ -172,24 +187,16 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
}, [dispatch, panelInfo, selectedIndex]);
useEffect(() => {
if (showDetailInfo && showDetailInfo.length > 0) {
setPlayListInfo(showDetailInfo[0]);
}
if (panelInfo.type === "LIVE") {
setPlayListInfo(liveChannelInfos);
} else if (panelInfo.type === "VOD") {
setPlayListInfo(featuredShowsInfos);
}
}, [featuredShowsInfos, liveChannelInfos, selectedIndex]);
}, [showDetailInfo, liveChannelInfos, selectedIndex]);
useEffect(() => {
switch (panelInfo.type) {
case "VOD":
if (featuredShowsInfos && featuredShowsInfos.length > 0) {
for (let i = 0; i < featuredShowsInfos.length; i++) {
if (featuredShowsInfos[i].showId === panelInfo.showId) {
setSelectedIndex(i);
}
}
}
break;
case "LIVE":
if (liveChannelInfos && liveChannelInfos.length > 0) {
for (let i = 0; i < liveChannelInfos.length; i++) {
@@ -202,10 +209,6 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
}
}, []);
console.log("#playlist", playListInfo);
console.log("#full", fullVideoData);
console.log("#panelInfo", panelInfo);
useEffect(() => {
if (!isActive) {
unableToPlay.start(toastUnableToPlay);
@@ -229,11 +232,7 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
backButton={backButton()} // 뒤로가기 버튼
>
<source
src={
playListInfo &&
playListInfo.length > 0 &&
playListInfo[selectedIndex].showUrl
}
src={playListInfo && playListInfo?.showUrl}
type="type=application/mpegurl"
/>
@@ -242,11 +241,7 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
) : (
<ReactPlayer
className={""}
url={
playListInfo &&
playListInfo.length > 0 &&
playListInfo[selectedIndex].showUrl
} // 플레이어 url
url={playListInfo && playListInfo?.showUrl} // 플레이어 url
playing={true} // 자동 재생 on = true off = false
muted={false} // 자동 재생 on = true off = false
width={"1920"} // 플레이어 크기 (가로)
@@ -276,7 +271,7 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
show
/>
)}
{panelInfo?.type === "LIVE" && <PlayerOverlayChat />}
<PlayerOverlayChat />
{/* <PlayerOverlayQRCode /> */}
<div
className={classNames(
@@ -301,13 +296,18 @@ const PlayerPanel = ({ hideChildren, isTabActivated, ...props }) => {
listType={LIST_TYPE.small}
/>
{tab === 0 && <ShopNowContents />}
{tab === 0 && (
<ShopNowContents productInfos={playListInfo.productInfos} />
)}
{playListInfo.liveFlag === "N" && tab === 1 && (
<FeaturedShowContents />
)}
{panelInfo.type === "LIVE" && tab === 1 && <LiveChannelContents />}
{showNowProduct !== "undefined" &&
showNowProduct &&
showNowProduct.length < 3 &&
tab === 0 && <YouMayLikeContents />}
{panelInfo.type === "LIVE" && tab === 1 && <LiveChannelContents />}
{panelInfo.type === "VOD" && tab === 1 && <FeaturedShowContents />}
</Container>
)}
</TPanel>

View File

@@ -18,25 +18,24 @@ import { panel_names } from '../../../utils/Config';
import PlayerTabLoading from './PlayerTabLoading';
import css from './ShopNowContents.module.less';
export default function ShopNowContents() {
export default function ShopNowContents({ productInfos }) {
const dispatch = useDispatch();
const showNowProduct = useSelector((state) => state.main.showNowProduct);
const [height, setHeight] = useState();
const gridStyle = useMemo(() => ({ height: `${height}px` }), [height]);
useEffect(() => {
if (showNowProduct && showNowProduct.length < 3) {
if (productInfos && productInfos.length < 3) {
return;
} else {
setHeight(956);
}
}, [showNowProduct]);
}, [productInfos]);
const renderItem = useCallback(
({ index, ...rest }) => {
const { imgUrls600, patnrId, prdtId, prdtNm, priceInfo, offerInfo } =
showNowProduct[index];
productInfos[index];
const handleItemClick = () => {
dispatch(
@@ -64,15 +63,15 @@ export default function ShopNowContents() {
/>
);
},
[showNowProduct]
[productInfos]
);
return (
<>
<div className={css.container}>
{showNowProduct && showNowProduct.length > 0 ? (
{productInfos && productInfos.length > 0 ? (
<TVirtualGridList
style={gridStyle}
dataSize={showNowProduct.length}
dataSize={productInfos.length}
direction="vertical"
renderItem={renderItem}
itemWidth={600}

View File

@@ -1,13 +1,16 @@
import React, { memo, useCallback } from "react";
import React, {
memo,
useCallback,
} from 'react';
import { useDispatch } from "react-redux";
import { useDispatch } from 'react-redux';
import Spottable from "@enact/spotlight/Spottable";
import Spottable from '@enact/spotlight/Spottable';
import IcLiveShow from "../../../../../assets/images/tag/tag-liveshow.svg";
import { pushPanel } from "../../../../actions/panelActions";
import { panel_names } from "../../../../utils/Config";
import css from "./SearchShowCard.module.less";
import IcLiveShow from '../../../../../assets/images/tag/tag-liveshow.svg';
import { pushPanel } from '../../../../actions/panelActions';
import { panel_names } from '../../../../utils/Config';
import css from './SearchShowCard.module.less';
const CardContainer = Spottable("div");
@@ -32,8 +35,11 @@ export default memo(function SearchShowCard({
pushPanel({
name: panel_names.PLAYER_PANEL,
panelInfo: {
patnrId: partnerId,
showId: showId,
playInfo: {
patnrId: partnerId,
showId: showId,
type: "VOD",
},
},
})
);