reza added some option to dashboard

temp
Reza_ashrafi 3 years ago
parent fa7f68e45b
commit 2bffd0fbbf
  1. 6
      src/components/BottomNavigation/index.js
  2. 27
      src/components/FloatingButton/index.js
  3. 3
      src/components/FloatingButton/plus.svg
  4. 5
      src/components/Footer/index.js
  5. 2
      src/redux/reducers/book.js
  6. 20
      src/router.js
  7. 36
      src/views/Address/index.js
  8. 11
      src/views/Contact/index.js
  9. 19
      src/views/Contact/layouts/Ticket.js
  10. 2
      src/views/Contact/layouts/index.scss
  11. 26
      src/views/Dashboard/index.js
  12. 115
      src/views/Dashboard/layouts/Main/Addresses/index.js
  13. 10
      src/views/Dashboard/layouts/Main/Addresses/menu.svg
  14. 15
      src/views/Dashboard/layouts/Main/index.js
  15. 10
      src/views/Dashboard/layouts/SidebarMenu/address.svg
  16. 6
      src/views/Dashboard/layouts/SidebarMenu/favorites.svg
  17. 40
      src/views/Dashboard/layouts/SidebarMenu/index.js
  18. 7
      src/views/Dashboard/layouts/SidebarMenu/myBooks.svg
  19. 10
      src/views/Dashboard/layouts/SidebarMenu/myVideos.svg
  20. 7
      src/views/Dashboard/layouts/SidebarMenu/orders.svg
  21. 8
      src/views/Favorites/book.svg
  22. 7
      src/views/Favorites/bookmark.svg
  23. 63
      src/views/Favorites/index.js
  24. 41
      src/views/Product/Desktop/ProductOverAll/index.js
  25. 26
      src/views/Product/Desktop/index.js
  26. 70
      src/views/Products/layouts/Desktop/Main.js
  27. 14
      src/views/Profile/index.js
  28. 6
      src/views/ShoppingCart/Code/index.js
  29. 6
      src/views/Video/components/Desktop/Table.js
  30. 32
      src/views/Video/index.js

@ -82,15 +82,15 @@ BottomNavigation.defaultProps = {
}, },
{ {
id: 3, id: 3,
name: "آزمون", name: "سبد خرید",
link: "/test", link: "/cart",
activeIcon: activeTestIcon, activeIcon: activeTestIcon,
deactiveIcon: deactiveTestIcon, deactiveIcon: deactiveTestIcon,
}, },
{ {
id: 4, id: 4,
name: "حساب کاربری", name: "حساب کاربری",
link: "/profile", link: "/dashboard",
activeIcon: activeProfileIcon, activeIcon: activeProfileIcon,
deactiveIcon: deactiveProfileIcon, deactiveIcon: deactiveProfileIcon,
}, },

@ -0,0 +1,27 @@
import React from "react";
import { connect } from "react-redux";
//assets
import plusIcon from "./plus.svg";
export const FloatingButton = ({ action, position, icon }) => {
return (
<button
onClick={() => action()}
className={`fixed bg-blueC0 w-20 h-20 rounded-full transform transition-all hover:scale-110 active:scale-90 flex justify-center items-center shadow-xl z-10`}
style={position}
>
<img src={icon} alt="" className="w-7" style={{transform: 'translateX(-0px) translateY(3px)'}} />
</button>
);
};
const mapStateToProps = (state) => ({});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(FloatingButton);
FloatingButton.defaultProps = {
icon: plusIcon,
};

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="36" viewBox="0 0 14 36">
<text id="_" data-name="+" transform="translate(14 24)" fill="#fff" font-size="24" font-family="IRANSansX-Medium, IRANSansX" font-weight="500"><tspan x="-13.44" y="0">+</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 277 B

@ -14,7 +14,7 @@ const FooterDesign1 = ({ color, bg, items, hasHeader }) => {
return ( return (
<> <>
{hasHeader ? ( {hasHeader ? (
<div className=" bg-gray-100 w-full"> <div className=" bg-gray-100 w-full z-20">
<div className="w-11/12 mx-auto flex items-center justify-between py-6 text-blue52"> <div className="w-11/12 mx-auto flex items-center justify-between py-6 text-blue52">
<div className="flex items-center"> <div className="flex items-center">
<div className="flex items-center ml-8 "> <div className="flex items-center ml-8 ">
@ -50,7 +50,7 @@ const FooterDesign1 = ({ color, bg, items, hasHeader }) => {
</div> </div>
) : null} ) : null}
<footer <footer
className={`flex flex-col bg-gray-200 py-16 md:flex-row justify-around items-start md:items-start relative shadow-md ${bg}`} 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}`}
> >
<div className="w-11/12 flex justify-between"> <div className="w-11/12 flex justify-between">
<div className="flex flex-row gap-10"> <div className="flex flex-row gap-10">
@ -174,4 +174,5 @@ FooterDesign1.defaultProps = {
], ],
bg: "bg-white", bg: "bg-white",
color: "text-gray-600", color: "text-gray-600",
hasHeader : true
}; };

@ -10,7 +10,7 @@ const initialState = {
filterResult: [], filterResult: [],
subjects: [], subjects: [],
levels: [], levels: [],
sortFilters: ["محبوب ترین", "جدیدترین"], sortFilters: ["محبوب ترین", "جدیدترین", "ارزان ترین"],
selectedVideo: null, selectedVideo: null,
gradeFilterBooks: null, gradeFilterBooks: null,
sortFilterCourse: null, sortFilterCourse: null,

@ -96,7 +96,7 @@ function Router({ isDark, isMobile, headerOptions, dialog }) {
/> />
} }
/> />
<Route path="/profile" exact element={<Auth page="profile" />} /> {/* <Route path="/profile" exact element={<Auth page="profile" />} /> */}
<Route <Route
path="/products" path="/products"
exact exact
@ -337,7 +337,23 @@ function Router({ isDark, isMobile, headerOptions, dialog }) {
/> />
} }
/> />
<Route path="/dashboard" exact element={<Dashboard />} /> <Route
path="/dashboard"
exact
element={
<Dashboard
headerOptions={{
logo: true,
hamburgerMenu: true,
qr: true,
title: false,
shown: true,
menu: false,
back: false,
}}
/>
}
/>
<Route <Route
path="/ar" path="/ar"
exact exact

@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { publicApi, userAddress } from "../../redux/actions"; import { publicApi, userAddress, dialog } from "../../redux/actions";
import onInput from "../../utils/onInput"; import onInput from "../../utils/onInput";
import Input from "../../components/Input"; import Input from "../../components/Input";
import Select from "../../components/Select"; import Select from "../../components/Select";
@ -26,17 +26,10 @@ export const Address = ({
cityLoading, cityLoading,
isMobile, isMobile,
isDark, isDark,
setDialog
}) => { }) => {
const [addressFields, setAddressFields] = useState({}); const [addressFields, setAddressFields] = useState({});
const [mapAddress, setMapAddress] = useState(null); const [mapAddress, setMapAddress] = useState(null);
const [dialog, setDialog] = useState({
text: null,
type: null,
setOpen: null,
accept: null,
color: null,
open: null,
});
useEffect(() => { useEffect(() => {
if (province.length <= 1) { if (province.length <= 1) {
@ -74,10 +67,7 @@ export const Address = ({
setDialog({ setDialog({
text: "نام خود را وارد کنید.", text: "نام خود را وارد کنید.",
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -86,10 +76,7 @@ export const Address = ({
setDialog({ setDialog({
text: "نام خانوادگی خود را وارد کنید.", text: "نام خانوادگی خود را وارد کنید.",
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -98,10 +85,7 @@ export const Address = ({
setDialog({ setDialog({
text: "شماره موبایل خود را وارد کنید.", text: "شماره موبایل خود را وارد کنید.",
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -110,10 +94,7 @@ export const Address = ({
setDialog({ setDialog({
text: "شماره تلفن خود را وارد کنید.", text: "شماره تلفن خود را وارد کنید.",
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -122,10 +103,7 @@ export const Address = ({
setDialog({ setDialog({
text: "نام استان خود را وارد کنید.", text: "نام استان خود را وارد کنید.",
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -134,10 +112,7 @@ export const Address = ({
setDialog({ setDialog({
text: "نام شهرستان خود را وارد کنید.", text: "نام شهرستان خود را وارد کنید.",
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -146,10 +121,7 @@ export const Address = ({
setDialog({ setDialog({
text: "کد پستی خود را وارد کنید.", text: "کد پستی خود را وارد کنید.",
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -158,10 +130,7 @@ export const Address = ({
setDialog({ setDialog({
text: "آدرس خود را از روی نقشه انتخاب کن", text: "آدرس خود را از روی نقشه انتخاب کن",
type: "alert", type: "alert",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => {}, accept: () => {},
bg: "bg-white dark:bg-black dark:bg-opacity-30",
color: "text-gray70 dark:text-white",
open: true, open: true,
}); });
return; return;
@ -423,6 +392,7 @@ const mapDispatchToProps = {
getProvince: publicApi.getProvince, getProvince: publicApi.getProvince,
getCity: publicApi.getCity, getCity: publicApi.getCity,
createAddress: userAddress.add, createAddress: userAddress.add,
setDialog : dialog.set,
}; };
export default connect(mapStateToProps, mapDispatchToProps)(Address); export default connect(mapStateToProps, mapDispatchToProps)(Address);

@ -2,11 +2,12 @@ import React, { useEffect } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { publicApi } from "../../redux/actions"; import { publicApi } from "../../redux/actions";
import Ticket from './layouts/Ticket'; import Ticket from "./layouts/Ticket";
import Header from "../Activation/components/Header"; import Header from "../Activation/components/Header";
import NotFound from "../Faq/components/NotFound"; import NotFound from "../Faq/components/NotFound";
import Info from "./layouts/Info"; import Info from "./layouts/Info";
import Map from "../../components/Map"; import Map from "../../components/Map";
import Divider from "../../components/Divider";
//assets //assets
import contactBgImage from "./contact-bg.svg"; import contactBgImage from "./contact-bg.svg";
@ -47,10 +48,11 @@ function Contact({ headerOptions, setHeaderOptions, info, isMobile, isDark }) {
<div className="w-1/3"> <div className="w-1/3">
<Ticket /> <Ticket />
</div> </div>
<div className="w-1/3 flex flex-col"> <div className="w-1/3 flex flex-col justify-between">
{Object.keys(info).map((item, index) => ( {Object.keys(info).map((item, index) => (
<Info info={info[item]} key={index} /> <Info info={info[item]} key={index} />
))} ))}
<Divider type="vertical" />
<NotFound <NotFound
title={""} title={""}
subTitle={ subTitle={
@ -59,7 +61,10 @@ function Contact({ headerOptions, setHeaderOptions, info, isMobile, isDark }) {
link="/faq" link="/faq"
/> />
</div> </div>
<div className="w-1/3 rounded-md overflow-hidden" style={{height:'400px'}}> <div
className="w-1/3 rounded-md overflow-hidden"
style={{ height: "400px" }}
>
<Map /> <Map />
</div> </div>
</div> </div>

@ -55,7 +55,7 @@ export const Ticket = ({
accept: () => {}, accept: () => {},
open: true, open: true,
}); });
}else if(!ticket?.unit){ } else if (!ticket?.unit) {
setDialog({ setDialog({
text: "واحد مورد نظر خود را وارد نکرده اید.", text: "واحد مورد نظر خود را وارد نکرده اید.",
type: "alert", type: "alert",
@ -82,7 +82,7 @@ export const Ticket = ({
{!status && ( {!status && (
<> <>
<Input <Input
width="55%" width="100%"
label="نام و نام خانوادگی" label="نام و نام خانوادگی"
name="name" name="name"
onChange={(name, value) => setTicket({ name, value })} onChange={(name, value) => setTicket({ name, value })}
@ -90,7 +90,7 @@ export const Ticket = ({
regex={(val) => val} regex={(val) => val}
/> />
<Input <Input
width="55%" width="100%"
label="شماره تماس" label="شماره تماس"
name="cellphone" name="cellphone"
onChange={(name, value) => setTicket({ name, value })} onChange={(name, value) => setTicket({ name, value })}
@ -104,11 +104,13 @@ export const Ticket = ({
options={status && myProductList?.length ? opt : opt.slice(0, 3)} options={status && myProductList?.length ? opt : opt.slice(0, 3)}
name="unit" name="unit"
onChange={(name, value) => setTicket({ name, value })} onChange={(name, value) => setTicket({ name, value })}
width={"w-10/12"} width={"w-full"}
backgroundColor={isDark ? "dark:bg-transparent dark:text-white" : ""} backgroundColor={isDark ? "dark:bg-transparent dark:text-white" : ""}
fill={isDark ? "fill-white" : "fill-gray-600"} fill={isDark ? "fill-white" : "fill-gray-600"}
/> />
{ticket?.unit === "واحد محتوایی" && ( {ticket?.unit === "واحد محتوایی" && (
<>
<div className="mt-2"></div>
<Select <Select
name="bookId" name="bookId"
options={[ options={[
@ -122,13 +124,16 @@ export const Ticket = ({
), ),
]} ]}
onChange={(name, value) => setTicket({ name, value })} onChange={(name, value) => setTicket({ name, value })}
width={"w-10/12"} width={"w-full"}
backgroundColor={isDark ? "dark:bg-transparent dark:text-white" : ""} backgroundColor={
isDark ? "dark:bg-transparent dark:text-white" : ""
}
fill={isDark ? "fill-white" : "fill-gray-600"} fill={isDark ? "fill-white" : "fill-gray-600"}
/> />
</>
)} )}
<Input <Input
width="85%" width="100%"
name="subject" name="subject"
onChange={(name, value) => setTicket({ name, value })} onChange={(name, value) => setTicket({ name, value })}
value={ticket?.subject || ""} value={ticket?.subject || ""}

@ -3,7 +3,7 @@
color: gray !important; color: gray !important;
margin: 10px auto; margin: 10px auto;
width: 100%; width: 100%;
height: 50px; height: 100px;
border-radius: 10px; border-radius: 10px;
border: 2px dashed #d1d1d1; border: 2px dashed #d1d1d1;
position: relative; position: relative;

@ -1,18 +1,15 @@
import React, { useState } from "react"; import React, { useState, useEffect } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { publicApi } from "../../redux/actions";
//components
import Sidebar from "./layouts/SidebarMenu"; import Sidebar from "./layouts/SidebarMenu";
import Main from "./layouts/Main"; import Main from "./layouts/Main";
import Dialog from "../../components/Dialog";
export const Dashboard = ({ isMobile }) => { export const Dashboard = ({ isMobile, headerOptions, setHeaderOptions }) => {
const [dialog, setDialog] = useState({ useEffect(() => {
text: null, setHeaderOptions(headerOptions);
type: null, },[]);
setOpen: null,
accept: null,
color: null,
open: null,
});
const [page, setPage] = useState("userItems"); const [page, setPage] = useState("userItems");
@ -21,9 +18,8 @@ export const Dashboard = ({ isMobile }) => {
) : ( ) : (
<div className="w-full"> <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 flex-row bg-transparent justify-end">
<Sidebar page={page} setPage={setPage} setDialog={setDialog} dialog={dialog} /> <Sidebar page={page} setPage={setPage} />
<Main page={page} /> <Main page={page} />
{dialog.open && <Dialog dialog={dialog} />}
</div> </div>
</div> </div>
); );
@ -33,6 +29,8 @@ const mapStateToProps = (state) => ({
isMobile: state.publicApi.isMobile, isMobile: state.publicApi.isMobile,
}); });
const mapDispatchToProps = {}; const mapDispatchToProps = {
setHeaderOptions: publicApi.setHeaderOptions,
};
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard); export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);

@ -0,0 +1,115 @@
import React from "react";
import { connect } from "react-redux";
import { userAddress, userFactor } from "../../../../../redux/actions";
//components
import Button from "../../../../../components/Button";
import FloatingButton from "../../../../../components/FloatingButton";
//assets
import menuIcon from "./menu.svg";
const ProfileAddress = ({
addresses,
update,
getList,
userId,
userAddressId,
getFactorInfo,
loading,
isMobile,
isDark,
}) => {
React.useEffect(() => {
getFactorInfo({ userId });
getList();
}, []);
return (
<div className={`flex-1 ${isMobile ? "" : "w-1/2"} mx-auto`}>
<div className={`p-0 m-0 flex flex-col mb-4`}>
{addresses.map((address, index) => (
<Location
address={address}
key={index}
userId={userId}
active={userAddressId === address?.id}
isDark={isDark}
update={update}
/>
))}
</div>
<FloatingButton
action={() => {}}
position={{ right: isMobile ? "" : 350, bottom: 50 }}
/>
</div>
);
};
const Location = ({ address, active, userId, isDark, update }) => {
return (
<div
className={`flex items-center w-full px-3 py-4 rounded-md mt-2 border-2 border-solid ${
active
? "border-gray-300 bg-blueC0 bg-opacity-5"
: "border-green-400 bg-white"
}`}
onClick={() =>
active ? {} : update({ userAddressId: address.id, userId })
}
>
<div className="flex flex-1 flex-col mr-2">
{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>
</div>
<img src={menuIcon} alt="" className="w-6" />
</div>
)}
<div className="flex w-full">
<div className="flex flex-col flex-1 mb-4">
<span className="mb-2 leading-6">
{"آدرس:" + " " + address.address}
</span>
<span className="mb-2 leading-6">
{"نام:" + " " + address.firstName + " " + address.lastName}
</span>
<span className="mb-2 leading-6">
{"کد پستی:" + " " + address.postalCode}
</span>
<span className="mb-2 leading-6">
{"شماره تماس:" + " " + address.cellphone}
</span>
</div>
</div>
<Button
title="مشاهده روی نقشه"
backgroundColor={isDark ? "bg-blueC0" : "bg-blueC0"}
border={{ color: isDark ? "#ffffff55" : "#196EC055", width: "0px" }}
width="100%"
color={"text-white"}
onClick={() => {}}
/>
</div>
</div>
);
};
const mapStateToProps = (state) => ({
userId: state.user.status?.id,
userAddressId: state.userFactor.info?.userAddressId,
addresses: state.userAddress.list,
isMobile: state.publicApi.isMobile,
isDark: state.publicApi.isDark,
});
const mapDispatchToProps = {
getFactorInfo: userFactor.info,
update: userFactor.update,
getList: userAddress.list,
};
export default connect(mapStateToProps, mapDispatchToProps)(ProfileAddress);

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="vuesax_linear_more" data-name="vuesax/linear/more" transform="translate(0 24) rotate(-90)">
<g id="more">
<path id="Vector" d="M2,0A2,2,0,1,0,4,2,2.006,2.006,0,0,0,2,0Z" transform="translate(3 10)" fill="#07612c"/>
<path id="Vector-2" data-name="Vector" d="M2,0A2,2,0,1,0,4,2,2.006,2.006,0,0,0,2,0Z" transform="translate(17 10)" fill="#07612c"/>
<path id="Vector-3" data-name="Vector" d="M2,0A2,2,0,1,0,4,2,2.006,2.006,0,0,0,2,0Z" transform="translate(10 10)" fill="#07612c"/>
<path id="Vector-4" data-name="Vector" d="M0,0H24V24H0Z" fill="#07612c" opacity="0"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 707 B

@ -4,17 +4,26 @@ import { publicApi } from "../../../../redux/actions";
import Orders from "../../../Orders"; import Orders from "../../../Orders";
import UserItems from "../Main/UserItems"; import UserItems from "../Main/UserItems";
import MyBooks from './MyBooks'; import MyBooks from "./MyBooks";
import Ticket from "../../../Contact/layouts/Ticket";
import Favorites from "../../../Favorites/index";
import Addresses from "./Addresses";
export const Main = ({ setHeaderOptions, page }) => { export const Main = ({ setHeaderOptions, page }) => {
useEffect(() => { useEffect(() => {
setHeaderOptions({ shown: true }); setHeaderOptions({ shown: true });
}, []); }, []);
const views = { const views = {
orders: <Orders />, orders: <Orders />,
mybooks : <MyBooks />, mybooks: <MyBooks />,
userItems: <UserItems />, userItems: <UserItems />,
setTicket: (
<div className="w-1/2">
<Ticket />
</div>
),
favorites : <Favorites />,
addresses : <Addresses />
}; };
return ( return (
<div <div

@ -0,0 +1,10 @@
<svg id="arrow-square" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group" transform="translate(5.34 6.75)">
<path id="Vector" d="M0,6.53V4.57A4.569,4.569,0,0,1,4.57,0H6.53" transform="translate(6.8 1.79)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-2" data-name="Vector" d="M0,0H1.96A4.569,4.569,0,0,1,6.53,4.57V8.7" transform="translate(0.28 1.8)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-3" data-name="Vector" d="M1.8,0,0,1.8,1.8,3.6" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-4" data-name="Vector" d="M0,0,1.8,1.8,0,3.6" transform="translate(11.52)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
</g>
<path id="Vector-5" data-name="Vector" d="M7,20h6c5,0,7-2,7-7V7c0-5-2-7-7-7H7C2,0,0,2,0,7v6C0,18,2,20,7,20Z" transform="translate(2 2)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-6" data-name="Vector" d="M0,0H24V24H0Z" fill="none" opacity="0"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,6 @@
<svg id="archive-add" xmlns="http://www.w3.org/2000/svg" width="25.5" height="25.5" viewBox="0 0 25.5 25.5">
<path id="Vector" d="M5.313,0H0" transform="translate(10.094 11.316)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-2" data-name="Vector" d="M0,0V5.313" transform="translate(12.75 8.723)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-3" data-name="Vector" d="M14.344,0H4.1A4.111,4.111,0,0,0,0,4.1V19.072c0,1.912,1.371,2.72,3.049,1.8l5.185-2.879a2.251,2.251,0,0,1,1.987,0l5.185,2.879c1.679.935,3.049.128,3.049-1.8V4.1A4.127,4.127,0,0,0,14.344,0Z" transform="translate(3.528 2.125)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-4" data-name="Vector" d="M0,0H25.5V25.5H0Z" fill="none" opacity="0"/>
</svg>

After

Width:  |  Height:  |  Size: 925 B

@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
import Avatar from "../../../../components/Avatar"; import Avatar from "../../../../components/Avatar";
import { connect } from "react-redux"; import { connect } from "react-redux";
import {useNavigate} from "react-router-dom"; import {useNavigate} from "react-router-dom";
import { publicApi, user } from "../../../../redux/actions"; import { publicApi, user, dialog } from "../../../../redux/actions";
import "./index.scss"; import "./index.scss";
@ -12,6 +12,11 @@ import moon from "./moon.svg";
import sms from "./sms.svg"; import sms from "./sms.svg";
import userEdit from "./user-edit.svg"; import userEdit from "./user-edit.svg";
import dropdownIcon from "../../../../assets/icons/dropdown-blue.svg"; import dropdownIcon from "../../../../assets/icons/dropdown-blue.svg";
import myVideosIcon from "./myVideos.svg";
import myBooksIcon from "./myBooks.svg";
import ordersIcon from "./orders.svg";
import favoritesIcon from "./favorites.svg";
import addressIcon from "./address.svg";
const SidebarMenu = ({ const SidebarMenu = ({
profile, profile,
@ -23,8 +28,7 @@ const SidebarMenu = ({
setPage, setPage,
logout, logout,
setDialog, setDialog,
dialog, isLogin,
isLogin
}) => { }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const [toggleList, setToggleList] = useState({ const [toggleList, setToggleList] = useState({
@ -86,23 +90,35 @@ const SidebarMenu = ({
const buttons = [ const buttons = [
{ {
icon: null, icon: myBooksIcon,
title: "کتاب های من", title: "کتاب های من",
onClick: () => setPage("mybooks"), onClick: () => setPage("mybooks"),
name: "mybooks", name: "mybooks",
}, },
{ {
icon: null, icon: myVideosIcon,
title: "ویدئوهای من", title: "ویدئوهای من",
onClick: () => setPage("myvideos"), onClick: () => setPage("myvideos"),
name: "myvideos", name: "myvideos",
}, },
{ {
icon: null, icon: ordersIcon,
title: "سفارشات", title: "سفارشات",
onClick: () => setPage("orders"), onClick: () => setPage("orders"),
name: "orders", name: "orders",
}, },
{
icon: favoritesIcon,
title: "علاقمندی ها",
onClick: () => setPage("favorites"),
name: "favorites",
},
{
icon: addressIcon,
title: "آدرس ها",
onClick: () => setPage("addresses"),
name: "addresses",
},
{ icon: moon, title: "حالت شب", onClick: () => {}, name: "dark" }, { icon: moon, title: "حالت شب", onClick: () => {}, name: "dark" },
{ {
icon: logoutIcon, icon: logoutIcon,
@ -112,10 +128,7 @@ const SidebarMenu = ({
setDialog({ setDialog({
text: "میخوای تنهامون بذاری؟", text: "میخوای تنهامون بذاری؟",
type: "confirm", type: "confirm",
setOpen: (val) => setDialog({ ...dialog, open: val }),
accept: () => logout(), accept: () => logout(),
bg: "bg-white bg-opacity-10",
color: "text-green4F",
open: true, open: true,
}), }),
name: "logout", name: "logout",
@ -129,10 +142,10 @@ const SidebarMenu = ({
},[isLogin]); },[isLogin]);
return ( return (
<div <div
className="bg-gray-50 py-5 border-l-2 pl-4 pr-8 shadow-sm border-gray-300 border-solid overflow-y-scroll no-scrollbar divide-y divide-solid divide-gray-200" className="bg-gray-50 py-5 border-l-2 pl-4 pr-2 shadow-sm border-gray-300 border-solid overflow-y-scroll no-scrollbar divide-y divide-solid divide-gray-200"
style={{ style={{
height: "calc(100vh - 80px)", height: "calc(100vh - 80px)",
minWidth: 400, minWidth: 300,
}} }}
> >
{/* profile */} {/* profile */}
@ -146,7 +159,6 @@ const SidebarMenu = ({
list={support.list} list={support.list}
title={support.title} title={support.title}
name={support.name} name={support.name}
active={true}
icon={support.icon} icon={support.icon}
active={dashboardOptions.support} active={dashboardOptions.support}
/> />
@ -154,7 +166,6 @@ const SidebarMenu = ({
list={profile.list} list={profile.list}
title={profile.title} title={profile.title}
name={profile.name} name={profile.name}
active={true}
icon={profile.icon} icon={profile.icon}
active={dashboardOptions.profile} active={dashboardOptions.profile}
/> />
@ -193,6 +204,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = { const mapDispatchToProps = {
setDashboardOptions: publicApi.setDashboardOptions, setDashboardOptions: publicApi.setDashboardOptions,
logout: user.logout, logout: user.logout,
setDialog : dialog.set,
}; };
export default connect(mapStateToProps, mapDispatchToProps)(SidebarMenu); export default connect(mapStateToProps, mapDispatchToProps)(SidebarMenu);
@ -211,7 +223,7 @@ SidebarMenu.defaultProps = {
title: "پشتیبانی", title: "پشتیبانی",
notification: null, notification: null,
list: [ list: [
{ title: "تیکت ها", value: "tickets" }, { title: "ثبت نظر", value: "setTicket" },
], ],
}, },
}; };

@ -0,0 +1,7 @@
<svg id="book" xmlns="http://www.w3.org/2000/svg" width="24" height="23.746" viewBox="0 0 24 23.746">
<path id="Vector" d="M20,13.886V1.98A1.959,1.959,0,0,0,17.83.017h-.06A19.029,19.029,0,0,0,10.7,2.355l-.17.109a1.121,1.121,0,0,1-1.06,0l-.25-.148A18.935,18.935,0,0,0,2.16.007,1.957,1.957,0,0,0,0,1.97V13.886a2.036,2.036,0,0,0,1.74,1.953l.29.039a25.941,25.941,0,0,1,7.44,2.407l.04.02a1.094,1.094,0,0,0,.96,0,25.705,25.705,0,0,1,7.46-2.427l.33-.039A2.036,2.036,0,0,0,20,13.886Z" transform="translate(2 2.662)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-2" data-name="Vector" d="M0,0V15" transform="translate(12 5.236)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-3" data-name="Vector" d="M2.25,0H0" transform="translate(17.705 8.4)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-4" data-name="Vector" d="M3,0H0" transform="translate(16.918 11.369)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-5" data-name="Vector" d="M0,0H24V23.746H0Z" transform="translate(24 23.746) rotate(180)" fill="none" opacity="0"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24.613" height="21.519" viewBox="0 0 24.613 21.519">
<g id="Group_2005" data-name="Group 2005" transform="translate(0.75 0.75)">
<g id="vuesax_linear_music-playlist" data-name="vuesax/linear/music-playlist">
<g id="music-playlist" transform="translate(0)">
<path id="Vector" d="M17.335,20.019H5.778c-3.467,0-5.778-2-5.778-6.673V6.673C0,2,2.311,0,5.778,0H17.335c3.467,0,5.778,2,5.778,6.673v6.673C23.113,18.017,20.8,20.019,17.335,20.019Z" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
</g>
</g>
<path id="Vector-2" data-name="Vector" d="M0,3.572V2.108C0,.23,1.329-.538,2.951.4l1.268.732,1.268.732c1.622.939,1.622,2.476,0,3.415L4.22,6.011l-1.268.732C1.329,7.681,0,6.913,0,5.035V3.572Z" transform="translate(8.204 6.438)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 961 B

@ -0,0 +1,7 @@
<svg id="bag-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path id="Vector" d="M0,5.662v-.97A4.773,4.773,0,0,1,4.06.022,4.5,4.5,0,0,1,9,4.5v1.38" transform="translate(7.5 2.008)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-2" data-name="Vector" d="M5.751,14h6c4.02,0,4.74-1.61,4.95-3.57l.75-6c.27-2.44-.43-4.43-4.7-4.43h-8C.481,0-.219,1.99.051,4.43l.75,6C1.011,12.39,1.731,14,5.751,14Z" transform="translate(3.249 8)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-3" data-name="Vector" d="M.495.5H.5" transform="translate(15.001 11.5)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<path id="Vector-4" data-name="Vector" d="M.495.5H.5" transform="translate(8 11.5)" fill="none" stroke="#37a865" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<path id="Vector-5" data-name="Vector" d="M0,0H24V24H0Z" fill="none" opacity="0"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 60 KiB

@ -0,0 +1,7 @@
<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="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="#37a865"/>
<path id="Vector-2" data-name="Vector" d="M0,0H29.778V29.778H0Z" fill="none" opacity="0"/>
<path id="Vector-3" data-name="Vector" d="M6.2,0H0" transform="translate(11.787 13.214)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 776 B

@ -0,0 +1,63 @@
import React from "react";
import { connect } from "react-redux";
//assets
import bookImage from "./book.svg";
import bookmarkIcon from "./bookmark.svg";
const Favorites = ({ bookmarkList, isMobile }) => {
const Bookmark = ({ bookmark }) => {
return (
<div className="lg:w-1/2 xl:w-1/3 p-2 mb-4">
<div
className={`flex justify-between px-3.5 py-2 border-2 border-gray-300 border-solid rounded-md relative`}
>
<div className={"flex w-full"}>
<img src={bookmark.image} alt="" className="w-1/5" />
<div className={`flex flex-col mr-2 pt-2`}>
<strong className="text-base text-gray1">{bookmark.name}</strong>
<span className="text-sm mt-2 text-green7B font-bold">{bookmark.grade}</span>
</div>
</div>
<img src={bookmarkIcon} alt="" className="w-7 absolute left-2 top-2" />
</div>
</div>
);
};
return (
<div className="flex flex-row flex-wrap">
{bookmarkList.map((bookmark, index) => (
<Bookmark key={index} bookmark={bookmark} />
))}
</div>
);
};
const mapStateToProps = (state) => ({
loading: state.userFactor.loading,
isMobile: state.publicApi.isMobile,
});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(Favorites);
Favorites.defaultProps = {
bookmarkList: [
{
name: "کتاب آموزشی علوم تجربی",
grade: "پایه ششم ابتدایی",
image: bookImage,
},
{
name: "کتاب آموزشی علوم تجربی",
grade: "پایه ششم ابتدایی",
image: bookImage,
},
{
name: "کتاب آموزشی علوم تجربی",
grade: "پایه ششم ابتدایی",
image: bookImage,
},
],
};

@ -6,6 +6,8 @@ import Button from "../../../../components/Button";
import StarRating from "../../../../components/StarRating"; import StarRating from "../../../../components/StarRating";
import ProductImages from "../../../../components/ProductImage"; import ProductImages from "../../../../components/ProductImage";
import ProductStatusCard from "../../../../components/ProductStatusCard"; import ProductStatusCard from "../../../../components/ProductStatusCard";
import ProductTab from "../../../../components/ProductTab";
import Table from "../../../Video/components/Desktop/Table";
//assets //assets
import arrow from "../../../../assets/icons/dropdown-blue.svg"; import arrow from "../../../../assets/icons/dropdown-blue.svg";
@ -13,7 +15,7 @@ import arrow from "../../../../assets/icons/dropdown-blue.svg";
export const ProductOverAll = ({ book, grades, isDark, loading }) => { export const ProductOverAll = ({ book, grades, isDark, loading }) => {
const [type, setType] = useState("1"); const [type, setType] = useState("1");
return ( return (
<div className="w-full"> <div className="w-full flex flex-col">
<header className={`w-full flex flex-row justify-between gap-5`}> <header className={`w-full flex flex-row justify-between gap-5`}>
<ProductImages images={book?.fileIds} /> <ProductImages images={book?.fileIds} />
<div className="flex flex-col w-1/2 divide-y divide-solid divide-gray-200"> <div className="flex flex-col w-1/2 divide-y divide-solid divide-gray-200">
@ -29,7 +31,8 @@ export const ProductOverAll = ({ book, grades, isDark, loading }) => {
<StarRating value={book?.rate || 4} /> <StarRating value={book?.rate || 4} />
</div> </div>
<div className="p-2 border-0 border-solid border-r border-gray-100 text-sm text-gray-400"> <div className="p-2 border-0 border-solid border-r border-gray-100 text-sm text-gray-400">
بیش از {book?.product[type]?.suggestedCounter} نفر امتیاز داده اند بیش از {book?.product[type]?.suggestedCounter} نفر امتیاز داده
اند
</div> </div>
</div> </div>
</div> </div>
@ -96,7 +99,11 @@ export const ProductOverAll = ({ book, grades, isDark, loading }) => {
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 flex-row items-center justify-center"
> >
مشاهده دوره ویدیویی این محصول مشاهده دوره ویدیویی این محصول
<img src={arrow} alt="" className="mr-2 transform rotate-90 w-5" /> <img
src={arrow}
alt=""
className="mr-2 transform rotate-90 w-5"
/>
</Link> </Link>
</div> </div>
</div> </div>
@ -113,6 +120,34 @@ export const ProductOverAll = ({ book, grades, isDark, loading }) => {
/> />
</div> </div>
</header> </header>
{book?.product[type]?.properties?.length > 0 && (
<ProductTab
tabs={[
{
title: "مشخصات",
components: (
<Table specifications={book?.product[type]?.properties} />
),
},
{
title: "نقد و بررسی",
components: (
<div className="bg-gray-100 rounded-md mt-4 w-full flex justify-center items-center h-40 text-green4F text-tiny">
این بخش فعلا قابل دسترسی نیست.
</div>
),
},
{
title: "پرسش و پاسخ",
components: (
<div className="bg-gray-100 rounded-md mt-4 w-full flex justify-center items-center h-40 text-green4F text-tiny">
این بخش فعلا قابل دسترسی نیست.
</div>
),
},
]}
/>
)}
</div> </div>
); );
}; };

@ -2,12 +2,10 @@ import React, { useEffect } from "react";
//components //components
import ProductOverAll from "./ProductOverAll"; import ProductOverAll from "./ProductOverAll";
import ProductTab from "../../../components/ProductTab";
import ProductSuggestions from "../../../components/ProductSuggestion"; import ProductSuggestions from "../../../components/ProductSuggestion";
import Rate from "../Rate"; import Rate from "../Rate";
import Comments from "../../../components/Comments"; import Comments from "../../../components/Comments";
import QandA from "../../../components/QandA"; import QandA from "../../../components/QandA";
import Table from "../../Video/components/Desktop/Table";
const DesktopProductLayout = () =>{ const DesktopProductLayout = () =>{
@ -17,30 +15,6 @@ const DesktopProductLayout = () =>{
return ( return (
<div className="w-11/12 flex flex-col overflow-y-hidden mt-3 mb-64 items-center"> <div className="w-11/12 flex flex-col overflow-y-hidden mt-3 mb-64 items-center">
<ProductOverAll /> <ProductOverAll />
<ProductTab
tabs={[
{
title: "مشخصات",
components: <Table />,
},
{
title: "نقد و بررسی",
components: (
<div className="bg-gray-100 rounded-md mt-4 w-full flex justify-center items-center h-40 text-green4F text-tiny">
این بخش فعلا قابل دسترسی نیست.
</div>
),
},
{
title: "پرسش و پاسخ",
components: (
<div className="bg-gray-100 rounded-md mt-4 w-full flex justify-center items-center h-40 text-green4F text-tiny">
این بخش فعلا قابل دسترسی نیست.
</div>
),
},
]}
/>
<div className="w-full"> <div className="w-full">
<ProductSuggestions /> <ProductSuggestions />
</div> </div>

@ -7,8 +7,15 @@ import Product from "../../../../components/Product";
import VodProduct from "../../../../components/VodProduct"; import VodProduct from "../../../../components/VodProduct";
import Loading from "../../../../components/Loading"; import Loading from "../../../../components/Loading";
import { book, publicApi } from "../../../../redux/actions"; import { book, publicApi } from "../../../../redux/actions";
import moment from "jalali-moment";
export const Main = ({ books, grades, sortMethods, filterOptions }) => { export const Main = ({
books,
grades,
sortMethods,
filterOptions,
setFilterOptions,
}) => {
const [filterLoading, setFilterLoading] = useState(false); const [filterLoading, setFilterLoading] = useState(false);
useEffect(() => { useEffect(() => {
@ -27,6 +34,7 @@ export const Main = ({ books, grades, sortMethods, filterOptions }) => {
let byGradeFilter; let byGradeFilter;
let bySubjectFilter; let bySubjectFilter;
let byAvailableFilter; let byAvailableFilter;
let bySortFilter;
if (grade) { if (grade) {
byGradeFilter = books?.filter((book) => grades[book?.gradeId] === grade); byGradeFilter = books?.filter((book) => grades[book?.gradeId] === grade);
} else { } else {
@ -48,8 +56,27 @@ export const Main = ({ books, grades, sortMethods, filterOptions }) => {
} else { } else {
byAvailableFilter = bySubjectFilter; byAvailableFilter = bySubjectFilter;
} }
if (sort) {
if (sort === "ارزان ترین") {
bySortFilter = byAvailableFilter?.sort(
(a, b) => a.product[type].price - b.product[type].price
);
} else if (sort === "محبوب ترین") {
bySortFilter = byAvailableFilter?.sort(
(a, b) => a.product[type].rate - b.product[type].rate
);
} else if (sort === "جدیدترین") {
bySortFilter = byAvailableFilter?.sort(
(a, b) => moment(a.createdAt) - moment(b.createdAt)
);
} else {
bySortFilter = byAvailableFilter;
}
} else {
bySortFilter = byAvailableFilter;
}
return type === 2 return type === 2
? byAvailableFilter?.map((item, index) => ( ? bySortFilter?.map((item, index) => (
<VodProduct <VodProduct
video={item} video={item}
key={index} key={index}
@ -58,7 +85,7 @@ export const Main = ({ books, grades, sortMethods, filterOptions }) => {
grades={grades} grades={grades}
/> />
)) ))
: byAvailableFilter?.map((product, index) => ( : bySortFilter?.map((product, index) => (
<> <>
{(productType ? productType === "کتاب دیجیتال" : true) && ( {(productType ? productType === "کتاب دیجیتال" : true) && (
<Link <Link
@ -95,9 +122,12 @@ export const Main = ({ books, grades, sortMethods, filterOptions }) => {
}; };
return ( return (
<div className="flex flex-col w-3/4 relative pb-20 min-h-screen" style={{minWidth: 'calc(100% * 3 / 4)'}}> <div
className="flex flex-col w-3/4 pb-20 min-h-screen"
style={{ minWidth: "calc(100% * 3 / 4)" }}
>
<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 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 mx-2"> <div className="flex text-sm items-center mr-2 ml-4">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="24" width="24"
@ -163,30 +193,41 @@ export const Main = ({ books, grades, sortMethods, filterOptions }) => {
{sortMethods?.map((item, index) => ( {sortMethods?.map((item, index) => (
<li <li
key={index} key={index}
className="text-sm rounded text-black py-2 px-3 transition-all duration-700 hover:bg-greenBA hover:bg-opacity-5 hover:text-greenBA cursor-pointer" className={`text-sm rounded text-black py-2 px-3 transition-all font-semibold duration-300 cursor-pointer ${
filterOptions.sort === item ? "bg-greenBA text-white" : ""
}`}
onClick={() =>
filterOptions.sort !== item
? setFilterOptions({ ...filterOptions, sort: item })
: setFilterOptions({ ...filterOptions, sort: null })
}
> >
{item} {item}
</li> </li>
))} ))}
</ul> </ul>
</div> </div>
<div className="flex flex-col w-full relative">
{filterLoading && (
<div
className="w-full flex justify-center items-center bg-white bg-opacity-70 z-20 backdrop-filter backdrop-blur-xl absolute left-0 top-0"
style={{ height: "calc(100vh - 180px)" }}
>
<Loading size={4} color="bg-green-400" />
</div>
)}
{(filterOptions?.productType {(filterOptions?.productType
? filterOptions.productType === "دوره ویدئویی" ? filterOptions.productType === "دوره ویدئویی"
: true) && ( : true) && (
<ScrollingCarousel className="py-3 max-w-full">{Items(2)}</ScrollingCarousel> <ScrollingCarousel className="py-3 max-w-full">
{Items(2)}
</ScrollingCarousel>
)} )}
<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"> <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)} {Items(1)}
</div> </div>
{filterLoading && (
<div
className="w-full flex justify-center items-center bg-white bg-opacity-20 backdrop-filter backdrop-blur-xl absolute left-0 top-0"
style={{ height: "calc(100vh - 80px)" }}
>
<Loading size={4} color="bg-green-400" />
</div> </div>
)}
</div> </div>
); );
}; };
@ -205,6 +246,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = { const mapDispatchToProps = {
getList: book.list, getList: book.list,
setHeaderOptions: publicApi.setHeaderOptions, setHeaderOptions: publicApi.setHeaderOptions,
setFilterOptions: book.setFilterOptions,
}; };
export default connect(mapStateToProps, mapDispatchToProps)(Main); export default connect(mapStateToProps, mapDispatchToProps)(Main);

@ -0,0 +1,14 @@
import React from 'react'
import { connect } from 'react-redux'
export const Profile = ({}) => {
return (
<div>Profile</div>
)
}
const mapStateToProps = (state) => ({})
const mapDispatchToProps = {}
export default connect(mapStateToProps, mapDispatchToProps)(Profile)

@ -10,14 +10,14 @@ function Code({ codeId, setCodeId, userId, factorId }) {
} }
return ( return (
<form className="flex w-full flex-row border border-blueC0 border-solid rounded-md mt-3 mb-4 overflow-hidden lg:w-2/5 lg:mt-5"> <div className="flex w-full flex-row border border-blueC0 border-solid rounded-md mt-3 mb-4 overflow-hidden lg:w-2/5 lg:mt-5">
<input <input
type="text" type="text"
className="border-0 flex-1 text-right pr-3 font-medium text-tiny dark:bg-gray2077 placeholder:text-blue5F dark:text-white outline-none lg:text-base lg:font-bold" className="border-0 flex-1 text-right pr-3 font-medium text-tiny dark:bg-gray2077 placeholder:text-blue5F dark:text-white outline-none lg:text-base lg:font-bold"
placeholder={"کد تخفیف دارید ؟"} placeholder={"کد تخفیف دارید ؟"}
/> />
<button className={"py-3 px-4 lg:py-4 text-tiny bg-blueC0 text-white border border-blueC0 border-solid lg:font-bold"} onClick={setOff}>ثبت کد</button> <button className={"py-3 px-4 lg:py-4 text-tiny bg-blueC0 text-white border border-blueC0 border-solid lg:font-bold"} onClick={() => setOff()}>ثبت کد</button>
</form> </div>
); );
} }

@ -14,19 +14,19 @@ const persian = {
const Table = ({ specifications }) => { const Table = ({ specifications }) => {
return ( return (
<ul className="w-full"> <ul className="w-full">
{Object.keys(specifications).map((specification, index) => ( {specifications?.map((property, index) => (
<li className="flex my-3 cursor-pointer group" key={index}> <li className="flex my-3 cursor-pointer group" key={index}>
<div <div
className=" bg-grayF9 rounded px-3 py-4 ml-2 text-greenBA text-sm group-hover:bg-blueC0 group-hover:bg-opacity-10" className=" bg-grayF9 rounded px-3 py-4 ml-2 text-greenBA text-sm group-hover:bg-blueC0 group-hover:bg-opacity-10"
style={{ flex: 2 }} style={{ flex: 2 }}
> >
{persian[specification]} {property.description}
</div> </div>
<div <div
className="bg-grayF9 rounded px-3 py-4 text-sm group-hover:bg-blueC0 group-hover:bg-opacity-10" className="bg-grayF9 rounded px-3 py-4 text-sm group-hover:bg-blueC0 group-hover:bg-opacity-10"
style={{ flex: 8 }} style={{ flex: 8 }}
> >
{specifications[specification]} {property.value}
</div> </div>
</li> </li>
))} ))}

@ -5,12 +5,15 @@ import { Link } from "react-router-dom";
import { publicApi, userProduct } from "../../redux/actions"; import { publicApi, userProduct } from "../../redux/actions";
import location from "../../utils/location"; import location from "../../utils/location";
import separate from "../../utils/separate"; import separate from "../../utils/separate";
//components
import Season from "./components/Season"; import Season from "./components/Season";
import Videos from "./components/Desktop/Videos"; import Videos from "./components/Desktop/Videos";
import StarRating from "../../components/StarRating"; import StarRating from "../../components/StarRating";
import Button from "../../components/Button"; import Button from "../../components/Button";
import ProductTab from "../../components/ProductTab"; import ProductTab from "../../components/ProductTab";
import Table from "./components/Desktop/Table"; import Table from "./components/Desktop/Table";
import Comments from "../../components/Comments";
//assets //assets
import tickIcon from "../../components/ProductStatusCard/tick-circle.svg"; import tickIcon from "../../components/ProductStatusCard/tick-circle.svg";
@ -117,7 +120,13 @@ function Video({
}, },
{ {
title: "مشخصات", title: "مشخصات",
components: <Table />, components: (
<Table
specifications={
book?.product[2]?.properties.length > 0 || []
}
/>
),
}, },
{ {
title: "نقد و بررسی", title: "نقد و بررسی",
@ -144,35 +153,39 @@ function Video({
<h1 className="text-blue5F mb-3 font-semibold text-xl dark:text-white"> <h1 className="text-blue5F mb-3 font-semibold text-xl dark:text-white">
{"دوره ویدئویی" + " " + book?.product[2]?.name} {"دوره ویدئویی" + " " + book?.product[2]?.name}
</h1> </h1>
<div className="text-blueC0 text-sm dark:text-greenBA"> <div className="text-blueC0 text-tiny dark:text-greenBA font-bold">
{"پایه" + " " + grades[book?.gradeId]} {"پایه" + " " + grades[book?.gradeId]}
</div> </div>
<div className="flex justify-end"> <div className="flex justify-end">
<div className="p-2"> <div className="p-2">
<StarRating value={book?.rate || 4} /> <StarRating value={book?.product[2]?.rate || 4} />
</div> </div>
<div className="p-2 border-0 border-solid border-r border-gray-100 text-sm text-gray-400"> <div className="p-2 border-0 border-solid border-r border-gray-100 text-sm text-gray-400">
بیش از 160 نفر امتیاز داده اند بیش از {book?.product[2]?.suggestedCounter} نفر امتیاز داده اند
</div> </div>
</div> </div>
</div> </div>
<div className="bg-grayF9 w-full flex flex-col rounded-md divide-y divide-solid divide-gray-200 mb-4"> <div className="bg-grayF9 w-full flex flex-col rounded-md divide-y divide-solid divide-gray-200 mb-4 px-4">
<div className="flex flex-row justify-center items-center w-full gap-5 my-5"> <div className="flex flex-row items-center w-full gap-5 my-5">
<img src={tickIcon} alt="" className="w-9" /> <img src={tickIcon} alt="" className="w-9" />
<p className="text-blue52 text-sm font-light">{`توسعه خرید توسط ${ <p className="text-blue52 text-sm font-light">{`توصیه خرید توسط ${
book?.recommendedPeople || 4234 book?.product[2]?.suggestedCounter
} نفر`}</p> } نفر`}</p>
</div> </div>
<div className="flex flex-col w-full py-4 px-4"> <div className="flex flex-col w-full py-4 px-4">
<div className="flex flex-row items-center justify-center gap-2"> <div className="flex flex-row items-center justify-center gap-2">
<strong className="text-blueC0 text-xl"> <strong className="text-blueC0 text-5xl">
{separate(book?.product[2]?.price)} {separate(book?.product[2]?.price)}
</strong> </strong>
<span className="text-sm text-gray-500">تومان</span> <span className="text-sm text-gray-500">تومان</span>
</div> </div>
{book?.product[2]?.fakePrice ? (
<p className="text-gray-500 text-xs text-center mt-2 mb-4"> <p className="text-gray-500 text-xs text-center mt-2 mb-4">
با خرید این کالا 540.000 صرفه جویی کنید با خرید این کالا 540.000 صرفه جویی کنید
</p> </p>
) : (
<div className="mb-4"></div>
)}
<Button <Button
title="اضافه کردن به سبد خرید" title="اضافه کردن به سبد خرید"
backgroundColor={isDark ? "bg-blueC0" : "bg-blueC0"} backgroundColor={isDark ? "bg-blueC0" : "bg-blueC0"}
@ -204,6 +217,7 @@ function Video({
</Link> </Link>
</div> </div>
</header> </header>
<Comments indent={false} />
</div> </div>
); );
} }

Loading…
Cancel
Save