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", | |
| };
 | |
| 
 |