Merge branch 'master' of https://git.sitenevis.com/Danovin/application

Conflicts:
	yarn.lock
master
Your Name 2 years ago
commit f443fe281c
  1. 6
      postcss.config.js
  2. 1
      src/App.scss
  3. 8
      src/assets/icons/bookmark-active-dark.svg
  4. 8
      src/assets/icons/bookmark-active-light.svg
  5. 2
      src/components/BottomNavigation/index.js
  6. 17
      src/components/ButtonBetween/index.js
  7. 14
      src/components/Comments/index.js
  8. 8
      src/components/CourseChapter/index.js
  9. 4
      src/components/Dialog/index.js
  10. 110
      src/components/Drawer/index.js
  11. 24
      src/components/Footer/index.js
  12. 2
      src/components/Header/index.js
  13. 24
      src/components/Modal/index.js
  14. 242
      src/components/Navbar/index.js
  15. 2
      src/components/OR/index.js
  16. 2
      src/components/ProductImage/index.js
  17. 24
      src/components/ProductStatusCard/index.js
  18. 6
      src/components/ProductSuggestion/index.js
  19. 2
      src/components/ProductTab/index.js
  20. 22
      src/components/QandA/index.js
  21. 3
      src/components/StarRating/index.js
  22. 4
      src/components/VerticalExpandableProductFilter/index.js
  23. 1
      src/index.css
  24. 4
      src/redux/actions/blog.js
  25. 1
      src/redux/actions/comment.js
  26. 12
      src/redux/actions/config.js
  27. 1
      src/redux/actions/index.js
  28. 16
      src/redux/reducers/blog.js
  29. 24
      src/redux/reducers/config.js
  30. 2
      src/redux/reducers/form.js
  31. 1
      src/redux/reducers/index.js
  32. 91
      src/router.js
  33. 7
      src/views/About/index.js
  34. 4
      src/views/About/index.scss
  35. 2
      src/views/Activation/components/Alert.js
  36. 12
      src/views/Address/index.js
  37. 71
      src/views/Auth/Desktop/index.js
  38. 4
      src/views/Auth/Profile/index.js
  39. 100
      src/views/Auth/SignUp/index.js
  40. 15
      src/views/Auth/index.js
  41. 67
      src/views/Blog/index.js
  42. 58
      src/views/Blogs/index.js
  43. 45
      src/views/Blogs/layouts/Blog.js
  44. 23
      src/views/Blogs/layouts/Hashtags.js
  45. 2
      src/views/Blogs/layouts/Join.js
  46. 4
      src/views/Blogs/layouts/New.js
  47. 2
      src/views/Blogs/layouts/Suggest.js
  48. 6
      src/views/Blogs/layouts/Target.js
  49. 36
      src/views/Contact/index.js
  50. 2
      src/views/Contact/layouts/Info.js
  51. 26
      src/views/Contact/layouts/Ticket.js
  52. 8
      src/views/Contact/layouts/Upload.js
  53. 2
      src/views/Dashboard/index.js
  54. 35
      src/views/Dashboard/layouts/Main/Addresses/index.js
  55. 2
      src/views/Dashboard/layouts/Main/MyBooks/index.js
  56. 14
      src/views/Dashboard/layouts/Mobile/List.js
  57. 30
      src/views/Dashboard/layouts/Mobile/ProfileAddress/index.js
  58. 8
      src/views/Dashboard/layouts/Mobile/ProfileBookmark/index.js
  59. 8
      src/views/Dashboard/layouts/Mobile/Trophy.js
  60. 6
      src/views/Dashboard/layouts/Mobile/User.js
  61. 32
      src/views/Dashboard/layouts/SidebarMenu/index.js
  62. 44
      src/views/DeliveryForm/Address/index.js
  63. 6
      src/views/DeliveryForm/PaymentMethod/index.js
  64. 6
      src/views/DeliveryForm/TransportDate/index.js
  65. 2
      src/views/DeliveryForm/TransportMethod/index.js
  66. 14
      src/views/DeliveryForm/index.js
  67. 2
      src/views/Faq/components/NotFound.js
  68. 2
      src/views/Faq/components/Question.js
  69. 2
      src/views/Faq/index.js
  70. 2
      src/views/Favorites/index.js
  71. 2
      src/views/Home/Desktop/Part2/index.js
  72. 2
      src/views/Home/Desktop/Part4/index.js
  73. 2
      src/views/Home/Desktop/SalesContainer/index.js
  74. 2
      src/views/Home/Landscape/Page1/Lights/index.js
  75. 6
      src/views/Home/Landscape/Page1/index.js
  76. 2
      src/views/Home/Landscape/Page2/Mobile/QrResult/Link/index.js
  77. 2
      src/views/Home/Landscape/Page2/Mobile/QrResult/PDF/index.js
  78. 4
      src/views/Home/Landscape/Page2/Mobile/QrResult/index.js
  79. 2
      src/views/Home/Landscape/Page3/index.js
  80. 2
      src/views/Home/Landscape/Page4/index.js
  81. 2
      src/views/Home/Landscape/Test/Question.js
  82. 6
      src/views/Home/Landscape/Test/index.js
  83. 4
      src/views/Home/Landscape/VideoTube/LessonPlayList/index.js
  84. 4
      src/views/Home/Landscape/VideoTube/index.js
  85. 12
      src/views/Home/Portrait/Private/Blogs/index.js
  86. 60
      src/views/Home/Portrait/Private/MyBooks/index.js
  87. 4
      src/views/Home/Portrait/Private/Videos/index.js
  88. 2
      src/views/Home/Portrait/Public/Features/index.js
  89. 4
      src/views/Home/Portrait/Public/Header/index.js
  90. 2
      src/views/Home/Portrait/Public/Platforms/index.js
  91. 4
      src/views/Home/Portrait/Public/Responsive/index.js
  92. 6
      src/views/Order/components/Book.js
  93. 34
      src/views/Order/index.js
  94. 12
      src/views/Orders/components/Order.js
  95. 4
      src/views/Product/Comment/index.js
  96. 6
      src/views/Product/Desktop/ProductOverAll/index.js
  97. 131
      src/views/Product/Rate/index.js
  98. 229
      src/views/Product/index.js
  99. 5
      src/views/Products/index.js
  100. 142
      src/views/Products/layouts/Desktop/Main.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

@ -1,3 +1,4 @@
@import "./constants/size.scss";
@import "./constants/colors.scss";
@import "./views/Home/Landscape/Page1/index.scss";

@ -0,0 +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">
<g id="archive-add" transform="translate(0)">
<path id="Vector" d="M6.2,0H0" transform="translate(11.787 13.214)" fill="#fff" stroke="#fff" 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="#fff" 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="#fff" stroke="#fff" 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"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +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">
<g id="archive-add" transform="translate(0)">
<path id="Vector" d="M6.2,0H0" transform="translate(11.787 13.214)" fill="rgb(19, 123, 79)" 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="rgb(19, 123, 79)" 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="rgb(19, 123, 79)" 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="rgb(19, 123, 79)" opacity="0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -38,7 +38,7 @@ export const BottomNavigation = ({ pages, isDark }) => {
return (
<>
<footer
className="w-full flex flex-row justify-around items-center fixed bottom-0 left-0 py-2 z-20 lg:hidden"
className="w-full flex justify-around items-center fixed bottom-0 left-0 py-2 z-20 lg:hidden"
style={{ background: isDark ? "hsla(209, 39%, 28%)" : "#E8FCFF" }}
>
{pages.map((page, index) => (

@ -1,6 +1,9 @@
import React from "react";
import { connect } from "react-redux";
//components
import Loading from "../Loading";
export const ButtonBetween = ({
item,
status,
@ -8,6 +11,7 @@ export const ButtonBetween = ({
width,
active,
toggle,
loading,
}) => {
return toggle ? (
<button
@ -17,6 +21,9 @@ export const ButtonBetween = ({
onClick={() => onClick()}
style={{ width, padding: "18px 8px" }}
>
{loading ? (
<Loading size={2} color="bg-green-500" />
) : (
<strong
className={`text-tiny ${
active ? "text-green-700" : "text-gray-700"
@ -24,6 +31,8 @@ export const ButtonBetween = ({
>
{item}
</strong>
)}
{status && (
<span
className={`pr-3 border-r border-solid ${
@ -42,7 +51,13 @@ export const ButtonBetween = ({
onClick={() => onClick()}
style={{ width, padding: "18px 8px" }}
>
<strong className="text-tiny text-green-700 font-semibold">{item}</strong>
{loading ? (
<Loading size={2} color="bg-green-500" />
) : (
<strong className="text-tiny text-green-700 font-semibold">
{item}
</strong>
)}
{status && (
<span className="pr-3 border-r border-solid border-green-600 text-tiny text-green-700 font-semibold">
{status}

@ -39,8 +39,8 @@ export const Comments = ({ comments, indent }) => {
const Comment = ({ comment }) => {
return (
<div className="flex flex-col w-full">
<header className="w-full flex flex-row justify-between py-1">
<div className="flex flex-row items-end">
<header className="w-full flex justify-between py-1">
<div className="flex items-end">
<Avatar source={comment?.userImage} size={60} rounded={true} />
<div className="flex flex-col">
<div className="flex items-center">
@ -48,18 +48,18 @@ export const Comments = ({ comments, indent }) => {
<span className="text-tiny text-greenBA mr-3">
{comment?.userRoll || window.t("خریدار محصول")}
</span>
<div className="flex flex-row items-center mr-10 font-semibold">
<div className="flex items-center mr-10 font-semibold">
<StarRating />
</div>
</div>
<div
className="flex flex-row divide-x divide-gray-300 mt-4 divided items-center"
className="flex divide-x divide-gray-300 mt-4 divided items-center"
style={{ direction: "ltr" }}
></div>
</div>
</div>
<div
className="flex flex-row divide-x divide-gray-300 divided items-center"
className="flex divide-x divide-gray-300 divided items-center"
style={{ direction: "ltr" }}
>
<span className="px-2 text-sm text-blue-400">
@ -73,9 +73,9 @@ export const Comments = ({ comments, indent }) => {
<div className="flex flex-row">
<div style={{ width: 60 }} className="min-h-full"></div>
<div className="flex flex-1 flex-col px-3">
<header className="w-full flex flex-row justify-between items-center">
<header className="w-full flex justify-between items-center">
<div>&nbsp;</div>
<div className="flex flex-row items-center">
<div className="flex items-center">
{comment?.status === true && (
<>
<img src={positiveIcon} alt="" className="w-6 ml-2" />

@ -33,7 +33,7 @@ const CourseChapter = ({
height: isMobile ? "auto" : "calc(100vh - 300px)",
}}
>
<div className="hidden lg:flex flex-row w-full items-center justify-between">
<div className="hidden lg:flex w-full items-center justify-between">
<div>
<h2 className="text-green7B bg-opacity-5 text-base font-semibold">
{window.t("سرفصل دوره")}
@ -48,7 +48,7 @@ const CourseChapter = ({
</div>
<span className="hidden lg:flex w-full h-px bg-blue-200 my-4"></span>
<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 items-center justify-between mb-2">
<p className="text-tiny font-bold text-white">
{seasons?.length > 0 &&
playList?.length > 0 &&
@ -65,7 +65,7 @@ const CourseChapter = ({
key={index}
>
<div
className="flex flex-row items-center justify-around"
className="flex items-center justify-around"
key={index}
>
{/* right div dot dot */}
@ -108,7 +108,7 @@ const CourseChapter = ({
disabled={true}
>
{/* top */}
<div className="flex flex-row items-center justify-between p-3 border-0 border-b border-solid border-green-200">
<div className="flex items-center justify-between p-3 border-0 border-b border-solid border-green-200">
<p
className={`text-base lg:text-tiny font-bold
${selectedVideo?.id === video?.id ? "text-white" : ""}`}

@ -47,7 +47,7 @@ export const Dialog = ({ dialog, setDialog }) => {
{text}
</p>
{type === "confirm" && (
<div className="flex flex-row gap-4 w-full">
<div className="flex gap-4 w-full">
<button
className="py-2.5 w-1/2 shadow-md rounded-sm bg-blueC0 text-white"
onClick={() => acceptFunc()}
@ -63,7 +63,7 @@ export const Dialog = ({ dialog, setDialog }) => {
</div>
)}
{type === "alert" && (
<div className="flex flex-row gap-4 w-full">
<div className="flex gap-4 w-full">
<button
className="py-2.5 w-full shadow-md rounded-sm bg-blue-400 text-white"
onClick={() => setDialog({ ...dialog, open: !dialog.open })}

@ -10,7 +10,7 @@ import homeDarkIcon from "./home-dark.svg";
import logoutIcon from "./logout.svg";
import logoutDarkIcon from "./logout-dark.svg";
import dangerIcon from "./mobile-danger.svg";
import dangerDarkIcon from "./mobile-danger-dark.svg";
// import dangerDarkIcon from "./mobile-danger-dark.svg";
import activationIcon from "./activation.svg";
import activationDarkIcon from "./activation-dark.svg";
import contactIcon from "./contact.svg";
@ -24,7 +24,7 @@ import cartDarkIcon from "./mobile-basket-dark.svg";
import faqIcon from "./faq.svg";
import faqDarkIcon from "./faq-dark.svg";
import arrowLeftVideo from "../../assets/icons/dropdown-white.svg";
// import arrowLeftVideo from "../../assets/icons/dropdown-white.svg";
import sunIcon from "./sun.svg";
import moonIcon from "./moon.svg";
@ -40,49 +40,10 @@ const MyDrawer = ({
setDialog,
logout,
}) => {
const [addUserDropdown, setAddUserDropdown] = useState(false);
const publicLink = [
{
name: window.t("صفحه اصلی"),
link: "/",
icon: (
<img
src={homeIcon}
className="opacity-50 dark:bg-white"
alt={window.t("صفحه اصلی")}
/>
),
toast: "",
message: "",
},
{
name: window.t("ورود یا ثبت نام"),
link: "/signup",
icon: (
<img
src={logoutIcon}
className="opacity-50 dark:bg-white"
alt={window.t("کتابهای من")}
/>
),
toast: "",
message: "",
},
{
name: window.t("پشتیبانی"),
link: "/contact-us",
icon: (
<img
src={dangerIcon}
className="opacity-50 dark:bg-white"
alt={window.t("پشتیبانی")}
/>
),
toast: "",
message: "",
},
];
const privateLink = [
// const [addUserDropdown, setAddUserDropdown] = useState(false);
const privateLink = React.useMemo(() => {
return [
{
name: window.t("صفحه اصلی"),
link: "/",
@ -220,6 +181,51 @@ const MyDrawer = ({
},
},
];
},[isDark, user]);
const publicLink = React.useMemo(() => {
return [
{
name: window.t("صفحه اصلی"),
link: "/",
icon: (
<img
src={homeIcon}
className="opacity-50 dark:bg-white"
alt={window.t("صفحه اصلی")}
/>
),
toast: "",
message: "",
},
{
name: window.t("ورود یا ثبت نام"),
link: "/signup",
icon: (
<img
src={logoutIcon}
className="opacity-50 dark:bg-white"
alt={window.t("کتابهای من")}
/>
),
toast: "",
message: "",
},
{
name: window.t("پشتیبانی"),
link: "/contact-us",
icon: (
<img
src={dangerIcon}
className="opacity-50 dark:bg-white"
alt={window.t("پشتیبانی")}
/>
),
toast: "",
message: "",
},
];
},[isDark, user]);
return (
<Drawer
@ -238,7 +244,7 @@ const MyDrawer = ({
className="flex flex-col justify-between h-1/6 pt-3 px-3 bg-green-500 dark:bg-blue90"
style={{ minHeight: "calc(100vh / 6)" }}
>
<div className="flex flex-row justify-between">
<div className="flex justify-between">
<Avatar size={70} rounded={true} />
<img
src={isDark ? sunIcon : moonIcon}
@ -247,7 +253,7 @@ const MyDrawer = ({
onClick={() => changeDarkMode(!isDark)}
/>
</div>
<div className="flex flex-row justify-between px-2 pb-3 mt-1">
<div className="flex justify-between px-2 pb-3 mt-1">
<div className="flex flex-col">
<strong className="text-lg text-white">
{user && user?.firstName + " " + user?.lastName}
@ -256,25 +262,25 @@ const MyDrawer = ({
{user?.cellphone}
</span>
</div>
<img
{/* <img
src={arrowLeftVideo}
alt=""
className={`transform ${
addUserDropdown ? "rotate-90" : "-rotate-90"
} cursor-pointer`}
onClick={() => setAddUserDropdown(() => !addUserDropdown)}
/>
/> */}
</div>
</header>
<ul
{/* <ul
className={`flex flex-col ${
addUserDropdown ? "h-20" : "h-0"
} transition-all duration-500`}
></ul>
></ul> */}
<ul className="h-full flex flex-col py-6 px-4 gap-6">
{(!user ? publicLink : privateLink).map((item, key) => (
<Link to={item.link} key={key} onClick={() => item.onClick()}>
<div className="flex flex-row items-center">
<div className="flex items-center">
{item.icon}
<div className="text-gray70 text-tiny mr-5 dark:text-white">
{item.name}

@ -20,22 +20,22 @@ const FooterDesign1 = ({ color, bg, items, hasHeader }) => {
<div className="flex items-center ml-8 ">
<img src={callIcon} className="p-2" />
<div>
<h1 className="text-2xl mb-4 font-bold">
<span className=" text-blueC0 font-black">7</span>
<h1 className="text-lg mb-4 font-bold">
<span className=" text-blueC0 font-black">7 </span>
{window.t("روز هفته")}
<span className="text-blueC0 font-black">24</span>
<span className="text-blueC0 font-black"> 24 </span>
{window.t("ساعته")}
</h1>
<p className="text-lg font-light text-blue5F">
<p className="text-tiny font-light text-blue5F">
{window.t("منتظر شنیدن صدای گرمتان هستیم")}
</p>
</div>
</div>
<div className="mr-8 text-lg flex flex-col font-black transform translate-y-0.5">
<div className="mr-8 text-base flex flex-col font-black transform translate-y-0.5">
<a href="tel:654412 021" className="text-left mb-5">
654412 021
</a>
<a href="mailto:Info@danovin.ir">Info@danovin.ir</a>
<a href="mailto:Info@danovin.ir" className="text-tiny">Info@danovin.ir</a>
{/* <a href="https://info@danovin.ir">Info@danovin.ir</a> */}
</div>
</div>
@ -44,7 +44,7 @@ const FooterDesign1 = ({ color, bg, items, hasHeader }) => {
<a
href="http://danovin.ir/app.apk"
download
className="py-4 px-5 text-base font-bold rounded-md bg-blueC0 transition-all transform hover:scale-110 text-white"
className="py-4 px-5 text-tiny font-bold rounded-md bg-blueC0 transition-all transform hover:scale-110 text-white"
>
{window.t("دانلود اپلیکیشن اندروید")}
</a>
@ -53,18 +53,18 @@ const FooterDesign1 = ({ color, bg, items, hasHeader }) => {
</div>
) : null}
<footer
className={`flex flex-col bg-gray-200 py-16 md:flex-row justify-around items-start md:items-start relative shadow-md z-20 ${bg}`}
className={`flex flex-col bg-gray-200 py-16 md:justify-around items-start md:items-start relative shadow-md z-20 ${bg}`}
>
<div className="w-11/12 flex justify-between">
<div className="flex flex-row gap-10">
<div className="w-11/12 flex justify-between mx-auto">
<div className="flex gap-10">
{items.map((item, index) => (
<div className="flex flex-col" key={index}>
<strong className="text-xl text-gray70">{item.name}</strong>
<strong className="text-base text-gray70">{item.name}</strong>
<ul className="flex flex-col mt-0">
{item.links.map((link, index) => (
<li className="mt-6" key={index}>
<Link
className="text-gray70 text-base "
className="text-gray70 text-tiny"
to={link.link}
key={index}
>

@ -6,7 +6,7 @@ import arrowWhiteIcon from "../../assets/icons/arrow-left-white.svg";
function Header({ title, link, isDark }) {
return (
<header className="w-full flex flex-row justify-between items-center pl-0">
<header className="w-full flex justify-between items-center pl-0">
<strong className="text-green7B dark:text-white font-semibold text-base lg:text-sm">
{title}
</strong>

@ -0,0 +1,24 @@
import React from "react";
export default function Modal({ children, open, onClose }) {
const [animationFlag, setAnimationFlag] = React.useState(false);
React.useEffect(() => {
setAnimationFlag(true);
return () => {
setAnimationFlag(false);
};
}, []);
return open ? (
<div
className={`w-full h-full fixed top-0 left-0 z-50 flex items-center justify-center backdrop-filter backdrop-blur-sm bg-black bg-opacity-25 transform transition-all duration-500 origin-center ${
animationFlag ? "scale-100" : "scale-0"
}`}
onClick={() => onClose()}
>
{children}
</div>
) : null;
}

@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { Link, useNavigate, NavLink } from "react-router-dom";
import { connect } from "react-redux";
import { userProduct, userFavorite } from "../../redux/actions";
import location from "../../utils/location";
@ -9,6 +9,7 @@ import _ from "lodash";
import Drawer from "../Drawer";
import Search from "../Search";
import SearchResult from "./SearchResult";
import Loading from "../Loading";
//assets
import cartIcon from "./cart-blue.svg";
@ -24,18 +25,24 @@ import arrowBlueIcon from "../../assets/icons/arrow-right-blue.svg";
import arrowWhiteIcon from "../../assets/icons/arrow-left-white.svg";
import dotsMenuDarkIcon from "../../assets/icons/dots-menu-dark.svg";
import bookmarkDeactiveDarkIcon from "../../assets/icons/bookmark-deactive-dark.svg";
import bookmarkActiveDarkIcon from "../../assets/icons/bookmark-active-dark.svg";
import dotsMenuLightIcon from "../../assets/icons/dots-menu-light.svg";
import bookmarkDeactiveLightIcon from "../../assets/icons/bookmark-deactive-light.svg";
import bookmarkActiveLightIcon from "../../assets/icons/bookmark-active-light.svg";
function Navbar({
getCartProducts,
getUserFavorite,
cartProductsLength,
pages,
isDark,
isMobile,
isLogin,
user,
headerOptions,
addToFavorite,
deleteBookmark,
bookmarkLoading,
userFavoriteList,
language,
}) {
const navigation = useNavigate();
@ -46,11 +53,22 @@ function Navbar({
const [search, setSearch] = useState(null);
const [drawerOpen, setDrawerOpen] = useState(false);
const isActiveBookmark = React.useMemo(() => {
return userFavoriteList?.find((object) =>
headerOptions?.productId
? object?.productId === headerOptions?.productId
: object?.contentId === headerOptions?.contentId
);
}, [headerOptions, userFavoriteList]);
console.log(Boolean(isActiveBookmark));
useEffect(() => {
if (window.scrollY === 0) {
setTop(() => true);
}
if (isMobile) {
// getUserFavorite();
window.addEventListener("scroll", () => {
if (window.scrollY === 0) {
setTop(() => true);
@ -62,30 +80,60 @@ function Navbar({
}, []);
useEffect(() => {
if (!isMobile && isLogin) {
console.log(111);
if (!isMobile && user) {
getCartProducts();
}
}, [isLogin]);
}, [user]);
return isMobile ? (
return (
<div
className={_.join(
[
"z-50 flex flex-1 flex-row fixed left-0 top-0 justify-between w-full lg:bg-opacity-20 lg:bg-transparent lg:shadow-sm lg:backdrop-filter lg:backdrop-blur-md lg:px-5 xl:px-10 transition-all duration-300",
],
" "
)}
className="z-50 flex fixed left-0 top-0 w-full"
style={{
backgroundColor: !top ? (isDark ? "#061B30" : "white") : "",
}}
>
{/* landscape start */}
{/* landscape end */}
{/* portrait start */}
<div className="w-full lg:w-11/12 lg:mx-auto relative flex items-center justify-between py-3 px-4" style={{
backgroundColor: isDark ? "#061B30" : "white"
}}>
{/* desktop */}
<div className=" items-center hidden lg:flex">
<Link
to="/"
className="flex items-center text-2xl font-black text-green7B"
>
<img src={logoIcon} className="w-8 relative bottom-1 ml-1" alt="" />
{window.t("دانوین")}
</Link>
<div className="w-full h-full relative flex flex-row items-center justify-between lg:hidden py-3 px-4">
<div className="relative">
<ul className="flex list-none items-center relative top-0.5 mr-4">
{pages.map((page, index) => (
<li key={index}>
<NavLink
to={page.link}
className="text-tiny py-2 px-4 mx-4"
style={({ isActive }) => ({
color: isActive ? "rgb(19, 123, 79)" : "#202020",
fontWeight: isActive ? "700" : "200",
})}
>
{page.name}
</NavLink>
</li>
))}
</ul>
</div>
{logo && (
<Link
to="/"
className="lg:hidden absolute left-1/2 transform -translate-y-1/2 top-1/2 -translate-x-1/2"
>
<img src={logoIcon} className="w-6 h-8" />
</Link>
)}
{/* desktop */}
{/* <div className="flex items-center"></div> */}
<div className="flex lg:hidden relative">
{hamburgerMenu && (
<>
<span className="w-2.5 h-2.5 rounded-full bg-redFF1 absolute -left-1 -top-1 animate-bounce"></span>
@ -97,7 +145,6 @@ function Navbar({
/>
</>
)}
{!title && back ? (
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
@ -112,29 +159,31 @@ function Navbar({
</strong>
)}
</div>
{logo && (
<Link
to="/"
className="absolute left-1/2 transform -translate-y-1/2 top-1/2 -translate-x-1/2"
<div className="flex items-center">
{overLayer && (
<div
className="z-30 w-screen h-full fixed top-0 right-0 backdrop-filter blur-sm bg-opacity-60 bg-gray-600"
onClick={() => setOverLayer(false)}
>
<img src={logoIcon} className="w-6 h-8" />
</Link>
<div className="relative w-full h-full">
<div
className="flex flex-col w-full absolute left-1/2 top-16 transform -translate-x-1/2 z-50 rounded-md"
style={{ maxWidth: "calc(100vw / 3)" }}
onClick={(e) => e.stopPropagation()}
>
<Search onChange={(val) => setSearch(val)} />
{search && <SearchResult text={search} setText={setSearch} />}
</div>
</div>
</div>
)}
<div className="flex flex-row items-center">
{qr && (
<>
<Link
to="/scan"
className={_.join(
[
"rounded-sm p-1.5",
isDark
? "bg-blueC0 bg-opacity-10 ml-2"
: " ml-3 shadow-sm",
],
" "
)}
className={`flex lg:hidden rounded-sm p-1.5 ${
isDark ? "bg-blueC0 bg-opacity-10 ml-2" : " ml-3 shadow-sm"
}`}
style={{
border: `1px solid ${isDark ? "#D7E3FC20" : "#D7E3FC"}`,
}}
@ -147,13 +196,9 @@ function Navbar({
</Link>
<Link
to="/ar"
className={_.join(
[
"rounded-sm p-1.5",
isDark ? "bg-blueC0 bg-opacity-10" : " shadow-sm",
],
" "
)}
className={`flex lg:hidden rounded-sm p-1.5 ${
isDark ? "bg-blueC0 bg-opacity-10" : "shadow-sm"
}`}
style={{
border: `1px solid ${isDark ? "#D7E3FC20" : "#D7E3FC"}`,
}}
@ -166,93 +211,56 @@ function Navbar({
</Link>
</>
)}
{bookmark && (
{bookmark ? (
bookmarkLoading ? (
<Loading size={2} color="bg-green-500" />
) : isActiveBookmark ? (
<img
src={
isDark ? bookmarkActiveDarkIcon : bookmarkActiveLightIcon
}
alt="bookmark"
className="w-7 flex lg:hidden"
onClick={() =>
deleteBookmark({
id: userFavoriteList?.find(
(object) => object?.productId === headerOptions?.productId
)?.id,
})
}
/>
) : (
<img
src={
isDark ? bookmarkDeactiveDarkIcon : bookmarkDeactiveLightIcon
}
alt="bookmark"
className="w-7"
className="w-7 flex lg:hidden"
onClick={() => addToFavorite({ [bookmark]: location.getId() })}
/>
)}
)
) : null}
{menu && (
<img
src={isDark ? dotsMenuDarkIcon : dotsMenuLightIcon}
alt="menu"
className="w-7 mr-2"
className="w-7 mr-2 flex lg:hidden"
/>
)}
{title && back ? (
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
alt="back"
className={`w-6 transform ${isDark ? "" : "-rotate-180"}`}
className={`w-6 flex lg:hidden transform ${
isDark ? "" : "-rotate-180"
}`}
onClick={() => navigation(-1)}
/>
) : null}
</div>
</div>
<Drawer drawerOpen={drawerOpen} setDrawerOpen={setDrawerOpen} />
{/* portrait end */}
</div>
) : (
<header
className={`w-full border-b border-gray-200 border-solid fixed top-0 right-0 bg-white z-20`}
style={{ boxShadow: "0px 0px 10px rgba(0,0,0,0.1)" }}
>
<div className={`w-11/12 mx-auto flex flex-col`}>
<div className="w-full flex flex-row items-center py-3 relative justify-between h-ful">
<div className="flex flex-row items-center">
<Link
to="/"
className="flex flex-row items-center text-2xl font-black text-green7B"
>
<img
src={logoIcon}
className="w-8 relative bottom-1 ml-1"
alt=""
/>
{window.t("دانوین")}
</Link>
<ul className="flex flex-row list-none items-center relative top-0.5 mr-6">
{pages.map((page, index) => (
<li key={index}>
<Link
to={page.link}
className="text-tiny font-semibold text-green7B py-2 px-4 mx-4"
>
{page.name}
</Link>
</li>
))}
</ul>
</div>
{overLayer && (
<div
className="z-30 w-screen h-full fixed top-0 right-0 backdrop-filter blur-sm bg-opacity-60 bg-gray-600"
onClick={() => setOverLayer(false)}
>
<div className="relative w-full h-full">
<div
className="flex flex-col w-full absolute left-1/2 top-16 transform -translate-x-1/2 z-50 rounded-md"
style={{ maxWidth: "calc(100vw / 3)" }}
onClick={(e) => e.stopPropagation()}
>
<Search onChange={(val) => setSearch(val)} />
{search && <SearchResult text={search} setText={setSearch} />}
</div>
</div>
</div>
)}
<div className="flex flex-row items-center">
{/* desktop */}
<select
style={{ width: "100px" }}
className="flex items-center text-blueC0 border border-blueC0 px-1 rounded base py-1.5 ml-4 cursor-pointer"
className="hidden lg:flex items-center text-blueC0 border border-blueC0 px-1 rounded base py-1.5 ml-4 cursor-pointer"
>
{language.map((item, index) => (
<option
@ -267,12 +275,12 @@ function Navbar({
<img
src={searchIcon}
alt=""
className="w-7 ml-3 cursor-pointer"
className="w-7 ml-3 cursor-pointer lg:flex hidden"
onClick={() => setOverLayer(true)}
/>
{isLogin && (
<div className="flex justify-end items-center gap-4">
{user && (
<div className="hidden lg:flex justify-end items-center gap-4">
<Link to="/cart" className="relative">
<img src={cartIcon} alt="" className="w-8" />
<span className="absolute -right-2 -top-0.5 w-4 p-2.5 h-4 flex justify-center items-center bg-green-700 bg-opacity-100 rounded-full text-white text-xs">
@ -285,7 +293,7 @@ function Navbar({
</div>
)}
{!isLogin ? (
{!user ? (
<Link
to="/signup"
className="bg-blueC0 font-semibold text-white rounded-md px-4 py-3 text-sm mr-7 hover:bg-opacity-90 shadow-sm"
@ -295,15 +303,17 @@ function Navbar({
) : (
<Link
to="/dashboard"
className="bg-blueC0 font-semibold text-white rounded-md px-4 py-3 text-sm mr-7 hover:bg-opacity-90 shadow-sm"
className="hidden lg:flex bg-blueC0 font-semibold text-white rounded-md px-4 py-3 text-sm mr-7 hover:bg-opacity-90 shadow-sm"
>
{window.t("حساب کاربری")}
</Link>
)}
{/* desktop */}
</div>
</div>
<Drawer drawerOpen={drawerOpen} setDrawerOpen={setDrawerOpen} />
</div>
</header>
);
}
@ -311,15 +321,19 @@ const mapStateToProps = (state) => ({
isDark: state.publicApi.isDark,
isMobile: state.publicApi.isMobile,
headerOptions: state.publicApi.headerOptions,
isLogin: state.user.status,
user: state.user.status,
cartProductsLength: state.userProduct.list?.filter(
(product) => product.condition < 2
)?.length,
bookmarkLoading: state.userFavorite.loading,
userFavoriteList: state.userFavorite.list,
});
const mapDispatchToProps = {
getCartProducts: userProduct.list,
addToFavorite: userFavorite.add,
deleteBookmark: userFavorite.del,
getUserFavorite: userFavorite.list
};
export default connect(mapStateToProps, mapDispatchToProps)(Navbar);

@ -2,7 +2,7 @@ import React from "react";
function OR({}) {
return (
<div className="w-full flex flex-row justify-between items-center my-3 lg:my-5">
<div className="w-full flex justify-between items-center my-3 lg:my-5">
<div
style={{ width: "43%", height: 1, backgroundColor: "#EFEFEF" }}
></div>

@ -13,7 +13,7 @@ const ProductImage = ({ images }) => {
}
}, [images]);
return (
<div className="flex flex-row w-1/3 gap-2">
<div className="flex w-1/3 gap-2">
<div
className="flex flex-col items-center justify-between w-1/5"
style={{ height: "calc(100vw / 5)" }}

@ -37,8 +37,8 @@ const ProductStatusCard = ({
return (
<section className="w-full" style={{ minWidth: 350 }}>
<div className="bg-grayF9 rounded-md px-4 py-2 divide-y divide-solid divide-gray-200">
<div className="flex flex-row items-center justify-between py-3">
<div className="flex flex-row items-center">
<div className="flex items-center justify-between py-3">
<div className="flex items-center">
<img src={tick} alt="" className="w-8" />
<div className="flex flex-col mr-3">
<div className="text-sm">{`${window.t(
@ -49,8 +49,8 @@ const ProductStatusCard = ({
</div>
{seller && (
<div className="flex flex-row items-center justify-between py-3">
<div className="flex flex-row items-center">
<div className="flex items-center justify-between py-3">
<div className="flex items-center">
<img src={shop} alt="" className="w-8" />
<div className="flex flex-1 flex-col mr-3 text-sm gap-2">
<div className="text-tiny">{"فروشنده" + " " + seller.name}</div>
@ -63,11 +63,11 @@ const ProductStatusCard = ({
</div>
)}
<div className="flex flex-row items-center justify-between py-3">
<div className="flex flex-row items-center">
<div className="flex items-center justify-between py-3">
<div className="flex items-center">
<img src={delivery} alt="" className="w-8" />
<div className="flex flex-col mr-3">
<div className="flex flex-row gap-1 text-sm">
<div className="flex gap-1 text-sm">
&nbsp;{shippingTime}
</div>
</div>
@ -75,18 +75,18 @@ const ProductStatusCard = ({
</div>
{garanty && (
<div className="flex flex-row items-center justify-between py-3">
<div className="flex flex-row items-center">
<div className="flex items-center justify-between py-3">
<div className="flex items-center">
<img src={shield} alt="" className="w-8" />
<div className="flex flex-col mr-3">
<div className="flex flex-row gap-1 text-sm">{garanty}</div>
<div className="flex gap-1 text-sm">{garanty}</div>
</div>
</div>
</div>
)}
{bookmark && (
<div className="flex flex-row items-center py-3">
<div className="flex items-center py-3">
<img
src={
isDark ? bookmarkDeactiveDarkIcon : bookmarkDeactiveLightIcon
@ -141,7 +141,7 @@ const ProductStatusCard = ({
}
/>
</div>
<div className="bg-grayF9 rounded px-4 py-2 mt-4 flex flex-row items-center">
<div className="bg-grayF9 rounded px-4 py-2 mt-4 flex items-center">
<div>
<img src={arrow} alt="" className="w-20 h-20" />
</div>

@ -46,10 +46,10 @@ const ProductSuggestion = ({
{window.t("این کالاها برای خرید به شما پیشنهام می دهیم")}
</h2>
{/* product design */}
<div className="flex flex-row flex-wrap items-center justify-center mt-5 w-full gap-10">
<div className="flex flex-wrap items-center justify-center mt-5 w-full gap-10">
{similarList.map((book, index) => (
<div
className="flex flex-row mb-7 justify-center relative"
className="flex mb-7 justify-center relative"
style={{ maxWidth: "calc(100% / 5)" }}
key={index}
>
@ -98,7 +98,7 @@ const ProductSuggestion = ({
</div>
{/* bottom */}
<div className="flex flex-col justify-center items-center mt-4">
<div className="flex flex-row mb-5">
<div className="flex mb-5">
<p className="text-base text-productPrice font-bold">
&nbsp;
{window.t("جمع لوازم اختیاری خریداری شده")}

@ -7,7 +7,7 @@ const ProductTab = ({ tabs }) => {
return (
<section className="mt-10 flex flex-col w-full">
<div className="rounded-md bg-grayF9">
<ul className="flex flex-row justify-center gap-16">
<ul className="flex justify-center gap-16">
{tabs.map((tab, index) =>
tab.shown ? (
<li

@ -14,8 +14,8 @@ const QandA = ({ comments }) => {
return (
<>
<div className="flex flex-col leading-7 w-full py-6 border-t-2 border-solid border-gray-200">
<header className="w-full flex flex-row justify-between py-1">
<div className="flex flex-row items-end">
<header className="w-full flex justify-between py-1">
<div className="flex items-end">
<div className="flex items-center">
<strong className="text-lg mx-2">{comment.username}</strong>
{comment.isCostumer ? (
@ -26,7 +26,7 @@ const QandA = ({ comments }) => {
</div>
</div>
<div
className="flex flex-row divide-x divide-gray-300 divided items-center"
className="flex divide-x divide-gray-300 divided items-center"
style={{ direction: "ltr" }}
>
<span className="px-2 text-sm text-blue-400">
@ -38,11 +38,11 @@ const QandA = ({ comments }) => {
</span>
</div>
</header>
<div className="flex flex-row py-4">
<div className="flex py-4">
<div style={{ width: 60 }} className="min-h-full"></div>
<div className="flex flex-1 flex-col px-3">
<header className="w-full flex flex-row justify-between items-center">
<div className="flex flex-row items-center">
<header className="w-full flex justify-between items-center">
<div className="flex items-center">
<div className="py-4 px-6 bg-blue-100 text-gray-400 rounded">
<h1>{window.t("پرسش")}</h1>
</div>
@ -58,11 +58,11 @@ const QandA = ({ comments }) => {
{comment.answers.length > 0 ? (
comment.answers.slice(0, numberOfAnswers).map((item, index) => (
<div className="flex flex-row py-1" key={index}>
<div className="flex py-1" key={index}>
<div style={{ width: 60 }} className="min-h-full"></div>
<div className="flex flex-1 flex-col px-3">
<header className="w-full flex flex-row justify-between items-center">
<div className="flex flex-row items-center">
<header className="w-full flex justify-between items-center">
<div className="flex items-center">
<div className="py-4 px-6 bg-green-100 text-gray-400 rounded">
<h1>{window.t("پاسخال پاسخ")}</h1>
</div>
@ -79,8 +79,8 @@ const QandA = ({ comments }) => {
</div>
))
) : (
<header className="w-full flex flex-row justify-between items-center">
<div className="flex w-4/5 flex-row items-center">
<header className="w-full flex justify-between items-center">
<div className="flex w-4/5 items-center">
<div className="py-4 px-6 bg-green-100 text-gray-400 mx-16 rounded">
<h1>{window.t("ارسال پاسخ")}</h1>
</div>

@ -19,7 +19,8 @@ function StarRating({
const [rate, setRating] = React.useState(null);
useMemo(() => {
if (isLogin) getUserProducts();
//console.log("gl2");
// if (isLogin && !userProducts.length) getUserProducts();
}, []);
React.useEffect(() => {

@ -55,9 +55,9 @@ export default function VerticalExpandableProductFilter(props) {
(item1, i) => (
<li
key={i}
className="hover:bg-gray-100 px-3 flex flex-row items-center justify-between py-2"
className="hover:bg-gray-100 px-3 flex items-center justify-between py-2"
>
<div className="flex flex-row items-center">
<div className="flex items-center">
<Checkbox
name={`ch${name}_${i}`}
checked={true}

@ -2,6 +2,7 @@
@tailwind components;
@tailwind utilities;
.bg-dark {
background: hsla(209, 39%, 28%, 1);

@ -7,7 +7,9 @@ const blog = {
info: (data) => async (dispatch) =>
await proxy.get("public/blogInfo", data, { dispatch }),
active: (data) => async (dispatch) =>
await dispatch({ type: "public/active", data }),
await dispatch({ type: "blog/active", data }),
setActiveHashtag: (data) => async (dispatch) =>
await dispatch({ type: "blog/activeHashtag", data }),
letterAdd: (data) => async (dispatch) =>
await proxy.post("news/LetterAdd", data, { dispatch }),
};

@ -13,6 +13,7 @@ const comment = {
(data = {}, data2) =>
async (dispatch) => {
await proxy.post("comment/add", data, { dispatch });
dispatch({ type : "form/ticket/reset" });
if (data2) await proxy.get("book/info", data2, { dispatch });
},
del:

@ -0,0 +1,12 @@
import proxy from "../proxy";
const config = {
setDevice: (data) => async (dispatch) =>
await dispatch({ type: "config/setDevice", data }),
getAvailableForSell:
(data = {}) =>
async (dispatch) =>
await proxy.get("config/availableForSell", data, { dispatch }),
};
export default config;

@ -19,3 +19,4 @@ export {default as comment} from "./comment";
export {default as form} from "./form";
export {default as dialog} from "./dialog";
export {default as menu} from "./menu";
export {default as config} from "./config";

@ -5,31 +5,37 @@ const initialState = {
error: null,
list: [],
info: null,
hashtags : [],
hashtags: [],
active: null,
activeHashtag: "همه",
};
export default function blog(state = initialState, action) {
let { type, data } = action;
switch (type) {
case "blog/activeHashtag":
return {
...state,
activeHashtag: data,
};
case "public/blogList":
return {
...state,
loading: false,
list: data,
hashtags: [...new Set(data.map((object) => object.tag))],
hashtags: ["همه", ...new Set(data.map((object) => object.tag))],
error: null,
};
case "public/active":
case "blog/active":
return {
...state,
active : data,
active: data,
loading: false,
error: null,
};
case "public/blogInfo":
return { ...state, loading: false, error: null, blog: data };
case "news/LetterAdd":
toast.success('.به خبرنامه دانوین خوش آمدید');
toast.success(".به خبرنامه دانوین خوش آمدید");
return { ...state, loading: false, error: null };
case "blog/loading":
return { ...state, loading: true };

@ -0,0 +1,24 @@
const initialState = {
device: "mobile",
availableForSell: [],
};
export default function config(state = initialState, action) {
let { type, data } = action;
switch (type) {
case "config/setDevice":
return {
...state,
device: data,
};
case "config/availableForSell":
return {
...state,
loading: false,
availableForSell: data.productTypes,
error: null,
};
default:
return state;
}
}

@ -15,6 +15,8 @@ export default function form(state = initialState, action) {
ticket: { ...state.ticket, [data.name]: data.value },
error: null,
};
case "form/ticket/reset":
return { ...state, ticket: {} };
case "form/loading":
return { ...state, loading: true };
case "form/error":

@ -19,3 +19,4 @@ export {default as comment} from "./comment";
export {default as form} from "./form";
export {default as dialog} from "./dialog";
export {default as menu} from "./menu";
export {default as config} from "./config";

@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Navigate } from "react-router-dom";
import { connect } from "react-redux";
import { publicApi, menu } from "./redux/actions";
import { publicApi, menu, config, userProduct } from "./redux/actions";
import Navbar from "./components/Navbar";
import BG from "./components/BG";
import BottomNavigation from "./components/BottomNavigation";
@ -35,11 +35,60 @@ import Address from "./views/Address";
import Favorites from "./views/Favorites";
import Addresses from "./views/Dashboard/layouts/Mobile/ProfileAddress";
function Router({ isDark, isMobile, headerOptions, dialog, menu, setMenu }) {
function Router({
isDark,
isMobile,
headerOptions,
dialog,
menu,
setMenu,
setDevice,
device,
getAvailableForSell,
getUserProducts
}) {
useEffect(() => {
window.addEventListener("scroll", () => {});
getAvailableForSell();
getUserProducts();
const width = window.innerWidth;
if (width <= 640) {
setDevice("mobile");
}
if (width > 640 && width < 1024) {
setDevice("tablet");
}
if (width > 1024) {
setDevice("desktop");
}
}, []);
React.useEffect(() => {
window.addEventListener("resize", () => {
const width = window.innerWidth;
if (width <= 640) {
if (device === "mobile") {
return;
} else {
setDevice("mobile");
}
}
if (width > 640 && width < 1024) {
if (device === "tablet") {
return;
} else {
setDevice("tablet");
}
}
if (width > 1024) {
if (device === "desktop") {
return;
} else {
setDevice("desktop");
}
}
});
}, [device]);
const prevDefault = (e) => {
setMenu();
e.stopPropagation();
@ -116,7 +165,17 @@ function Router({ isDark, isMobile, headerOptions, dialog, menu, setMenu }) {
path="/products"
exact
element={
<Products headerOptions={{ shown: isMobile ? false : true }} />
<Products
headerOptions={{
logo: true,
hamburgerMenu: true,
qr: true,
title: false,
back: false,
shown: true,
menu: false,
}}
/>
}
/>
<Route
@ -478,15 +537,15 @@ function Router({ isDark, isMobile, headerOptions, dialog, menu, setMenu }) {
exact
element={
<Blogs
// headerOptions={{
// logo: true,
// hamburgerMenu: true,
// qr: true,
// title: false,
// back: false,
// shown: true,
// menu: false,
// }}
headerOptions={{
logo: true,
hamburgerMenu: true,
qr: true,
title: false,
back: false,
shown: true,
menu: false,
}}
/>
}
/>
@ -535,16 +594,20 @@ function Router({ isDark, isMobile, headerOptions, dialog, menu, setMenu }) {
const mapStateToProps = (state) => ({
isDark: state.publicApi.isDark,
isMobile: state.publicApi.isMobile,
isMobile: state.config.device === "mobile",
isLogin: state.user.status,
headerOptions: state.publicApi.headerOptions,
dialog: state.dialog.dialog,
menu: state.menu.open,
device: state.config.device,
});
const mapDispatchToProps = {
setDesktopContentTransform: publicApi.setDesktopContentTransform,
setMenu: menu.set,
setDevice: config.setDevice,
getAvailableForSell: config.getAvailableForSell,
getUserProducts: userProduct.list
};
export default connect(mapStateToProps, mapDispatchToProps)(Router);

@ -17,8 +17,9 @@ function About({
first,
setHeaderOptions,
}) {
useEffect(() => {
setHeaderOptions({ shown: true });
setHeaderOptions({ shown: true, hamburgerMenu : true, logo: true, qr : true });
}, []);
useEffect(() => {
@ -26,8 +27,8 @@ function About({
}, []);
return (
<div className={_.join(["about w-11/12 mx-auto flex flex-col"], " ")}>
<main className="flex flex-col items-center pt-16 ">
<div className="about w-11/12 mx-auto flex flex-col py-8 lg:py-16">
<main className="flex flex-col items-center">
<header>
<h1>{first.title}</h1>
<p

@ -1,4 +1,4 @@
$gray : #aaa;
$gray : #222;
$green3 : #00cc69;
@ -6,7 +6,7 @@ $green3 : #00cc69;
main {
li::before {
color: $gray;
content: "\2022";
// content: "\2022";
font-weight: bold;
display: inline-block;
width: 1em;

@ -4,7 +4,7 @@ import React from 'react'
import alertIcon from '../../../assets/icons/alert.svg';
function Alert({text}) {
return (
<div className="flex flex-row items-center bg-blueFD rounded-md border border-solid border-blueC0 py-3 px-2 w-full my-3 dark:bg-opacity-5">
<div className="flex items-center bg-blueFD rounded-md border border-solid border-blueC0 py-3 px-2 w-full my-3 dark:bg-opacity-5">
<img src={alertIcon} alt="" />
<p className="text-blueC0 text-xs mr-3 dark:text-white leading-5 lg:text-sm">
{text}

@ -335,7 +335,7 @@ export const Address = ({
onClick={() => submit()}
/>
<button
className="bg-transparent mt-4 text-base lg:text-tiny border border-blueC0 text-blueC0 font-bold rounded-md py-3.5 lg:py-4 flex flex-row justify-center items-center"
className="bg-transparent mt-4 text-base lg:text-tiny border border-blueC0 text-blueC0 font-bold rounded-md py-3.5 lg:py-4 flex justify-center items-center"
onClick={() => {
setPhase("deliveryForm");
navigation(-1);
@ -363,7 +363,7 @@ export const Address = ({
<div className="flex item-center gap-x-4">
{/* my self */}
<div
className={`flex flex-row items-center mb-7 cursor-pointer
className={`flex items-center mb-7 cursor-pointer
`}
onClick={() => {
setActiveCheckbox(true);
@ -380,7 +380,7 @@ export const Address = ({
</div>
{/* someone else */}
<div
className={`flex flex-row items-center mb-7 cursor-pointer
className={`flex items-center mb-7 cursor-pointer
`}
onClick={() => {
setActiveCheckbox(false);
@ -410,7 +410,7 @@ export const Address = ({
)}
/>
<div className="flex flex-col lg:flex-row items-center lg:gap-5 w-full mb-4">
<div className="flex flex-col lg:items-center lg:gap-5 w-full mb-4">
<Input
width={isMobile ? "100%" : "50%"}
label={window.t("نام")}
@ -457,7 +457,7 @@ export const Address = ({
)}
/>
<div className="flex flex-col lg:flex-row items-center lg:gap-5 w-full mb-4">
<div className="flex flex-col lg:items-center lg:gap-5 w-full mb-4">
<Input
width={isMobile ? "100%" : "50%"}
label={window.t("شماره موبایل")}
@ -526,7 +526,7 @@ export const Address = ({
)}
/>
<div className="flex flex-col lg:flex-row items-center gap-3 lg:gap-5 w-full">
<div className="flex flex-col lg:items-center gap-3 lg:gap-5 w-full">
<Select
selectProvince={"استان"}
options={provinces.map((e) => ({ value: e.id, name: e.name }))}

@ -1,90 +1,29 @@
import React, { useState, useEffect } from "react";
import { useState, useEffect, useMemo, useCallback } from "react";
import { connect } from "react-redux";
import { publicApi } from "../../../redux/actions";
import { useNavigate } from "react-router-dom";
import SignUp from "../SignUp";
import Button from "../../../components/Button";
//assets
import logoIcon from "../SignUp/assets/logo.svg";
import bgImage from "./bg.svg";
import arrowIcon from "../../../assets/icons/dropdown-blue.svg";
export const Desktop = ({ setHeaderOptions }) => {
const [phase, setPhase] = useState("signup");
export const Desktop = ({ setHeaderOptions, level, setLevel}) => {
const navigate = useNavigate();
useEffect(() => {
setHeaderOptions({ show: false });
}, []);
const UserMangement = () => {
return (
<div
className={`flex flex-col items-center justify-center w-full relative h-full transform transition-all duration-700 ${
phase !== "manage" ? "translate-x-full" : ""
}`}
>
<img
src={logoIcon}
alt=""
className="w-20 absolute left-1/2 top-10 transform -translate-x-1/2"
/>
<strong className="text-2xl text-blueC0 self-start tracking-tighter">
{window.t("ورود یا ثبت نام")}
</strong>
<p className="text-tiny self-start text-gray-500 mt-6 leading-6">
{window.t(" کاربر گرامی لطفا یکی از دوگزینه زیر را انتخاب نمائید.")}
<br />
{window.t("درصورتی که عضو نیستید روی دکمه ثبت نام بزنید")}
</p>
<div className="mt-16 flex flex-col gap-4 w-full">
<Button
title={window.t("ورود یا ثبت نام")}
backgroundColor="bg-blueC0"
border={{ color: "#196EC055", width: "0px" }}
width="100%"
color="text-white"
onClick={() => setPhase("signup")}
/>
{/* <Button
title="ورود"
backgroundColor="bg-transparent border border-solid border-blueC0"
border={{ color: "", width: 1 }}
width="100%"
color="text-blueC0"
onClick={() => setPhase("login")}
/> */}
</div>
</div>
);
};
const phases = {
manage: <UserMangement />,
signup: <SignUp />,
login: <SignUp />,
};
return (
<div className="h-screen w-full flex justify-center items-center">
<div className="w-4/5 h-4/5 rounded-xl flex overflow-hidden border border-solid border-gray-200">
<div className="w-2/5 h-full flex justify-center items-center">
<div
className="w-4/5 flex justify-center items-center relative"
className="w-4/5 flex justify-center items-center"
style={{ height: "90%" }}
>
<button
className="absolute left-0 top-0 p-3 bg-grayF4 rounded-xl z-20"
onClick={() =>
setPhase(() =>
phase === "manage" ? navigate("/blogs") : "manage"
)
}
>
<img src={arrowIcon} className="transform rotate-90" alt="" />
</button>
{phases[phase]}
<SignUp setLevel={setLevel} level={level} />
</div>
</div>
<div className="w-3/5 h-full bg-grayF9 flex justify-center items-center">

@ -422,7 +422,7 @@ function Profile({
</div>
) : (
<ul className="flex flex-col flex-1">
<li className="flex flex-row gap-5">
<li className="flex gap-5">
<div className="flex flex-col w-4/12">
<strong>{window.t(" اطلاعات هویتی")}</strong>
<p>
@ -431,7 +431,7 @@ function Profile({
)}
</p>
</div>
<div className="flex flex-row w-8/12"></div>
<div className="flex w-8/12"></div>
</li>
</ul>
);

@ -11,6 +11,7 @@ import { user, publicApi } from "../../../redux/actions";
import _ from "lodash";
//assets
import logoIcon from "./assets/logo.svg";
import arrowIcon from "../../../assets/icons/dropdown-blue.svg";
function SignUp({
sendOtp,
@ -20,8 +21,10 @@ function SignUp({
headerOptions,
setHeaderOptions,
loading,
level,
setLevel,
isMobile,
}) {
const [level, setLevel] = useState("phonenumber");
const [signUpFields, setSignUpFiels] = useState({});
const [error, setError] = useState("");
const [resend, setResend] = useState(false);
@ -103,18 +106,21 @@ function SignUp({
}
};
const numberInput = useRef();
useEffect(() => {
// numberInput.current.focus();
setHeaderOptions(headerOptions);
}, []);
useEffect(() => {
if (signUpFields?.otp?.length === 4) {
if (
signUpFields?.otp1 &&
signUpFields?.otp2 &&
signUpFields?.otp3 &&
signUpFields?.otp4
) {
sendOtp({
cellphone: signUpFields?.cellphone,
otp: signUpFields?.otp,
otp: signUpFields?.otp1 + signUpFields?.otp2 + signUpFields?.otp3 + signUpFields?.otp4,
userToken: "2",
applicationToken: "22",
});
@ -135,33 +141,40 @@ function SignUp({
}
}, [loginFlag]);
const light = theme === "light";
return (
<div
className="w-screen overflow-x-hidden flex flex-row transform -translate-y-10 relative"
className="w-screen overflow-x-hidden flex transform relative"
style={{ height: "calc(100vh - 160px)" }}
>
<button
className="absolute left-4 top-4 lg:top-8 p-3 bg-grayF4 rounded-xl z-20"
onClick={() =>
setLevel(level === "phonenumber" ? navigate("/") : "phonenumber")
}
>
<img src={arrowIcon} className="transform rotate-90" alt="" />
</button>
<div
className={`flex flex-col items-center justify-center h-full w-full p-4 transition transform duration-300 absolute top-0 left-0 ${
className={`flex flex-col items-center lg:pb-8 justify-between h-full w-full px-4 pt-16 lg:pt-16 transition transform duration-300 absolute top-0 left-0 ${
level === "phonenumber" ? "translate-x-0" : "-translate-x-full"
}`}
>
<img src={logoIcon} alt="" className="" />
<div className="mt-7">
<p className="text-sm align-start ">
<div className="w-full flex flex-col items-center gap-6">
<img src={logoIcon} alt="" className="w-1/5 lg:w-1/6" />
<p className="text-lg lg:text-base align-start">
{window.t("سلام به ")}
<span className="font-bold text-blueC0">
{window.t(" دانوین خوش ")}
</span>
{window.t("آمدید")}
</p>
<p className="text-sm mt-4">
</div>
<div className="w-full flex flex-col">
<p className="text-base lg:text-sm mt-4">
{window.t(
" لطفا جهت ورود یا ثبت نام شماره همراه خود را وارد نمایید."
)}
</p>
</div>
<div className="w-full flex flex-col mt-4">
<Input
label={window.t("شماره موبایل")}
@ -185,74 +198,92 @@ function SignUp({
/>
</div>
</div>
</div>
<div
className={`flex flex-col items-center justify-center w-full h-full p-4 transition transform duration-300 absolute top-0 left-0 ${
className={`flex flex-col items-center justify-between w-full lg:pb-8 h-full px-4 pt-16 transition transform duration-300 absolute top-0 left-0 ${
level === "otp" ? "translate-x-0" : "translate-x-full"
}`}
>
<img src={logoIcon} alt="" className="" />
<div className="flex flex-col w-full items-center">
<img src={logoIcon} alt="" className="w-1/5" />
{!resend && (
<div className="w-full leading-6 dark:text-white mt-10 text-xs lg:text-sm text-gray1">
<div className="w-full leading-6 dark:text-white mt-10 text-sm lg:text-sm text-gray1">
{window.t("یک کد چهار رقمی تا")} &nbsp;
<Timer seconds={120} refresh={setResend} /> &nbsp;
{window.t("دیگر برای شماره")}
&nbsp;
<span className="text-greenBA text-sm lg:text-tiny">
{signUpFields?.cellphone}
</span>
&nbsp; {window.t("ارسال خواهد شد.")}
</div>
)}
</div>
<div className="w-full flex flex-col mt-5">
<div className="w-full flex flex-row-reverse justify-center">
<div className="w-full flex flex-col">
<div className="w-full flex flex-row-reverse justify-between">
<input
inputMode="numeric"
style={{ direction: "ltr" }}
style={{
direction: "ltr",
width: isMobile ? "calc(100% / 4)" : "70px",
height: isMobile ? "calc((100vw - 32px) / 4.1)" : "70px",
}}
name="otp1"
className="bg-grayF9 dark:bg-opacity-10 outline-none rounded-md p-4 w-16 text-2xl font-bold lg:text-lg text-center text-blueC0 mx-1"
className="bg-grayF9 dark:bg-opacity-10 outline-none rounded-md text-2xl font-bold lg:text-lg text-center text-blueC0 mx-1"
onChange={(e) =>
onChange(
e.target.name,
(e.target.value = onInput.numberOnly(e.target.value))
)
}
maxlength="1"
maxLength="1"
ref={otp1}
/>
<input
inputMode="numeric"
style={{ direction: "ltr" }}
style={{
direction: "ltr",
width: isMobile ? "calc(100% / 4)" : "70px",
height: isMobile ? "calc((100vw - 32px) / 4.1)" : "70px",
}}
name="otp2"
className="bg-grayF9 dark:bg-opacity-10 outline-none rounded-md p-4 w-16 text-2xl font-bold lg:text-lg text-center text-blueC0 mx-1"
className="bg-grayF9 dark:bg-opacity-10 outline-none rounded-md text-2xl font-bold lg:text-lg text-center text-blueC0 mx-1"
onChange={(e) =>
onChange(
e.target.name,
(e.target.value = onInput.numberOnly(e.target.value))
)
}
maxlength="1"
maxLength="1"
ref={otp2}
/>
<input
inputMode="numeric"
style={{ direction: "ltr" }}
style={{
direction: "ltr",
width: isMobile ? "calc(100% / 4)" : "70px",
height: isMobile ? "calc((100vw - 32px) / 4.1)" : "70px",
}}
name="otp3"
className="bg-grayF9 dark:bg-opacity-10 outline-none rounded-md p-4 w-16 text-2xl font-bold lg:text-lg text-center text-blueC0 mx-1"
className="bg-grayF9 dark:bg-opacity-10 outline-none rounded-md text-2xl font-bold lg:text-lg text-center text-blueC0 mx-1"
onChange={(e) =>
onChange(
e.target.name,
(e.target.value = onInput.numberOnly(e.target.value))
)
}
maxlength="1"
maxLength="1"
ref={otp3}
/>
<input
inputMode="numeric"
style={{ direction: "ltr" }}
style={{
direction: "ltr",
width: isMobile ? "calc(100% / 4)" : "70px",
height: isMobile ? "calc((100vw - 32px) / 4.1)" : "70px",
}}
name="otp4"
className="bg-grayF9 dark:bg-opacity-10 outline-none rounded-md p-4 w-16 text-2xl font-bold lg:text-lg text-center text-blueC0 mx-1"
className="bg-grayF9 dark:bg-opacity-10 outline-none rounded-md text-2xl font-bold lg:text-lg text-center text-blueC0 mx-1"
onChange={(e) =>
onChange(
e.target.name,
@ -261,7 +292,7 @@ function SignUp({
))
)
}
maxlength="1"
maxLength="1"
ref={otp4}
/>
</div>
@ -277,8 +308,8 @@ function SignUp({
level === "phonenumber" ? checkPhoneNumber(e) : checkOtp(e)
}
/>
<div className="mt-10 flex flex-row text-center w-full justify-center">
<div className="text-xs text-gray1 dark:text-gray-200 lg:text-sm">
<div className="mt-10 flex text-center w-full justify-center">
<div className="text-sm text-gray1 dark:text-gray-200 lg:text-sm">
{window.t(" شماره خود را اشتباه وارد کردید؟")}
<button
className="bg-transparent border-none text-greenBA font-medium"
@ -297,6 +328,7 @@ function SignUp({
const mapStateToProps = (state) => ({
loginFlag: state.user.status,
loading: state.user.loading,
isMobile: state.publicApi.isMobile,
});
const mapDispatchToProps = {

@ -6,20 +6,29 @@ import { connect } from "react-redux";
function Auth(props) {
const [page, setPage] = useState(props.page);
const [level, setLevel] = useState("phonenumber");
useEffect(() => {
setPage(() => props.page);
}, [props.page]);
return props.isMobile ? (
<>
{page === "signup" && (
<SignUp theme={props.theme} headerOptions={props.headerOptions} />
<SignUp
theme={props.theme}
headerOptions={props.headerOptions}
level={level}
setLevel={setLevel}
/>
)}
{page === "profile" && <Profile theme={props.theme} />}
</>
) : <Desktop />
) : (
<Desktop level={level} setLevel={setLevel} />
);
}
export default connect((state) => ({
theme: state.publicApi.theme,
isMobile: state.publicApi.isMobile
isMobile: state.publicApi.isMobile,
}))(Auth);

@ -2,55 +2,41 @@ import React, { useEffect } from "react";
import { connect } from "react-redux";
import { blog, publicApi } from "../../redux/actions";
import { Carousel } from "@trendyol-js/react-carousel";
import location from "../../utils/location";
import { useParams } from "react-router-dom";
import Hashtags from "../Blogs/layouts/Hashtags";
//components
import Header from "../Blogs/layouts/Header";
import Suggest from "../Blogs/layouts/Suggest";
import New from "../Blogs/layouts/New";
import Avatar from "../../components/Avatar";
import { useParams } from "react-router-dom";
//assets
import arrow from "../../assets/icons/dropdown-blue.svg";
export const Blog = ({
isMobile,
getInfo,
blog,
setHeaderOptions,
headerOptions,
getList,
blogs,
activeBlog,
}) => {
let { id } = useParams();
console.log(id);
// let id = location.getId();
useEffect(() => {
setHeaderOptions(headerOptions);
getInfo({ id: location.getId() });
if (blogs.length === 0) {
getList();
}
}, [id]);
useEffect(() => {
getInfo({ id: location.getId() });
}, [activeBlog]);
setHeaderOptions(headerOptions);
}, []);
useEffect(() => {
// alert();
window.scrollTo(0, 0);
window.scroll({ top: 0, behavior: "smooth" });
getInfo({ id });
}, [id]);
return (
<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 />
{isMobile && (
return blogs?.length ? (
<div className="flex flex-col lg:w-11/12 mx-auto lg:py-24 lg:px-0 px-4 lg:pb-10 pb-24">
<div
className="w-full rounded-md overflow-hidden relative"
className="flex lg:hidden w-full rounded-md overflow-hidden relative"
style={{
minHeight: 200,
}}
@ -84,8 +70,7 @@ export const Blog = ({
</div>
</div>
</div>
)}
{!isMobile && (
<div
className="w-full hidden lg:flex"
style={{
@ -97,13 +82,13 @@ export const Blog = ({
backgroundPosition: "center bottom",
}}
></div>
)}
<div className="flex lg:flex-row my-5 gap-5">
<div className="flex lg:my-5 gap-5">
<strong className="flex-1 lg:text-5xl lg:font-black dark:text-gray-200">
{blog?.title}
</strong>
{!isMobile && (
<div className="flex flex-col">
{/* desktop */}
<div className="hidden lg:flex flex-col">
<div className="flex">
<Avatar size={60} />
<div className="flex flex-col py-2 mr-2 justify-center">
@ -124,28 +109,28 @@ export const Blog = ({
</span>
</div>
</div>
)}
{/* desktop */}
</div>
<div
className="leading-8 lg:text-base text-sm dark:text-white"
dangerouslySetInnerHTML={{ __html: blog?.text }}
/>
<Header title={window.t("پیشنهادی")} />
{isMobile ? (
<div className="w-full flex overflow-x-scroll no-scrollbar gap-4">
{/* mobile */}
<div className="lg:hidden 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" }}>
{blogs.length > 0 && (
{/* mobile */}
{/* desktop */}
<div className="hidden lg:flex w-full relative ltr">
<Carousel
show={4}
slide={2}
swiping={true}
useArrowKeys={true}
key={id}
transition={0.5}
rightArrow={
<img
@ -165,16 +150,18 @@ export const Blog = ({
}
>
{blogs
.filter((e) => e.id != blog.id)
?.slice(0, 10)
?.filter((blog) => Number(blog?.id) !== Number(id))
.map((blog, index) => (
<Suggest blog={blog} key={index} />
))}
</Carousel>
)}
</div>
)}
{/* desktop */}
</div>
);
) : <div className="w-full h-screen">
</div>;
};
const mapStateToProps = (state) => ({

@ -4,6 +4,7 @@ import { blog, publicApi } from "../../redux/actions";
import { Carousel } from "@trendyol-js/react-carousel";
import Hashtags from "./layouts/Hashtags";
import Blog from "./layouts/Blog";
import Single from "./layouts/Single";
import Join from "./layouts/Join";
import New from "./layouts/New";
@ -14,37 +15,39 @@ import Target from "./layouts/Target";
//assets
import arrow from "../../assets/icons/dropdown-blue.svg";
export const Blogs = ({ isMobile, getList, blogs, setHeaderOptions }) => {
export const Blogs = ({
isMobile,
getList,
blogs,
setHeaderOptions,
headerOptions,
activeHashtag,
}) => {
useEffect(() => {
if (isMobile) {
setHeaderOptions({
shown: true,
hamburgerMenu: true,
qr: true,
});
} else {
setHeaderOptions({ shown: true });
}
setHeaderOptions(headerOptions);
getList();
}, []);
useEffect(() => {
window.scrollTo(0, 0);
window.scroll({ top: 0, behavior: "smooth" });
}, []);
return (
<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 ">
<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-16">
<Hashtags />
{activeHashtag === "همه" ? (
<>
<Single />
<Header title={window.t(" تازهترینها از وبلاگ")} />
{isMobile ? (
<div className="w-full flex overflow-x-scroll no-scrollbar gap-4">
<div className=" w-full flex lg:hidden 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="hidden lg:flex w-full relative"
style={{ direction: "ltr" }}
>
{blogs.length > 0 && (
<Carousel
show={3}
@ -75,16 +78,16 @@ export const Blogs = ({ isMobile, getList, blogs, setHeaderOptions }) => {
</Carousel>
)}
</div>
)}
<Header title={window.t("پیشنهاد سردبیر")} />
{isMobile ? (
<div className="w-full flex overflow-x-scroll no-scrollbar gap-4">
<div className="w-full flex lg:hidden 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="hidden lg:flex w-full relative"
style={{ direction: "ltr" }}
>
{blogs.length > 0 && (
<Carousel
show={4}
@ -115,9 +118,19 @@ export const Blogs = ({ isMobile, getList, blogs, setHeaderOptions }) => {
</Carousel>
)}
</div>
)}
<Header title={window.t("از دنیای آموزش")} />
<Target blogs={blogs?.slice(0, 4)} />
</>
) : (
<div className="flex flex-wrap items-center">
{blogs
?.filter((blog) => blog?.tag === activeHashtag)
?.map((blog, index) => (
<Blog blog={blog} key={index} />
))}
</div>
)}
<Join />
</div>
);
@ -126,6 +139,7 @@ export const Blogs = ({ isMobile, getList, blogs, setHeaderOptions }) => {
const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile,
blogs: state.blog.list,
activeHashtag: state.blog.activeHashtag,
});
const mapDispatchToProps = {

@ -0,0 +1,45 @@
import React from "react";
import { connect } from "react-redux";
import { useNavigate } from "react-router-dom";
const height = {
mobile: "calc((100vw - 32px) / 16 * 9)",
tablet: "calc((100vw - 32px) / 16 * 9)",
desktop: "calc((100vw / 12 * 11) / 4 / 16 * 9)",
};
export const Blog = ({ blog, device }) => {
const navigation = useNavigate();
return (
<article className="flex w-full lg:w-1/4 p-2">
<div
className="cursor-pointer flex flex-col gap-4 w-full"
onClick={() =>
navigation(`/blogs/${blog?.id}`, { state: { id: blog?.id } })
}
>
<div
className="w-full rounded-md"
style={{
backgroundImage: `url(https://dnvn.ir/api/v1/file/${blog?.fileIds})`,
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
backgroundSize: "cover",
minHeight: height[device],
}}
></div>
<strong className="text-sm lg:text-tiny xl:text-base text-backgroundText h-20">
{blog?.title}
</strong>
</div>
</article>
);
};
const mapStateToProps = (state) => ({
device: state.config.device,
});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(Blog);

@ -1,17 +1,25 @@
import React from "react";
import { connect } from "react-redux";
import { blog } from "../../../redux/actions";
//assets
import arrowIcon from "../arrow.svg";
export const Hashtags = ({ hashtags }) => {
export const Hashtags = ({ hashtags, setActive, activeHashtag }) => {
return (
<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">
<div className="flex py-1 lg: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" />
<ul className="list-none flex justify-around items-center lg:flex-1 lg:ml-0 ml-4">
<ul className="list-none flex items-center lg:flex-1 lg:ml-0 ml-4">
{hashtags.map((hashtag, index) => (
<li className="text-tiny font-semibold cursor-pointer mx-4 lg:px-0 flex-1">
{hashtag}
<li
className={`text-tiny w-16 lg:w-28 font-medium cursor-pointer rounded-md text-center py-2 transition-all mx-4 flex-1 ${
activeHashtag === hashtag
? "bg-green-400 text-white"
: "text-green79"
}`}
onClick={() => setActive(hashtag)}
>
{"#" + hashtag}
</li>
))}
</ul>
@ -21,8 +29,11 @@ export const Hashtags = ({ hashtags }) => {
const mapStateToProps = (state) => ({
hashtags: state.blog.hashtags,
activeHashtag: state.blog.activeHashtag,
});
const mapDispatchToProps = {};
const mapDispatchToProps = {
setActive: blog.setActiveHashtag,
};
export default connect(mapStateToProps, mapDispatchToProps)(Hashtags);

@ -97,7 +97,7 @@ export const Join = ({ isMobile, join, userId }) => {
};
const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile,
isMobile: state.config.device === 'mobile',
userId: state.user.status?.id,
});

@ -36,7 +36,7 @@ export const New = ({ blog, isMobile, setActive }) => {
<Avatar size={60} />
<div className="flex flex-col py-2 mr-2 justify-center">
<strong className="lg:text-tiny lg:font-black text-gray1">
{"نوشته از:" + " " + "کامران ایزدی"}
{`{window.t("نوشته از:")}` + " " + `{window.t("کامران ایزدی")}`}
</strong>
<p className="lg:text-sm lg:font-semibold text-gray70 mt-2">
{window.t("سردبیر بخش وبلاگ دانوین")}
@ -45,7 +45,7 @@ export const New = ({ blog, isMobile, setActive }) => {
</div>
<div className="flex flex-col i justify-center items-end">
<span className="lg:text-sm text-gray1 lg:font-black">
{"زمان مطالعه" + " " + "۳۰ دقیقه"}
{`{window.t("زمان مطالعه")}` + " " + `{window.t("۳۰ دقیقه")}`}
</span>
<span className="mt-2 lg:text-sm text-gray1 lg:font-black">
{window.t("1400/11/24")}

@ -20,7 +20,7 @@ export const Suggest = ({ blog }) => {
className="w-full rounded-md"
style={{ height: "calc(100vw / 12 * 11 / 3 / 21 * 9)" }}
/>
<strong className="text-lg my-4 leading-7">{blog?.title}</strong>
<strong className="text-tiny my-4 leading-7">{blog?.title}</strong>
</Link>
);
};

@ -78,12 +78,12 @@ export const Target = ({ blogs, isMobile }) => {
const Small = ({ blogs }) => {
return (
<div className="w-full lg:w-1/2 flex flex-row flex-wrap lg:flex-col justify-between">
<div className="w-full lg:w-1/2 flex flex-wrap lg:flex-col justify-between">
{blogs.map((blog, index) => (
<Link
to={"/blogs/" + blog.id}
key={index}
className="lg:mb-0 mb-3 lg:flex-row lg:flex lg:gap-2"
className="lg:mb-0 mb-3 flex flex-col lg:flex-row lg:gap-2"
style={{ width: isMobile ? "48%" : "100%" }}
>
<img
@ -115,7 +115,7 @@ export const Target = ({ blogs, isMobile }) => {
);
};
return (
<div className="flex flex-col lg:flex-row gap-10">
<div className="flex flex-col lg:flex-row lg:gap-10">
<Large blog={blogs[0]} />
<Small blogs={blogs?.slice(0, 3)} />
</div>

@ -32,7 +32,7 @@ function Contact({ headerOptions, setHeaderOptions, info, isMobile, isDark }) {
>
<Header
bg={isMobile ? contactBgImage : desktopContactBgImage}
title="تماس با ما"
title={window.t("تماس با ما")}
/>
{isMobile ? (
<div className="w-full flex flex-col px-4 transform -translate-y-16">
@ -41,14 +41,14 @@ function Contact({ headerOptions, setHeaderOptions, info, isMobile, isDark }) {
))}
<NotFound
title={""}
subTitle={
subTitle={window.t(
"شاید سوالی که بدنبال آن هستید را در قسمت پرسشهای متداول بتوانید پیدا کنید"
}
)}
link="/faq"
/>
</div>
) : (
<div className="flex flex-row gap-10 transform -translate-y-12 w-11/12 mx-auto">
<div className="flex gap-10 transform -translate-y-12 w-11/12 mx-auto">
<div className="w-1/3">
<Ticket />
</div>
@ -59,9 +59,9 @@ function Contact({ headerOptions, setHeaderOptions, info, isMobile, isDark }) {
<Divider type="vertical" />
<NotFound
title={""}
subTitle={
"شاید سوالی که بدنبال آن هستید را در قسمت پرسشهای متداول بتوانید پیدا کنید"
}
subTitle={window.t(
"پششاید سوالی که بدنبال آن هستید را در قسمت پرسشهای متداول بتوانید پیدا کنید"
)}
link="/faq"
/>
</div>
@ -91,13 +91,15 @@ Contact.defaultProps = {
info: {
onlineSupport: {
icon: onlineSupportIcon,
title: { text: "پشتیبانی آنلاین", color: "#D3B702" },
title: { text: window.t("پشتیبانی آنلاین"), color: "#D3B702" },
description: {
text: "همکاران ما در قسمت فروش و پشتیبانی، پاسخگوی شما هستند هر سوالی در مورد کتابهای ما داشتید بپرسید",
text: window.t(
"همکاران ما در قسمت فروش و پشتیبانی، پاسخگوی شما هستند هر سوالی در مورد کتابهای ما داشتید بپرسید"
),
color: "#766600",
},
link: {
title: "ارتباط با بخش پشتیبانی",
title: window.t("ارتباط با بخش پشتیبانی"),
link: "/support",
color: "#766600",
},
@ -106,9 +108,11 @@ Contact.defaultProps = {
},
call: {
icon: callIcon,
title: { text: "شماره تماس", color: "#06A02A" },
title: { text: window.t("شماره تماس"), color: "#06A02A" },
description: {
text: "در صورت هرگونه سوال شما میتوانید در ساعات اداری 9 الی 17 با شماره 021۸۸۸۱۴۶۳۷ تماس حاصل فرمایید",
text: window.t(
"در صورت هرگونه سوال شما میتوانید در ساعات اداری 9 الی 17 با شماره ۰۲۱۸۸۸۱۴۶۳۷ تماس حاصل فرمایید"
),
color: "#025816",
},
link: null,
@ -117,13 +121,15 @@ Contact.defaultProps = {
},
address: {
icon: addressIcon,
title: { text: "نشانی", color: "#0EAD98" },
title: { text: window.t("نشانی"), color: "#0EAD98" },
description: {
text: "نشانی دفتر مرکزی: تهران میدان فردوسی خیابان عباس موسوی پلاک 30",
text: window.t(
"نشانی دفتر مرکزی: تهران میدان فردوسی خیابان عباس موسوی پلاک 30"
),
color: "#066A5C",
},
link: {
title: "لیست نمایندگیهای فروش",
title: window.t("لیست نمایندگیهای فروش"),
link: "/sell",
color: "#0A7769",
},

@ -5,7 +5,7 @@ import { connect } from "react-redux";
function Info({ info, isDark }) {
return (
<div
className="flex flex-row py-4 px-3 rounded-md mt-4"
className="flex py-4 px-3 rounded-md mt-4"
style={{
backgroundColor: info.bg,
border: `1px solid ${info.borderColor}`,

@ -29,7 +29,12 @@ export const Ticket = ({
setDialog,
}) => {
let opt = useMemo(
() => ["واحد مورد نظر", "واحد فروش", "واحد فنی", "واحد محتوایی"],
() => [
window.t("واحد مورد نظر"),
window.t("واحد فروش"),
window.t("واحد فنی"),
window.t("واحد محتوایی"),
],
[status]
);
@ -50,17 +55,14 @@ export const Ticket = ({
const send = useCallback(async () => {
if (!ticket?.subject) {
setDialog({
text: "موضوع پیام خود را وارد کنید.",
text: window.t("موضوع پیام خود را وارد کنید."),
type: "alert",
accept: () => {},
open: true,
});
// console.log("mahdi");
console.log(ticket?.subject);
// console.log("mahdi");
} else if (!ticket?.unit) {
setDialog({
text: "واحد مورد نظر خود را وارد نکرده اید.",
text: window.t("واحد مورد نظر خود را وارد نکرده اید."),
type: "alert",
accept: () => {},
open: true,
@ -78,7 +80,7 @@ export const Ticket = ({
};
await submit(data);
}
}, [status]);
}, [status, ticket]);
useEffect(() => {
window.scrollTo(0, 0);
@ -115,7 +117,7 @@ export const Ticket = ({
backgroundColor={isDark ? "dark:bg-transparent dark:text-white" : ""}
fill={isDark ? "fill-white" : "fill-gray-600"}
/>
{ticket?.unit === "واحد محتوایی" && (
{ticket?.unit === window.t("1400/11/24") && (
<>
<div className="mt-2"></div>
<Select
@ -124,7 +126,7 @@ export const Ticket = ({
...new Set(
myProductList?.map((item) => [
item?.product?.book?.id,
`${item?.product?.book.name} پایه ${
`${item?.product?.book.name} {window.t("پایه")} ${
Object.values(grades)[item.product.book.gradeId]
}`,
]) || []
@ -145,10 +147,10 @@ export const Ticket = ({
onChange={(name, value) => setTicket({ name, value })}
value={ticket?.subject || ""}
regex={(val) => val}
label="موضوع"
label={window.t("موضوع")}
/>
<Textarea
placeholder="پیام خود را اینجا بنویسید"
placeholder={window.t("پیام خود را اینجا بنویسید")}
name="text"
onChange={(name, value) => setTicket({ name, value })}
value={ticket?.text || ""}
@ -161,7 +163,7 @@ export const Ticket = ({
/>
<br />
<Button
title="ارسال پیام"
title={window.t("ارسال پیام")}
backgroundColor={isDark ? "bg-blueC0" : "bg-blueC0"}
border={{ color: isDark ? "#ffffff55" : "#196EC055", width: "0px" }}
width="100%"

@ -21,10 +21,10 @@ function Document({ onChange, name, value, isMobile }) {
margin: "auto",
}}
>
{value?.name || "تصویر بارگزاری شد"}
{value?.name || window.t("تصویر بارگزاری شد")}
</span>
) : (
<span>در صورت نیاز تصویر مرتبط را انتخاب کنید.</span>
<span>{window.t("در صورت نیاز تصویر مرتبط را انتخاب کنید.")} </span>
)}
</div>
) : (
@ -42,7 +42,7 @@ function Document({ onChange, name, value, isMobile }) {
margin: "auto",
}}
>
{value?.name || "فایل ثبت شد"}
{value?.name || window.t("فایل ثبت شد")}
</span>
) : (
<span
@ -52,7 +52,7 @@ function Document({ onChange, name, value, isMobile }) {
margin: "auto",
}}
>
در صورت نیاز تصویر مرتبط را انتخاب کنید.
{window.t("در صورت نیاز تصویر مرتبط را انتخاب کنید.")}
</span>
)}
</div>

@ -30,7 +30,7 @@ export const Dashboard = ({ isMobile, headerOptions, setHeaderOptions }) => {
</div>
) : (
<div className="w-full">
<div className="gap-5 w-full h-screen pt-20 mx-auto flex flex-row bg-transparent justify-end">
<div className="gap-5 w-full h-screen pt-20 mx-auto flex bg-transparent justify-end">
<Sidebar page={page} setPage={setPage} />
<Main page={page} />
</div>

@ -51,7 +51,7 @@ const ProfileAddress = ({
isMobile ? "p-0" : "px-10"
} mx-auto`}
>
<div className="w-full flex flex-row justify-between items-center mt-4">
<div className="w-full flex justify-between items-center mt-4">
<button
className={`flex justify-center text-tiny lg:text-sm rounded-md py-3 bg-grayF9 dark:bg-blueC0 dark:bg-opacity-30 cursor:pointer ${
isDark ? "text-white" : "text-gray70"
@ -63,7 +63,8 @@ const ProfileAddress = ({
border: `1px solid ${isDark ? "#DBDBDB22" : "#DBDBDB"}`,
}}
>
&nbsp;یک آدرس جدید اضافه کنید
&nbsp;
{window.t("یک آدرس جدید اضافه کنید")}
<strong className="text-lg transform translate-y-0.5 mr-1">+</strong>
</button>
</div>
@ -116,7 +117,7 @@ const Location = ({
const delAddress = (id) => {
setMenu();
setDialog({
text: "آدرس رو حذف کنیم؟",
text: window.t("آدرس رو حذف کنیم؟"),
type: "confirm",
accept: () => deleteAddress({ id }),
open: true,
@ -155,24 +156,30 @@ const Location = ({
{active && (
<div className="w-full flex justify-between mb-3">
<div className="flex items-center">
<strong className="text-base">آدرس انتخابی شما</strong>
<span className="mr-4 text-sm">فعال</span>
<strong className="text-base">
{window.t("آدرس انتخابی شما")}
</strong>
<span className="mr-4 text-sm"> {window.t("فعال")}</span>
</div>
</div>
)}
<div className={`flex w-full ${active ? "" : "flex-row"}`}>
<div className="flex flex-col flex-1 mb-4">
<span className="mb-2 leading-6">
{"آدرس:" + " " + address.address}
{`{window.t("آدرس")}` + " " + address.address}
</span>
<span className="mb-2 leading-6">
{"نام:" + " " + address.firstName + " " + address.lastName}
{`{window.t("نام:")}` +
" " +
address.firstName +
" " +
address.lastName}
</span>
<span className="mb-2 leading-6">
{"کد پستی:" + " " + address.postalCode}
{`{window.t("کد پستی:")}` + " " + address.postalCode}
</span>
<span className="mb-2 leading-6">
{"شماره تماس:" + " " + address.cellphone}
{`{window.t("شماره تماس:")}` + " " + address.cellphone}
</span>
</div>
</div>
@ -182,24 +189,24 @@ const Location = ({
<Link
style={{ border: "solid 1px #12CF7F" }}
to={"/editAddress/" + address.id}
className="w-full flex flex-row text-sm items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
className="w-full flex text-sm items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
onClick={() => setMenu()}
>
ویرایش
{window.t("ویرایش")}
<img src={editButton} alt="edit-address" className="w-5 mr-3 " />
</Link>
<div
style={{ border: "solid 1px #fca5a5" }}
class="w-full flex flex-row items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
class="w-full flex items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
onClick={() => delAddress(address.id)}
>
<button class="text-sm ">حذف</button>
<button class="text-sm ">{window.t("حذف")}</button>
<img src={trash} alt="delete-address" className="w-5 mr-3" />
</div>
</div>
</div>
<Button
title="مشاهده روی نقشه"
title={window.t("مشاهده روی نقشه")}
backgroundColor={isDark ? "bg-blueC0" : "bg-blueC0"}
border={{ color: isDark ? "#ffffff55" : "#196EC055", width: "0px" }}
width="100%"

@ -50,7 +50,7 @@ export const MyBooks = ({ books, grades, isMobile }) => {
))} */}
<div className="w-full scrolling-carousel mt-4 pb-2">
<p className="text-green7B font-bold text-2xl lg:text-base">
کتاب های من
{window.t("کتاب های من")}
</p>
<ScrollingCarousel className="py-3">
{books?.map((book, index) => (

@ -15,32 +15,32 @@ const List = ({ mobile }) => {
const pages = [
{
icon: <img src={userGreenIcon} alt="" />,
name: "اطلاعات حساب کاربری",
name: window.t("اطلاعات حساب کاربری"),
link: "/editProfile",
},
{
icon: <img src={cartGreenIcon} />,
name: "سفارشات",
name: window.t("سفارشات"),
link: "/Orders",
},
{
icon: <img src={bookGreenIcon} />,
name: "کتابهای من",
name: window.t("کتابهای من"),
link: "/AR",
},
{
icon: <img src={videoGreenIcon} />,
name: "دورههای من",
name: window.t("دورههای من"),
link: "#",
},
{
icon: <img src={bookmarkGreenIcon} />,
name: "لیست علاقهمندیها",
name: window.t("لیست علاقهمندیها"),
link: "/favorites",
},
{
icon: <img src={addressGreenIcon} />,
name: "آدرسها",
name: window.t("آدرسها"),
link: "/addresses",
},
];
@ -51,7 +51,7 @@ const List = ({ mobile }) => {
<Link
key={index}
to={page.link}
className={`w-full flex items-center justify-between mb-6 pb-4 flex-row shadow-sm`}
className={`w-full flex items-center justify-between mb-6 pb-4 shadow-sm`}
>
<div className={`flex items-center flex-row`}>
{page.icon}

@ -63,7 +63,7 @@ const ProfileAddress = ({
</div>
</div>
) : (
<Empty text="هیچ آدرسی ثبت نشده :(" />
<Empty title={window.t("هیچ آدرسی ثبت نشده")} />
)}
<FloatingButton
action={() => navigation("/createAddress", { state: { panel: true } })}
@ -102,7 +102,7 @@ const Location = ({
const delAddress = (id) => {
setMenu();
setDialog({
text: "آدرس رو حذف کنیم؟",
text: window.t("آدرس رو حذف کنیم؟"),
type: "confirm",
accept: () => deleteAddress({ id }),
open: true,
@ -140,7 +140,7 @@ const Location = ({
className="py-3 pr-2 pl-10 text-sm font-bold bg-blue-300"
onClick={() => setMenu()}
>
ویرایش
{window.t("ویرایش")}
</Link>
<button
className="py-3 pr-2 pl-10 border-none m-0 text-sm text-red19 font-bold"
@ -151,12 +151,14 @@ const Location = ({
</div>
<div className={"flex flex-col flex-1 mr-2"}>
{active && (
<div className={"w-full flex flex-row justify-between mb-3"}>
<div className={"flex flex-row items-center"}>
<div className={"w-full flex justify-between mb-3"}>
<div className={"flex items-center"}>
<strong className={"text-base font-bold text-gray1"}>
آدرس انتخابی شما
{window.t("آدرس انتخابی شما")}
</strong>
<span className={"text-xs text-gray1 mr-2.5"}>فعال</span>
<span className={"text-xs text-gray1 mr-2.5"}>
{window.t("فعال")}
</span>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -177,16 +179,20 @@ const Location = ({
<div className={`flex w-full ${active ? "" : "flex-row"}`}>
<div className={"flex flex-col flex-1 mb-4"}>
<span className={"text-sm leading-6"}>
{"آدرس:" + " " + address.address}
{`{window.t("آدرس:")}` + " " + address.address}
</span>
<span className={"text-sm leading-6 mt-1.5"}>
{"نام:" + " " + address.firstName + " " + address.lastName}
{`{window.t("نام:")}` +
" " +
address.firstName +
" " +
address.lastName}
</span>
<span className={"text-sm leading-6 mt-1.5"}>
{"کد پستی:" + " " + address.postalCode}
{`{window.t("کد پستی:")}` + " " + address.postalCode}
</span>
<span className={"text-sm leading-6 mt-1.5"}>
{"شماره تماس:" + " " + address.cellphone}
{`{window.t("شماره تماس:")}` + " " + address.cellphone}
</span>
</div>
{!active && (
@ -207,7 +213,7 @@ const Location = ({
)}
</div>
<Button
title="مشاهده روی نقشه"
title={window.t("مشاهده روی نقشه")}
backgroundColor={isDark ? "bg-transparent" : "bg-blueC0"}
border={{
color: isDark ? "#ffffff55" : "#196EC055",

@ -46,12 +46,12 @@ const ProfileBookmark = ({ bookmarkList, getList }) => {
backgroundColor: "white",
}}
>
x
headerOptions={{
x headerOptions=
{{
logo: false,
menu: false,
hamburgerMenu: false,
title: "لیست علاقهمندیها",
title: window.t("لیست علاقهمندیها"),
bookmark: false,
qr: false,
back: true,
@ -71,7 +71,7 @@ const ProfileBookmark = ({ bookmarkList, getList }) => {
</View>
</ScrollView>
) : (
<Empty text="لیست علاقهمندیها خالی است." />
<Empty text={window.t("لیست علاقهمندیها خالی است.")} />
)}
</SafeAreaView>
);

@ -6,9 +6,9 @@ const Trophy = ({}) => {
const [dropdown, setDropdown] = React.useState(true);
return (
<div
className={`w-full flex py-5 px-3 justify-between items-center flex-row bg-yellow4 bg-opacity-40`}
className={`w-full flex py-5 px-3 justify-between items-center bg-yellow4 bg-opacity-40`}
>
<div className={`flex flex-row items-center`}>
<div className={`flex items-center`}>
<svg xmlns="http://www.w3.org/2000/svg" width={23.862} height={23.862}>
<g fill="none" stroke="#d6d020" data-name="vuesax/linear/cup">
<path
@ -39,11 +39,11 @@ const Trophy = ({}) => {
</g>
</svg>
<strong className="text-sm mr-2.5 text-green4F">
{"امتیاز شما" + " " + 14560}
{`{window.t("امتیاز شما")}` + " " + 14560}
</strong>
</div>
<Link to="#" className="text-sm text-green4F">
مشاهده جوایز
{window.t("مشاهده جوایز")}
</Link>
</div>
);

@ -7,7 +7,7 @@ const User = ({ user, mobile }) => {
return (
<div className={`w-full`}>
<button
className={`w-full mt-2 mb-2 flex flex-row justify-between items-center border-none`}
className={`w-full mt-2 mb-2 flex justify-between items-center border-none`}
onClick={() => setDropdown(!dropdown)}
>
<div className={`flex items-center flex-row`}>
@ -49,10 +49,10 @@ const User = ({ user, mobile }) => {
}`}
>
<div
className={`flex items-center w-full pb-3 mb-3 flex-row border-b border-solid border-gray-100`}
className={`flex items-center w-full pb-3 mb-3 border-b border-solid border-gray-100`}
>
<strong className="text-sm text-gray1">
افزودن حساب کاربری جدید
{window.t("افزودن حساب کاربری جدید")}
</strong>
<span className="mr-1 mt-1 text-xl text-gray1">+</span>
</div>

@ -40,7 +40,7 @@ const SidebarMenu = ({
return (
<div className="flex flex-col">
<div
className="flex flex-row justify-between items-center py-2 my-2 cursor-pointer group hover:bg-blueC0 hover:bg-opacity-10 rounded-md px-1"
className="flex justify-between items-center py-2 my-2 cursor-pointer group hover:bg-blueC0 hover:bg-opacity-10 rounded-md px-1"
onClick={() =>
setToggleList({ ...toggleList, [name]: !toggleList[name] })
}
@ -69,7 +69,7 @@ const SidebarMenu = ({
{list.map((item, index) => (
<li
key={index}
className={`flex flex-row items-center cursor-pointer rounded-md hover:bg-gray-100`}
className={`flex items-center cursor-pointer rounded-md hover:bg-gray-100`}
onClick={() => (page !== item.value ? setPage(item.value) : {})}
>
<span
@ -91,42 +91,42 @@ const SidebarMenu = ({
const buttons = [
{
icon: myBooksIcon,
title: "کتاب های من",
title: window.t("کتاب های من"),
onClick: () => setPage("mybooks"),
name: "mybooks",
},
{
icon: myVideosIcon,
title: "ویدئوهای من",
title: window.t("ویدئوهای من"),
onClick: () => setPage("myvideos"),
name: "myvideos",
},
{
icon: ordersIcon,
title: "سفارشات",
title: window.t("سفارشات"),
onClick: () => setPage("orders"),
name: "orders",
},
{
icon: favoritesIcon,
title: "علاقمندی ها",
title: window.t("علاقمندی ها"),
onClick: () => setPage("favorites"),
name: "favorites",
},
{
icon: addressIcon,
title: "آدرس ها",
title: window.t("آدرس ها"),
onClick: () => setPage("addresses"),
name: "addresses",
},
{ icon: moon, title: "حالت شب", onClick: () => {}, name: "dark" },
{ icon: moon, title: window.t("حالت شب"), onClick: () => {}, name: "dark" },
{
icon: logoutIcon,
title: "خروج از حساب کاربری",
title: window.t("خروج از حساب کاربری"),
// onClick: () => logout(),
onClick: () =>
setDialog({
text: "میخوای تنهامون بذاری؟",
text: window.t("میخوای تنهامون بذاری؟"),
type: "confirm",
accept: () => logout(),
open: true,
@ -150,7 +150,7 @@ const SidebarMenu = ({
}}
>
{/* profile */}
<div className="flex flex-row items-center mb-10">
<div className="flex items-center mb-10">
<Avatar size={60} rounded={true} />
<p className="text-green7B font-bold text-base flex-1 mx-2">
{user.firstName === null ? "" : user.firstName + " " + user.lastName}
@ -177,7 +177,7 @@ const SidebarMenu = ({
key={i}
>
<div
className={`flex flex-row items-center cursor-pointer rounded-md py-0 my-3 px-1`}
className={`flex items-center cursor-pointer rounded-md py-0 my-3 px-1`}
>
<img src={button.icon} alt="" />
<strong
@ -214,16 +214,16 @@ SidebarMenu.defaultProps = {
profile: {
name: "profile",
icon: userEdit,
title: "حساب کاربری",
title: window.t("حساب کاربری"),
notification: null,
list: [{ title: "ویرایش حساب کاربری", value: "profile" }],
list: [{ title: window.t("ویرایش حساب کاربری"), value: "profile" }],
},
support: {
name: "support",
icon: sms,
title: "پشتیبانی",
title: window.t("پشتیبانی"),
notification: null,
list: [{ title: "ثبت نظر", value: "setTicket" }],
list: [{ title: window.t("ثبت نظر"), value: window.t("setTicket") }],
},
};

@ -62,16 +62,16 @@ function Address({
<div className="flex items-center gap-x-4 mt-2">
<div
style={{ border: "solid 1px #fca5a5" }}
class="w-full flex flex-row items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
class="w-full flex items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
>
<button class="text-sm">حذف</button>
<button class="text-sm">{window.t("حذف")}</button>
<img src={trash} alt="delete-address" className="w-5 mr-3" />
</div>
<div
style={{ border: "solid 1px #12CF7F" }}
class="w-full flex flex-row items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
class="w-full flex items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
>
<button class="text-sm">ویرایش</button>
<button class="text-sm">{window.t("ویرایش")}</button>
<img src={editButton} alt="edit-address" className="w-5 mr-3 " />
</div>
</div>
@ -106,34 +106,38 @@ function Address({
)}
<div className="flex flex-col gap-y-2">
<li className="text-right text-tiny leading-6 text-blue52 dark:text-white">
آدرس:&nbsp;{address.address}
{window.t(" آدرس:")}
&nbsp;{address.address}
</li>
<li className="text-right text-tiny leading-6 text-blue52 dark:text-white">
کد پستی:&nbsp;{address.postalCode}
{window.t("کد پستی:")}
&nbsp;{address.postalCode}
</li>
</div>
</div>
<div className="flex flex-col">
<li className="text-right text-tiny leading-6 text-blue52 dark:text-white">
نام تحویل گیرنده:&nbsp;{address.firstName + " " + address.lastName}
{window.t("نام تحویل گیرنده:")}
&nbsp;{address.firstName + " " + address.lastName}
</li>
<li className="text-right text-tiny leading-6 text-blue52 dark:text-white mt-3">
شماره تماس:&nbsp;{address.cellphone}
{window.t("شماره تماس:")}
&nbsp;{address.cellphone}
</li>
</div>
<div className="flex flex-col items-center gap-y-2">
<div
style={{ border: "solid 1px #fca5a5" }}
class="w-full flex flex-row items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
class="w-full flex items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
>
<button class="text-sm">حذف</button>
<button class="text-sm">{window.t("حذف")}</button>
<img src={trash} alt="delete-address" className="w-5 mr-3" />
</div>
<div
style={{ border: "solid 1px #12CF7F" }}
class="w-full flex flex-row items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
class="w-full flex items-center justify-between px-2 py-1 rounded-sm cursor-pointer"
>
<button class="text-sm">ویرایش</button>
<button class="text-sm">{window.t("ویرایش")}</button>
<img src={editButton} alt="edit-address" className="w-5 mr-3 " />
</div>
</div>
@ -148,7 +152,7 @@ function Address({
return isMobile ? (
<section className="mt-2 w-full">
<strong className="font-bold text-green7B dark:text-white lg:text-tiny">
انتخاب آدرس
{window.t("انتخاب آدرس")}
</strong>
<ul className="list-none p-0 m-0 flex flex-col gap-y-3">
{addresses.map((address, index) => (
@ -159,7 +163,7 @@ function Address({
/>
))}
</ul>
<div className="w-full flex flex-row justify-between items-center mt-4">
<div className="w-full flex justify-between items-center mt-4">
<button
className={`flex justify-center text-tiny py-3 rounded-md bg-grayF9 dark:bg-blueC0 dark:bg-opacity-10 w-full ${
isDark ? "text-white" : "text-gray70"
@ -169,14 +173,17 @@ function Address({
border: `1px solid ${isDark ? "#DBDBDB22" : "#DBDBDB"}`,
}}
>
&nbsp;یک آدرس جدید اضافه کنید
&nbsp;
{window.t("یک آدرس جدید اضافه کنید")}
<strong className="text-lg transform translate-y-0.5 mr-1">+</strong>
</button>
</div>
</section>
) : (
<section className="mt-0.5 w-full">
<strong className="font-medium dark:text-white">انتخاب آدرس</strong>
<strong className="font-medium dark:text-white">
{window.t("انتخاب آدرس")}
</strong>
<ul className="list-none p-0 m-0 flex flex-col gap-y-2">
{addresses.map((address, index) => (
<Location
@ -186,7 +193,7 @@ function Address({
/>
))}
</ul>
<div className="w-full flex flex-row justify-between items-center mt-4">
<div className="w-full flex justify-between items-center mt-4">
<button
className={`flex justify-center text-tiny lg:text-sm rounded-md py-3 bg-grayF9 dark:bg-blueC0 dark:bg-opacity-30 ${
isDark ? "text-white" : "text-gray70"
@ -196,7 +203,8 @@ function Address({
border: `1px solid ${isDark ? "#DBDBDB22" : "#DBDBDB"}`,
}}
>
&nbsp;یک آدرس جدید اضافه کنید
&nbsp;
{window.t("یک آدرس جدید اضافه کنید")}
<strong className="text-lg transform translate-y-0.5 mr-1">+</strong>
</button>
</div>

@ -19,8 +19,10 @@ function PaymentMethods({ paymentMethods }) {
};
return (
<section className="mt-8">
<strong className="font-medium dark:text-white text-base">انتخاب شیوه پرداخت</strong>
<ul className="list-none p-0 m-0 flex flex-row justify-between flex-wrap">
<strong className="font-medium dark:text-white text-base">
{window.t("انتخاب شیوه پرداخت")}
</strong>
<ul className="list-none p-0 m-0 flex justify-between flex-wrap">
{paymentMethods.map((method, index) => (
<Method method={method} key={index} />
))}

@ -50,7 +50,7 @@ function TransportDate({ transportDate, isMobile }) {
activeDate === time ? "text-green7B" : "text-blue52"
}`}
>
تکمیل ظرفیت
{window.t("تکمیل ظرفیت")}
</span>
)}
</button>
@ -62,7 +62,7 @@ function TransportDate({ transportDate, isMobile }) {
{/* <strong className="font-bold text-green7B dark:text-white lg:text-tiny">
زمان ارسال را انتخاب کنید
</strong>
<ul className="list-none p-0 m-0 flex flex-row justify-between flex-wrap w-full gap-4 mt-4">
<ul className="list-none p-0 m-0 flex justify-between flex-wrap w-full gap-4 mt-4">
{transportDate.times.map((time, index) => (
<Time time={time} key={index} />
))}
@ -73,7 +73,7 @@ function TransportDate({ transportDate, isMobile }) {
{/* <strong className="font-medium dark:text-white">
زمان ارسال را انتخاب کنید
</strong>
<ul className="list-none p-0 m-0 flex flex-row flex-wrap w-full gap-2">
<ul className="list-none p-0 m-0 flex flex-wrap w-full gap-2">
{transportDate.times.map((time, index) => (
<Time time={time} key={index} />
))}

@ -102,7 +102,7 @@ function TransportMethod({
<strong className="font-medium dark:text-white">
لطفا یک روش ارسال انتخاب کنید
</strong>
<ul className="list-none p-0 m-0 flex flex-row gap-5 flex-wrap">
<ul className="list-none p-0 m-0 flex gap-5 flex-wrap">
{list.map((method, index) => (
<Method
method={method}

@ -34,7 +34,7 @@ export const DeliveryForm = ({
const PriceStatus = ({ name, value, type }) => {
return (
<div className="w-full flex flex-row justify-between py-2">
<div className="w-full flex justify-between py-2">
<strong className="font-light text-sm dark:text-white">{name}</strong>
<span
className="font-bold text-sm dark:text-white"
@ -50,13 +50,13 @@ export const DeliveryForm = ({
return isMobile ? (
<div className="w-full flex flex-col pt-4 pb-4">
<div className="w-full flex flex-row gap-5">
<div className="w-full flex gap-5">
<Address addresses={list} setPhase={setPhase} />
</div>
<div className="w-full flex flex-row gap-5 mt-8">
<div className="w-full flex gap-5 mt-8">
<TransportMethod />
</div>
<div className="w-full flex flex-row gap-5 mt-8">
<div className="w-full flex gap-5 mt-8">
<TransportDate transportDate={form.transportDate} />
</div>
{isMobile && (
@ -80,19 +80,19 @@ export const DeliveryForm = ({
</div>
) : (
<div className="w-full flex flex-col px-4 pb-10">
<div className="w-full flex flex-row gap-5">
<div className="w-full flex gap-5">
<span className="w-6 h-6 rounded-full bg-grayF4 flex justify-center items-center text-sm">
1
</span>
<Address addresses={list} setPhase={setPhase} />
</div>
<div className="w-full flex flex-row gap-5 mt-8">
<div className="w-full flex gap-5 mt-8">
<span className="w-6 h-6 rounded-full bg-grayF4 flex justify-center items-center text-sm">
2
</span>
<TransportMethod />
</div>
{/* <div className="w-full flex flex-row gap-5 mt-8">
{/* <div className="w-full flex gap-5 mt-8">
<span className="w-6 h-6 rounded-full bg-grayF4 flex justify-center items-center text-sm">
3
</span>

@ -8,7 +8,7 @@ function NotFound({ title, subTitle, link }) {
return (
<Link
to={link}
className="flex flex-row items-center justify-between py-3.5 px-2 rounded-sm bg-blueC0 bg-opacity-10 mt-4 self-end lg:self-auto lg:ml-1/2 w-full lg:w-auto"
className="flex items-center justify-between py-3.5 px-2 rounded-sm bg-blueC0 bg-opacity-10 mt-4 self-end lg:self-auto lg:ml-1/2 w-full lg:w-auto"
>
<div className="flex flex-col w-full lg:w-full">
{title && <strong className="text-xs text-green4F text-opacity-70 lg:text-tiny">{title}</strong>}

@ -15,7 +15,7 @@ function Question({ item, selectFaq }) {
}
}
>
<div className="flex flex-row justify-between items-center">
<div className="flex justify-between items-center">
<strong className="flex-1 text-green4F text-xs lg:text-tiny font-medium dark:text-white lg:text-green4F">
{item.title}
</strong>

@ -41,7 +41,7 @@ function Faq({ headerOptions, setHeaderOptions, isMobile, list, getList, selectF
<Question key={index} item={item} selectFaq={selectFaq} />
))}
</div>
<div className="w-full flex flex-row lg:w-4/5 justify-end">
<div className="w-full flex lg:w-4/5 justify-end">
<NotFound
title={"پرسش خود را در لیست بالا پیدا نکردید؟"}
subTitle={"برای ما پیام ارسال کنید"}

@ -26,7 +26,7 @@ const Favorites = ({
}, []);
return (
<div className="flex flex-row flex-wrap">
<div className="flex flex-wrap">
{bookmarkList.map((bookmark, index) => (
<Bookmark key={index} bookmark={bookmark} />
))}

@ -23,7 +23,7 @@ const Part2 = ({ books }) => {
<div>
<Link
to="/products"
className="py-3 px-4 rounded bg-grayF4 text-blue3D text-tiny flex flex-row items-center"
className="py-3 px-4 rounded bg-grayF4 text-blue3D text-tiny flex items-center"
>
مشاهده بیشتر
<div className="transform rotate-90 translate-y-px mr-1">

@ -15,7 +15,7 @@ const Part4 = ({ books, grades }) => {
<div>
<Link
to="/products"
className="py-3 px-4 rounded bg-grayF4 text-blue3D text-tiny flex flex-row items-center"
className="py-3 px-4 rounded bg-grayF4 text-blue3D text-tiny flex items-center"
>
مشاهده بیشتر
<div className="transform rotate-90 translate-y-px mr-1">

@ -14,7 +14,7 @@ const SalesContainer = ({ books }) => {
return (
<div className="w-full my-10">
<div className="w-full py-10 pl-2 bg-white flex justify-between items-center gap-3">
<div className="flex flex-row items-center pl-4">
<div className="flex items-center pl-4">
{/* <div className="w-6 h-6 bg-blue-300 ml-4 rounded-full"></div> */}
<div className="text-3xl leading-normal">
<h3 className=" bg-blueC0 text-white text-center bold text-7xl">

@ -6,7 +6,7 @@ import _ from "lodash";
export default function Lights({ degrees}) {
return (
<div className="w-full">
<header className="container hidden flex-row px-12 lg:px-0 justify-between z-20 transform -translate-y-16 lg:-translate-y-24">
<header className="container hidden px-12 lg:px-0 justify-between z-20 transform -translate-y-16 lg:-translate-y-24">
{degrees.map((light, index) => (
<Light degree={light} key={index} />
))}

@ -101,10 +101,10 @@ function Page1({ list, top }) {
/>
</div>
<div
className="container flex flex-row justify-between relative transform translate-y-12"
className="container flex justify-between relative transform translate-y-12"
style={{ alignItems: "start" }}
>
<div className="list-none flex flex-row bg-blueB0 bg-opacity-40 p-2.5 rounded-md backdrop-filter backdrop-blur-md">
<div className="list-none flex bg-blueB0 bg-opacity-40 p-2.5 rounded-md backdrop-filter backdrop-blur-md">
<strong className="text-white text-sm font-light ml-1 border-l-2 pl-2 border-gray-300">
لیست محصولات
</strong>
@ -129,7 +129,7 @@ function Page1({ list, top }) {
</p>
<Link
to="/products"
className="flex flex-row items-center text-white text-xs bg-blueC0 px-4 py-3 rounded-md backdrop-filter backdrop-blur-md mt-5 self-end animate-bounce"
className="flex items-center text-white text-xs bg-blueC0 px-4 py-3 rounded-md backdrop-filter backdrop-blur-md mt-5 self-end animate-bounce"
>
ورود به فروشگاه <img src={arrowLeftWhite} alt="" className="mr-2" />
</Link>

@ -5,7 +5,7 @@ export default function PDF({ link }) {
return (
<a
href={link.value}
className="w-full flex flex-row justify-between py-3 px-4 rounded-md bg-yellow2 my-2"
className="w-full flex justify-between py-3 px-4 rounded-md bg-yellow2 my-2"
>
<p className="text-xs font-medium text-yellow1">{link.name}</p>
<img src={linkIcon} className="w-5 h-5" />

@ -6,7 +6,7 @@ export default function PDF({ pdf }) {
<a
download
href={pdf.value}
className="w-full flex flex-row justify-between py-3 px-4 rounded-md bg-redFF my-2"
className="w-full flex justify-between py-3 px-4 rounded-md bg-redFF my-2"
>
<p className="text-xs font-medium text-red5F">{pdf.name}</p>
<img src={pdfIcon} className="w-5 h-5" />

@ -44,7 +44,7 @@ function QrResult({ book, grades, checked, dataTypes, list }) {
)}
onClick={(e) => e.stopPropagation()}
>
<div className="w-full flex flex-row items-center">
<div className="w-full flex items-center">
<img src={book.imageUrl} alt={book.name} className="rounded-md w-1/3" />
<div className="flex flex-col">
<h1 className="font-semibold text-primary">{book.name}</h1>
@ -60,7 +60,7 @@ function QrResult({ book, grades, checked, dataTypes, list }) {
className="flex flex-col justify-start rounded-md border border-blueFE overflow-hidden"
style={{ borderWidth: 1, borderColor: "#C1E0FE", borderStyle: "solid" }}
>
<ul className="w-full flex flex-row list-none items-center">
<ul className="w-full flex list-none items-center">
{dataTypes.map((item, index) => (
<li
key={index}

@ -10,7 +10,7 @@ function Page3({ top, translateY }) {
<div
className={_.join(
[
"fixed left-0 h-screen w-full bg-white transition-opacity duration-1000 flex flex-row justify-center items-end z-30",
"fixed left-0 h-screen w-full bg-white transition-opacity duration-1000 flex justify-center items-end z-30",
top > 50 ? "opacity-0" : "opacity-100",
],
" "

@ -35,7 +35,7 @@ function Page4({ top }) {
رنگی پر نشد، به یاد هم باشیم شاید فردا ما هم در کنار هم نباشیم
</p>
<div
className="flex flex-row justify-center w-full mt-5"
className="flex justify-center w-full mt-5"
style={{ width: "30%" }}
>
<img src={bazarImage} alt="" className="w-36 mx-5 cursor-pointer" />

@ -18,7 +18,7 @@ export default function Question({ question }) {
onClick={() => setSelect(option)}
className={_.join(
[
"rounded-md w-full overflow-hidden flex flex-row items-center my-2 cursor-pointer transition-all duration-500",
"rounded-md w-full overflow-hidden flex items-center my-2 cursor-pointer transition-all duration-500",
],
" "
)}

@ -15,17 +15,17 @@ function Test({ title, duration, questions, translateY }) {
}}
>
<header
className="w-3/4 flex flex-row justify-between py-3 px-3 rounded-md"
className="w-3/4 flex justify-between py-3 px-3 rounded-md"
style={{ border: "1px solid #777" }}
>
<div className="flex flex-row items-center">
<div className="flex items-center">
<span
className="w-2 h-2 rounded-full ml-2"
style={{ backgroundColor: "#CEFDFF" }}
></span>
<h1 className="text-blueE8 text-md font-medium">{title}</h1>
</div>
<div className="flex flex-row items-center">
<div className="flex items-center">
<img src={timerIcon} className="w-4 h-4 ml-1" />
<div className="text-sm text-green71">
{_.join(["زمان باقیمانده", duration], " ")}

@ -36,7 +36,7 @@ function LessonPlayList({
{
<div className={_.join(["w-full mb-2.5 flex flex-col border"], " ")}>
{/* {bookId && (
<header className="mb-1 flex flex-row items-center">
<header className="mb-1 flex items-center">
<h3 className="py-1 px-2.5 m-0 bg-white inline">
{
realCategories.filter(
@ -57,7 +57,7 @@ function LessonPlayList({
<div
className={_.join(
[
"flex flex-row items-center py-2",
"flex items-center py-2",
video?.id === selectedVideo?.id ? "bg-white" : "",
],
" "

@ -31,7 +31,7 @@ function VodTube({
onClick={(e) => e.stopPropagation()}
className={_.join(
[
"fixed flex flex-row rtl pt-20 lg:px-5 xl:px-10 w-full bg-white dark:bg-black bg-opacity-80 transition-opacity duration-500 min-h-screen backdrop-filter backdrop-blur-md",
"fixed flex rtl pt-20 lg:px-5 xl:px-10 w-full bg-white dark:bg-black bg-opacity-80 transition-opacity duration-500 min-h-screen backdrop-filter backdrop-blur-md",
top > 10 ? "opacity-0 z-0" : "opacity-100 z-10",
],
" "
@ -59,7 +59,7 @@ function VodTube({
{/* <p className="desktop">{selectedVideo.text}</p> */}
</section>
<section className="md:hidden sm:hidden xs:hidden pb-7 flex flex-col">
<header className="flex flex-row justify-between items-center px-5 py-0">
<header className="flex justify-between items-center px-5 py-0">
<h2 className="m-0">نظرات</h2>
<button className="border-0">بستن نظرات</button>
</header>

@ -12,7 +12,7 @@ function Blogs({ list, isDark, setActive }) {
return (
<div className="w-full pr-4">
<div className="w-full flex flex-col rounded-md py-4 overflow-hidden">
<header className="w-full flex flex-row justify-between items-center">
<header className="w-full flex justify-between items-center">
<strong className="text-green7B dark:text-white font-bold text-base lg:text-sm">
خواندنیها
</strong>
@ -32,7 +32,7 @@ function Blogs({ list, isDark, setActive }) {
)}
</Link>
</header>
<ul className="list-none w-full overflow-x-scroll pt-3 flex flex-row pb-16 no-scrollbar">
<ul className="list-none w-full overflow-x-scroll pt-3 flex pb-16 no-scrollbar">
{list.map((blog, index) => (
<Blog blog={blog} key={index} setActive={setActive} />
))}
@ -47,7 +47,7 @@ const Blog = ({ blog, setActive }) => {
<li className="flex flex-col ml-3">
<Link
to={"/blogs/" + blog?.id}
className="flex flex-row justify-center items-end rounded-md"
className="flex justify-center items-end rounded-md"
style={{
background: `url(https://dnvn.ir/api/v1/file/${blog?.fileIds})`,
backgroundPosition: "contain",
@ -65,8 +65,8 @@ const Blog = ({ blog, setActive }) => {
<h2 className="text-xs font-semibold text-blue5F dark:text-white leading-5">
{blog.title}
</h2>
<div className="w-full flex flex-row justify-between items-center mt-3">
<div className="flex flex-row items-center">
<div className="w-full flex justify-between items-center mt-3">
<div className="flex items-center">
<img
src={`https://dnvn.ir/api/v1/file/${blog?.fileIds}`}
alt=""
@ -76,7 +76,7 @@ const Blog = ({ blog, setActive }) => {
{"حامد دژبانی نسب"}
</span>
</div>
<div className="flex flex-row items-center">
<div className="flex items-center">
<span className="text-xs font-light text-gray70 dark:text-greenBA">
{_.join(["زمان مناسب", "30"], " ")}
</span>

@ -1,14 +1,23 @@
import React from "react";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import { connect } from "react-redux";
import { ScrollingCarousel } from "@trendyol-js/react-carousel";
//components
import Progress from "../../../../../components/Progress";
import Modal from "../../../../../components/Modal";
//assets
import exitImage from "../../../../../assets/icons/exit.svg";
function MyBooks({ books, grades, isMobile }) {
const Book = ({ book }) => {
const [selectedModal, setSelectedModal] = React.useState(null);
const Book = React.useCallback(
({ book }) => {
return (
<li className=" flex flex-col lg:ml-6 lg:p-2 lg:border lg:border-solid lg:border-green-200 lg:rounded-md lg:pt-4">
<Link to={"/products/" + book.id}>
<div onClick={() => setSelectedModal(book?.id)}>
<img
src={`https://dnvn.ir/api/v1/file/${book.fileIds}`}
alt=""
@ -22,6 +31,7 @@ function MyBooks({ books, grades, isMobile }) {
maxWidth: isMobile ? 70 : "",
}}
/>
<h2 className="mt-2 text-tiny lg:text-tiny font-semibold text-blue5F dark:text-white lg:mt-4">
{book.name}
</h2>
@ -29,10 +39,45 @@ function MyBooks({ books, grades, isMobile }) {
grades[book.gradeId]
}`}</p>
<Progress percent={60} direction="float-right" />
</div>
<Modal
open={selectedModal === book?.id}
onClose={() => setSelectedModal(null)}
>
<div
className="w-2/3 rounded-md flex flex-col items-center p-2 gap-3 bg-white relative"
onClick={(e) => e.stopPropagation()}
>
<img
src={exitImage}
alt="خروج"
className="p-2 rounded-full w-8 bg-white absolute right-1 -top-6"
onClick={() => setSelectedModal(null)}
/>
<img
src={`https://dnvn.ir/api/v1/file/${book.fileIds}`}
alt={book?.name}
className="w-full object-cover"
/>
<Link
to={"/scan"}
className="w-full text-center py-3 bg-blueC0 text-white font-medium rounded-sm text-tiny"
>
اسکن کد QR
</Link>
<a
href={`https://ar.dnvn.ir/lunch?id=${book.id}`}
className="w-full text-center py-3 bg-gray-400 text-white font-medium rounded-sm text-tiny"
>
واقعیت افزوده
</a>
</div>
</Modal>
</li>
);
};
},
[isMobile, grades, books, selectedModal]
);
return (
<div className="px-4 mb-5 lg:mb-0" style={{ maxWidth: "100%" }}>
@ -40,21 +85,18 @@ function MyBooks({ books, grades, isMobile }) {
<strong className="text-green7B dark:text-white font-bold text-base lg:text-base mb-2">
کتابهای من
</strong>
{isMobile ? (
<ul className="list-none w-full overflow-x-scroll pt-2 flex flex-row lg:pt-5 lg:flex-wrap lg:overflow-y-scroll gap-3 lg:gap-10 no-scrollbar">
<ul className=" list-none w-full overflow-x-scroll pt-2 flex lg:hidden lg:pt-5 lg:flex-wrap lg:overflow-y-scroll gap-3 lg:gap-10 no-scrollbar">
{books?.slice(0, 5)?.map((book, index) => (
<Book book={book} key={index} />
))}
</ul>
) : (
<div className="w-full scrolling-carousel mt-4 pb-2">
<div className="hidden lg:flex w-full scrolling-carousel mt-4 pb-2">
<ScrollingCarousel className="py-3">
{books?.map((book, index) => (
<Book book={book} key={index} />
))}
</ScrollingCarousel>
</div>
)}
</div>
</div>
);

@ -47,7 +47,7 @@ function Videos({ videos, grades, isDark, isMobile }) {
return (
<div className="w-full px-4 lg:py-4">
<div className="w-full flex flex-col py-4 lg:px-3 overflow-hidden lg:border lg:border-solid lg:border-gray-200 rounded-md lg:bg-blueC0 lg:bg-opacity-5">
<header className="w-full flex flex-row justify-between items-center">
<header className="w-full flex justify-between items-center">
<strong className="text-green7B dark:text-white font-bold text-base lg:text-base mt-2">
دورههای ویدئویی شما
</strong>
@ -66,7 +66,7 @@ function Videos({ videos, grades, isDark, isMobile }) {
)}
</header>
{isMobile ? (
<ul className="list-none w-full overflow-x-scroll pt-3 gap-3 lg:gap-5 flex flex-row lg:pt-5 lg:flex-wrap lg:overflow-y-scroll no-scrollbar">
<ul className="list-none w-full overflow-x-scroll pt-3 gap-3 lg:gap-5 flex lg:pt-5 lg:flex-wrap lg:overflow-y-scroll no-scrollbar">
{videos?.slice(0, 5)?.map((video, index) => (
<Video video={video} key={index} />
))}

@ -6,7 +6,7 @@ import interactiveIcon from "../../../../../assets/icons/interactive.svg";
function Features({ features }) {
return (
<div className="w-full flex flex-row flex-wrap justify-between px-2">
<div className="w-full flex flex-wrap justify-between px-2">
{features.map((feature, index) => (
<Feature feature={feature} key={index} />
))}

@ -66,7 +66,7 @@ function Header({ list }) {
<div className="w-full flex justify-center mt-5">
<Link
to="/products"
className="flex flex-row items-center text-white text-tiny bg-blueC0 px-4 py-3 rounded-md backdrop-filter backdrop-blur-md mt-5 self-end"
className="flex items-center text-white text-tiny bg-blueC0 px-4 py-3 rounded-md backdrop-filter backdrop-blur-md mt-5 self-end"
>
ورود به فروشگاه
</Link>
@ -79,7 +79,7 @@ function Header({ list }) {
</div>
<h1 className="inline">با طعم لذت</h1>
</div>
<div className="flex flex-row my-1.5">
<div className="flex my-1.5">
<h1 className="inline">از اول تا یازدهم &nbsp;</h1>
<div className="relative">
<h1 className="inline z-20 pb-1">کنارتونیم</h1>

@ -15,7 +15,7 @@ function Platforms({ platforms }) {
const Platform = ({ platform }) => {
return (
<div
className="w-full flex flex-row rounded-sm p-4 items-start mb-5"
className="w-full flex rounded-sm p-4 items-start mb-5"
style={{
backgroundColor: platform.backgroundColor,
border: `1px solid ${platform.borderColor}`,

@ -13,12 +13,12 @@ function Responsive() {
}}
>
<div className="flex flex-col items-center text-center font-extrabold text-blue5F dark:text-gray-300 text-lg mt-3 transform translate-y-4">
<div className="flex flex-row ">
<div className="flex ">
<h1 className="inline z-50">
از طریق موبایل یا کامپیوتر میتونی
</h1>
</div>
<div className="flex flex-row my-1.5">
<div className="flex my-1.5">
<div className="relative">
<h1 className="inline z-50 pb-1">به محتوای دیجیتال &nbsp;</h1>
<span className="h-1 w-full absolute bottom-0 left-0 bg-green1"></span>

@ -3,8 +3,8 @@ import _ from "lodash";
export default function Book({ book }) {
return (
<div className="w-full flex flex-row justify-between py-3 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex flex-row items-center flex-1">
<div className="w-full flex justify-between py-3 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex items-center flex-1">
<img
src={book}
className="rounded-md"
@ -16,7 +16,7 @@ export default function Book({ book }) {
<span className="mt-2 text-xs lg:text-sm text-gray70 dark:text-white">نسخه دیجیتال</span>
</div>
</div>
<div className="flex flex-row items-center">
<div className="flex items-center">
<span className="py-1 px-2 rounded-sm text-green4F2 text-sm lg:text-base bg-grayF9 dark:bg-gray-500 dark:text-white">
1
</span>

@ -25,11 +25,11 @@ function OrderDetails({ order, setHeaderOptions, headerOptions }) {
},[]);
return (
<div className="px-4 flex flex-col py-5 lg:pt-24 lg:w-3/5 lg:mx-auto">
<div className="flex flex-row w-full justify-between items-center p-3 bg-blueC0 bg-opacity-10 rounded-t-md dark:bg-blueC0 dark:bg-opacity-10">
<div className="flex w-full justify-between items-center p-3 bg-blueC0 bg-opacity-10 rounded-t-md dark:bg-blueC0 dark:bg-opacity-10">
<strong className="font-medium text-sm lg:text-tiny text-blue52 dark:text-white">
{_.join(["شماره سفارش:", order.number], " ")}
</strong>
<div className="flex flex-row items-center">
<div className="flex items-center">
<span className="text-xs lg:text-tiny font-light text-blue52 dark:text-white">
{status[order.status]}
</span>
@ -39,20 +39,20 @@ function OrderDetails({ order, setHeaderOptions, headerOptions }) {
></div>
</div>
</div>
<div className="w-full flex flex-row items-center py-4 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="w-full flex items-center py-4 border-b border-solid border-blueFF1 dark:border-gray45">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white">آدرس تحویل:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{order.address}
</span>
</div>
<div className="w-full flex flex-row justify-between py-0 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex flex-row py-4">
<div className="w-full flex justify-between py-0 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex py-4">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white">مشخصات تحویل گیرنده:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{order.name}
</span>
</div>
<div className="flex flex-row py-4">
<div className="flex py-4">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white">شماره موبایل:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{order.cellphone}
@ -72,50 +72,50 @@ function OrderDetails({ order, setHeaderOptions, headerOptions }) {
<Book book={item} key={index} />
))}
</div>
<div className="w-full flex flex-row justify-between py-2 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex flex-row py-4">
<div className="w-full flex justify-between py-2 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex py-4">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white">مبلغ سبد خرید:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{_.join([order.shoppingCardPrice, "تومان"], " ")}
</span>
</div>
<div className="flex flex-row py-4">
<div className="flex py-4">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white">تخفیف:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{_.join([order.discountPrice, "تومان"], " ")}
</span>
</div>
</div>
<div className="w-full flex flex-row justify-between py-2 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex flex-row py-4">
<div className="w-full flex justify-between py-2 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex py-4">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white"> هزینه ارسال کالا:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{_.join([order.sendPrice, "تومان"], " ")}
</span>
</div>
<div className="flex flex-row py-4 border">
<div className="flex py-4 border">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white">جمع هزینه پرداختی:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{_.join([order.totalPrice, "تومان"], " ")}
</span>
</div>
</div>
<div className="w-full flex flex-row justify-between py-2 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex flex-row py-4">
<div className="w-full flex justify-between py-2 border-b border-solid border-blueFF1 dark:border-gray45">
<div className="flex py-4">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white">نحوه پرداخت:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{order.payMethod}
</span>
</div>
<div className="flex flex-row py-4">
<div className="flex py-4">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white"> شماره تراکنش:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{order.transactionNumber}
</span>
</div>
</div>
<div className="w-full flex flex-row justify-between py-2">
<div className="w-full flex flex-row py-4">
<div className="w-full flex justify-between py-2">
<div className="w-full flex py-4">
<strong className="text-xs lg:text-tiny text-green4F dark:text-white">تاریخ تحویل:</strong>
<span className="flex-1 font-light text-right mr-2 text-xs lg:text-tiny text-green4F dark:text-white">
{order.date}

@ -21,11 +21,11 @@ const status = {
function Order({ order, isMobile }) {
return (
<div className="w-full flex flex-col rounded-md overflow-hidden my-3 border border-solid border-blueC0 border-opacity-50 dark:border-blueC0 dark:border-opacity-10 lg:w-4/5 mx-auto">
<div className="flex flex-row w-full justify-between items-center p-3 bg-blueC0 bg-opacity-10 dark:bg-blueC0 dark:bg-opacity-10">
<div className="flex w-full justify-between items-center p-3 bg-blueC0 bg-opacity-10 dark:bg-blueC0 dark:bg-opacity-10">
<strong className="font-medium text-sm lg:text-tiny text-green4F dark:text-white">
{_.join(["شماره سفارش:", order.number], " ")}
</strong>
<div className="flex flex-row items-center">
<div className="flex items-center">
<span className="text-xs lg:text-tiny font-light text-green4F dark:text-white">
{status[order.status]}
</span>
@ -35,9 +35,9 @@ function Order({ order, isMobile }) {
></div>
</div>
</div>
<div className="w-full flex flex-row justify-between p-3">
<div className="w-full flex justify-between p-3">
<div className="flex flex-col">
<div className="flex flex-row mb-2">
<div className="flex mb-2">
{order.items.length < 2
? order?.items?.map((item, index) => (
<img
@ -63,7 +63,7 @@ function Order({ order, isMobile }) {
))}
{isMobile && order.items.length >= 2 && (
<div
className="flex flex-row items-center justify-center relative rounded-md overflow-hidden bg-grayEE dark:bg-gray-400"
className="flex items-center justify-center relative rounded-md overflow-hidden bg-grayEE dark:bg-gray-400"
style={{
width: 60,
height: 90,
@ -104,7 +104,7 @@ function Order({ order, isMobile }) {
</strong>
<Link
to="/orders/order"
className="rounded-md flex flex-row justify-center px-5 py-2.5 border border-solid border-blueC0 text-green4F bg-blueC0 bg-opacity-10"
className="rounded-md flex justify-center px-5 py-2.5 border border-solid border-blueC0 text-green4F bg-blueC0 bg-opacity-10"
>
جزئیات سفارش
<img

@ -7,8 +7,8 @@ function Comment({ comment }) {
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">
<div className="flex flex-row items-center">
<header className="flex justify-between">
<div className="flex items-center">
<img src={userImage} alt="" className="h-10 w-10 rounded-full" />
<strong className="text-blue5F text-md mr-1 dark:text-white">
{comment?.name}

@ -16,7 +16,7 @@ export const ProductOverAll = ({ book, grades, isDark, loading }) => {
const [type, setType] = useState("1");
return (
<div className="w-full flex flex-col">
<header className={`w-full flex flex-row justify-between gap-5`}>
<header className={`w-full flex justify-between gap-5`}>
<ProductImages images={book?.fileIds} />
<div className="flex flex-col w-1/2 divide-y divide-solid divide-gray-200">
<div className="w-full flex flex-col pr-2 py-2 border-0">
@ -43,7 +43,7 @@ export const ProductOverAll = ({ book, grades, isDark, loading }) => {
به من کمک کن انتخاب کنم
</p>
</div>
<div className="w-full flex flex-row justify-between items-center mt-4 gap-5">
<div className="w-full flex justify-between items-center mt-4 gap-5">
<Button
title="نسخه فیزیکی"
backgroundColor={isDark ? "bg-transparent" : "bg-white"}
@ -102,7 +102,7 @@ export const ProductOverAll = ({ book, grades, isDark, loading }) => {
<div className="flex py-4">
<Link
to={"/videos/" + book?.id}
className="bg-blueC0 text-green7B bg-opacity-5 font-semibold text-tiny rounded-md border border-solid border-blueC0 w-2/3 py-4 text-center flex flex-row items-center justify-center"
className="bg-blueC0 text-green7B bg-opacity-5 font-semibold text-tiny rounded-md border border-solid border-blueC0 w-2/3 py-4 text-center flex items-center justify-center"
>
مشاهده دوره ویدیویی این محصول
<img

@ -1,73 +1,112 @@
import React from "react";
import separate from '../../../utils/separate';
import separate from "../../../utils/separate";
//components
import StarRating from "../../../components/StarRating";
import Progress from "../../../components/Progress";
function Rate({ desktop, productId, rateDetail }) {
const fiveCount = React.useMemo(() => {
return rateDetail?.find((rate) => rate?.rate === 5);
}, [rateDetail]);
const fourCount = React.useMemo(() => {
return rateDetail?.find((rate) => rate?.rate === 4);
}, [rateDetail]);
const threeCount = React.useMemo(() => {
return rateDetail?.find((rate) => rate?.rate === 3);
}, [rateDetail]);
const twoCount = React.useMemo(() => {
return rateDetail?.find((rate) => rate?.rate === 2);
}, [rateDetail]);
const oneCount = React.useMemo(() => {
return rateDetail?.find((rate) => rate?.rate === 1);
}, [rateDetail]);
const allCount = React.useMemo(() => {
return rateDetail?.reduce((a, b) => a + b?.count, 0);
}, [rateDetail]);
const rate = React.useMemo(() => {
return rateDetail?.length
? ((oneCount?.count || 0) * 1 +
(twoCount?.count || 0) * 2 +
(threeCount?.count || 0) * 3 +
(fourCount?.count || 0) * 4 +
(fiveCount?.count || 0) * 5) /
rateDetail?.length
: 0;
}, [rateDetail]);
function Rate({ avarage, all, fields, desktop }) {
return (
<div className="w-full flex flex-row justify-between items-center mt-5">
<div className="w-full flex justify-between items-center mt-5">
<div className="flex flex-col items-center justify-center h-full ml-4">
{
desktop ?
{desktop ? (
<h1 className={`text-gray-600 mb-2 font-bold dark:text-white`}>
{avarage}
{rate}
</h1>
:
<strong className={`text-blue5F mb-2 font-bold dark:text-white`} style={{ fontSize: 'calc(100vw / 10)' }}>
{avarage}
) : (
<strong
className={`text-blue5F mb-2 font-bold dark:text-white`}
style={{ fontSize: "calc(100vw / 10)" }}
>
{rate}
</strong>
}
)}
<div className="">
<StarRating />
<StarRating value={rate} />
</div>
<span className="text-base text-gray70 mt-2 dark:text-white">{separate(all)}</span>
<span className="text-base text-gray70 mt-2 dark:text-white">
{" "}
{`از بین ${allCount} نفر`}
</span>
</div>
<ul className="p-0 m-0 list-none flex flex-col flex-1">
{fields.map((item, index) => (
<li key={index} className="w-full flex flex-row-reverse items-center justify-between">
<span className="mr-2 text-xs text-blue5F dark:text-white">{item.name}</span>
{
desktop ? <Progress deskTop percent={item.percent} /> : <Progress percent={item.percent} />
}
<span className="ml-2 text-xs text-blue5F dark:text-white">{item.percent + "%"}</span>
</li>
))}
</ul>
</div>
);
}
export default Rate;
Rate.defaultProps = {
avarage: 4.8,
all: 4780,
fields: [
{[
{
name: "5 ستاره",
percent: 49,
name: "یک ستاره",
value: ((oneCount?.count || 0) / allCount) * 100,
},
{
name: "4 ستاره",
percent: 31,
name: "دو ستاره",
value: ((twoCount?.count || 0) / allCount) * 100,
},
{
name: "3 ستاره",
percent: 9,
name: "سه ستاره",
value: ((threeCount?.count || 0) / allCount) * 100,
},
{
name: "2 ستاره",
percent: 5,
name: "چهار ستاره",
value: ((fourCount?.count || 0) / allCount) * 100,
},
{
name: "1 ستاره",
percent: 6,
name: "پنج ستاره",
value: ((fiveCount?.count || 0) / allCount) * 100,
},
],
};
].map((item, index) => (
<li
key={index}
className="w-full flex flex-row-reverse items-center justify-between"
>
<span className="mr-2 text-xs text-blue5F dark:text-white">
{item.name}
</span>
{desktop ? (
<Progress deskTop percent={item.value} />
) : (
<Progress percent={item.value} />
)}
<span className="ml-2 text-xs text-blue5F dark:text-white">
{item.value + "%"}
</span>
</li>
))}
</ul>
</div>
);
}
export default Rate;

@ -1,7 +1,7 @@
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { toast } from "react-toastify";
import { book, userProduct, publicApi } from "../../redux/actions";
import { book, userProduct, publicApi, dialog } from "../../redux/actions";
import { Link, useNavigate } from "react-router-dom";
import proxy from "../../redux/proxy";
import location from "../../utils/location";
@ -22,6 +22,7 @@ import arrow from "../../assets/icons/dropdown-blue.svg";
export const Product = ({
isMobile,
productType,
userProducts,
getInfo,
book,
grades,
@ -29,15 +30,62 @@ export const Product = ({
userId,
pushToCart,
headerOptions,
userProductLoading,
setHeaderOptions,
availableForSell,
setDialog,
}) => {
const [type, setType] = useState("physical");
const [whichTypeAdded, setWhichTypeAdded] = React.useState(null);
const [desktopContentTransform, setDesktopContentTransform] = useState(false);
const navigation = useNavigate();
const physicalAvailableForSell = React.useMemo(() => {
return availableForSell?.find((product) => product === 2);
}, [availableForSell]);
const digitalAvailableForSell = React.useMemo(() => {
return availableForSell?.find((product) => product === 1);
}, [availableForSell]);
const videoAvailableForSell = React.useMemo(() => {
return availableForSell?.find((product) => product === 4);
}, [availableForSell]);
const physicalProduct = React.useMemo(() => {
return book?.product?.find((product) => product?.productType === 2);
}, [book]);
const digitalProduct = React.useMemo(() => {
return book?.product?.find((product) => product?.productType === 1);
}, [book]);
const videoProduct = React.useMemo(() => {
return book?.product?.find((product) => product?.productType === 4);
}, [book]);
const physicalAvailabileInCart = React.useMemo(() => {
return userProducts?.find(
(product) =>
product?.productId === physicalProduct?.id && product?.condition < 2
);
}, [userProducts, book]);
const digitalAvailabileInCart = React.useMemo(() => {
return userProducts?.find(
(product) =>
product?.productId === digitalProduct?.id && product?.condition < 2
);
}, [userProducts, book]);
const videoAvailabileInCart = React.useMemo(() => {
return userProducts?.find(
(product) =>
product?.productId === videoProduct?.id && product?.condition < 2
);
}, [userProducts, book]);
useEffect(() => {
getInfo({ id: location.getId(), vod: true });
setHeaderOptions(headerOptions);
if (!isMobile) {
window.addEventListener("scroll", () => {
if (window.scrollY >= 64) {
@ -49,6 +97,18 @@ export const Product = ({
}
}, []);
useEffect(() => {
if (!userProductLoading) {
setWhichTypeAdded(null);
}
}, [userProductLoading]);
useEffect(() => {
if (book) {
setHeaderOptions({ ...headerOptions, productId: book?.id });
window.scroll({ top: 0, behavior: "smooth" });
}
}, [book]);
return (
<>
{/* Portrait */}
@ -79,52 +139,112 @@ export const Product = ({
</div>
</header>
<ul
className="list-none flex flex-row divide-x items-center mt-5"
className="list-none flex divide-x items-center mt-5"
style={{ direction: "ltr" }}
>
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white">
{book?.pagesNum} <br /> صفحه
</li>
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white">
{"فیزیکی - دیجیتالی"} <br /> در دسترس
<span>{videoAvailableForSell ? "ویدئویی - " : ""}</span>
<span>{digitalAvailableForSell ? "دیجیتال - " : ""}</span>
<span>{physicalAvailableForSell ? "فیزیکی" : ""}</span>
<br /> در دسترس
</li>
{book?.rate ? (
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white">
{book?.rate} <br /> امتیاز
</li>
) : null}
</ul>
<h2 className="text-green7B text-base font-semibold mt-10 dark:text-greenBA">
نسخه محصول را انتخاب کنید
</h2>
<div className="w-full flex flex-row justify-between items-center mt-5">
{physicalProduct && physicalAvailableForSell ? (
<div className="w-full flex justify-between items-center mt-5 gap-2">
<ButtonBetween
width="100%"
width="72%"
item={"خرید نسخه فیزیکی کتاب"}
status={separate(book?.product[1]?.price) + " " + "تومان"}
onClick={() =>
userId
? pushToCart({
productId: book?.product[1]?.id,
userId,
status={separate(physicalProduct?.price) + " " + "تومان"}
onClick={() => {
if (userId) {
if (physicalAvailabileInCart) {
setDialog({
text: window.t(
"این محصول قبلا به سبد خرید شما اضافه شده است."
),
type: "confirm",
accept: () => navigation("/cart"),
open: true,
});
} else {
setWhichTypeAdded("physical");
pushToCart({
productId: physicalProduct?.id,
userId: userId,
count: 1,
})
: toast.info("ابتدا وارد حساب کاربری خود شوید.")
});
}
} else {
setDialog({
text: window.t(
"ابتدا میبایست وارد حساب کاربری خود شوید."
),
type: "confirm",
accept: () => navigation("/login"),
open: true,
});
}
}}
loading={userProductLoading && whichTypeAdded === "physical"}
/>
<a
href={`https://dnvn.ir/xpdf/${book?.sampleFileId}`}
className="flex-1 border-2 border-solid text-sm border-green-500 bg-green-50 bg-opacity-70 rounded-sm font-bold text-green-700 text-center"
style={{ padding: "18px 0px" }}
>
مشاهده نمونه
</a>
</div>
<div className="w-full flex flex-row justify-between items-center mt-4 gap-2">
) : null}
{digitalProduct && digitalAvailableForSell ? (
<div className="w-full flex justify-between items-center mt-4 gap-2">
<ButtonBetween
width="72%"
item={"خرید نسخه دیجیتال کتاب"}
status={separate(book?.product[0]?.price) + " " + "تومان"}
onClick={() =>
userId
? pushToCart({
productId: book?.product[0]?.id,
userId,
status={separate(digitalProduct?.price) + " " + "تومان"}
onClick={() => {
if (userId) {
if (digitalAvailabileInCart) {
setDialog({
text: window.t(
"این محصول قبلا به سبد خرید شما اضافه شده است."
),
type: "confirm",
accept: () => navigation("/cart"),
open: true,
});
} else {
setWhichTypeAdded("digital");
pushToCart({
productId: digitalProduct?.id,
userId: userId,
count: 1,
})
: toast.info("ابتدا وارد حساب کاربری خود شوید.")
});
}
} else {
setDialog({
text: window.t(
"ابتدا میبایست وارد حساب کاربری خود شوید."
),
type: "confirm",
accept: () => navigation("/login"),
open: true,
});
}
}}
loading={userProductLoading && whichTypeAdded === "digital"}
/>
<a
href={`https://dnvn.ir/xpdf/${book?.sampleFileId}`}
@ -134,20 +254,44 @@ export const Product = ({
مشاهده نمونه
</a>
</div>
<div className="w-full flex flex-row justify-between items-center mt-4">
) : null}
{videoProduct && videoAvailableForSell ? (
<div className="w-full flex justify-between items-center mt-4">
<ButtonBetween
width="72%"
item={"خرید نسخه ویدئویی کتاب"}
status={separate(book?.product[2]?.price) + " " + "تومان"}
onClick={() =>
userId
? pushToCart({
productId: book?.product[2]?.id,
userId,
status={separate(videoProduct?.price) + " " + "تومان"}
onClick={() => {
if (userId) {
if (videoAvailabileInCart) {
setDialog({
text: window.t(
"این محصول قبلا به سبد خرید شما اضافه شده است."
),
type: "confirm",
accept: () => navigation("/cart"),
open: true,
});
} else {
setWhichTypeAdded("video");
pushToCart({
productId: videoProduct?.id,
userId: userId,
count: 1,
})
: toast.info("ابتدا وارد حساب کاربری خود شوید.")
});
}
} else {
setDialog({
text: window.t(
"ابتدا میبایست وارد حساب کاربری خود شوید."
),
type: "confirm",
accept: () => navigation("/login"),
open: true,
});
}
}}
loading={userProductLoading && whichTypeAdded === "video"}
/>
<ButtonBetween
width="25%"
@ -155,6 +299,8 @@ export const Product = ({
onClick={() => navigation("/videos/" + book?.id)}
/>
</div>
) : null}
<div className="w-full flex flex-col justify-between items-center mt-8">
<Header title="توضیحات" link="#" />
<p className="text-sm text-gray70 mt-2 dark:text-white leading-6">
@ -170,14 +316,18 @@ export const Product = ({
</div>
<div className="w-full flex flex-col justify-between items-center mt-10">
<Header title="امتیازات و نظرات" link="#" />
<Rate value={book?.rate || 0} />
<Rate
value={book?.rate || 0}
productId={physicalProduct?.id}
rateDetail={physicalProduct?.rateDetail}
/>
</div>
<div
className="flex flex-row w-full pb-4 mt-10 no-scrollbar"
className="flex w-full pb-4 mt-10 no-scrollbar"
style={{ overflowX: "scroll" }}
>
{[0, 1, 2, 2].map((comment, index) => (
<Comment key={index} />
{book?.comment?.map((comment, index) => (
<Comment comment={comment} key={index} />
))}
</div>
</div>
@ -196,12 +346,17 @@ const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile,
isDark: state.publicApi.isDark,
userId: state.user.status?.id,
bookmarkLoading: state.userFavorite.loading,
availableForSell: state.config.availableForSell,
userProduct: state.userProduct.list,
userProductLoading: state.userProduct.loading,
});
const mapDispatchToProps = {
getInfo: book.info,
pushToCart: userProduct.add,
setHeaderOptions: publicApi.setHeaderOptions,
setDialog: dialog.set,
};
export default connect(mapStateToProps, mapDispatchToProps)(Product);

@ -23,6 +23,7 @@ export const Products = ({
useEffect(() => {
getList({ vod: true });
setHeaderOptions(headerOptions);
window.scroll({top: 0, behavior : 'smooth'});
}, []);
return (
@ -40,9 +41,9 @@ export const Products = ({
</div>
) : (
<div
className={`w-full flex flex-row gap-10 px-5 overflow-y-hidden mt-3 justify-center lg:pt-24 lg:mt-0`}
className={`w-full flex gap-10 px-5 overflow-y-hidden mt-3 justify-center lg:pt-24 lg:mt-0`}
>
<div className="w-11/12 flex flex-row gap-5 justify-end">
<div className="w-11/12 flex gap-5 justify-end">
<Sidebar />
<Main books={books} grades={grades} />
</div>

@ -14,6 +14,7 @@ import moment from "jalali-moment";
import dropdownIcon from "../../../../assets/icons/dropdown-blue.svg";
import Posts from "./Posts";
import Pagination from "./Pagination";
const num = 6;
export const Main = ({
books,
@ -24,18 +25,26 @@ export const Main = ({
isMobile,
}) => {
const [filterLoading, setFilterLoading] = useState(false);
const [page, setPage] = useState(1);
console.log(page);
const [total, setTotal] = useState(books.length);
useEffect(() => {
setFilterLoading(() => true);
setTimeout(() => {
setFilterLoading(() => false);
}, 500);
// setFilterLoading(() => true);
// setTimeout(() => {
// setFilterLoading(() => false);
// }, 500);
setPage(1);
}, [filterOptions]);
useEffect(() => {
window.scrollTo(0, 0);
}, []);
useEffect(() => {
setTotal(books.length);
}, [books]);
const Items = (type) => {
const { grade, subject, available, sort, productType } = filterOptions;
let byGradeFilter;
@ -82,91 +91,23 @@ export const Main = ({
} else {
bySortFilter = byAvailableFilter;
}
return type === 2
? bySortFilter?.map((item, index) => (
<VodProduct
video={item}
key={index}
index={index}
height={"calc(100vh / 5)"}
grades={grades}
/>
))
: bySortFilter?.map((product, index) => (
<>
{(productType ? productType === "کتاب دیجیتال" : true) && (
<Link
to={"/products/" + product?.id}
className="w-full lg:w-1/3 xl:w-1/4 2xl:w-1/5"
>
<Product
key={index}
product={product}
index={Number(index)}
grades={grades}
imageSize={4.5}
type={0}
/>
</Link>
)}
{(productType ? productType === "کتاب فیزیکی" : true) && (
<Link
to={"/products/" + product?.id}
className="w-full lg:w-1/3 xl:w-1/4 2xl:w-1/5"
>
<Product
key={index}
product={product}
index={Number(index)}
grades={grades}
imageSize={4.5}
type={1}
/>
</Link>
)}
</>
));
};
// pagination
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [postsPerPage] = useState(10);
useEffect(() => {
const fetchPosts = async () => {
setLoading(true);
const res = await axios.get("https://jsonplaceholder.typicode.com/posts");
setPosts(res.data);
setLoading(false);
console.log("render here !");
return bySortFilter;
// setTotal(bySortFilter.length);
};
fetchPosts();
}, []);
// get current post
const indexOfLastPost = currentPage * postsPerPage;
const indexOfFirstPost = indexOfLastPost - postsPerPage;
const currentPosts = posts.slice(indexOfFirstPost, indexOfLastPost);
const elements = Items(1);
const vods = Items(2);
console.log(elements.length);
// change page
const paginate = (pageNumber) => setCurrentPage(pageNumber);
const lastPage = Math.floor((elements.length - 1) / num) + 1;
const pages = lastPage > 1 ? [...Array(lastPage)].map((e, i) => i + 1) : [];
return (
<div
className="flex flex-col w-3/4 pb-20 min-h-screen"
style={{ minWidth: "calc(100% * 3 / 4)" }}
>
<div className="bg-red-400 ">
<h1 className="mb-5">My Blog</h1>
<Posts posts={currentPosts} loading={loading} />
<Pagination
postsPerPage={postsPerPage}
totalPosts={posts.length}
paginate={paginate}
/>
</div>
<div className="flex w-full bg-blue rounded-lg border border-solid border-gray-200 p-2 items-center my-1.5 justify-center text-blue52">
<div className="flex text-sm items-center mr-2 ml-4">
<svg
@ -258,6 +199,7 @@ export const Main = ({
<Loading size={4} color="bg-green-400" />
</div>
)}
{books.length > 0 && (
<div className="relative w-full mt-7 " style={{ direction: "ltr" }}>
<Carousel
@ -293,12 +235,46 @@ export const Main = ({
/>
}
>
{Items(2)}
{vods.map((item, index) => (
<VodProduct
video={item}
key={index}
index={index}
height={"calc(100vh / 5)"}
grades={grades}
/>
))}
</Carousel>
</div>
)}
<div className="w-full flex flex-row flex-wrap mt-0 border-t-2 border-solid border-gray-100 overflow-y-hidden gap-4 justify-evenly pt-3">
{Items(1)}
<div className="w-full flex flex-wrap mt-0 border-t-2 border-solid border-gray-100 overflow-y-hidden gap-4 justify-evenly pt-3">
{elements
?.slice((page - 1) * num, page * num)
.map((product, index) => (
<Product
key={index}
product={product}
index={Number(index)}
grades={grades}
imageSize={4.5}
type={0}
/>
))}
{/* pagination */}
<div className="w-full flex justify-center gap-x-2">
{pages.map((e) => (
<div
className={`w-8 p-2 text-sm text-center rounded-md text-green7B cursor-pointer transform translate ${
page === true ? "bg-red-400" : "bg-blue-600"
}`}
onClick={() => setPage(e)}
>
{e}
</div>
))}
</div>
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save