You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
293 lines
11 KiB
293 lines
11 KiB
import React, { useState, useEffect } from "react"; |
|
import { connect } from "react-redux"; |
|
import { toast } from "react-toastify"; |
|
import { book, userProduct, publicApi, dialog } from "../../redux/actions"; |
|
import { Link, useNavigate } from "react-router-dom"; |
|
import proxy from "../../redux/proxy"; |
|
import location from "../../utils/location"; |
|
import separate from "../../utils/separate"; |
|
|
|
//components |
|
import Button from "../../components/Button"; |
|
import Header from "../../components/Header"; |
|
import Comment from "./Comment"; |
|
import Rate from "./Rate"; |
|
import DesktopProductLayout from "./Desktop"; |
|
import Loading from "../../components/Loading"; |
|
import ButtonBetween from "../../components/ButtonBetween"; |
|
|
|
//assets |
|
import arrow from "../../assets/icons/dropdown-blue.svg"; |
|
|
|
export const Product = ({ |
|
isMobile, |
|
productType, |
|
userProducts, |
|
getInfo, |
|
book, |
|
grades, |
|
isDark, |
|
userId, |
|
pushToCart, |
|
headerOptions, |
|
userProductLoading, |
|
setHeaderOptions, |
|
availableForSell, |
|
setDialog, |
|
}) => { |
|
const [whichTypeAdded, setWhichTypeAdded] = React.useState(null); |
|
const [desktopContentTransform, setDesktopContentTransform] = useState(false); |
|
const navigation = useNavigate(); |
|
|
|
const physicalAvailableForSell = React.useMemo(() => { |
|
return availableForSell?.find((product) => product === 2); |
|
}, [availableForSell]); |
|
|
|
const digitalAvailableForSell = React.useMemo(() => { |
|
return availableForSell?.find((product) => product === 1); |
|
}, [availableForSell]); |
|
|
|
const videoAvailableForSell = React.useMemo(() => { |
|
return availableForSell?.find((product) => product === 4); |
|
}, [availableForSell]); |
|
|
|
const physicalProduct = React.useMemo(() => { |
|
return book?.product?.find((product) => product?.productType === 2); |
|
}, [book]); |
|
|
|
const digitalProduct = React.useMemo(() => { |
|
return book?.product?.find((product) => product?.productType === 1); |
|
}, [book]); |
|
|
|
const videoProduct = React.useMemo(() => { |
|
return book?.product?.find((product) => product?.productType === 4); |
|
}, [book]); |
|
|
|
const physicalAvailabileInCart = React.useMemo(() => { |
|
return userProducts?.find( |
|
(product) => |
|
product?.productId === physicalProduct?.id && product?.condition < 2 |
|
); |
|
}, [userProducts, book]); |
|
|
|
const digitalAvailabileInCart = React.useMemo(() => { |
|
return userProducts?.find( |
|
(product) => |
|
product?.productId === digitalProduct?.id && product?.condition < 2 |
|
); |
|
}, [userProducts, book]); |
|
|
|
const videoAvailabileInCart = React.useMemo(() => { |
|
return userProducts?.find( |
|
(product) => |
|
product?.productId === videoProduct?.id && product?.condition < 2 |
|
); |
|
}, [userProducts, book]); |
|
|
|
useEffect(() => { |
|
if(!isMobile){ |
|
setHeaderOptions(headerOptions); |
|
|
|
} |
|
getInfo({ id: location.getId(), vod: true }); |
|
if (!isMobile) { |
|
window.addEventListener("scroll", () => { |
|
if (window.scrollY >= 64) { |
|
setDesktopContentTransform(() => true); |
|
} else { |
|
setDesktopContentTransform(() => false); |
|
} |
|
}); |
|
} |
|
}, []); |
|
|
|
useEffect(() => { |
|
if (!userProductLoading) { |
|
setWhichTypeAdded(null); |
|
} |
|
}, [userProductLoading]); |
|
|
|
useEffect(() => { |
|
if (book && isMobile) { |
|
setHeaderOptions({ ...headerOptions, productId: book?.id }); |
|
window.scroll({ top: 0, behavior: "smooth" }); |
|
} |
|
}, [book]); |
|
return ( |
|
<> |
|
{/* Portrait */} |
|
{isMobile ? ( |
|
<div className="w-full flex flex-col bg-transparent px-4 pb-24"> |
|
{!book && ( |
|
<div className="w-full h-screen flex justify-center items-center bg-white bg-opacity-20 backdrop-filter backdrop-blur-xl fixed left-0 top-0 z-50"> |
|
<Loading size={4} color="bg-green-400" /> |
|
</div> |
|
)} |
|
<header |
|
className={`w-full flex ${ |
|
productType === "book" ? "flex-row" : "flex-col" |
|
}`} |
|
> |
|
<img |
|
src={`https://dnvn.ir/api/v1/file/${book?.fileIds}`} |
|
alt="" |
|
className="w-5/12 rounded-sm object-contain" |
|
/> |
|
<div className="flex flex-1 flex-col pr-2 pt-2"> |
|
<h1 className="text-blue5F mb-3 font-semibold text-base dark:text-white"> |
|
{book?.name} |
|
</h1> |
|
<div className="text-green7B text-tiny dark:text-greenBA"> |
|
{window.t("پایه") + " " + grades[book?.gradeId]} |
|
</div> |
|
</div> |
|
</header> |
|
<ul |
|
className="list-none flex divide-x items-center mt-5" |
|
style={{ direction: "ltr" }} |
|
> |
|
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white"> |
|
{book?.pagesNum} <br /> {window.t("صفحه")} |
|
</li> |
|
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white"> |
|
{window.t("فیزیکی - دیجیتالی")} |
|
<br /> {window.t("در دسترس")} |
|
</li> |
|
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white"> |
|
{book?.rate} <br /> |
|
{window.t("امتیاز")} |
|
</li> |
|
{book?.rate ? ( |
|
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white"> |
|
{book?.rate} <br /> امتیاز |
|
</li> |
|
) : null} |
|
</ul> |
|
<h2 className="text-green7B text-base font-semibold mt-10 dark:text-greenBA"> |
|
{window.t("نسخه محصول را انتخاب کنید")} |
|
</h2> |
|
<div className="w-full flex flex-row justify-between items-center mt-5"> |
|
<ButtonBetween |
|
width="100%" |
|
item={window.t("خرید نسخه فیزیکی کتاب")} |
|
status={ |
|
separate(book?.product[1]?.price) + " " + window.t("تومان") |
|
} |
|
onClick={() => |
|
userId |
|
? pushToCart({ |
|
productId: book?.product[1]?.id, |
|
userId, |
|
count: 1, |
|
}) |
|
: toast.info(window.t("ابتدا وارد حساب کاربری خود شوید")) |
|
} |
|
/> |
|
</div> |
|
<div className="w-full flex flex-row justify-between items-center mt-4 gap-2"> |
|
<ButtonBetween |
|
width="72%" |
|
item={window.t("خرید نسخه دیجیتال کتاب")} |
|
status={ |
|
separate(book?.product[0]?.price) + " " + window.t("تومان") |
|
} |
|
onClick={() => |
|
userId |
|
? pushToCart({ |
|
productId: book?.product[0]?.id, |
|
userId, |
|
count: 1, |
|
}) |
|
: toast.info(window.t("ابتدا وارد حساب کاربری خود شوید.")) |
|
} |
|
/> |
|
<a |
|
href={`https://dnvn.ir/xpdf/${book?.sampleFileId}`} |
|
className="flex-1 border-2 border-solid text-sm border-green-500 bg-green-50 bg-opacity-70 rounded-sm font-bold text-green-700 text-center" |
|
style={{ padding: "18px 0px" }} |
|
> |
|
{window.t("مشاهده نمونه")} |
|
</a> |
|
</div> |
|
<div className="w-full flex flex-row justify-between items-center mt-4"> |
|
<ButtonBetween |
|
width="72%" |
|
item={window.t("خرید نسخه ویدئویی کتاب")} |
|
status={ |
|
separate(book?.product[2]?.price) + " " + window.t("تومان") |
|
} |
|
onClick={() => |
|
userId |
|
? pushToCart({ |
|
productId: book?.product[2]?.id, |
|
userId, |
|
count: 1, |
|
}) |
|
: toast.info(window.t("ابتدا وارد حساب کاربری خود شوید.")) |
|
} |
|
/> |
|
<ButtonBetween |
|
width="25%" |
|
item={window.t("پیش نمایش")} |
|
onClick={() => navigation("/videos/" + book?.id)} |
|
/> |
|
</div> |
|
<div className="w-full flex flex-col justify-between items-center mt-8"> |
|
<Header title={window.t("توضیحات")} link="#" /> |
|
<p className="text-sm text-gray70 mt-2 dark:text-white leading-6"> |
|
خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ |
|
ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ” ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ |
|
ﻫﺮﮔﺰ ﺩﺯﺩﯼ ﻧﮑﻦ ” ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻭ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻭ |
|
ﻫﺮﮔﺰ ﺩﺳﺖ ﮐﺞ ﻧﺪﺍﺷﺘﻪ ﭘﺪﺭ ﺑﻪ ﻧﮕﺎﻩ ﻣﺘﻌﺠﺐ ﻓﺮﺯﻧﺪ ﻟﺒﺨﻨﺪﯼ ﺯﺩ ﻭ ﺍﺩﺍﻣﻪ ﺩﺍﺩ : |
|
ﺩﺭ ﺯﻧﺪﮔﯽ ﺩﺭﻭﻍ ﻧﮕﻮ ﭼﺮﺍ ﮐﻪ ﺍﮔﺮ ﮔﻔﺘﯽ ﺻﺪﺍﻗﺖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺧﯿﺎﻧﺖ ﻧﮑﻦ ﮐﻪ |
|
ﺍﮔﺮ ﮐﺮﺩﯼ ﻋﺸﻖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺧﺸﻮﻧﺖ ﻧﮑﻦ ﺍﮔﺮ ﮐﺮﺩﯼ ﻣﺤﺒﺖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، |
|
ﻧﺎ ﺣﻖ ﻧﮕﻮ ﺍﮔﺮ ﮔﻔﺘﯽ ﺣﻖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺑﯽ ﺣﯿﺎﯾﯽ ﻧﮑﻦ ﺍﮔﺮ ﮐﺮﺩﯼ ﺷﺮﺍﻓﺖ ﺭﺍ |
|
ﺩﺯﺩﯾﺪﻩ ﺍی... ﭘﺲ ﺩﺭ ﺯﻧﺪﮔﯽ ﻓﻘﻂ ﺩﺯﺩﯼ نکن |
|
</p> |
|
</div> |
|
<div className="w-full flex flex-col justify-between items-center mt-10"> |
|
<Header title={window.t("امتیازات و نظرات")} link="#" /> |
|
<Rate value={book?.rate || 0} /> |
|
</div> |
|
<div |
|
className="flex w-full pb-4 mt-10 no-scrollbar" |
|
style={{ overflowX: "scroll" }} |
|
> |
|
{book?.comment?.map((comment, index) => ( |
|
<Comment comment={comment} key={index} /> |
|
))} |
|
</div> |
|
</div> |
|
) : ( |
|
<div className="flex flex-col items-center justify-center lg:py-24"> |
|
<DesktopProductLayout physicalProduct={physicalProduct} rate={book?.rate || 0} /> |
|
</div> |
|
)} |
|
</> |
|
); |
|
}; |
|
|
|
const mapStateToProps = (state) => ({ |
|
book: state.book.info, |
|
grades: state.publicApi.grades, |
|
isMobile: state.publicApi.isMobile, |
|
isDark: state.publicApi.isDark, |
|
userId: state.user.status?.id, |
|
bookmarkLoading: state.userFavorite.loading, |
|
availableForSell: state.config.availableForSell, |
|
userProduct: state.userProduct.list, |
|
userProductLoading: state.userProduct.loading, |
|
}); |
|
|
|
const mapDispatchToProps = { |
|
getInfo: book.info, |
|
pushToCart: userProduct.add, |
|
setHeaderOptions: publicApi.setHeaderOptions, |
|
setDialog: dialog.set, |
|
}; |
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(Product); |
|
|
|
Product.defaultProps = { |
|
productType: "book", |
|
};
|
|
|