reza added something

temp
Reza_ashrafi 3 years ago
parent 8d372deb20
commit cba7108f93
  1. 4
      src/assets/icons/arrow-right-blue.svg
  2. 6
      src/assets/icons/bookmark-deactive-light.svg
  3. 8
      src/assets/icons/dots-menu-light.svg
  4. 2
      src/assets/icons/dropdown-blue.svg
  5. 4
      src/components/BottomNavigation/index.js
  6. 4
      src/components/Button/index.js
  7. 81
      src/components/CourseChapter/index.js
  8. 2
      src/components/Divider/index.js
  9. 9
      src/components/Drawer/index.js
  10. 2
      src/components/Input/index.js
  11. 2
      src/components/JolPlayer/index.js
  12. 3
      src/components/Navbar/index.js
  13. 2
      src/components/Radio/index.js
  14. 4
      src/components/Radio/index.scss
  15. 5
      src/components/Select/index.js
  16. 18
      src/redux/reducers/public.js
  17. 13
      src/router.js
  18. 13
      src/views/404/index.js
  19. 132
      src/views/Address/index.js
  20. 65
      src/views/Blog/index.js
  21. 28
      src/views/Blogs/index.js
  22. 6
      src/views/Blogs/layouts/Hashtags.js
  23. 6
      src/views/Blogs/layouts/Header.js
  24. 44
      src/views/Blogs/layouts/Join.js
  25. 27
      src/views/Blogs/layouts/New.js
  26. 50
      src/views/Blogs/layouts/Single.js
  27. 65
      src/views/Blogs/layouts/Target.js
  28. 86
      src/views/DeliveryForm/Address/index.js
  29. 25
      src/views/DeliveryForm/TransportDate/index.js
  30. 55
      src/views/DeliveryForm/TransportMethod/index.js
  31. 62
      src/views/DeliveryForm/index.js
  32. 4
      src/views/Home/Portrait/Private/Blogs/index.js
  33. 11
      src/views/Home/Portrait/Private/Videos/index.js
  34. 2
      src/views/Home/Portrait/Private/index.js
  35. 4
      src/views/Product/Comment/index.js
  36. 47
      src/views/Product/index.js
  37. 4
      src/views/Products/layouts/Mobile/Header.js
  38. 30
      src/views/Products/layouts/Mobile/Main.js
  39. 12
      src/views/QR/Scan/index.js
  40. 2
      src/views/ShoppingCart/Code/index.js
  41. 42
      src/views/ShoppingCart/Product/index.js
  42. 90
      src/views/ShoppingCart/index.js
  43. 90
      src/views/Video/components/Season.js
  44. 117
      src/views/Video/index.js
  45. 86
      src/views/VideoDisplay/index.js
  46. 22
      src/views/Videos/components/MostViewedVideo.js
  47. 12
      src/views/Videos/components/NewestVideo.js
  48. 12
      src/views/Videos/index.js

@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="vuesax_linear_arrow-right" data-name="vuesax/linear/arrow-right" transform="translate(-620 -188)"> <g id="vuesax_linear_arrow-right" data-name="vuesax/linear/arrow-right" transform="translate(-620 -188)">
<g id="arrow-right"> <g id="arrow-right">
<path id="Vector" d="M0,0,6.07,6.07,0,12.14" transform="translate(634.43 193.93)" fill="none" stroke="#196ec0" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/> <path id="Vector" d="M0,0,6.07,6.07,0,12.14" transform="translate(634.43 193.93)" fill="none" stroke="rgb(19, 123, 79)" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/>
<path id="Vector-2" data-name="Vector" d="M0,0H16.83" transform="translate(623.5 200)" fill="none" stroke="#196ec0" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/> <path id="Vector-2" data-name="Vector" d="M0,0H16.83" transform="translate(623.5 200)" fill="none" stroke="rgb(19, 123, 79)" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/>
<path id="Vector-3" data-name="Vector" d="M0,0H24V24H0Z" transform="translate(644 212) rotate(180)" fill="none" opacity="0"/> <path id="Vector-3" data-name="Vector" d="M0,0H24V24H0Z" transform="translate(644 212) rotate(180)" fill="none" opacity="0"/>
</g> </g>
</g> </g>

Before

Width:  |  Height:  |  Size: 743 B

After

Width:  |  Height:  |  Size: 761 B

@ -1,8 +1,8 @@
<svg id="vuesax_linear_archive-add" data-name="vuesax/linear/archive-add" xmlns="http://www.w3.org/2000/svg" width="29.778" height="29.778" viewBox="0 0 29.778 29.778"> <svg id="vuesax_linear_archive-add" data-name="vuesax/linear/archive-add" xmlns="http://www.w3.org/2000/svg" width="29.778" height="29.778" viewBox="0 0 29.778 29.778">
<g id="archive-add" transform="translate(0)"> <g id="archive-add" transform="translate(0)">
<path id="Vector" d="M6.2,0H0" transform="translate(11.787 13.214)" fill="none" stroke="#196ec0" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/> <path id="Vector" d="M6.2,0H0" transform="translate(11.787 13.214)" fill="none" stroke="rgb(19, 123, 79)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-2" data-name="Vector" d="M0,0V6.2" transform="translate(14.889 10.187)" fill="none" stroke="#196ec0" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/> <path id="Vector-2" data-name="Vector" d="M0,0V6.2" transform="translate(14.889 10.187)" fill="none" stroke="rgb(19, 123, 79)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-3" data-name="Vector" d="M16.75,0H4.789A4.8,4.8,0,0,0,0,4.789V22.272c0,2.233,1.6,3.176,3.561,2.1l6.055-3.362a2.628,2.628,0,0,1,2.32,0l6.055,3.362c1.96,1.092,3.561.149,3.561-2.1V4.789A4.819,4.819,0,0,0,16.75,0Z" transform="translate(4.119 2.482)" fill="none" stroke="#196ec0" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/> <path id="Vector-3" data-name="Vector" d="M16.75,0H4.789A4.8,4.8,0,0,0,0,4.789V22.272c0,2.233,1.6,3.176,3.561,2.1l6.055-3.362a2.628,2.628,0,0,1,2.32,0l6.055,3.362c1.96,1.092,3.561.149,3.561-2.1V4.789A4.819,4.819,0,0,0,16.75,0Z" transform="translate(4.119 2.482)" fill="none" stroke="rgb(19, 123, 79)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-4" data-name="Vector" d="M0,0H29.778V29.778H0Z" fill="none" opacity="0"/> <path id="Vector-4" data-name="Vector" d="M0,0H29.778V29.778H0Z" fill="none" opacity="0"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -1,10 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" width="29.778" height="29.778" viewBox="0 0 29.778 29.778"> <svg xmlns="http://www.w3.org/2000/svg" width="29.778" height="29.778" viewBox="0 0 29.778 29.778">
<g id="vuesax_linear_more" data-name="vuesax/linear/more" transform="translate(29.778) rotate(90)"> <g id="vuesax_linear_more" data-name="vuesax/linear/more" transform="translate(29.778) rotate(90)">
<g id="more"> <g id="more">
<path id="Vector" d="M2.482,0A2.482,2.482,0,1,0,4.963,2.482,2.489,2.489,0,0,0,2.482,0Z" transform="translate(3.722 12.408)" fill="#196ec0"/> <path id="Vector" d="M2.482,0A2.482,2.482,0,1,0,4.963,2.482,2.489,2.489,0,0,0,2.482,0Z" transform="translate(3.722 12.408)" fill="rgb(19, 123, 79)"/>
<path id="Vector-2" data-name="Vector" d="M2.482,0A2.482,2.482,0,1,0,4.963,2.482,2.489,2.489,0,0,0,2.482,0Z" transform="translate(21.093 12.408)" fill="#196ec0"/> <path id="Vector-2" data-name="Vector" d="M2.482,0A2.482,2.482,0,1,0,4.963,2.482,2.489,2.489,0,0,0,2.482,0Z" transform="translate(21.093 12.408)" fill="rgb(19, 123, 79)"/>
<path id="Vector-3" data-name="Vector" d="M2.482,0A2.482,2.482,0,1,0,4.963,2.482,2.489,2.489,0,0,0,2.482,0Z" transform="translate(12.408 12.408)" fill="#196ec0"/> <path id="Vector-3" data-name="Vector" d="M2.482,0A2.482,2.482,0,1,0,4.963,2.482,2.489,2.489,0,0,0,2.482,0Z" transform="translate(12.408 12.408)" fill="rgb(19, 123, 79)"/>
<path id="Vector-4" data-name="Vector" d="M0,0H29.778V29.778H0Z" transform="translate(0 0)" fill="#196ec0" opacity="0"/> <path id="Vector-4" data-name="Vector" d="M0,0H29.778V29.778H0Z" transform="translate(0 0)" fill="rgb(19, 123, 79)" opacity="0"/>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 855 B

After

Width:  |  Height:  |  Size: 891 B

@ -1,4 +1,4 @@
<svg id="vuesax_linear_arrow-down" data-name="vuesax/linear/arrow-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <svg id="vuesax_linear_arrow-down" data-name="vuesax/linear/arrow-down" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<g id="arrow-down"> <g id="arrow-down">
<path id="Vector" d="M15.84,0,9.32,6.52a1.986,1.986,0,0,1-2.8,0L0,0" transform="translate(4.08 8.95)" fill="none" stroke="rgb(19, 123, 79)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/> <path id="Vector" d="M15.84,0,9.32,6.52a1.986,1.986,0,0,1-2.8,0L0,0" transform="translate(4.08 8.95)" fill="none" stroke="rgb(19, 123, 79)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<path id="Vector-2" data-name="Vector" d="M0,0H24V24H0Z" transform="translate(24 24) rotate(180)" fill="none" opacity="0"/> <path id="Vector-2" data-name="Vector" d="M0,0H24V24H0Z" transform="translate(24 24) rotate(180)" fill="none" opacity="0"/>

Before

Width:  |  Height:  |  Size: 525 B

After

Width:  |  Height:  |  Size: 525 B

@ -26,11 +26,11 @@ export const BottomNavigation = ({ pages, isDark }) => {
onClick={() => setActiveLink(page.link)} onClick={() => setActiveLink(page.link)}
> >
<img <img
className="w-8 h-8 mx-auto" className="w-7 h-7 mx-auto"
src={activeLink === page.link ? page.activeIcon : page.deactiveIcon} src={activeLink === page.link ? page.activeIcon : page.deactiveIcon}
alt="" alt=""
/> />
<span className="text-blueB9 text-sm text-center font-bold mt-1"> <span className="text-blueB9 text-xs text-center font-bold mt-1">
{page.name} {page.name}
</span> </span>
</NavLink> </NavLink>

@ -17,11 +17,11 @@ export default function Button({
}) { }) {
return ( return (
<button <button
className={`rounded-md flex py-3 justify-center text-sm lg:text-tiny ${ className={`rounded-md flex py-3 justify-center text-base lg:text-tiny ${
disabled ? "cursor-not-allowed" : "cursor-pointer" disabled ? "cursor-not-allowed" : "cursor-pointer"
} font-bold lg:py-4 ${ } font-bold lg:py-4 ${
selectable ? (active ? "bg-black" : backgroundColor) : backgroundColor selectable ? (active ? "bg-black" : backgroundColor) : backgroundColor
} ${selectable ? (active ? "text-green7B" : color) : color} ${ } ${selectable ? (active ? "text-blueC0" : color) : color} ${
selectable ? (active ? "bg-blueC0 bg-opacity-5" : bgOpacity) : bgOpacity selectable ? (active ? "bg-blueC0 bg-opacity-5" : bgOpacity) : bgOpacity
} `} } `}
style={{ style={{

@ -12,6 +12,7 @@ const CourseChapter = ({
selectedVideo, selectedVideo,
userId, userId,
setVideoActive, setVideoActive,
isMobile
}) => { }) => {
const duration = (value) => { const duration = (value) => {
const minute = value % 60; const minute = value % 60;
@ -26,13 +27,13 @@ const CourseChapter = ({
}; };
return ( return (
<section <section
className={`bg-green1 bg-opacity-10 shadow-md py-5 pr-5 overflow-hidden flex flex-col rounded-md`} className={`bg-transparent lg:bg-green1 bg-opacity-10 lg:bg-opacity-10 lg:shadow-md lg:py-5 lg:pr-5 overflow-hidden flex flex-col rounded-md`}
style={{ style={{
minWidth: "calc(100% / 12 * 3.5)", minWidth: "calc(100% / 12 * 3.5)",
height: "calc(100vh - 300px)", height: isMobile ? "auto" :"calc(100vh - 300px)",
}} }}
> >
<div className="flex flex-row w-full items-center justify-between"> <div className="hidden lg:flex flex-row w-full items-center justify-between">
<div> <div>
<h2 className="text-green7B bg-opacity-5 text-base font-semibold"> <h2 className="text-green7B bg-opacity-5 text-base font-semibold">
سرفصل دوره سرفصل دوره
@ -45,8 +46,8 @@ const CourseChapter = ({
</span> </span>
</div> </div>
</div> </div>
<span className="w-full h-px bg-blue-200 my-4"></span> <span className="hidden lg:flex w-full h-px bg-blue-200 my-4"></span>
<div className="overflow-y-scroll w-full hasScrollbar flex-1 flex flex-col"> <div className="lg:overflow-y-scroll w-full hasScrollbar flex-1 flex flex-col">
<div className="bg-green-600 rounded-sm p-4 flex flex-row items-center justify-between mb-2"> <div className="bg-green-600 rounded-sm p-4 flex flex-row items-center justify-between mb-2">
<p className="text-tiny font-bold text-white"> <p className="text-tiny font-bold text-white">
{seasons?.length > 0 && {seasons?.length > 0 &&
@ -58,7 +59,7 @@ const CourseChapter = ({
</div> </div>
{playList?.map((video, index) => ( {playList?.map((video, index) => (
<div <div
className={`flex flex-col pl-4 ${ className={`flex flex-col lg:pl-4 ${
video?.isFreeVod ? "cursor-pointer" : "cursor-not-allowed" video?.isFreeVod ? "cursor-pointer" : "cursor-not-allowed"
}`} }`}
key={index} key={index}
@ -69,7 +70,7 @@ const CourseChapter = ({
> >
{/* right div dot dot */} {/* right div dot dot */}
<div <div
className="flex items-center justify-center relative flex-col h-full" className="hidden lg:flex items-center justify-center relative flex-col h-full"
style={{ width: "10%" }} style={{ width: "10%" }}
> >
<span <span
@ -87,13 +88,13 @@ const CourseChapter = ({
></span> ></span>
</div> </div>
{/* left div content */} {/* left div content */}
<div className="py-1.5" style={{ width: "90%" }}> <div className="py-1.5" style={{ width: isMobile ? '100%' :"90%" }}>
<div <div
className={`w-full bg-white flex flex-col transition duration-400 hover:scale-95 shadow-md transform rounded-md className={`w-full bg-white flex flex-col transition duration-400 hover:scale-95 shadow-md border border-solid border-green-200 transform rounded-md
${ ${
selectedVideo?.id === video?.id selectedVideo?.id === video?.id
? "bg-green-600 text-white" ? "bg-green-600 text-white"
: "text-blueC0" : "text-blueC0 dark:bg-opacity-5"
} }
`} `}
onClick={() => onClick={() =>
@ -106,13 +107,13 @@ const CourseChapter = ({
{/* top */} {/* top */}
<div className="flex flex-row items-center justify-between p-3 border-0 border-b border-solid border-green-200"> <div className="flex flex-row items-center justify-between p-3 border-0 border-b border-solid border-green-200">
<p <p
className={`text-tiny font-bold className={`text-base lg:text-tiny font-bold
${selectedVideo?.id === video?.id ? "text-white" : ""}`} ${selectedVideo?.id === video?.id ? "text-white" : ""}`}
> >
{video?.name} {video?.name}
</p> </p>
<span <span
className={`text-tiny border-r border-solid border-blue-200 pr-1 className={`text-base lg:text-tiny border-r border-solid border-blue-200 pr-1
${ ${
selectedVideo?.id === video?.id selectedVideo?.id === video?.id
? "text-white" ? "text-white"
@ -130,7 +131,7 @@ const CourseChapter = ({
></div> ></div>
{/* bottom */} {/* bottom */}
<span <span
className={`text-tiny text-center font-medium p-3 className={`text-base lg:text-tiny text-center font-bold p-3
${ ${
selectedVideo?.id === video?.id selectedVideo?.id === video?.id
? "text-white" ? "text-white"
@ -156,6 +157,7 @@ const mapStateToProps = (state) => ({
grades: state.publicApi.grades, grades: state.publicApi.grades,
// vods: state.publicApi.bookSection?.vods, // vods: state.publicApi.bookSection?.vods,
userId: state?.user?.status?.id, userId: state?.user?.status?.id,
isMobile: state.publicApi.isMobile
}); });
const mapDispatchToProps = { const mapDispatchToProps = {
@ -163,56 +165,3 @@ const mapDispatchToProps = {
}; };
export default connect(mapStateToProps)(CourseChapter); export default connect(mapStateToProps)(CourseChapter);
CourseChapter.defaultProps = {
chapters: [
{
title: "فصل اول: مباحث جوشش مواد مذاب در مرکز",
duration: "2:30:13",
lessons: [
{
title: "آیا گوگل از ما دزدی میکند؟",
duration: "14:30",
play: "پخش",
passed: true,
},
{
title: "چگونگی ساخت نیروگاه های برقی",
duration: "22:31",
play: "در حال پخش",
passed: true,
},
{
title: "آیا از اینترنت می توان درآمد داشت؟",
duration: "10:09",
play: "نمایش",
passed: false,
},
{
title: "زمین سبز و آسمان آبی",
duration: "56:09",
play: "نمایش",
passed: false,
},
{
title: "زمین سبز و آسمان آبی",
duration: "56:09",
play: "نمایش",
passed: false,
},
{
title: "زمین سبز و آسمان آبی",
duration: "56:09",
play: "نمایش",
passed: false,
},
{
title: "زمین سبز و آسمان آبی",
duration: "56:09",
play: "نمایش",
passed: false,
},
],
},
],
};

@ -3,7 +3,7 @@ import React from "react";
const Divider = ({ type }) => { const Divider = ({ type }) => {
return ( return (
<span <span
className="bg-gray-100 my-3" className="bg-gray-100 dark:bg-opacity-30 my-3"
style={{ style={{
height: type === "horizontal" ? "100%" : 1, height: type === "horizontal" ? "100%" : 1,
width: type === "horizontal" ? 1 : "100%", width: type === "horizontal" ? 1 : "100%",

@ -79,14 +79,7 @@ const MyDrawer = ({
></ul> ></ul>
<ul className="h-full flex flex-col py-6 px-4 gap-6"> <ul className="h-full flex flex-col py-6 px-4 gap-6">
{(!user ? publicLink : privateLink).map((item, key) => ( {(!user ? publicLink : privateLink).map((item, key) => (
<Link <Link to={item.link} key={key} onClick={() => setDrawerOpen(false)}>
to={item.link}
key={key}
// onClick={
// item.onClick ||
// (() => (item.link === "" ? toast.error(item.toast) : null))
// }
>
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
{item.icon} {item.icon}
<div className="text-gray70 text-tiny mr-3 dark:text-white"> <div className="text-gray70 text-tiny mr-3 dark:text-white">

@ -83,7 +83,7 @@ export default function Input(props) {
placeholder={label} placeholder={label}
className={_.join( className={_.join(
[ [
`flex-1 border border-gray-300 dark:bg-opacity-10 rounded-md outline-none py-3 px-4 text-tiny ${ `flex-1 border border-gray-300 dark:bg-opacity-10 dark:text-white rounded-md outline-none py-3 px-4 text-tiny ${
backgroundColor ? backgroundColor : "bg-transparent" backgroundColor ? backgroundColor : "bg-transparent"
} ${align}`, } ${align}`,
inputStatusHandler( inputStatusHandler(

@ -22,7 +22,7 @@ function Video({ fileIds, posterId, autoPlay }) {
height: height:
window.innerWidth > 1024 window.innerWidth > 1024
? window.innerHeight - 300 ? window.innerHeight - 300
: window.innerHeight / 3.6, : Math.round(window.innerHeight / 3.6),
theme: "#4dd35b", theme: "#4dd35b",
language: "en", language: "en",
isShowMultiple: window.innerWidth > 700, isShowMultiple: window.innerWidth > 700,

@ -64,6 +64,7 @@ function Navbar({
} }
}, []); }, []);
useEffect(() => { useEffect(() => {
if (!isMobile && isLogin) { if (!isMobile && isLogin) {
getCartProducts(); getCartProducts();
@ -107,7 +108,7 @@ function Navbar({
/> />
) : null} ) : null}
{title && ( {title && (
<strong className="text-blueC0 text-lg font-semibold dark:text-white"> <strong className="text-green4F text-lg font-semibold dark:text-white">
{title} {title}
</strong> </strong>
)} )}

@ -4,7 +4,7 @@ import "./index.scss";
export default function Radio(props) { export default function Radio(props) {
return ( return (
<div className="radio flex items-center"> <div className="radio flex items-center">
<input id="radio-1" name={props.name} type="radio" checked={props.active} /> <input id="radio-1" name={props.name} type="radio" checked={props.active} onChange={() => {}} />
<label htmlFor="radio-1" className="radio-label text-xs"> <label htmlFor="radio-1" className="radio-label text-xs">
{/* {props.label} */} {/* {props.label} */}
</label> </label>

@ -12,8 +12,8 @@ $color2: #3197EE;
border-radius: 100%; border-radius: 100%;
border: 1px solid darken($color1, 25%); border: 1px solid darken($color1, 25%);
display: inline-block; display: inline-block;
width: 1.4em; width: 1.7em;
height: 1.4em; height: 1.7em;
position: relative; position: relative;
vertical-align: top; vertical-align: top;
margin-left: 0.5em; margin-left: 0.5em;

@ -8,11 +8,12 @@ function Select({
borderColor, borderColor,
backgroundColor, backgroundColor,
onChange, onChange,
name name,
width = "w-1/2"
}) { }) {
return ( return (
<div <div
className={`inline-block w-1/2 relative group rounded-md overflow-hidden ${margin} bg-transparent`} className={`inline-block ${width} relative group rounded-md overflow-hidden ${margin} bg-transparent`}
> >
<select <select
className={`text-gray70 text-base lg:text-tiny block appearance-none ${backgroundColor} w-full border border-solid px-4 py-3 pr-3 rounded-md leading-tight focus:outline-none focus:border-blueC0 focus:text-blueC0 ${borderColor}`} className={`text-gray70 text-base lg:text-tiny block appearance-none ${backgroundColor} w-full border border-solid px-4 py-3 pr-3 rounded-md leading-tight focus:outline-none focus:border-blueC0 focus:text-blueC0 ${borderColor}`}

@ -1,7 +1,7 @@
import location from "../../utils/location"; import location from "../../utils/location";
const initialState = { const initialState = {
isDark: localStorage.getItem("isDark") || false, isDark: localStorage.getItem("isDark") === "true" ? true : false,
isMobile: window.innerWidth < 1024, isMobile: window.innerWidth < 1024,
homeData: [], homeData: [],
newProducts: [], newProducts: [],
@ -63,11 +63,11 @@ const initialState = {
desktopContentTransform: false, desktopContentTransform: false,
overLayer: false, overLayer: false,
provinces: [], provinces: [],
cities : [], cities: [],
dashboardOptions : { dashboardOptions: {
profile : null, profile: null,
support : null, support: null,
} },
}; };
const grades = [ const grades = [
@ -90,7 +90,7 @@ export default function publicApi(state = initialState, action) {
let { type, data } = action; let { type, data } = action;
switch (type) { switch (type) {
case "public/dashboard": case "public/dashboard":
return {...state,error : null, loading :false, dashboardOptions : data } return { ...state, error: null, loading: false, dashboardOptions: data };
case "public/setOverLayer": case "public/setOverLayer":
return { ...state, overLayer: data }; return { ...state, overLayer: data };
case "public/setDesktopContentTransform": case "public/setDesktopContentTransform":
@ -182,7 +182,7 @@ export default function publicApi(state = initialState, action) {
loading: false, loading: false,
error: null, error: null,
province: [...state.province, ...data.map((item) => item.name)], province: [...state.province, ...data.map((item) => item.name)],
provinces : data provinces: data,
}; };
case "public/city": case "public/city":
return { return {
@ -190,7 +190,7 @@ export default function publicApi(state = initialState, action) {
loading: false, loading: false,
error: null, error: null,
city: [...data.map((item) => item.name)], city: [...data.map((item) => item.name)],
cities : data, cities: data,
}; };
case "public/selectMenu": case "public/selectMenu":
return { ...state, loading: false, error: null, selectedMenu: data }; return { ...state, loading: false, error: null, selectedMenu: data };

@ -42,24 +42,15 @@ function Router({
}) { }) {
useEffect(() => { useEffect(() => {
window.addEventListener("scroll", () => { window.addEventListener("scroll", () => {
// if (!isMobile) {
// window.addEventListener("scroll", () => {
// if (window.scrollY >= 64) {
// setDesktopContentTransform(true);
// } else {
// setDesktopContentTransform(false);
// }
// });
// }
}); });
}, []); }, []);
return ( return (
<div className={_.join([isDark ? "dark" : ""], " ")}> <div className={`${isDark ? "dark" : ""}`}>
<div <div
className={_.join( className={_.join(
[ [
"min-h-screen min-w-screen rtl overflow-x-hidden lg:pb-20 lg:py-0", "min-h-screen min-w-screen rtl overflow-x-hidden lg:py-0",
isDark ? "" : "bg-white", isDark ? "" : "bg-white",
headerOptions?.shown ? "pt-16" : "pt-0", headerOptions?.shown ? "pt-16" : "pt-0",
], ],

@ -3,13 +3,16 @@ import { connect } from "react-redux";
import notFoundImage from "./404.svg"; import notFoundImage from "./404.svg";
import { publicApi } from "../../redux/actions"; import { publicApi } from "../../redux/actions";
function NotFound({ headerOptions, setHeaderOptions }) { function NotFound({ headerOptions, setHeaderOptions, isMobile }) {
useEffect(() => { useEffect(() => {
setHeaderOptions(headerOptions); setHeaderOptions({ shown: true, back: true });
}, []); }, []);
return ( return (
<div <div
className="w-full flex h-screen transform justify-center items-center flex-col bg-transparent px-4" className="w-full flex transform justify-center items-center flex-col bg-transparent px-4"
style={{
height: isMobile ? "calc(100vh - 100px)" : "calc(100vh)",
}}
> >
<h1 <h1
className="dark:text-white text-5xl font-semibold" className="dark:text-white text-5xl font-semibold"
@ -27,7 +30,9 @@ function NotFound({ headerOptions, setHeaderOptions }) {
); );
} }
const mapStateToProps = (state) => ({}); const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile,
});
const mapDispatchToProps = { const mapDispatchToProps = {
setHeaderOptions: publicApi.setHeaderOptions, setHeaderOptions: publicApi.setHeaderOptions,

@ -11,6 +11,8 @@ import Loading from "../../components/Loading";
//assets //assets
import dropdownIcon from "../../assets/icons/dropdown-blue.svg"; import dropdownIcon from "../../assets/icons/dropdown-blue.svg";
import arrowBlueIcon from "../../assets/icons/arrow-right-blue.svg";
import arrowWhiteIcon from "../../assets/icons/arrow-left-white.svg";
export const Address = ({ export const Address = ({
city, city,
@ -23,6 +25,8 @@ export const Address = ({
loading, loading,
setPhase, setPhase,
cityLoading, cityLoading,
isMobile,
isDark,
}) => { }) => {
const [addressFields, setAddressFields] = useState({}); const [addressFields, setAddressFields] = useState({});
const [mapAddress, setMapAddress] = useState(null); const [mapAddress, setMapAddress] = useState(null);
@ -73,8 +77,8 @@ export const Address = ({
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }), setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-black bg-opacity-60", bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-white", color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -85,8 +89,8 @@ export const Address = ({
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }), setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-black bg-opacity-60", bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-white", color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -97,8 +101,8 @@ export const Address = ({
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }), setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-black bg-opacity-60", bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-white", color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -109,8 +113,8 @@ export const Address = ({
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }), setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-black bg-opacity-60", bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-white", color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -121,8 +125,8 @@ export const Address = ({
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }), setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-black bg-opacity-60", bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-white", color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -133,8 +137,8 @@ export const Address = ({
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }), setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-black bg-opacity-60", bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-white", color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -145,8 +149,8 @@ export const Address = ({
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }), setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-black bg-opacity-60", bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-white", color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -157,8 +161,8 @@ export const Address = ({
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }), setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-black bg-opacity-60", bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-white", color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -183,18 +187,22 @@ export const Address = ({
const Header = ({ title, text }) => { const Header = ({ title, text }) => {
return ( return (
<div className="flex flex-row items-center gap-2 mb-4"> <div className="flex flex-col lg:flex-row lg:items-center gap-2 lg:mb-4 mt-2 lg:mt-0">
<strong className="text-blue5F text-base">{title}</strong> <strong className="text-green4F text-base dark:text-white">
<p className="mt-1 inline flex-1 text-sm text-gray70">{text}</p> {title}
</strong>
<p className="mt-1 inline flex-1 text-sm text-gray70 dark:text-white">
{text}
</p>
</div> </div>
); );
}; };
return ( return (
<div <div
className="flex flex-row-reverse flex-1 pb-20 gap-5 divide-x divide-solid divide-gray-200" className="flex flex-col lg:flex-row-reverse flex-1 pt-10 lg:pt-0 pb-20 gap-5 lg:divide-x lg:divide-solid lg:divide-gray-200"
// style={{ minHeight: "calc(100vh - 500px)" }} // style={{ minHeight: "calc(100vh - 500px)" }}
> >
<div className="flex flex-col w-1/2 px-4"> <div className="flex flex-col-reverse w-full lg:w-1/2">
<Input <Input
width="100%" width="100%"
label={"ادرس انتخاب شده در نقشه"} label={"ادرس انتخاب شده در نقشه"}
@ -207,11 +215,11 @@ export const Address = ({
/> />
<div <div
className="w-full overflow-hidden rounded-md mt-6" className="w-full overflow-hidden rounded-md mt-6"
style={{ height: "calc(100vh / 2)" }} style={{ height: isMobile ? "calc(100vh / 4)" : "calc(100vh / 2)" }}
> >
<ReverseMap setAddress={(val) => setMapAddress(val)} /> <ReverseMap setAddress={(val) => setMapAddress(val)} />
</div> </div>
<div className="flex w-full items-end mt-8 flex-col"> <div className="hidden lg:flex w-full items-end mt-8 flex-col">
<div className="flex flex-col items-cente w-2/5"> <div className="flex flex-col items-cente w-2/5">
<Button <Button
loading={loading} loading={loading}
@ -236,14 +244,14 @@ export const Address = ({
</div> </div>
</div> </div>
</div> </div>
<div className="flex flex-col w-1/2 pl-4"> <div className="flex flex-col w-full lg:w-1/2 lg:pl-4">
<Header <Header
title="اطلاعات هویتی" title="اطلاعات هویتی"
text="( لطفا نام و نام خانوادگی خود را به طور کامل وارد نمایید )" text="( لطفا نام و نام خانوادگی خود را به طور کامل وارد نمایید )"
/> />
<div className="flex flex-row items-center gap-5 w-full"> <div className="flex flex-col lg:flex-row items-center lg:gap-5 w-full">
<Input <Input
width="50%" width={isMobile ? "100%" : "50%"}
label={"نام"} label={"نام"}
regex={(val) => val} regex={(val) => val}
name="firstName" name="firstName"
@ -253,7 +261,7 @@ export const Address = ({
direction="rtl" direction="rtl"
/> />
<Input <Input
width="50%" width={isMobile ? "100%" : "50%"}
label={"نام خانوادگی"} label={"نام خانوادگی"}
regex={(val) => val} regex={(val) => val}
name="lastName" name="lastName"
@ -263,16 +271,20 @@ export const Address = ({
direction="rtl" direction="rtl"
/> />
</div> </div>
{!isMobile && (
<>
<br /> <br />
<br /> <br />
</>
)}
<Header <Header
title="شماره تماس" title="شماره تماس"
text="( شماره موبایل و شماره تلفن ثابت خود را text="( شماره موبایل و شماره تلفن ثابت خود را
به همراه پیش شماره وارد کنید )" به همراه پیش شماره وارد کنید )"
/> />
<div className="flex flex-row items-center gap-5 w-full"> <div className="flex flex-col lg:flex-row items-center lg:gap-5 w-full">
<Input <Input
width="50%" width={isMobile ? "100%" : "50%"}
label={"شماره موبایل"} label={"شماره موبایل"}
regex={(val) => onInput.numberOnly(val)} regex={(val) => onInput.numberOnly(val)}
name="cellphone" name="cellphone"
@ -283,7 +295,7 @@ export const Address = ({
maxLength={11} maxLength={11}
/> />
<Input <Input
width="50%" width={isMobile ? "100%" : "50%"}
label={"شماره تلفن"} label={"شماره تلفن"}
regex={(val) => onInput.numberOnly(val)} regex={(val) => onInput.numberOnly(val)}
name="phone" name="phone"
@ -294,24 +306,38 @@ export const Address = ({
maxLength={11} maxLength={11}
/> />
</div> </div>
{!isMobile && (
<>
<br /> <br />
<br /> <br />
</>
)}
<Header <Header
title="آدرس" title="آدرس"
text="( لطفا نام استان و شهرستان و آدرس text="( لطفا نام استان و شهرستان و آدرس
خود را با دقت تکمیل نمایید )" خود را با دقت تکمیل نمایید )"
/> />
<div className="flex flex-row items-center gap-5 w-full mt-3"> <div className="flex flex-col lg:flex-row items-center gap-3 lg:gap-5 w-full mt-3">
<Select <Select
options={province} options={province}
name="provinceId" name="provinceId"
onChange={(name, value) => onChange(name, value)} onChange={(name, value) => onChange(name, value)}
width={isMobile ? "w-full" : "w-1/2"}
backgroundColor={
isDark ? "dark:bg-transparent dark:text-white" : ""
}
fill={isDark ? "fill-white" : "fill-gray-600"}
/> />
{!cityLoading ? ( {!cityLoading ? (
<Select <Select
options={city} options={city}
name="cityId" name="cityId"
onChange={(name, value) => onChange(name, value)} onChange={(name, value) => onChange(name, value)}
width={isMobile ? "w-full" : "w-1/2"}
backgroundColor={
isDark ? "dark:bg-transparent dark:text-white" : ""
}
fill={isDark ? "fill-white" : "fill-gray-600"}
/> />
) : ( ) : (
<div className="flex justify-between border-gray-300 border border-solid rounded-md w-1/2 py-3.5 px-2"> <div className="flex justify-between border-gray-300 border border-solid rounded-md w-1/2 py-3.5 px-2">
@ -328,7 +354,7 @@ export const Address = ({
</div> </div>
<br /> <br />
<Input <Input
width="50%" width={isMobile ? "100%" : "50%"}
label={"کد پستی"} label={"کد پستی"}
regex={(val) => onInput.numberOnly(val)} regex={(val) => onInput.numberOnly(val)}
name="postalCode" name="postalCode"
@ -338,7 +364,47 @@ export const Address = ({
direction="ltr" direction="ltr"
maxLength={10} maxLength={10}
/> />
<div className="flex lg:hidden flex-col items-cente w-full mt-3">
<Button
loading={loading}
title="ثبت آدرس"
backgroundColor="bg-blueC0"
border={{ color: "#196EC055", width: "0px" }}
width="100%"
color="text-white"
onClick={() => submit()}
/>
<button
className="bg-transparent mt-4 text-base py-3 flex flex-row justify-center items-center border-2 border-solid border-blueC0 text-green7B dark:text-blueC0 rounded-full"
onClick={() => setPhase("deliveryForm")}
>
بازگشت
<img
src={dropdownIcon}
alt=""
className="w-3.5 transform rotate-90"
/>
</button>
</div>
</div> </div>
{isMobile && (
<div
className="fixed top-0 left-0 flex justify-between items-center py-3 px-4 w-full"
style={{
backgroundColor: isDark ? "#061B30" : "white",
}}
>
<strong className="text-green4F text-lg font-semibold dark:text-white">
آدرس جدید
</strong>
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
alt="back"
className={`w-6 transform ${isDark ? " rotate-0" : "rotate-180"}`}
onClick={() => setPhase("deliveryForm")}
/>
</div>
)}
{dialog.open && <Dialog dialog={dialog} />} {dialog.open && <Dialog dialog={dialog} />}
</div> </div>
); );
@ -351,6 +417,8 @@ const mapStateToProps = (state) => ({
cities: state.publicApi.cities, cities: state.publicApi.cities,
loading: state.userAddress.loading, loading: state.userAddress.loading,
cityLoading: state.publicApi.loading, cityLoading: state.publicApi.loading,
isMobile: state.publicApi.isMobile,
isDark: state.publicApi.isDark,
}); });
const mapDispatchToProps = { const mapDispatchToProps = {

@ -7,6 +7,7 @@ import location from "../../utils/location";
import Hashtags from "../Blogs/layouts/Hashtags"; import Hashtags from "../Blogs/layouts/Hashtags";
import Header from "../Blogs/layouts/Header"; import Header from "../Blogs/layouts/Header";
import Suggest from "../Blogs/layouts/Suggest"; import Suggest from "../Blogs/layouts/Suggest";
import New from "../Blogs/layouts/New";
import Avatar from "../../components/Avatar"; import Avatar from "../../components/Avatar";
//assets //assets
@ -21,30 +22,70 @@ export const Blog = ({
blogs, blogs,
}) => { }) => {
useEffect(() => { useEffect(() => {
setHeaderOptions({ shown: true }); setHeaderOptions({ shown: true, menu: true, back: true, bookmark: true });
getInfo({ id: location.getId() }); getInfo({ id: location.getId() });
if (blogs.length === 0) { if (blogs.length === 0) {
getList(); getList();
} }
}, []); }, []);
return ( return (
<div className="flex flex-col lg:w-11/12 mx-auto lg:py-24"> <div className="flex flex-col lg:w-11/12 mx-auto lg:py-24 lg:px-0 px-4 lg:pb-0 pb-24">
<Hashtags /> <Hashtags />
{isMobile && (
<div <div
className="w-full" className="w-full rounded-md overflow-hidden relative"
style={{
minHeight: 200,
}}
>
<img
src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`}
alt=""
className="w-full h-full absolute left-0 top-0"
/>
<div className="flex flex-col justify-end bg-gradient-to-t from-black absolute top-0 left-0 z-10 w-full h-full pb-2 px-2">
<div className="w-full flex justify-between">
<div className="flex">
<Avatar size={40} />
<div className="flex flex-col py-2 mr-2 justify-center">
<strong className="text-gray-300 text-tiny font-bold">
{"نوشته از:" + " " + "کامران ایزدی"}
</strong>
<p className="text-gray-300 mt-2 text-xs">
{"سردبیر بخش وبلاگ دانوین"}
</p>
</div>
</div>
<div className="flex flex-col justify-center items-end">
<span className="text-gray-300 text-sm">
{"زمان مطالعه" + " " + "۳۰ دقیقه"}
</span>
<span className="mt-2 text-gray-300 text-sm font-bold">
{"1400/11/24"}
</span>
</div>
</div>
</div>
</div>
)}
{!isMobile && (
<div
className="w-full hidden lg:flex"
style={{ style={{
backgroundImage: `url(https://dnvn.ir/api/v1/file/${blog?.fileIds})`, backgroundImage: `url(https://dnvn.ir/api/v1/file/${blog?.fileIds})`,
height: "calc(100vh / 2)", height: "calc(100vh / 2)",
backgroundRepeat: "no-repeat", backgroundRepeat: "no-repeat",
backgroundAttachment: "fixed", backgroundAttachment: "fixed",
backgroundSize: "cover", backgroundSize: "cover",
backgroundPosition: 'center bottom', backgroundPosition: "center bottom",
}} }}
></div> ></div>
)}
<div className="flex lg:flex-row my-5 gap-5"> <div className="flex lg:flex-row my-5 gap-5">
<strong className="flex-1 lg:text-5xl lg:font-black"> <strong className="flex-1 lg:text-5xl lg:font-black dark:text-gray-200">
{blog?.title} {blog?.title}
</strong> </strong>
{!isMobile && (
<div className="flex flex-col"> <div className="flex flex-col">
<div className="flex"> <div className="flex">
<Avatar size={60} /> <Avatar size={60} />
@ -66,9 +107,20 @@ export const Blog = ({
</span> </span>
</div> </div>
</div> </div>
)}
</div> </div>
<div className="leading-8 lg:text-base" dangerouslySetInnerHTML={{ __html: blog?.text }} />{" "} <div
className="leading-8 lg:text-base text-sm dark:text-white"
dangerouslySetInnerHTML={{ __html: blog?.text }}
/>{" "}
<Header title={"پیشنهادی "} /> <Header title={"پیشنهادی "} />
{isMobile ? (
<div className="w-full flex overflow-x-scroll no-scrollbar gap-4">
{blogs.map((blog, index) => (
<New blog={blog} key={index} />
))}
</div>
) : (
<div className="w-full relative" style={{ direction: "ltr" }}> <div className="w-full relative" style={{ direction: "ltr" }}>
{blogs.length > 0 && ( {blogs.length > 0 && (
<Carousel <Carousel
@ -100,6 +152,7 @@ export const Blog = ({
</Carousel> </Carousel>
)} )}
</div> </div>
)}
</div> </div>
); );
}; };

@ -16,16 +16,31 @@ import arrow from "../../assets/icons/dropdown-blue.svg";
export const Blogs = ({ isMobile, getList, blogs, setHeaderOptions }) => { export const Blogs = ({ isMobile, getList, blogs, setHeaderOptions }) => {
useEffect(() => { useEffect(() => {
if (isMobile) {
setHeaderOptions({
shown: true,
hamburgerMenu: true,
qr: true,
});
} else {
setHeaderOptions({ shown: true }); setHeaderOptions({ shown: true });
}
if (blogs.length === 0) { if (blogs.length === 0) {
getList(); getList();
} }
}, []); }, []);
return ( return (
<div className="flex flex-col lg:w-11/12 mx-auto lg:py-24"> <div className="flex w-full px-4 lg:px-0 flex-col lg:w-11/12 mx-auto lg:py-24 pb-24 lg:pb-0">
<Hashtags /> <Hashtags />
<Single /> <Single />
<Header title={"تازهترینها از وبلاگ"} /> <Header title={"تازهترینها از وبلاگ"} />
{isMobile ? (
<div className="w-full flex overflow-x-scroll no-scrollbar gap-4">
{blogs.map((blog, index) => (
<New blog={blog} key={index} />
))}
</div>
) : (
<div className="w-full relative" style={{ direction: "ltr" }}> <div className="w-full relative" style={{ direction: "ltr" }}>
{blogs.length > 0 && ( {blogs.length > 0 && (
<Carousel <Carousel
@ -57,7 +72,15 @@ export const Blogs = ({ isMobile, getList, blogs, setHeaderOptions }) => {
</Carousel> </Carousel>
)} )}
</div> </div>
)}
<Header title={"پیشنهاد سردبیر"} /> <Header title={"پیشنهاد سردبیر"} />
{isMobile ? (
<div className="w-full flex overflow-x-scroll no-scrollbar gap-4">
{blogs.map((blog, index) => (
<New blog={blog} key={index} />
))}
</div>
) : (
<div className="w-full relative" style={{ direction: "ltr" }}> <div className="w-full relative" style={{ direction: "ltr" }}>
{blogs.length > 0 && ( {blogs.length > 0 && (
<Carousel <Carousel
@ -89,8 +112,9 @@ export const Blogs = ({ isMobile, getList, blogs, setHeaderOptions }) => {
</Carousel> </Carousel>
)} )}
</div> </div>
)}
<Header title={"از دنیای آموزش"} /> <Header title={"از دنیای آموزش"} />
<Target blogs={blogs?.slice(0,4)} /> <Target blogs={blogs?.slice(0, 4)} />
<Join /> <Join />
</div> </div>
); );

@ -6,11 +6,11 @@ import arrowIcon from "../arrow.svg";
export const Hashtags = ({ hashtags }) => { export const Hashtags = ({ hashtags }) => {
return ( return (
<div className="flex py-3 px-2 rounded-full border-2 border-green-50 shadow-sm border-solid items-center w-full mb-7"> <div className="flex py-3 px-2 rounded-full border-2 border-green-50 dark:border-opacity-20 shadow-sm border-solid items-center w-full mb-7 overflow-x-scroll no-scrollbar">
<img src={arrowIcon} alt="" className="w-7" /> <img src={arrowIcon} alt="" className="w-7" />
<ul className="list-none flex justify-around items-center flex-1"> <ul className="list-none flex justify-around items-center lg:flex-1 lg:ml-0 ml-4">
{hashtags.map((hashtag, index) => ( {hashtags.map((hashtag, index) => (
<li className="text-tiny font-semibold cursor-pointer" style={{ color: hashtag.color }}> <li className="text-tiny font-semibold cursor-pointer w-32 lg:px-0 flex-1 lg:w-auto" style={{ color: hashtag.color }}>
{"#" + " " + hashtag.title} {"#" + " " + hashtag.title}
</li> </li>
))} ))}

@ -3,9 +3,9 @@ import { connect } from "react-redux";
export const Header = ({ title, color }) => { export const Header = ({ title, color }) => {
return ( return (
<div className="flex w-full items-center gap-5 mt-12 mb-4"> <div className="flex w-full items-center lg:gap-5 gap-3 mt-5 lg:mt-12 mb-4">
<storng className="py-5 pr-5 pl-10 bg-gray2C text-white font-semibold text-lg">{title}</storng> <storng className="lg:py-5 py-2.5 lg:pr-5 pr-2.5 lg:pl-10 pl-5 bg-gray2C dark:bg-opacity-40 dark:bg-blueC0 text-white font-semibold text-tiny lg:text-lg">{title}</storng>
<span className="flex-1 h-px shadow-md bg-gray-300"></span> <span className="flex-1 h-px shadow-md bg-gray-300 dark:bg-opacity-50"></span>
</div> </div>
); );
}; };

@ -4,28 +4,51 @@ import { connect } from "react-redux";
//assets //assets
import picImage from "../pic.svg"; import picImage from "../pic.svg";
export const Join = ({}) => { export const Join = ({ isMobile }) => {
return ( return (
<div className="w-full h-72 border-2 border-solid border-gray-200 rounded-md flex mt-32"> <div className="w-full lg:h-72 border-2 px-3 lg:p-0 py-4 border-solid border-gray-200 dark:border-opacity-30 rounded-md flex lg:flex-row flex-col-reverse mt-7 lg:mt-32">
<img <img
src={picImage} src={picImage}
alt="" alt=""
style={{ height: "115%", transform: "translateY(-15%)" }} style={{
height: isMobile ? "calc(100vw / 2.5)" : "115%",
transform: isMobile ? "translateY(15%) translateX(25%)" : "translateY(-15%)",
}}
/> />
<div className="flex flex-col justify-center h-full mr-4"> {isMobile && (
<strong className="text-2xl bold">اینجا خبری از اسپم نیست!</strong> <div className="flex lg:hidden flex-col flex-1 h-full justify-center items-center">
<form className="flex flex-col w-full rounded-md mt-3 overflow-hidden">
<input
type="text"
className="flex-1 text-center py-3 mb-4 font-normal text-tiny dark:bg-transparent placeholder:text-blue5F dark:text-white border border-gray-300 border-solid outline-none"
placeholder={"آدرس ایمیل شما"}
/>
<button
className={
"py-3 w-full text-base bg-yellow4 text-black border-none"
}
// onClick={setOff}
>
عضویت
</button>
</form>
</div>
)}
<div className="flex flex-col justify-center h-full my-4 lg:my-0 lg:mr-4">
<strong className="text-base lg:text-2xl bold dark:text-gray-200">اینجا خبری از اسپم نیست!</strong>
<strong <strong
className="text-7xl bold my-4 text-red-600" className="text-xl lg:text-7xl bold my-4 text-red-600"
style={{ fontSize: "clamp(30px, calc(100vw / 35), 45px)" }} style={{ fontSize: "clamp(30px, calc(100vw / 35), 45px)" }}
> >
خبرنامه وبلاگ دانوین خبرنامه وبلاگ دانوین
</strong> </strong>
<p className="leading-7 text-gray70" style={{ maxWidth: 400 }}> <p className="text-tiny lg:text-tiny leading-5 lg:leading-7 text-gray70 dark:text-gray-200" style={{ maxWidth: 400 }}>
بهترین و آخرین اخبار علمی و آموزشی را در ایمیل خودتون دریافت کنید. هر بهترین و آخرین اخبار علمی و آموزشی را در ایمیل خودتون دریافت کنید. هر
زمان هم که لازم نداشتید می تونید عضویت رو لغو کنید زمان هم که لازم نداشتید می تونید عضویت رو لغو کنید
</p> </p>
</div> </div>
<div className="flex flex-col flex-1 h-full justify-center items-center"> {!isMobile && (
<div className="hidden lg:flex flex-col flex-1 h-full justify-center items-center">
<form className="flex w-full flex-row-reverse rounded-md mt-3 overflow-hidden lg:w-11/12"> <form className="flex w-full flex-row-reverse rounded-md mt-3 overflow-hidden lg:w-11/12">
<input <input
type="text" type="text"
@ -42,11 +65,14 @@ export const Join = ({}) => {
</button> </button>
</form> </form>
</div> </div>
)}
</div> </div>
); );
}; };
const mapStateToProps = (state) => ({}); const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile,
});
const mapDispatchToProps = {}; const mapDispatchToProps = {};

@ -3,25 +3,32 @@ import { connect } from "react-redux";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import Avatar from "../../../components/Avatar"; import Avatar from "../../../components/Avatar";
export const New = ({ blog }) => { export const New = ({ blog, isMobile }) => {
return ( return (
<Link <Link
to={'/blogs/' + blog?.id} to={"/blogs/" + blog?.id}
className="px-4 flex flex-col" className="lg:px-4 flex flex-col"
style={{ direction: "rtl" }} style={{ direction: isMobile ? "" : "rtl" }}
> >
<img <img
src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`} src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`}
alt="" alt=""
className="w-full rounded-md" className="w-full rounded-md"
style={{ height: "calc(100vw / 12 * 11 / 3 / 16 * 9)" }} style={{
height: isMobile
? "calc(100vh / 5)"
: "calc(100vw / 12 * 11 / 3 / 16 * 9)",
minWidth: isMobile ? "calc(100vh / 5 * 4.5 / 3)" : "",
}}
/> />
<strong className="text-lg my-4 leading-7">{blog?.title}</strong> <strong className="text-base lg:text-lg lg:my-4 my-2 leading-6 lg:leading-7 dark:text-gray-200">
<p className="text-tiny leading-6 mb-3"> {blog?.title}
</strong>
<p className="text-tiny leading-5 lg:leading-6 mb-3 dark:text-gray-200">
هر نفسی که فرو می بریم، مرگی را که مدام به ما دست اندازی میکند پس هر نفسی که فرو می بریم، مرگی را که مدام به ما دست اندازی میکند پس
میزند در نهایت این مرگ{" "} میزند در نهایت این مرگ{" "}
</p> </p>
<div className="w-full flex justify-between"> <div className="w-full hidden lg;flex justify-between">
<div className="flex"> <div className="flex">
<Avatar size={60} /> <Avatar size={60} />
<div className="flex flex-col py-2 mr-2 justify-center"> <div className="flex flex-col py-2 mr-2 justify-center">
@ -46,7 +53,9 @@ export const New = ({ blog }) => {
); );
}; };
const mapStateToProps = (state) => ({}); const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile,
});
const mapDispatchToProps = {}; const mapDispatchToProps = {};

@ -1,34 +1,59 @@
import React from "react"; import React from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import {Link} from 'react-router-dom'; import { Link } from "react-router-dom";
import Avatar from "../../../components/Avatar"; import Avatar from "../../../components/Avatar";
export const Single = ({ blog, isMobile }) => { export const Single = ({ blog, isMobile }) => {
return ( return (
<Link to={'/blogs/' + blog?.id} className="flex flex-col lg:flex-row lg:gap-5"> <Link
to={"/blogs/" + blog?.id}
className="flex flex-col lg:flex-row lg:gap-5 overflow-y-hidden"
>
<div <div
className="w-full lg:w-1/2 rounded-md overflow-hidden" className="w-full lg:w-1/2 rounded-md overflow-hidden relative"
style={{ style={{
height: isMobile ? "" : "calc(100vh / 2)", height: isMobile ? "" : "calc(100vh / 2)",
minHeight: isMobile ? "" : 300, minHeight: isMobile ? 200 : 300,
}} }}
> >
<img <img
src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`} src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`}
alt="" alt=""
className="w-full h-full" className="w-full h-full absolute left-0 top-0"
/> />
<div className="flex flex-col justify-end bg-gradient-to-t from-black lg:hidden absolute top-0 left-0 z-10 w-full h-full pb-2 px-2">
<div className="w-full flex justify-between">
<div className="flex">
<Avatar size={40} />
<div className="flex flex-col py-2 mr-2 justify-center">
<strong className="text-gray-300 text-tiny font-bold">
{"نوشته از:" + " " + "کامران ایزدی"}
</strong>
<p className="text-gray-300 mt-2 text-xs">
{"سردبیر بخش وبلاگ دانوین"}
</p>
</div>
</div>
<div className="flex flex-col justify-center items-end">
<span className="text-gray-300 text-sm">
{"زمان مطالعه" + " " + "۳۰ دقیقه"}
</span>
<span className="mt-2 text-gray-300 text-sm font-bold">{"1400/11/24"}</span>
</div>
</div>
</div>
</div> </div>
<div className="flex flex-col lg:w-1/2 lg:pt-5 justify-between"> <div className="flex flex-col lg:w-1/2 lg:pt-5 justify-between">
<div className="flex flex-col"> <div className="flex flex-col mt-3 lg:mt-0 ">
<h1 className="lg:text-5xl font-bold leading-6">{blog?.title}</h1> <h1 className="lg:text-5xl font-bold leading-6 dark:text-gray-200">{blog?.title}</h1>
<p className="lg:text-tiny text-gray70 lg:w-4/5 lg:mt-6 lg:leading-7"> <p className="text-tiny leading-6 lg:text-tiny text-gray70 dark:text-gray-200 lg:w-4/5 mt-4 lg:mt-6 lg:leading-7">
هر نفسی که فرو می بریم، مرگی را که مدام به ما دست اندازی میکند پس هر نفسی که فرو می بریم، مرگی را که مدام به ما دست اندازی میکند پس
میزند... در نهایت این مرگ است که باید پیروز شود، زیرا از هنگام تولد میزند... در نهایت این مرگ است که باید پیروز شود، زیرا از هنگام تولد
بخشی از سرنوشت ما شده و فقط مدت کوتاهی پیش از بلعیدن طعمه اش، با آن بخشی از سرنوشت ما شده و فقط مدت کوتاهی پیش از بلعیدن طعمه اش، با آن
بازی می کند. با این همه، ما تا آنجا که ممکن است، با علاقه فراوان{" "} بازی می کند. با این همه، ما تا آنجا که ممکن است، با علاقه فراوان{" "}
</p> </p>
</div> </div>
{!isMobile && (
<div className="w-full flex justify-between"> <div className="w-full flex justify-between">
<div className="flex"> <div className="flex">
<Avatar size={80} /> <Avatar size={80} />
@ -42,10 +67,15 @@ export const Single = ({ blog, isMobile }) => {
</div> </div>
</div> </div>
<div className="flex flex-col i justify-center items-end"> <div className="flex flex-col i justify-center items-end">
<span className="lg:text-tiny text-gray1 lg:font-black">{"زمان مطالعه" + " " + "۳۰ دقیقه"}</span> <span className="lg:text-tiny text-gray1 lg:font-black">
<span className="mt-3 lg:text-tiny text-gray1 lg:font-black">{'1400/11/24'}</span> {"زمان مطالعه" + " " + "۳۰ دقیقه"}
</span>
<span className="mt-3 lg:text-tiny text-gray1 lg:font-black">
{"1400/11/24"}
</span>
</div> </div>
</div> </div>
)}
</div> </div>
</Link> </Link>
); );

@ -3,9 +3,45 @@ import { connect } from "react-redux";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import Avatar from "../../../components/Avatar"; import Avatar from "../../../components/Avatar";
export const Target = ({ blogs }) => { export const Target = ({ blogs, isMobile }) => {
const Large = ({ blog }) => { const Large = ({ blog }) => {
return ( return isMobile ? (
<div className="flex flex-col w-full">
<div
className="relative w-full rounded-md overflow-hidden"
style={{ height: "calc(100vh / 4.5)" }}
>
<img
src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`}
alt=""
className="w-full h-full absolute left-0 top-0"
/>
<div className="w-full h-full absolute left-0 top-0 bg-gradient-to-t from-black z-10"></div>
</div>
<strong className="font-bold my-3 leading-7 text-black dark:text-gray-200">
{blog?.title}
</strong>
<div className="w-full flex justify-between">
<div className="flex">
<Avatar size={45} />
<div className="flex flex-col py-1 mr-1 justify-center">
<strong className="text-opacity-75 text-tiny text-black dark:text-gray-200">
{"نوشته از:" + " " + "کامران ایزدی"}
</strong>
<p className="text-black text-sm text-opacity-75 mt-2 dark:text-gray-200">
{"سردبیر بخش وبلاگ دانوین"}
</p>
</div>
</div>
<div className="flex flex-col i justify-center items-end">
<span className="text-gray1 text-sm dark:text-gray-200">
{"زمان مطالعه" + " " + "۳۰ دقیقه"}
</span>
<span className="mt-2 text-gray1 text-sm dark:text-gray-200">{"1400/11/24"}</span>
</div>
</div>
</div>
) : (
<Link <Link
to={"/blogs/" + blog?.id} to={"/blogs/" + blog?.id}
className="lg:w-1/2 relative rounded-md overflow-hidden" className="lg:w-1/2 relative rounded-md overflow-hidden"
@ -40,25 +76,30 @@ export const Target = ({ blogs }) => {
const Small = ({ blogs }) => { const Small = ({ blogs }) => {
return ( return (
<div className="lg:w-1/2 flex flex-col justify-between"> <div className="w-full lg:w-1/2 flex flex-row flex-wrap lg:flex-col justify-between">
{blogs.map((blog, index) => ( {blogs.map((blog, index) => (
<Link <Link
to={"/blogs/" + blog.id} to={"/blogs/" + blog.id}
key={index} key={index}
className="lg:flex gap-4 w-full" className="lg:mb-0 mb-3 lg:flex-row lg:flex lg:gap-2"
style={{width : isMobile ? "48%" : "100%"}}
> >
<img <img
src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`} src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`}
alt="" alt=""
style={{ style={{
height: "calc(100vw / 12 * 11 / 2 * 9 / 14 / 3.4)", height: isMobile
width: "calc(100vw / 12 * 11 / 2 * 9 / 14 / 3 * 16 / 10)", ? "calc(100vh / 8)"
: "calc(100vw / 12 * 11 / 2 * 9 / 14 / 3.4)",
width: isMobile
? "100%"
: "calc(100vw / 12 * 11 / 2 * 9 / 14 / 3 * 16 / 10)",
}} }}
className="rounded-md" className="rounded-md"
/> />
<div className="flex flex-col justify-center"> <div className="flex flex-col justify-center lg:gap-4">
<strong className="lg:font-bold lg:text-lg">{blog?.title}</strong> <strong className="lg:font-bold lg:text-lg text-tiny my-2 leading-5 dark:text-gray-200">{blog?.title}</strong>
<p className="lg:w-4/5 text-gray70 mt-3 leading-6"> <p className="lg:w-4/5 text-gray70 lg:text-tiny text-tiny leading-5 lg:leading-6 dark:text-gray-200">
هر نفسی که فرو می بریم، مرگی را که مدام به ما دست اندازی هر نفسی که فرو می بریم، مرگی را که مدام به ما دست اندازی
میکند پس میزند در نهایت این مرگ{" "} میکند پس میزند در نهایت این مرگ{" "}
</p> </p>
@ -69,14 +110,16 @@ export const Target = ({ blogs }) => {
); );
}; };
return ( return (
<div className="flex lg:flex-row gap-10"> <div className="flex flex-col lg:flex-row gap-10">
<Large blog={blogs[0]} /> <Large blog={blogs[0]} />
<Small blogs={blogs?.slice(0, 3)} /> <Small blogs={blogs?.slice(0, 3)} />
</div> </div>
); );
}; };
const mapStateToProps = (state) => ({}); const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile,
});
const mapDispatchToProps = {}; const mapDispatchToProps = {};

@ -18,25 +18,29 @@ function Address({
const Location = ({ address, active }) => { const Location = ({ address, active }) => {
return isMobile ? ( return isMobile ? (
<button <button
className={`flex flex-row border-2 border-solid items-center w-full px-3 py-4 rounded-md mt-4 transition-all duration-500 dark:bg-opacity-5 ${ className={`flex flex-row border-2 border-solid items-center w-full px-3 py-2 rounded-md mt-2 transition-all duration-500 dark:bg-opacity-5 ${
userAddressId === address?.id userAddressId === address?.id
? "bg-blueFD border-blueC0" ? "bg-blueC0 bg-opacity-5 border-blueC0"
: "bg-grayF9 border-gray45" : "bg-grayF9 border-gray-200 dark:border-gray-500"
}`} }`}
onClick={() =>
userAddressId === address?.id
? {}
: update({ userAddressId: address.id, userId })
}
> >
<Radio /> {loading && userAddressId !== address?.id ? (
<div className="flex flex-1 flex-col mr-3"> <Loading size={2} color="bg-gray-400" />
<li className="text-right text-sm lg:text-xs text-blue52 dark:text-white leading-4"> ) : (
آدرس:&nbsp;{address.address} <Radio active={active} />
</li> )}
<li className="text-right text-sm lg:text-xs text-blue52 dark:text-white mt-1.5"> <div className="flex flex-1 flex-col mr-2">
نام تحویل گیرنده:&nbsp;{address.receiver} <li
</li> className={`text-right text-sm font-semibold leading-5 text-blue52 ${
<li className="text-right text-sm lg:text-xs text-blue52 dark:text-white mt-1.5"> userAddressId === address?.id ? "dark:text-blueC0" : "dark:text-gray-400"
کد پستی:&nbsp;{address.postalCode} }`}
</li> >
<li className="text-right text-sm lg:text-xs text-blue52 dark:text-white mt-1.5"> {address.address}
شماره تماس:&nbsp;{address.cellphone}
</li> </li>
</div> </div>
</button> </button>
@ -82,24 +86,31 @@ function Address({
}; };
return isMobile ? ( return isMobile ? (
<section className="mt-2"> <section className="mt-2">
<strong className="font-medium dark:text-white lg:text-tiny"> <strong className="font-bold text-green7B dark:text-white lg:text-tiny">
انتخاب آدرس انتخاب آدرس
</strong> </strong>
<ul className="list-none p-0 m-0 flex flex-col"> <ul className="list-none p-0 m-0 flex flex-col mt-2">
{addresses.map((address, index) => ( {addresses.map((address, index) => (
<Location address={address} key={index} /> <Location
address={address}
key={index}
active={userAddressId === address?.id}
/>
))} ))}
</ul> </ul>
<div className="w-full flex flex-row justify-between items-center mt-4"> <div className="w-full flex flex-row justify-between items-center mt-4">
<Button <button
title="یک آدرس جدید اضافه کنید +" className={`flex justify-center text-tiny py-3 rounded-md bg-grayF9 dark:bg-blueC0 dark:bg-opacity-10 ${
backgroundColor="bg-grayF9 dark:bg-blueC0 dark:bg-opacity-30" isDark ? "text-white" : "text-gray70"
border={{ color: isDark ? "#DBDBDB22" : "#DBDBDB", width: "1px" }} } items-center w-full`}
bgOpacity="bg-opacity-100" onClick={() => setPhase("address")}
width="100%" style={{
color={isDark ? "text-white" : "text-gray70"} border: `1px solid ${isDark ? "#DBDBDB22" : "#DBDBDB"}`,
onClick={() => {}} }}
/> >
&nbsp;یک آدرس جدید اضافه کنید
<strong className="text-lg transform translate-y-0.5 mr-1">+</strong>
</button>
</div> </div>
</section> </section>
) : ( ) : (
@ -115,15 +126,18 @@ function Address({
))} ))}
</ul> </ul>
<div className="w-full flex flex-row justify-between items-center mt-4"> <div className="w-full flex flex-row justify-between items-center mt-4">
<Button <button
title="یک آدرس جدید اضافه کنید +" className={`flex justify-center text-tiny lg:text-sm rounded-md py-3 bg-grayF9 dark:bg-blueC0 dark:bg-opacity-30 ${
backgroundColor="bg-grayF9 dark:bg-blueC0 dark:bg-opacity-30" isDark ? "text-white" : "text-gray70"
border={{ color: isDark ? "#DBDBDB22" : "#DBDBDB", width: "1px" }} } items-center w-full`}
bgOpacity="bg-opacity-100"
width="100%"
color={isDark ? "text-white" : "text-gray70"}
onClick={() => setPhase("address")} onClick={() => setPhase("address")}
/> style={{
border: `1px solid ${isDark ? "#DBDBDB22" : "#DBDBDB"}`,
}}
>
&nbsp;یک آدرس جدید اضافه کنید
<strong className="text-lg transform translate-y-0.5 mr-1">+</strong>
</button>
</div> </div>
</section> </section>
); );

@ -8,16 +8,19 @@ function TransportDate({ transportDate, isDark, isMobile }) {
const Time = ({ time }) => { const Time = ({ time }) => {
return isMobile ? ( return isMobile ? (
<button <button
className={`flex flex-col border border-solid items-center flex-1 mx-1 px-2 py-3 rounded-md mt-4 relative transition-all duration-500 ${ className={`flex flex-col border-2 border-solid items-center px-2 py-3 rounded-md mt-4 relative transition-all duration-500 ${
activeDate === time activeDate === time
? "bg-blueFD border-blueC0 dark:bg-opacity-5" ? "bg-blueC0 bg-opacity-5 border-blueC0 dark:bg-opacity-5"
: "bg-grayF9 border-grayDB dark:bg-opacity-5" : "bg-grayF9 border-gray-200 dark:border-gray-500 dark:bg-opacity-5"
}`} }`}
onClick={() => setActiveDate(time)} onClick={() => setActiveDate(time)}
style={{ width: "48%" }}
> >
<strong <strong
className={`text-sm transition-all duration-500 dark:text-white ${ className={`text-tiny transition-all duration-500 dark:text-white ${
activeDate === time ? "text-blueC0" : "text-blue52" activeDate === time
? "text-green7B dark:text-blueC0"
: "text-blue52 dark:text-gray-400"
}`} }`}
> >
{time.time} {time.time}
@ -25,7 +28,9 @@ function TransportDate({ transportDate, isDark, isMobile }) {
{time.status === "completed" && ( {time.status === "completed" && (
<span <span
className={`lg:text-xs text-sm mt-1 transition-all duration-500 dark:text-white ${ className={`lg:text-xs text-sm mt-1 transition-all duration-500 dark:text-white ${
activeDate === time ? "text-blueC0" : "text-blue52" activeDate === time
? "text-green7B dark:text-blueC0"
: "text-blue52 dark:text-gray-400"
}`} }`}
> >
تکمیل ظرفیت تکمیل ظرفیت
@ -61,11 +66,11 @@ function TransportDate({ transportDate, isDark, isMobile }) {
); );
}; };
return isMobile ? ( return isMobile ? (
<section className="mt-8"> <section className="mt-0 w-full">
<strong className="font-medium dark:text-white text-base"> <strong className="font-bold text-green7B dark:text-white lg:text-tiny">
زمان ارسال را انتخاب کنید زمان ارسال را انتخاب کنید
</strong> </strong>
<ul className="list-none p-0 m-0 flex flex-row justify-between flex-wrap"> <ul className="list-none p-0 m-0 flex flex-row justify-between flex-wrap w-full">
{transportDate.times.map((time, index) => ( {transportDate.times.map((time, index) => (
<Time time={time} key={index} /> <Time time={time} key={index} />
))} ))}
@ -76,7 +81,7 @@ function TransportDate({ transportDate, isDark, isMobile }) {
<strong className="font-medium dark:text-white"> <strong className="font-medium dark:text-white">
زمان ارسال را انتخاب کنید زمان ارسال را انتخاب کنید
</strong> </strong>
<ul className="list-none p-0 m-0 flex flex-row flex-wrap w-full"> <ul className="list-none p-0 m-0 flex flex-row flex-wrap w-full gap-2">
{transportDate.times.map((time, index) => ( {transportDate.times.map((time, index) => (
<Time time={time} key={index} /> <Time time={time} key={index} />
))} ))}

@ -25,36 +25,55 @@ function TransportMethod({
const Method = ({ method }) => { const Method = ({ method }) => {
return isMobile ? ( return isMobile ? (
<button <button
className={`flex flex-col border border-solid items-center w-full px-2 py-3 rounded-md mt-4 relative transition-all duration-500 ${ className={`flex flex-col border-2 border-solid items-center w-full px-2 py-2 rounded-md mt-4 relative transition-all duration-500 ${
factorInfo?.transportId === method?.id factorInfo?.transportId === method?.id
? "bg-blueFD border-blueC0 dark:bg-opacity-5" ? "bg-blueC0 border-blueC0 bg-opacity-5 dark:bg-opacity-5"
: "bg-grayF9 border-grayDB dark:bg-opacity-5" : "bg-grayF9 border-gray-200 dark:border-gray-500 dark:bg-opacity-5"
}`} }`}
onClick={() => setActiveMethod(method)} onClick={() =>
factorInfo?.transportId !== method?.id
? setTransport(
{ factorId: factorInfo?.id, transportId: method?.id },
{ userId },
{}
)
: {}
}
> >
{loading && factorInfo?.transportId !== method?.id ? (
<Loading
size={2}
color={
factorInfo?.transportId === method?.id
? "bg-green-500"
: "bg-gray-500"
}
/>
) : (
<strong <strong
className={`text-sm transition-all duration-500 ${ className={`text-tiny transition-all duration-500 ${
activeMethod === method factorInfo?.transportId === method?.id
? "text-blueC0 dark:text-white" ? "text-green7B dark:text-blueC0"
: "text-blue52 dark:text-white" : "text-blue52 dark:text-gray-400"
}`} }`}
> >
{method.name} {method.name}
</strong> </strong>
)}
<span <span
className={`lg:text-xs text-sm mt-1 transition-all duration-500 ${ className={`lg:text-xs text-tiny mt-2 transition-all duration-500 ${
activeMethod === method factorInfo?.transportId === method?.id
? "text-blueC0 dark:text-white" ? "text-green7B dark:text-blueC0"
: "text-blue52 dark:text-white" : "text-blue52 dark:text-gray-400"
}`} }`}
> >
هزینه ارسال &nbsp; {method.cost} هزینه ارسال &nbsp; {separate(method.price)}
</span> </span>
<img {/* <img
src={method.icon} src={method.icon}
alt={method.name} alt={method.name}
className="w-7 absolute left-3 top-1/2 transform -translate-y-1/2" className="w-7 absolute left-3 top-1/2 transform -translate-y-1/2"
/> /> */}
</button> </button>
) : ( ) : (
<button <button
@ -107,11 +126,11 @@ function TransportMethod({
); );
}; };
return isMobile ? ( return isMobile ? (
<section className="mt-8"> <section className="mt-0 w-full">
<strong className="font-medium dark:text-white text-base"> <strong className="text-green7B font-bold dark:text-white text-base">
لطفا یک روش ارسال انتخاب کنید لطفا یک روش ارسال انتخاب کنید
</strong> </strong>
<ul className="list-none p-0 m-0 flex flex-col"> <ul className="list-none p-0 m-0 flex flex-col w-full">
{list.map((method, index) => ( {list.map((method, index) => (
<Method method={method} key={index} /> <Method method={method} key={index} />
))} ))}

@ -8,6 +8,8 @@ import PaymentMethods from "./PaymentMethod";
//assets //assets
import ExpressIcon from "../../assets/icons/express.svg"; import ExpressIcon from "../../assets/icons/express.svg";
import PishtazIcon from "../../assets/icons/pishtaz.svg"; import PishtazIcon from "../../assets/icons/pishtaz.svg";
import arrowBlueIcon from "../../assets/icons/arrow-right-blue.svg";
import arrowWhiteIcon from "../../assets/icons/arrow-left-white.svg";
export const DeliveryForm = ({ export const DeliveryForm = ({
getList, getList,
@ -24,7 +26,7 @@ export const DeliveryForm = ({
}) => { }) => {
useEffect(() => { useEffect(() => {
if (isMobile) { if (isMobile) {
setHeaderOptions(headerOptions); setHeaderOptions({shown : false});
} }
getFactorInfo({ userId }); getFactorInfo({ userId });
getList(); getList();
@ -47,37 +49,34 @@ export const DeliveryForm = ({
}; };
return isMobile ? ( return isMobile ? (
<div className="w-full flex flex-col px-4 pb-10"> <div className="w-full flex flex-col pt-4 pb-4">
<Address addresses={form.addresses} /> <div className="w-full flex flex-row gap-5">
<TransportMethod transportMethods={form.transportMethods} /> <Address addresses={list} setPhase={setPhase} />
</div>
<div className="w-full flex flex-row gap-5 mt-8">
<TransportMethod />
</div>
<div className="w-full flex flex-row gap-5 mt-8">
<TransportDate transportDate={form.transportDate} /> <TransportDate transportDate={form.transportDate} />
<div className="flex flex-col w-full border-t py-2 border-gray-300 border-b mt-6"> </div>
<PriceStatus {isMobile && (
name="مبلغ سبد خرید" <div
value={factorInfo?.sumPrice} className="fixed top-0 left-0 flex justify-between items-center py-3 px-4 w-full"
type="normal" style={{
isDark={isDark} backgroundColor: isDark ? "#061B30" : "white",
/> }}
<PriceStatus >
name="هزینه ارسال" <strong className="text-green4F text-lg font-semibold dark:text-white">
value={factorInfo?.transportPrice} تکمیل اطلاعات
type="normal" </strong>
isDark={isDark} <img
/> src={isDark ? arrowWhiteIcon : arrowBlueIcon}
<PriceStatus alt="back"
name="میزان تخفیف" className={`w-6 transform ${isDark ? " rotate-0" : "rotate-180"}`}
value={factorInfo?.offPrice} onClick={() => setPhase("products")}
type="error"
isDark={isDark}
/>
<PriceStatus
name="مالیات بر ارزش افزوده"
value={factorInfo?.sumPrice * 0.009}
type="error"
isDark={isDark}
/> />
</div> </div>
<PaymentMethods paymentMethods={form.paymentMethods} /> )}
</div> </div>
) : ( ) : (
<div className="w-full flex flex-col px-4 pb-10"> <div className="w-full flex flex-col px-4 pb-10">
@ -108,14 +107,13 @@ const mapStateToProps = (state) => ({
userId: state.user.status.id, userId: state.user.status.id,
isDark: state.publicApi.isDark, isDark: state.publicApi.isDark,
isMobile: state.publicApi.isMobile, isMobile: state.publicApi.isMobile,
list : state.userAddress.list list: state.userAddress.list,
}); });
const mapDispatchToProps = { const mapDispatchToProps = {
setHeaderOptions: publicApi.setHeaderOptions, setHeaderOptions: publicApi.setHeaderOptions,
getFactorInfo: userFactor.info, getFactorInfo: userFactor.info,
getList: userAddress.list getList: userAddress.list,
}; };
export default connect(mapStateToProps, mapDispatchToProps)(DeliveryForm); export default connect(mapStateToProps, mapDispatchToProps)(DeliveryForm);

@ -27,7 +27,7 @@ function Blogs({ list, isDark }) {
/> />
)} )}
</header> </header>
<ul className="list-none w-full overflow-x-scroll pt-3 flex flex-row pb-10 no-scrollbar"> <ul className="list-none w-full overflow-x-scroll pt-3 flex flex-row pb-16 no-scrollbar">
{list.map((blog, index) => ( {list.map((blog, index) => (
<Blog blog={blog} key={index} /> <Blog blog={blog} key={index} />
))} ))}
@ -56,7 +56,7 @@ const Blog = ({ blog }) => {
}} }}
> >
<div className="w-11/12 bg-white rounded-md shadow-md flex flex-col transform translate-y-1/2 p-2 dark:bg-gray36"> <div className="w-11/12 bg-white rounded-md shadow-md flex flex-col transform translate-y-1/2 p-2 dark:bg-gray36">
<h2 className="text-xs font-semibold text-blue5F dark:text-white"> <h2 className="text-xs font-semibold text-blue5F dark:text-white leading-5">
{blog.title} {blog.title}
</h2> </h2>
<div className="w-full flex flex-row justify-between items-center mt-3"> <div className="w-full flex flex-row justify-between items-center mt-3">

@ -7,12 +7,14 @@ import Progress from "../../../../../components/Progress";
//assets //assets
import arrowGreenIcon from "../../../../../assets/icons/dropdown-blue.svg"; import arrowGreenIcon from "../../../../../assets/icons/dropdown-blue.svg";
import arrowWhiteIcon from "../../../../../assets/icons/arrow-left-white.svg"; import arrowWhiteIcon from "../../../../../assets/icons/arrow-left-white.svg";
import whitePlayIcon from "../../../../../components/VodProduct/white-play-button-icon.svg";
function Videos({ videos, grades, isDark, isMobile }) { function Videos({ videos, grades, isDark, isMobile }) {
const Video = ({ video }) => { const Video = ({ video }) => {
return ( return (
<li className="flex flex-col lg:ml-6 lg:p-2 lg:border lg:border-solid lg:border-green-200 lg:rounded-md"> <li className="flex flex-col lg:ml-6 lg:p-2 lg:border lg:border-solid lg:border-green-200 lg:rounded-md">
<Link to={"/products/" + video.id}> <Link to={"/videos/" + video.id}>
<div className="relative w-full">
<img <img
src={`https://dnvn.ir/api/v1/file/${video?.fileIds}`} src={`https://dnvn.ir/api/v1/file/${video?.fileIds}`}
alt="" alt=""
@ -24,6 +26,13 @@ function Videos({ videos, grades, isDark, isMobile }) {
minWidth: isMobile ? "calc(100vw / 2)" : "", minWidth: isMobile ? "calc(100vw / 2)" : "",
}} }}
/> />
<div
className={`absolute left-1/2 top-1/2 rounded-full p-3 group-hover:scale-125 transform -translate-x-1/2 -translate-y-1/2 duration-300 bg-playButtonIcon bg-black bg-opacity-20 backdrop-filter backdrop-blur-md`}
>
<img src={whitePlayIcon} alt="" className="w-4 h-4" />
</div>
</div>
<h2 className="mt-3 mb-4 text-sm font-semibold text-blue5F dark:text-white lg:mt-4 lg:text-tiny lg:mb-5"> <h2 className="mt-3 mb-4 text-sm font-semibold text-blue5F dark:text-white lg:mt-4 lg:text-tiny lg:mb-5">
{"دوره ویدئویی" + " " + video?.product[2]?.name} {"دوره ویدئویی" + " " + video?.product[2]?.name}
</h2> </h2>

@ -17,7 +17,7 @@ function Private({ getList, products, blogs, getBlogList, grades }) {
// console.log(getBlogList()); // console.log(getBlogList());
}, []); }, []);
return ( return (
<div className="w-full flex-1 pb-6"> <div className="w-full flex-1 pb-24">
<MyBooks books={products} grades={grades} /> <MyBooks books={products} grades={grades} />
<Shop list={products} grades={grades} /> <Shop list={products} grades={grades} />
<Videos videos={products} grades={grades} /> <Videos videos={products} grades={grades} />

@ -3,7 +3,7 @@ import userImage from "../../../assets/images/user.png";
function Comment({ comment }) { function Comment({ comment }) {
return ( return (
<div className="flex flex-col py-3 px-2 rounded-sm border border-gray-200 border-solid dark:border-opacity-10 ml-4 w-auto" style={{minWidth: '250px'}}> <div className="flex flex-col py-3 px-2 rounded-md shadow-all border border-gray-200 border-solid dark:border-opacity-10 ml-4 w-auto" style={{minWidth: '250px'}}>
<header className="flex flex-row justify-between"> <header className="flex flex-row justify-between">
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<img src={userImage} alt="" className="h-10 w-10 rounded-full" /> <img src={userImage} alt="" className="h-10 w-10 rounded-full" />
@ -11,7 +11,7 @@ function Comment({ comment }) {
</div> </div>
<div className=""></div> <div className=""></div>
</header> </header>
<p className="text-xs text-gray70 mt-2 dark:text-white">{comment?.text}</p> <p className="text-sm leading-5 text-gray70 mt-2 dark:text-white">{comment?.text}</p>
</div> </div>
); );
} }

@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { book, userProduct, publicApi } from "../../redux/actions"; import { book, userProduct, publicApi } from "../../redux/actions";
import { Link } from "react-router-dom";
import proxy from "../../redux/proxy"; import proxy from "../../redux/proxy";
import location from "../../utils/location"; import location from "../../utils/location";
import Button from "../../components/Button"; import Button from "../../components/Button";
@ -10,6 +11,10 @@ import Comment from "./Comment";
import Rate from "./Rate"; import Rate from "./Rate";
import DesktopProductLayout from "./Desktop"; import DesktopProductLayout from "./Desktop";
//assets
import arrow from "../../assets/icons/dropdown-blue.svg";
export const Product = ({ export const Product = ({
isMobile, isMobile,
productType, productType,
@ -26,7 +31,7 @@ export const Product = ({
const [desktopContentTransform, setDesktopContentTransform] = useState(false); const [desktopContentTransform, setDesktopContentTransform] = useState(false);
useEffect(() => { useEffect(() => {
getInfo({ id: location.getId(), vod : true }); getInfo({ id: location.getId(), vod: true });
setHeaderOptions(headerOptions); setHeaderOptions(headerOptions);
if (!isMobile) { if (!isMobile) {
window.addEventListener("scroll", () => { window.addEventListener("scroll", () => {
@ -42,7 +47,7 @@ export const Product = ({
<> <>
{/* Portrait */} {/* Portrait */}
{isMobile ? ( {isMobile ? (
<div className="w-full flex flex-col bg-transparent px-4"> <div className="w-full flex flex-col bg-transparent px-4 pb-24">
<header <header
className={`w-full flex ${ className={`w-full flex ${
productType === "book" ? "flex-row" : "flex-col" productType === "book" ? "flex-row" : "flex-col"
@ -54,12 +59,12 @@ export const Product = ({
className="w-5/12 rounded-md" className="w-5/12 rounded-md"
/> />
<div className="flex flex-1 flex-col pr-2 pt-2"> <div className="flex flex-1 flex-col pr-2 pt-2">
<h1 className="text-blue5F mb-3 font-semibold text-sm dark:text-white"> <h1 className="text-blue5F mb-3 font-semibold text-base dark:text-white">
{type === "digital" {type === "digital"
? book?.product[0]?.name ? book?.product[0]?.name
: book?.product[1]?.name} : book?.product[1]?.name}
</h1> </h1>
<div className="text-blueC0 text-xs dark:text-greenBA"> <div className="text-green7B text-tiny dark:text-greenBA">
{"پایه" + " " + grades[book?.gradeId]} {"پایه" + " " + grades[book?.gradeId]}
</div> </div>
</div> </div>
@ -68,17 +73,17 @@ export const Product = ({
className="list-none flex flex-row divide-x items-center mt-4" className="list-none flex flex-row divide-x items-center mt-4"
style={{ direction: "ltr" }} style={{ direction: "ltr" }}
> >
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-xs font-medium text-blueC0 dark:text-white"> <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 /> صفحه {book?.pagesNum} <br /> صفحه
</li> </li>
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-xs font-medium text-blueC0 dark:text-white"> <li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white">
{"فیزیکی - دیجیتالی"} <br /> در دسترس {"فیزیکی - دیجیتالی"} <br /> در دسترس
</li> </li>
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-xs font-medium text-blueC0 dark:text-white"> <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 /> امتیاز {book?.rate} <br /> امتیاز
</li> </li>
</ul> </ul>
<h2 className="text-blueC0 text-sm font-semibold mt-7 dark:text-greenBA"> <h2 className="text-green7B text-sm font-semibold mt-7 dark:text-greenBA">
نسخه محصول را انتخاب کنید نسخه محصول را انتخاب کنید
</h2> </h2>
<div className="w-full flex flex-row justify-between items-center mt-4"> <div className="w-full flex flex-row justify-between items-center mt-4">
@ -133,7 +138,7 @@ export const Product = ({
"تومان" "تومان"
} }
backgroundColor="bg-blueC0" backgroundColor="bg-blueC0"
border={{ color: "#196EC055", width: "1px" }} border={{ color: "#196EC055", width: "0px" }}
width="65%" width="65%"
color="text-white" color="text-white"
/> />
@ -150,19 +155,21 @@ export const Product = ({
/> />
</div> </div>
<div className="w-full flex flex-row justify-between items-center mt-4"> <div className="w-full flex flex-row justify-between items-center mt-4">
<Button <Link
title="مشاهده دوره ویدئویی این محصول" to={"/videos/" + book?.id}
backgroundColor="bg-blueC0" className="bg-blueC0 text-green7B dark:text-blueC0 bg-opacity-5 font-semibold text-tiny rounded-md border border-solid border-blueC0 w-full py-3 text-center flex flex-row items-center justify-center"
border={{ color: "#196EC055", width: "0px" }} >
bgOpacity="bg-opacity-10" مشاهده دوره ویدیویی این محصول
width="100%" <img
color={isDark ? "text-white" : "text-blueC0"} src={arrow}
onClick={() => {}} alt=""
className="mr-2 transform rotate-90 w-5"
/> />
</Link>
</div> </div>
<div className="w-full flex flex-col justify-between items-center mt-4"> <div className="w-full flex flex-col justify-between items-center mt-4">
<Header title="توضیحات" link="#" /> <Header title="توضیحات" link="#" />
<p className="text-xs text-gray1 mt-2 dark:text-white"> <p className="text-sm text-gray70 mt-2 dark:text-white leading-5">
خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ
ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ
ﻫﺮﮔﺰ ﺩﺯﺩﯼ ﻧﮑﻦ ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻭ ﻫﺮﮔﺰ ﺩﺯﺩﯼ ﻧﮑﻦ ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻭ
@ -173,12 +180,12 @@ export const Product = ({
ﺩﺯﺩﯾﺪﻩ ﺍی... ﭘﺲ ﺩﺭ ﺯﻧﺪﮔﯽ ﻓﻘﻂ ﺩﺯﺩﯼ نکن{" "} ﺩﺯﺩﯾﺪﻩ ﺍی... ﭘﺲ ﺩﺭ ﺯﻧﺪﮔﯽ ﻓﻘﻂ ﺩﺯﺩﯼ نکن{" "}
</p> </p>
</div> </div>
<div className="w-full flex flex-col justify-between items-center mt-4"> <div className="w-full flex flex-col justify-between items-center mt-6">
<Header title="امتیازات و نظرات" link="#" /> <Header title="امتیازات و نظرات" link="#" />
<Rate /> <Rate />
</div> </div>
<div <div
className="flex flex-row w-full pb-4 mt-6" className="flex flex-row w-full pb-4 mt-6 no-scrollbar"
style={{ overflowX: "scroll" }} style={{ overflowX: "scroll" }}
> >
{[0, 1, 2, 2].map((comment, index) => ( {[0, 1, 2, 2].map((comment, index) => (

@ -18,9 +18,9 @@ export const Header = ({
return ( return (
<header className="w-full px-4 fixed top-0 left-0 pb-5 z-10" style={{backgroundColor: isDark ? '#061B30' : 'white'}}> <header className="w-full px-4 fixed top-0 left-0 pb-5 z-10" style={{backgroundColor: isDark ? '#061B30' : 'white'}}>
<Search <Search
backgroundColor="bg-gray-100 dark:bg-blueC0 dark:bg-opacity-70" backgroundColor="bg-gray-100"
borderColor="border-grayDB dark:border-gray45" borderColor="border-grayDB dark:border-gray45"
textColor="text-black dark:text-white" textColor="text-black dark:text-gray70"
icon={searchLight} icon={searchLight}
onChange={_.debounce( onChange={_.debounce(
(val) => setFilterOptions({ ...filterOptions, search: val }), (val) => setFilterOptions({ ...filterOptions, search: val }),

@ -58,12 +58,12 @@ export const Main = ({ books, filterOptions, grades }) => {
return filterOptions.productType === "دوره ویدئویی" return filterOptions.productType === "دوره ویدئویی"
? bySearchFilter?.map((product, index) => ( ? bySearchFilter?.map((product, index) => (
<Link <Link
to={"/products" + product?.id} to={"/videos/" + product?.id}
className={`w-full flex flex-col border-grayDB dark:border-gray45 p-3 border-solid mb-5 shadow-md mx-4`} className={`w-full flex flex-col p-3 mb-5 shadow-md mx-4`}
key={index} key={index}
> >
<div <div
className="relative w-full mb-2" className="relative w-full mb-3"
style={{ height: "calc(100vh / 5)" }} style={{ height: "calc(100vh / 5)" }}
> >
<img <img
@ -77,10 +77,10 @@ export const Main = ({ books, filterOptions, grades }) => {
</div> </div>
</div> </div>
<strong className="text-blue5F dark:text-white text-lg lg:text-tiny font-bold mb-2"> <strong className="text-blue5F dark:text-white text-tiny lg:text-tiny font-bold mb-2">
{product?.name} {product?.name}
</strong> </strong>
<span className="text-tiny lg:text-sm text-green7B dark:text-white font-light mb-4"> <span className="text-tiny lg:text-sm text-green7B dark:text-greenBA font-light mb-4">
{"پایه" + " " + grades[product?.gradeId]} {"پایه" + " " + grades[product?.gradeId]}
</span> </span>
<div className="w-full flex flex-row justify-center font-bold lg:font-medium text-lg lg:text-tiny text-blue5F dark:text-white"> <div className="w-full flex flex-row justify-center font-bold lg:font-medium text-lg lg:text-tiny text-blue5F dark:text-white">
@ -94,18 +94,16 @@ export const Main = ({ books, filterOptions, grades }) => {
<Link <Link
key={index} key={index}
to={"/products/" + product?.id} to={"/products/" + product?.id}
className={`w-1/2 flex flex-col border-t border-grayDB dark:border-gray45 p-3 border-solid ${ className={`w-1/2 flex flex-col p-3`}
index % 2 === 0 ? "border-l" : ""
}`}
> >
<img <img
src={"https://dnvn.ir/api/v1/file/" + product?.fileIds} src={"https://dnvn.ir/api/v1/file/" + product?.fileIds}
className="w-full rounded-md mb-2" className="w-full rounded-md mb-3"
/> />
<strong className="text-blue5F dark:text-white text-base lg:text-sm font-medium mb-2"> <strong className="text-blue5F dark:text-white text-tiny font-bold lg:text-sm lg:font-medium mb-2">
{"کتاب دیجیتال" + " " + product?.name} {"کتاب دیجیتال" + " " + product?.name}
</strong> </strong>
<span className="text-tiny lg:text-xs text-green7B dark:text-white font-light mb-4"> <span className="text-tiny lg:text-xs text-green7B dark:text-greenBA font-light mb-4">
{"پایه" + " " + grades[product?.gradeId]} {"پایه" + " " + grades[product?.gradeId]}
</span> </span>
<div className="w-full flex flex-row justify-center font-bold lg:font-medium text-lg lg:text-sm text-blue5F dark:text-white"> <div className="w-full flex flex-row justify-center font-bold lg:font-medium text-lg lg:text-sm text-blue5F dark:text-white">
@ -117,18 +115,16 @@ export const Main = ({ books, filterOptions, grades }) => {
<Link <Link
key={index} key={index}
to={"/products/" + product?.id} to={"/products/" + product?.id}
className={`w-1/2 flex flex-col border-t border-grayDB dark:border-gray45 p-3 border-solid ${ className={`w-1/2 flex flex-col p-3`}
index % 2 === 0 ? "border-l" : ""
}`}
> >
<img <img
src={"https://dnvn.ir/api/v1/file/" + product?.fileIds} src={"https://dnvn.ir/api/v1/file/" + product?.fileIds}
className="w-full rounded-md mb-2" className="w-full rounded-md mb-3"
/> />
<strong className="text-blue5F dark:text-white text-lg lg:text-sm font-medium mb-2"> <strong className="text-blue5F dark:text-white text-tiny font-bold lg:text-sm lg:font-medium mb-2">
{"کتاب فیزیکی" + " " + product?.name} {"کتاب فیزیکی" + " " + product?.name}
</strong> </strong>
<span className="text-tiny lg:text-xs text-green7B dark:text-white font-light mb-4"> <span className="text-tiny lg:text-xs text-green7B dark:text-greenBA font-light mb-4">
{"پایه" + " " + grades[product?.gradeId]} {"پایه" + " " + grades[product?.gradeId]}
</span> </span>
<div className="w-full flex flex-row justify-center font-bold lg:font-medium text-lg lg:text-sm text-blue5F dark:text-white"> <div className="w-full flex flex-row justify-center font-bold lg:font-medium text-lg lg:text-sm text-blue5F dark:text-white">

@ -21,25 +21,25 @@ export const Scan = ({
}; };
useEffect(() => { useEffect(() => {
setHeaderOptions(headerOptions); setHeaderOptions({shown : false});
}); });
return ( return (
<div <div
className="w-full h-screen bg-transparent px-0 transform -translate-y-16" className="w-full h-screen overflow-hidden bg-transparent px-0 transform -translate-y-16"
style={{ backgroundImage: `url(${laptopImage})` }} style={{ backgroundImage: `url(${laptopImage})` }}
> >
<div className="w-full h-full flex flex-col justify-center bg-gray50 items-center px-6 bg-opacity-70 backdrop-filter backdrop-blur-sm"> <div className="w-full h-full flex flex-col justify-center bg-gray-700 items-center px-6 bg-opacity-70 backdrop-filter backdrop-blur-sm">
<div className="rounded-3xl overflow-hidden w-full"> <div className="rounded-3xl overflow-hidden w-full">
<Scanner <Scanner
delay={300} delay={300}
onError={handleError} onError={handleError}
onScan={handleScan} onScan={handleScan}
style={{ width: "100%" }} style={{ width: "100%" }}
facingMode={facingMode[1]} facingMode={facingMode[0]}
/> />
</div> </div>
<strong className="mt-4 text-white text-xl"> <strong className="mt-4 text-white text-base">
اسکن کد QR فعالسازی کتاب اسکن کد QR فعالسازی کتاب
</strong> </strong>
<p className="text-sm text-white text-center mt-2 font-medium leading-5"> <p className="text-sm text-white text-center mt-2 font-medium leading-5">
@ -48,7 +48,7 @@ export const Scan = ({
</p> </p>
<button <button
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
className="py-3 mt-16 w-2/5 rounded-3xl border-2 border-solid border-blueB9 text-white text-lg font-semibold" className="py-3 mt-16 w-2/5 rounded-3xl border-2 border-solid border-blueC0 text-blueC0 text-lg font-semibold"
> >
بازگشت بازگشت
</button> </button>

@ -10,7 +10,7 @@ function Code({ codeId, setCodeId, userId, factorId }) {
} }
return ( return (
<form className="flex w-full flex-row border border-blueC0 border-solid rounded-md mt-3 overflow-hidden lg:w-2/5 lg:mt-5"> <form className="flex w-full flex-row border border-blueC0 border-solid rounded-md mt-3 mb-4 overflow-hidden lg:w-2/5 lg:mt-5">
<input <input
type="text" type="text"
className="border-0 flex-1 text-right pr-3 font-medium text-tiny dark:bg-gray2077 placeholder:text-blue5F dark:text-white outline-none lg:text-base lg:font-bold" className="border-0 flex-1 text-right pr-3 font-medium text-tiny dark:bg-gray2077 placeholder:text-blue5F dark:text-white outline-none lg:text-base lg:font-bold"

@ -18,13 +18,13 @@ function Product({ product, grades, pushToCart, isMobile, loading }) {
className="rounded-md w-20" className="rounded-md w-20"
/> />
<div className="flex flex-col pr-2"> <div className="flex flex-col pr-2">
<strong className="text-base text-blue5F mb-2 dark:text-white"> <strong className="text-base text-green4F mb-3 dark:text-white">
{product.product.book.name} {product.product.book.name}
</strong> </strong>
<span className="text-gray70 text-sm mb-2 dark:text-greenBA"> <span className="text-gray70 text-tiny mb-2 dark:text-greenBA">
{"پایه" + " " + grades[product.product.book.gradeId]} {"پایه" + " " + grades[product.product.book.gradeId]}
</span> </span>
<span className="text-gray70 text-sm dark:text-greenBA"> <span className="text-gray70 text-tiny dark:text-greenBA">
{product.productType === 2 ? "نسخه فیزیکی" : "نسخه دیجیتال"} {product.productType === 2 ? "نسخه فیزیکی" : "نسخه دیجیتال"}
</span> </span>
</div> </div>
@ -61,15 +61,36 @@ function Product({ product, grades, pushToCart, isMobile, loading }) {
> >
+ +
</button> </button>
<span className="mx-2.5 font-semibold text-md text-blueC0"> <span className="mx-2.5 font-semibold text-4xl text-blueC0">
{loading ? ( {loading ? (
<Loading size={2} color="bg-green-500" /> <Loading size={2} color="bg-green-500" />
) : ( ) : (
product.count product.count
)} )}
</span> </span>
{
<>
{product.count === 1 ? (
<img
onClick={() =>
pushToCart(
{
productId: product?.productId,
userId: product?.userId,
count:
product?.productType === 1 ? -1 : -product?.count,
},
{},
{ id: product?.factorId }
)
}
src={deleteIcon}
alt="delete"
className="border border-red-800 border-solid p-1 w-8 bg-red-100 rounded-md cursor-pointer"
/>
) : (
<button <button
className="rounded-md pt-2 pb-1.5 px-3 border border-solid border-grayDB text-grayDB dark:border-blueC0 dark:text-blueC0" className="rounded-md pt-2 pb-1.5 px-3 font-bold border border-solid border-blueC0 text-blueC0 dark:border-blueC0 dark:text-blueC0"
onClick={() => onClick={() =>
pushToCart({ pushToCart({
productId: product?.productId, productId: product?.productId,
@ -80,10 +101,13 @@ function Product({ product, grades, pushToCart, isMobile, loading }) {
> >
- -
</button> </button>
)}
</>
}
</div> </div>
)} )}
<strong className="font-bold text-md text-blue5F dark:text-white"> <strong className="font-bold text-md text-blue5F dark:text-white">
{product.product.price}&nbsp;تومان {separate(product.product.price * product.count)}&nbsp;تومان
</strong> </strong>
</div> </div>
</div> </div>
@ -134,11 +158,7 @@ function Product({ product, grades, pushToCart, isMobile, loading }) {
+ +
</button> </button>
<span className="mx-2.5 font-semibold text-5xl text-green4F w-8 flex justify-center"> <span className="mx-2.5 font-semibold text-5xl text-green4F w-8 flex justify-center">
{loading ? ( {loading ? <Loading size={2} color="bg-green-500" /> : product.count}
<Loading size={2} color="bg-green-500" />
) : (
product.count
)}
</span> </span>
{ {
<> <>

@ -40,6 +40,12 @@ function ShoppingCart({
setHeaderOptions(headerOptions); setHeaderOptions(headerOptions);
}, []); }, []);
useEffect(() => {
if (phase === "products") {
setHeaderOptions(headerOptions);
}
}, [phase]);
const productsLength = userProducts?.filter( const productsLength = userProducts?.filter(
(product) => product.condition < 2 (product) => product.condition < 2
)?.length; )?.length;
@ -86,15 +92,29 @@ function ShoppingCart({
const PriceStatus = ({ name, value, type }) => { const PriceStatus = ({ name, value, type }) => {
return isMobile ? ( return isMobile ? (
<div className="w-full flex flex-row justify-between py-2"> <div className="w-full flex flex-row justify-between py-3">
<strong className="font-light text-sm dark:text-white">{name}</strong> <strong className="font-semibold text-tiny dark:text-white text-blue5F">
{name}
</strong>
<span
className="font-medium text-lg dark:text-white"
style={{
color: !isDark
? type === "error"
? "#F1420D"
: "rgb(6, 186, 206)"
: "",
}}
>
{separate(Math.floor(value))}
<span <span
className="font-bold text-lg dark:text-white"
style={{ style={{
color: !isDark ? (type === "error" ? "#F1420D" : "#246E8A") : "", color: !isDark ? (type === "error" ? "#F1420D" : "") : "",
}} }}
className="text-sm mr-2"
> >
{value + " " + "تومان"} تومان
</span>
</span> </span>
</div> </div>
) : ( ) : (
@ -112,7 +132,7 @@ function ShoppingCart({
: "", : "",
}} }}
> >
{separate(value)} {separate(Math.floor(value))}
<span <span
style={{ style={{
color: !isDark ? (type === "error" ? "#F1420D" : "") : "", color: !isDark ? (type === "error" ? "#F1420D" : "") : "",
@ -127,7 +147,23 @@ function ShoppingCart({
}; };
const layouts = { const layouts = {
products: productsLength ? ( products: isMobile ? (
<>
{productsLength ? (
list
.sort((a, b) => a?.id - b?.id)
.map(
(product, index) =>
product.condition < 2 && (
<Product loading={loading} key={index} product={product} />
)
)
) : (
<strong className="text-blueC0">سبد خرید شما خالی است.</strong>
)}
<Code />
</>
) : productsLength ? (
<Table /> <Table />
) : ( ) : (
<strong className="text-blueC0">سبد خرید شما خالی است.</strong> <strong className="text-blueC0">سبد خرید شما خالی است.</strong>
@ -137,12 +173,11 @@ function ShoppingCart({
}; };
return isMobile ? ( return isMobile ? (
<div className="w-full flex flex-col px-4"> <div className="w-full flex flex-col px-4 pb-24">
{list.map((product, index) => ( <div className="flex flex-col flex-1">{layouts[phase]}</div>
<Product key={index} product={product} /> {phase !== "address" && (
))} <>
<Code /> <div className="flex flex-col w-full border-t border-gray-300 border-b">
<div className="flex flex-col w-full border-t py-2 border-gray-300 border-b mt-6">
<PriceStatus <PriceStatus
name="مبلغ سبد خرید" name="مبلغ سبد خرید"
value={factorInfo?.sumPrice} value={factorInfo?.sumPrice}
@ -160,30 +195,45 @@ function ShoppingCart({
/> />
</div> </div>
<div className="flex flex-row justify-between items-center w-full py-3"> <div className="flex flex-row justify-between items-center w-full py-3">
<strong className="font-light text-sm dark:text-white"> <strong className="font-bold text-tiny text-blue5F dark:text-white">
جمع کل سبد خرید جمع کل سبد خرید
</strong> </strong>
<p className="font-medium text-greenBA text-lg dark:text-white"> <p className="font-medium text-greenBA text-lg dark:text-white">
{factorInfo?.payPrice + " " + "تومان"} {separate(factorInfo?.payPrice) + " " + "تومان"}
</p> </p>
</div> </div>
<div <div
className="w-full rounded-md flex flex-row justify-center items-center py-2.5 px-3 my-5" className="w-full rounded-md flex flex-row justify-center items-center py-2.5 px-3 mt-5 mb-4"
style={{ backgroundColor: "#196EC01a" }} style={{ backgroundColor: isDark ? "#DEFFF111" : "#DEFFF188" }}
> >
<img src={alertIcon} className="w-5 ml-2" /> <img src={alertIcon} className="w-5 ml-2" />
<p className="text-xs text-blueC0 dark:text-white"> <p className="text-xs text-green71 dark:text-white text-justify font-medium">
هزینه ارسال کالا پس از تعیین محل آدرس مشخص میشود هزینه ارسال کالا پس از تعیین محل آدرس مشخص میشود
</p> </p>
</div> </div>
<Button <Button
title="ادامه فرایند خرید" title="ادامه فرایند خرید"
backgroundColor="bg-blueC0" backgroundColor="bg-blueC0"
border={{ color: "#196EC055", width: "1px" }} border={{ color: "#196EC055", width: "0px" }}
width="100%" width="100%"
color="text-white" color="text-white"
onClick={() => {}} onClick={next[phase]}
/> />
{phase !== "products" && (
<button
className="bg-transparent mt-4 text-base border-2 border-solid border-blueC0 text-green7B dark:text-blueC0 rounded-full py-3 flex flex-row justify-center items-center"
onClick={() => setPhase("products")}
>
بازگشت
<img
src={dropdownIcon}
alt=""
className="w-4 transform rotate-90"
/>
</button>
)}
</>
)}
</div> </div>
) : ( ) : (
<div <div

@ -38,37 +38,35 @@ const Season = ({
// const [activeSeason, setActiveSeason] = useState(null); // const [activeSeason, setActiveSeason] = useState(null);
const Unit = ({ unit, index }) => { const Unit = ({ unit, index }) => {
return isMobile ? ( return isMobile ? (
<Link <div className="d-flex flex-column">
to="/videos/0/display" <li
className="w-full flex flex-col rounded-md overflow-hidden mb-3 border border-solid border-blueFE dark:border-opacity-60 bg-blueFF dark:bg-opacity-10" className="lesson__files--sample justify-content-between align-items-center py-2 px-0 shadow-sm"
> style={{
<div className="w-full flex flex-row justify-between items-center py-3 px-2 border-b border-solid border-blueFE dark:border-opacity-60"> display: season[0].categoryId === activeSeason ? "flex" : "none",
<strong className="text-blueC0 text-sm dark:text-white font-normal"> }}
{unit.name}
</strong>
{/* <span className="text-sm text-blueC0 dark:text-white">
{unit.duration}
</span> */}
</div>
{/* <div className="w-full flex flex-row">
{unit.play && (
<Link
to={`/videos/${id}/display`}
className="flex flex-1 flex-row items-center py-2.5 px-2 border-l border-solid border-blueFE dark:border-opacity-60 justify-center text-sm text-blueC0 dark:text-white"
> >
نمایش <div className="flex items-center justify-between w-full">
</Link> <h5 className="text-tiny font-bold text-green7B dark:text-white">{unit.name}</h5>
)} <div className="flex items-center gap-4">
{unit.download && (
<Link <Link
to={`/videos/${id}/download`} to={
className="flex flex-1 flex-row items-center py-2.5 px-2 justify-center text-sm text-blueC0 dark:text-white" Number(index) === 0
? window.location.pathname + "/display"
: "#"
}
className={`bg-white border border-solid ${
Number(index) === 0
? "border-green-300 text-blueC0 dark:bg-opacity-0"
: "border-gray-300 text-gray70 cursor-not-allowed dark:bg-opacity-10"
} py-2 w-20 text-center text-tiny rounded-sm shadow-md`}
onClick={() => setCategory(season[0].categoryId, unit.name)}
> >
دانلود {Number(index) === 0 ? "تماشا" : "قفل"}
</Link>
)}
</div> */}
</Link> </Link>
</div>
</div>
</li>
</div>
) : ( ) : (
<div className="d-flex flex-column"> <div className="d-flex flex-column">
<li <li
@ -110,25 +108,43 @@ const Season = ({
onClick={() => toggle(season[0].categoryId)} onClick={() => toggle(season[0].categoryId)}
> >
<button <button
className="flex flex-row justify-between items-center rounded-md py-3 px-3 mb-3 bg-blueC0" className="flex flex-row justify-between items-center rounded-md py-3 px-3 mb-3 bg-blueC0 bg-opacity-5 border border-solid border-green-300"
// onClick={() => // onClick={() =>
// setActiveSeason(season.name === activeSeason ? null : season.name) // setActiveSeason(season.name === activeSeason ? null : season.name)
// } // }
> >
<strong className="text-sm text-white font-medium"> <strong className="text-tiny text-green7B font-bold dark:text-white">
{ {
realSeasons.filter((item) => item.id === season[0].categoryId)[0] realSeasons.filter((item) => item.id === season[0].categoryId)[0]
.name .name
} }
</strong> </strong>
<span className="text-xs text-white">{season.duration}</span> <img
src={dropdownIcon}
alt=""
className={`w-4 transform transition-all ${
season[0].categoryId === activeSeason ? "rotate-180" : ""
}`}
/>{" "}
</button> </button>
{season[0].categoryId === activeSeason && <ul
season.map((unit, index) => <Unit unit={unit} key={index} />)} className={`w-full flex flex-col px-2 ${
season[0].categoryId === activeSeason
? ""
: ""
} transform origin-bottom duration-1000 transition-all overflow-hidden`}
style={{
maxHeight: season[0].categoryId === activeSeason ? 1000 : 0,
}}
>
{season.map((unit, index) => (
<Unit unit={unit} key={index} index={index} />
))}
</ul>
</div> </div>
) : ( ) : (
<li className="w-full flex flex-col bg-blueC0 bg-opacity-10 rounded-md overflow-hidden shadow-md"> <li className="w-full flex flex-col bg-blueC0 bg-opacity-10 rounded-md overflow-hidden shadow-md mb-1">
<header <header
className="w-full flex flex-row justify-between items-center py-3 px-6" className="w-full flex flex-row justify-between items-center py-3 px-6"
onClick={() => toggle(season[0].categoryId)} onClick={() => toggle(season[0].categoryId)}
@ -148,13 +164,9 @@ const Season = ({
/> />
</header> </header>
<ul <ul
className={`w-full flex flex-col px-4 divide-y-2 divide-solid transform origin-bottom transition-all divide-green-100 overflow-hidden`} className={`w-full flex flex-col px-1.5 transform origin-bottom transition-all overflow-hidden`}
style={{ style={{
height: isMobile maxHeight: season[0].categoryId === activeSeason ? 1000 : 0,
? "auto"
: season[0].categoryId === activeSeason
? (24 + 34.5) * season.length
: 0,
}} }}
> >
{season.map((unit, index) => ( {season.map((unit, index) => (

@ -22,41 +22,7 @@ function Video({
isLogin, isLogin,
pushToCart, pushToCart,
userId, userId,
product = { product,
id: 0,
type: "کتاب ها",
name: "ریاضی",
price: "145.000 تومان",
imageUrl: "https://dnvn.ir/api/v1/file/2105",
poster: poster,
grade: "پایه هفتم ابتدایی",
seasons: [
{
name: "فصل اول: مباحث جوشش مواد مذاب در مرکز زمین",
duration: "2:30:13",
units: [
{
name: "مقدمه جالب توجه نویسنده کتاب برای شما",
duration: "14:30",
download: true,
play: true,
},
{
name: "چگونگی ساخت نیروگاههای برقی ",
duration: "14:30",
download: false,
play: true,
},
{
name: "آیا گوگل از ما دزدی میکند ؟",
duration: "14:30",
download: true,
play: true,
},
],
},
],
},
isMobile, isMobile,
isDark, isDark,
headerOptions, headerOptions,
@ -73,40 +39,65 @@ function Video({
getBook({ bookId: location.getId() }, { id: location.getId(), vod: true }); getBook({ bookId: location.getId() }, { id: location.getId(), vod: true });
setHeaderOptions(headerOptions); setHeaderOptions(headerOptions);
}, []); }, []);
return isMobile ? ( return isMobile ? (
<div className="w-full flex flex-col px-4"> <div className="w-full flex flex-col px-4 pb-24">
<div className="w-full flex flex-col"> <div className="w-full flex flex-col">
<div <div
className="w-full flex flex-row flex-1 justify-between items-center relative overflow-hidden" className="w-full flex flex-row flex-1 = relative overflow-hidden"
style={{ style={{}}
backgroundImage: `url(${product.poster})`,
backgroundSize: "100% 100%",
repeat: "no-repeat",
minWidth: "calc(100vw / 1.5)",
minHeight: "calc(100vw / 1.5 * 11 / 16)",
}}
> >
<img <img
src={`https://dnvn.ir/api/v1/file/${book?.fileIds}`} src={`https://dnvn.ir/api/v1/file/${book?.fileIds}`}
className="rounded-md absolute left-2 top-1/2 transform -translate-y-1/2" className="rounded-md"
style={{ width: 70, height: 100 }} style={{
width: "calc(100vh / 7)",
height: "calc(100vh / 7 * 4 / 3)",
}}
/> />
</div> <div className="flex flex-col py-1 pr-3">
<div className="flex flex-col flex-1 justify-between pr-2"> <strong className="text-blue5F text-lg dark:text-white font-black">
<div className="flex flex-col"> {"دوره ویدئویی" + " " + book?.product[2]?.name}
<strong className="mt-2 text-blue5F text-base dark:text-white font-normal">
{book?.name}
</strong> </strong>
<span className="text-blueC0 text-sm mb-1 dark:text-greenBA mt-2"> <span className="text-blueC0 text-base dark:text-greenBA mt-3 mb-5">
{"پایه" + " " + (grades[book?.gradeId] || "پایه دوازدهم")} {"پایه" + " " + (grades[book?.gradeId] || "پایه دوازدهم")}
</span> </span>
</div> </div>
<Divider type={"vertical"} /> </div>
<div className="flex flex-col flex-1 justify-between my-5">
<Button
title={
"خرید با قیمت" +
" " +
separate(book?.product[2]?.price) +
" " +
"تومان"
}
backgroundColor={isDark ? "bg-blueC0" : "bg-blueC0"}
border={{
color: isDark ? "#ffffff55" : "#196EC055",
width: "0px",
}}
width="100%"
color={"text-white"}
selectable={true}
onClick={() =>
isLogin
? pushToCart({
productId: book?.id,
userId: userId,
count: 1,
})
: toast.info("ابتدا وارد حساب کاربری خود شوید.")
}
/>
</div> </div>
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
{seasons?.map((season, index) => ( {seasons
<Season season={season} key={index} id={product.id} /> ?.sort((a, b) => a[0]?.categoryId - b[0]?.categoryId)
?.map((season, index) => (
<Season season={season} key={index} id={book?.id} />
))} ))}
</div> </div>
</div> </div>
@ -122,8 +113,10 @@ function Video({
title: "سر فصل ها", title: "سر فصل ها",
components: ( components: (
<div className="flex flex-col w-full mt-5 gap-5"> <div className="flex flex-col w-full mt-5 gap-5">
{seasons?.map((season, index) => ( {seasons
<Season season={season} key={index} id={product.id} /> ?.sort((a, b) => a[0]?.categoryId - b[0]?.categoryId)
?.map((season, index) => (
<Season season={season} key={index} id={book?.id} />
))} ))}
</div> </div>
), ),
@ -152,10 +145,10 @@ function Video({
/> />
)} )}
</div> </div>
<div className="w-3/12 flex flex-col" style={{minWidth: 350}}> <div className="w-3/12 flex flex-col" style={{ minWidth: 350 }}>
<div className="w-full flex flex-col pr-2 py-2 border-0"> <div className="w-full flex flex-col pr-2 py-2 border-0">
<h1 className="text-blue5F mb-3 font-semibold text-xl dark:text-white"> <h1 className="text-blue5F mb-3 font-semibold text-xl dark:text-white">
{"دوره ویدئویی" + " " + book?.name} {"دوره ویدئویی" + " " + book?.product[2]?.name}
</h1> </h1>
<div className="text-blueC0 text-sm dark:text-greenBA"> <div className="text-blueC0 text-sm dark:text-greenBA">
{"پایه" + " " + grades[book?.gradeId]} {"پایه" + " " + grades[book?.gradeId]}
@ -179,7 +172,7 @@ function Video({
<div className="flex flex-col w-full py-4 px-4"> <div className="flex flex-col w-full py-4 px-4">
<div className="flex flex-row items-center justify-center gap-2"> <div className="flex flex-row items-center justify-center gap-2">
<strong className="text-blueC0 text-xl"> <strong className="text-blueC0 text-xl">
{separate(book?.price)} {separate(book?.product[2]?.price)}
</strong> </strong>
<span className="text-sm text-gray-500">تومان</span> <span className="text-sm text-gray-500">تومان</span>
</div> </div>
@ -199,7 +192,7 @@ function Video({
onClick={() => onClick={() =>
isLogin isLogin
? pushToCart({ ? pushToCart({
productId: book?.id, productId: book?.product[2]?.id,
userId: userId, userId: userId,
count: 1, count: 1,
}) })
@ -224,7 +217,7 @@ function Video({
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile, isMobile: state.publicApi.isMobile,
isDark: state.publicApi.isDark, isDark: state.publicApi.isDark,
book: state.book.info?.product[2], book: state.book.info,
seasons: state.publicApi.categories, seasons: state.publicApi.categories,
grades: state.publicApi.grades, grades: state.publicApi.grades,
isLogin: state.user.status, isLogin: state.user.status,

@ -11,40 +11,6 @@ import Season from "./components/Season";
function VideoDisplay({ function VideoDisplay({
isMobile, isMobile,
product = {
type: "کتاب ها",
name: "ریاضی",
price: "145.000 تومان",
imageUrl: "https://dnvn.ir/api/v1/file/2105",
poster: poster,
grade: "پایه هفتم ابتدایی",
seasons: [
{
name: "فصل اول: مباحث جوشش مواد مذاب در مرکز زمین",
duration: "2:30:13",
units: [
{
name: "مقدمه جالب توجه نویسنده کتاب برای شما",
duration: "14:30",
download: true,
play: true,
},
{
name: "چگونگی ساخت نیروگاههای برقی ",
duration: "14:30",
download: false,
play: true,
},
{
name: "آیا گوگل از ما دزدی میکند ؟",
duration: "14:30",
download: true,
play: true,
},
],
},
],
},
headerOptions, headerOptions,
setHeaderOptions, setHeaderOptions,
book, book,
@ -59,47 +25,24 @@ function VideoDisplay({
8, 8,
window.location.pathname.lastIndexOf("/") window.location.pathname.lastIndexOf("/")
); );
getBook({bookId : id}, {id}); getBook({ bookId: id }, { id });
setHeaderOptions(headerOptions); setHeaderOptions(headerOptions);
const cat = localStorage.getItem("season")?.split(","); const cat = localStorage.getItem("season")?.split(",");
getSeason({ bookId: cat[0], categoryId: cat[1] }); getSeason({ bookId: cat[0], categoryId: cat[1] });
}, []); }, []);
useEffect(() => {
},[])
const enamad =
'<a referrerpolicy="origin" target="_blank" href="https://trustseal.enamad.ir/?id=224965&amp;Code=x8oNSO7tTnqAniyPpPyN"><img referrerpolicy="origin" src="https://Trustseal.eNamad.ir/logo.aspx?id=224965&amp;Code=x8oNSO7tTnqAniyPpPyN" alt="" style="cursor:pointer" id="x8oNSO7tTnqAniyPpPyN"></a>';
return isMobile ? ( return isMobile ? (
<div className="w-full flex flex-col px-4"> <div className="w-full flex flex-col px-4 pb-24 pt-4">
<div className="w-full flex flex-col mb-6"> <div className="w-full flex flex-col mb-6">
<div className="w-full flex flex-row flex-1 justify-between items-center overflow-hidden relative"> <JolPlayer
<video fileIds={selectedVideo?.fileIds}
style={{ width: "100%", height: "calc(100vw * 9 / 16 - 16)" }} posterId={selectedVideo?.posterId}
controls
>
<source
src={`https://dnvn.ir/api/v1/file/20540`}
type="video/mp4"
/> />
</video> <h1 className="mt-2 font-bold text-4xl text-blue52 dark:text-white pb-4 border-b-2 border-solid border-gray-200">
</div> {selectedVideo?.name}
{/* <div className="flex flex-col flex-1 justify-between pr-2"> </h1>
<div className="flex flex-col">
<strong className="mt-1 text-blue5F text-base dark:text-white">
{product.name}
</strong>
<span className="text-blueC0 text-xs mb-1 dark:text-greenBA">{product.grade}</span>
</div>
<Divider type={"vertical"} />
</div> */}
</div>
<div className="flex flex-col">
{product.seasons.map((season, index) => (
<Season season={season} key={index} />
))}
</div> </div>
<PlayList playList={book?.vods} />
</div> </div>
) : ( ) : (
<div className="w-11/12 flex flex-col mb-6 justify-center items-center mx-auto pt-24 pb-20"> <div className="w-11/12 flex flex-col mb-6 justify-center items-center mx-auto pt-24 pb-20">
@ -128,15 +71,6 @@ function VideoDisplay({
</div> </div>
<PlayList playList={book?.vods} /> <PlayList playList={book?.vods} />
</div> </div>
{/* <div className="flex flex-col flex-1 justify-between pr-2">
<div className="flex flex-col">
<strong className="mt-1 text-blue5F text-base dark:text-white">
{product.name}
</strong>
<span className="text-blueC0 text-xs mb-1 dark:text-greenBA">{product.grade}</span>
</div>
<Divider type={"vertical"} />
</div> */}
<div></div> <div></div>
</div> </div>
); );
@ -153,7 +87,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = { const mapDispatchToProps = {
setHeaderOptions: publicApi.setHeaderOptions, setHeaderOptions: publicApi.setHeaderOptions,
getBook: publicApi.bookInfo, getBook: publicApi.bookInfo,
getSeason: publicApi.bookSection getSeason: publicApi.bookSection,
}; };
export default connect(mapStateToProps, mapDispatchToProps)(VideoDisplay); export default connect(mapStateToProps, mapDispatchToProps)(VideoDisplay);

@ -1,14 +1,15 @@
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import separate from "../../../utils/separate";
import Header from "../../../components/Header"; import Header from "../../../components/Header";
import posterImage from "../../../assets/images/poster.svg"; import posterImage from "../../../assets/images/poster.svg";
function MostViewedVideo({videos, grades}) { function MostViewedVideo({ videos, grades }) {
const Video = ({ video }) => { const Video = ({ video }) => {
return ( return (
<Link <Link
to={"/videos/" + video.id} to={"/videos/" + video.id}
className="flex flex-col rounded-md ml-4 shadow-md p-2" className="flex flex-col rounded-md ml-4 shadow-md p-2 border border-solid border-gray-200 dark:border-opacity-30 mt-3"
> >
<div <div
className="w-full flex flex-row flex-1 justify-between items-center relative overflow-hidden" className="w-full flex flex-row flex-1 justify-between items-center relative overflow-hidden"
@ -29,14 +30,14 @@ function MostViewedVideo({videos, grades}) {
}} }}
/> />
</div> </div>
<strong className="text-tiny mt-1 text-blue5F dark:text-white font-normal"> <strong className="text-base mt-0 text-blue5F dark:text-white font-bold">
{video.name} {"دوره ویدئویی" + " " + video.name}
</strong> </strong>
<div className="w-full flex flex-row justify-between items-center mt-3"> <div className="w-full flex flex-row justify-between items-center mt-3">
<strong className="text-blue52 text-sm dark:text-greenBA"> <strong className="text-black text-tiny dark:text-greenBA">
{video.price} {separate(video?.product[2]?.price) + " " + "تومان"}
</strong> </strong>
<span className="text-blueC0 text-sm dark:text-white"> <span className="text-green7B text-sm dark:text-white">
{"پایه" + " " + grades[video.gradeId]} {"پایه" + " " + grades[video.gradeId]}
</span> </span>
</div> </div>
@ -46,12 +47,9 @@ function MostViewedVideo({videos, grades}) {
return ( return (
<div className="w-full flex flex-col"> <div className="w-full flex flex-col">
<Header title="پربازدیدترین" link="/videos/video" /> <Header title="پربازدیدترین" link="/videos/video" />
<div className="w-full flex flex-row overflow-x-scroll pb-4"> <div className="w-full flex flex-row overflow-x-scroll pb-4 no-scrollbar">
{videos.map((video, index) => ( {videos.map((video, index) => (
<Video <Video key={index} video={video} />
key={index}
video={video}
/>
))} ))}
</div> </div>
</div> </div>

@ -1,7 +1,8 @@
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import Header from "../../../components/Header"; import Header from "../../../components/Header";
import posterImage from "../../../assets/images/poster.svg"; import separate from "../../../utils/separate";
const NewestVideo = ({ videos, grades }) => { const NewestVideo = ({ videos, grades }) => {
const Video = ({ video }) => { const Video = ({ video }) => {
@ -25,9 +26,14 @@ const NewestVideo = ({ videos, grades }) => {
<strong className="text-base mt-2 text-blue5F dark:text-white font-normal"> <strong className="text-base mt-2 text-blue5F dark:text-white font-normal">
{video.name} {video.name}
</strong> </strong>
<span className="text-blueC0 text-sm mt-2 dark:text-greenBA"> <div className="flex items-center justify-between w-full mt-2">
<span className="text-green7B text-sm dark:text-greenBA">
{"پایه" + " " + grades[video.gradeId]} {"پایه" + " " + grades[video.gradeId]}
</span> </span>
<strong className="text-black text-tiny dark:text-greenBA">
{separate(video?.product[2]?.price) + " " + "تومان"}
</strong>
</div>
</Link> </Link>
); );
}; };
@ -35,7 +41,7 @@ const NewestVideo = ({ videos, grades }) => {
<div className="w-full flex flex-col"> <div className="w-full flex flex-col">
<Header title="جدیدترین دورهها" link="/videos/video" /> <Header title="جدیدترین دورهها" link="/videos/video" />
<div className="w-full flex flex-row flex-wrap justify-between overflow-x-scroll mt-3"> <div className="w-full flex flex-row flex-wrap justify-between overflow-x-scroll mt-3">
{videos.map((video, index) => ( {videos.slice(0, 5).map((video, index) => (
<Video key={index} video={video} /> <Video key={index} video={video} />
))} ))}
</div> </div>

@ -13,11 +13,11 @@ function Videos({ headerOptions, setHeaderOptions, getList, videos, grades }) {
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
useEffect(() => { useEffect(() => {
setHeaderOptions(headerOptions); setHeaderOptions(headerOptions);
getList(); getList({ vod: true });
}, []); }, []);
return ( return (
<div className="flex flex-col"> <div className="flex flex-col pb-24">
<div className="px-4"> {/* <div className="px-4">
<Search <Search
backgroundColor="bg-grayF9 dark:bg-gray2077" backgroundColor="bg-grayF9 dark:bg-gray2077"
borderColor="border-grayDB dark:border-gray45" borderColor="border-grayDB dark:border-gray45"
@ -30,7 +30,7 @@ function Videos({ headerOptions, setHeaderOptions, getList, videos, grades }) {
</div> </div>
<div className="px-4 flex flex-col"> <div className="px-4 flex flex-col">
<Divider type={"vertical"} /> <Divider type={"vertical"} />
</div> </div> */}
<div className="pr-4"> <div className="pr-4">
<MostViewedVideo videos={videos} grades={grades} /> <MostViewedVideo videos={videos} grades={grades} />
</div> </div>
@ -43,13 +43,13 @@ function Videos({ headerOptions, setHeaderOptions, getList, videos, grades }) {
} }
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
videos : state.book.list, videos: state.book.list,
grades: state.publicApi.grades, grades: state.publicApi.grades,
}); });
const mapDispatchToProps = { const mapDispatchToProps = {
setHeaderOptions: publicApi.setHeaderOptions, setHeaderOptions: publicApi.setHeaderOptions,
getList : book.list getList: book.list,
}; };
export default connect(mapStateToProps, mapDispatchToProps)(Videos); export default connect(mapStateToProps, mapDispatchToProps)(Videos);

Loading…
Cancel
Save