293 lines
7.4 KiB
JavaScript
293 lines
7.4 KiB
JavaScript
import React, {
|
|
memo,
|
|
use,
|
|
useCallback,
|
|
useEffect,
|
|
useMemo,
|
|
useState,
|
|
} from "react";
|
|
|
|
import classNames from "classnames";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
|
|
import Spottable from "@enact/spotlight/Spottable";
|
|
|
|
import defaultLogoImg from "../../../assets/images/ic-tab-partners-default@3x.png";
|
|
import defaultimgHorizontal from "../../../assets/images/img-thumb-empty-hor@3x.png";
|
|
import defaultImageItem from "../../../assets/images/img-thumb-empty-product@3x.png";
|
|
import defaultimgVertical from "../../../assets/images/img-thumb-empty-ver@3x.png";
|
|
import IcLiveShow from "../../../assets/images/tag/tag-liveshow.png";
|
|
import usePriceInfo from "../../hooks/usePriceInfo";
|
|
import { $L, removeSpecificTags } from "../../utils/helperMethods";
|
|
import CustomImage from "../CustomImage/CustomImage";
|
|
import css1 from "./TItemCard.module.less";
|
|
import css2 from "./TItemCard.v2.module.less";
|
|
import { sendLogTotalRecommend } from "../../actions/logActions";
|
|
|
|
const SpottableComponent = Spottable("div");
|
|
|
|
const TYPES = {
|
|
vertical: "vertical",
|
|
horizontal: "horizontal",
|
|
videoShow: "videoShow",
|
|
};
|
|
|
|
const IMAGETYPES = {
|
|
imgHorizontal: "imgHorizontal",
|
|
imgVertical: "imgVertical",
|
|
};
|
|
|
|
const STRING_CONF = {
|
|
SOLD_OUT: "SOLD OUT",
|
|
};
|
|
|
|
export const removeDotAndColon = (string) => {
|
|
return /[.:]/.test(string) ? string.replace(/[.:]/g, "") : string;
|
|
};
|
|
|
|
export default memo(function TItemCard({
|
|
children,
|
|
className,
|
|
disabled,
|
|
imageAlt,
|
|
imageSource,
|
|
imgType = IMAGETYPES.imgHorizontal,
|
|
logo,
|
|
logoDisplay = false,
|
|
isBestSeller = false,
|
|
isLive = false,
|
|
onBlur,
|
|
onClick,
|
|
onFocus,
|
|
onError,
|
|
offerInfo,
|
|
priceInfo,
|
|
productId,
|
|
productName,
|
|
catNm,
|
|
rank,
|
|
soldoutFlag,
|
|
spotlightId,
|
|
nonPosition = false,
|
|
type = TYPES.vertical,
|
|
firstLabel,
|
|
label,
|
|
lastLabel,
|
|
contextName,
|
|
messageId,
|
|
order,
|
|
patnerName,
|
|
brandName,
|
|
shelfId,
|
|
shelfLocation,
|
|
shelfTitle,
|
|
contentTitle,
|
|
category,
|
|
curationId,
|
|
curationTitle,
|
|
nowProductId,
|
|
nowCategory,
|
|
nowProductTitle,
|
|
showId,
|
|
showTitle,
|
|
contentId,
|
|
version = 1,
|
|
...rest
|
|
}) {
|
|
const css = version === 2 ? css2 : css1;
|
|
const dispatch = useDispatch();
|
|
const [defaultImage, setDefaultImage] = useState(null);
|
|
const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd);
|
|
|
|
useEffect(() => {
|
|
if (!imageSource) {
|
|
if (type === "videoShow") {
|
|
setDefaultImage(
|
|
imgType === IMAGETYPES.imgHorizontal
|
|
? defaultimgHorizontal
|
|
: defaultimgVertical
|
|
);
|
|
} else {
|
|
setDefaultImage(defaultImageItem);
|
|
}
|
|
}
|
|
}, [imageSource, type, imgType]);
|
|
|
|
const { originalPrice, discountedPrice, discountRate } =
|
|
usePriceInfo(priceInfo) || {};
|
|
|
|
const _onBlur = useCallback(() => {
|
|
if (onBlur) {
|
|
onBlur();
|
|
}
|
|
}, [onBlur]);
|
|
|
|
const _onClick = useCallback(
|
|
(e) => {
|
|
if (disabled) {
|
|
e.stopPropagation();
|
|
return;
|
|
}
|
|
|
|
if (onClick) {
|
|
onClick(e);
|
|
if (contextName && messageId) {
|
|
const params = {
|
|
contextName: contextName,
|
|
messageId: messageId,
|
|
shelfLocation: shelfLocation,
|
|
shelfId: shelfId,
|
|
shelfTitle: shelfTitle,
|
|
productId: productId,
|
|
productTitle: productName,
|
|
showId: showId ?? contentId,
|
|
showTitle: showTitle ?? contentTitle,
|
|
contentId: contentId,
|
|
nowProductId: nowProductId,
|
|
nowCategory: nowCategory,
|
|
nowProductTitle: nowProductTitle,
|
|
partner: patnerName,
|
|
brand: brandName,
|
|
price: originalPrice,
|
|
discount: discountRate,
|
|
location: order,
|
|
category: category ? category : catNm,
|
|
contentTitle: contentTitle,
|
|
curationId: curationId,
|
|
curationTitle: curationTitle,
|
|
};
|
|
dispatch(sendLogTotalRecommend(params));
|
|
}
|
|
}
|
|
},
|
|
[onClick, disabled, contextName, messageId, contentId, contentTitle]
|
|
);
|
|
const _onFocus = useCallback(() => {
|
|
if (onFocus) {
|
|
onFocus();
|
|
}
|
|
}, [onFocus]);
|
|
const addDefaultImg = useCallback(
|
|
(e) => {
|
|
// console.log("###titemcard", e);
|
|
},
|
|
[onError]
|
|
);
|
|
|
|
const prdtNum = label ? label : "";
|
|
const discountLabel = discountRate ? discountRate + " discount," : "";
|
|
const discountpriceLabel = discountRate
|
|
? "Sale price " + discountedPrice + ", "
|
|
: "";
|
|
|
|
const priceLabel =
|
|
originalPrice && parseFloat(originalPrice.replace("$", "")) === 0
|
|
? offerInfo
|
|
? " " + offerInfo
|
|
: ""
|
|
: originalPrice
|
|
? " Original price " + originalPrice + ", "
|
|
: "";
|
|
const lastLabeltext = lastLabel ? lastLabel : "";
|
|
const firstLabeltext = firstLabel ? firstLabel + " " : "";
|
|
const soldOutText = soldoutFlag === "Y" ? "Sold Out " : "";
|
|
const ariaLabel =
|
|
soldOutText +
|
|
firstLabeltext +
|
|
discountLabel +
|
|
productName +
|
|
discountpriceLabel +
|
|
priceLabel +
|
|
prdtNum +
|
|
lastLabeltext;
|
|
|
|
const productNameDangerousHTML = useMemo(() => {
|
|
const sanitizedString = removeSpecificTags(productName);
|
|
|
|
return sanitizedString;
|
|
}, [productName]);
|
|
return (
|
|
<SpottableComponent
|
|
className={classNames(
|
|
css[type],
|
|
nonPosition && css.nonPosition,
|
|
type === "videoShow" && css[imgType],
|
|
className && className
|
|
)}
|
|
onBlur={_onBlur}
|
|
onClick={_onClick}
|
|
onFocus={_onFocus}
|
|
spotlightId={spotlightId ?? "spotlightId-" + removeDotAndColon(productId)}
|
|
aria-label={ariaLabel}
|
|
role=""
|
|
{...rest}
|
|
>
|
|
<div className={css.imageWrap}>
|
|
<CustomImage
|
|
alt={imageAlt}
|
|
delay={0}
|
|
src={imageSource}
|
|
fallbackSrc={
|
|
type === "videoShow"
|
|
? imgType === IMAGETYPES.imgHorizontal
|
|
? defaultimgHorizontal
|
|
: defaultimgVertical
|
|
: defaultImageItem
|
|
}
|
|
/>
|
|
{priceInfo &&
|
|
discountRate &&
|
|
Number(discountRate.replace("%", "")) > 4 && (
|
|
<span>{discountRate}</span>
|
|
)}
|
|
{soldoutFlag && soldoutFlag === "Y" && (
|
|
<div
|
|
className={classNames(css.soldout, countryCode === "DE" && css.de)}
|
|
>
|
|
{$L(STRING_CONF.SOLD_OUT)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className={classNames(css.descWrap, catNm && css.hstNmWrap)}>
|
|
{logo && (
|
|
<div className={css.logo}>
|
|
<CustomImage src={logo} fallbackSrc={defaultLogoImg} />
|
|
</div>
|
|
)}
|
|
|
|
<div className={css.title}>
|
|
<h3
|
|
className={css.productNameTitle}
|
|
dangerouslySetInnerHTML={{ __html: productNameDangerousHTML }}
|
|
/>
|
|
</div>
|
|
|
|
{priceInfo ? (
|
|
<p className={css.priceInfo}>
|
|
{parseFloat(originalPrice.replace(/[^0-9.-]+/g, "")) === 0 ? (
|
|
<strong>{offerInfo}</strong>
|
|
) : discountRate ? (
|
|
discountedPrice
|
|
) : (
|
|
originalPrice
|
|
)}
|
|
{discountRate && <span>{originalPrice}</span>}
|
|
</p>
|
|
) : (
|
|
<p className={css.offerInfo}>{offerInfo}</p>
|
|
)}
|
|
</div>
|
|
|
|
{isBestSeller && rank && (
|
|
<div className={css.bestSeller}>
|
|
<span>{rank}</span>
|
|
</div>
|
|
)}
|
|
{isLive && <img className={css.liveTag} src={IcLiveShow} alt="" />}
|
|
</SpottableComponent>
|
|
);
|
|
});
|
|
|
|
export { IMAGETYPES, TYPES };
|