diff --git a/package.json b/package.json
index 7d9f7f9..8e8924f 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"@testing-library/user-event": "^12.1.10",
"@trendyol-js/react-carousel": "^2.0.0",
"axios": "^0.24.0",
+ "jalali-moment": "^3.3.10",
"jol-player": "^2.5.0",
"lodash": "^4.17.21",
"react": "^17.0.2",
diff --git a/src/App.js b/src/App.js
index 56e18d6..3fada8a 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,5 +1,7 @@
import "./App.scss";
import { Provider } from "react-redux";
+import { ToastContainer } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
import store from "./redux/store";
import Router from "./router";
@@ -7,6 +9,18 @@ function App({theme}) {
return (
+
);
}
diff --git a/src/App.scss b/src/App.scss
index c612a88..fee89fa 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -91,3 +91,7 @@
max-width: 1480px;
}
}
+
+.Toastify *{
+ font-size: 13px;
+}
diff --git a/src/assets/icons/arrow-left-green.png b/src/assets/icons/arrow-left-green.png
new file mode 100644
index 0000000..4d07993
Binary files /dev/null and b/src/assets/icons/arrow-left-green.png differ
diff --git a/src/assets/icons/arrow-left.png b/src/assets/icons/arrow-left.png
new file mode 100644
index 0000000..70d90d4
Binary files /dev/null and b/src/assets/icons/arrow-left.png differ
diff --git a/src/assets/icons/bottom-home-active.svg b/src/assets/icons/bottom-home-active.svg
new file mode 100644
index 0000000..b5aa911
--- /dev/null
+++ b/src/assets/icons/bottom-home-active.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/icons/bottom-products-deactive.svg b/src/assets/icons/bottom-products-deactive.svg
new file mode 100644
index 0000000..875ff38
--- /dev/null
+++ b/src/assets/icons/bottom-products-deactive.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/assets/icons/bottom-profile-deactive.svg b/src/assets/icons/bottom-profile-deactive.svg
new file mode 100644
index 0000000..8a9ae83
--- /dev/null
+++ b/src/assets/icons/bottom-profile-deactive.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/icons/bottom-test-deactive.svg b/src/assets/icons/bottom-test-deactive.svg
new file mode 100644
index 0000000..f040018
--- /dev/null
+++ b/src/assets/icons/bottom-test-deactive.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/assets/icons/bottom-video-deactive.svg b/src/assets/icons/bottom-video-deactive.svg
new file mode 100644
index 0000000..4250b15
--- /dev/null
+++ b/src/assets/icons/bottom-video-deactive.svg
@@ -0,0 +1,10 @@
+
diff --git a/src/assets/icons/dropdown.png b/src/assets/icons/dropdown.png
new file mode 100644
index 0000000..7d05d91
Binary files /dev/null and b/src/assets/icons/dropdown.png differ
diff --git a/src/components/BottomNavigation/index.js b/src/components/BottomNavigation/index.js
new file mode 100644
index 0000000..4de876c
--- /dev/null
+++ b/src/components/BottomNavigation/index.js
@@ -0,0 +1,91 @@
+import React, { useState } from "react";
+import { Link } from "react-router-dom";
+import { connect } from "react-redux";
+import activeHomeIcon from "../../assets/icons/bottom-home-active.svg";
+import deactiveProductsIcon from "../../assets/icons/bottom-products-deactive.svg";
+import deactiveVideoIcon from "../../assets/icons/bottom-video-deactive.svg";
+import deactiveProfileIcon from "../../assets/icons/bottom-profile-deactive.svg";
+import deactiveTestIcon from "../../assets/icons/bottom-test-deactive.svg";
+
+export const BottomNavigation = ({ pages, isDark }) => {
+ const [activeLink, setActiveLink] = useState("/");
+
+ const Tab = ({ page }) => {
+ return (
+ setActiveLink(page.link)}
+ >
+
+
+ {page.name}
+
+
+ );
+ };
+ return (
+ <>
+
+ >
+ );
+};
+
+const mapStateToProps = (state) => ({
+ isDark: state.publicApi.isDark,
+});
+
+const mapDispatchToProps = {};
+
+export default connect(mapStateToProps, mapDispatchToProps)(BottomNavigation);
+
+BottomNavigation.defaultProps = {
+ pages: [
+ {
+ id: 0,
+ name: "صفحه اصلی",
+ link: "/",
+ activeIcon: activeHomeIcon,
+ deactiveIcon: "",
+ },
+ {
+ id: 1,
+ name: "محصولات",
+ link: "/products",
+ activeIcon: "",
+ deactiveIcon: deactiveProductsIcon,
+ },
+ {
+ id: 2,
+ name: "ویدئو",
+ link: "/vod",
+ activeIcon: "",
+ deactiveIcon: deactiveVideoIcon,
+ },
+ {
+ id: 3,
+ name: "آزمون",
+ link: "/test",
+ activeIcon: "",
+ deactiveIcon: deactiveTestIcon,
+ },
+ {
+ id: 4,
+ name: "حساب کاربری",
+ link: "/profile",
+ activeIcon: "",
+ deactiveIcon: deactiveProfileIcon,
+ },
+ ],
+};
diff --git a/src/components/Button/index.js b/src/components/Button/index.js
index ca558a3..ac65d92 100644
--- a/src/components/Button/index.js
+++ b/src/components/Button/index.js
@@ -7,6 +7,7 @@ export default function Button({
border,
width,
bgOpacity,
+ onClick,
}) {
return (
diff --git a/src/components/Input/danger.png b/src/components/Input/danger.png
new file mode 100644
index 0000000..0bb622e
Binary files /dev/null and b/src/components/Input/danger.png differ
diff --git a/src/components/Input/index.js b/src/components/Input/index.js
new file mode 100644
index 0000000..004f9eb
--- /dev/null
+++ b/src/components/Input/index.js
@@ -0,0 +1,171 @@
+import React, { useState } from "react";
+import _ from "lodash";
+import "./index.scss";
+
+import tick from "./tick.png";
+import danger from "./danger.png";
+
+const langDetector = (lang, option1, option2) => {
+ return lang === "fa" ? option1 : option2;
+};
+
+const inputStatusHandler = (value, focus, status, primary, success, danger) => {
+ if (!focus) {
+ return "";
+ } else {
+ if (!value) {
+ return primary;
+ } else {
+ if (status) {
+ return success;
+ } else {
+ return danger;
+ }
+ }
+ }
+};
+
+export default function Input(props) {
+ const [value, setValue] = useState("");
+ const [focusToggle, setFocusToggle] = useState(false);
+
+ const { lang, theme, inputMode, label, status, maxLength, message } = props;
+
+ const onChange = (val) => {
+ setValue(val);
+ };
+
+ return (
+
+
+
onChange(e.target.value)}
+ value={value}
+ onFocus={() => setFocusToggle(true)}
+ onBlur={() => !value ? setFocusToggle(false) : setFocusToggle(true)}
+ maxLength={maxLength}
+ />
+ {!status && value && (
+
+ )}
+ {status && value && (
+
+ )}
+
+ {value && !status && (
+
+ {message}
+
+ )}
+ {value && (
+
+ {value.length + "/" + maxLength}
+
+ )}
+
+ );
+}
+
+Input.defaultProps = {
+ lang : 'fa',
+ inputMode : 'numeric',
+ label : 'label',
+ status : '',
+ maxLength : '',
+ message : '',
+}
\ No newline at end of file
diff --git a/src/components/Input/index.scss b/src/components/Input/index.scss
new file mode 100644
index 0000000..9b0bf19
--- /dev/null
+++ b/src/components/Input/index.scss
@@ -0,0 +1,60 @@
+$primary: #196EC0;
+$gray: #dbdbdb;
+$danger: #E00A0A;
+$success: #23C933;
+
+.input {
+ &__labelFocus{
+ top: 0px !important;
+ font-size: 9px !important;
+ color: $primary !important;
+ }
+ &__labelDanger{
+ top: 0px !important;
+ font-size: 9px !important;
+ color: $danger !important;
+ }
+ &__labelSuccess{
+ top: 0px !important;
+ font-size: 9px !important;
+ color: $success !important;
+ }
+
+
+ &__inputActive{
+ border-color: $primary !important;
+ }
+ &__inputSuccess{
+ border-color: $success !important;
+ }
+ &__inputDanger{
+ border-color: $danger !important;
+ }
+
+ &__message{
+ &Success{
+ color: $success;
+ }
+ &Danger{
+ color: $danger;
+ }
+ }
+ &__length{
+ &Success{
+ color: $success;
+ }
+ &Danger{
+ color: $danger;
+ }
+ }
+}
+
+.en {
+ direction: ltr;
+ text-align: left;
+}
+
+.fa {
+ direction: rtl;
+ text-align: right;
+}
\ No newline at end of file
diff --git a/src/components/Input/tick.png b/src/components/Input/tick.png
new file mode 100644
index 0000000..805f74a
Binary files /dev/null and b/src/components/Input/tick.png differ
diff --git a/src/components/Navbar/index.js b/src/components/Navbar/index.js
index 757a8cb..2aae4ce 100644
--- a/src/components/Navbar/index.js
+++ b/src/components/Navbar/index.js
@@ -12,7 +12,7 @@ import arBlueIcon from "../../assets/icons/ar-blue.svg";
import hamburgerIcon from "../../assets/icons/hamburger.svg";
import hamburgerBlueIcon from "../../assets/icons/hamburger-blue.svg";
-function Navbar({ pages, isDark, isLogin }) {
+function Navbar({ pages, isDark}) {
const [top, setTop] = useState(false);
useEffect(() => {
if (window.scrollY === 0) {
@@ -80,57 +80,55 @@ function Navbar({ pages, isDark, isLogin }) {
>
- {isLogin && (
-
-
-
-
-
-
-
-
- )}
+
+
+
+
+
+
+
+
+
- {/* portrait end */}
+ ){/* portrait end */}
);
}
const mapStateToProps = (state) => ({
isDark: state.publicApi.isDark,
- isLogin: state.user.status,
});
export default connect(mapStateToProps, {})(Navbar);
diff --git a/src/components/PrivateRouter/index.js b/src/components/PrivateRouter/index.js
new file mode 100644
index 0000000..017d7c6
--- /dev/null
+++ b/src/components/PrivateRouter/index.js
@@ -0,0 +1,32 @@
+import React from "react";
+import { Route, Redirect } from "react-router-dom";
+import { connect } from "react-redux";
+
+const PrivateRouter = ({
+ component: Component,
+ restricted,
+ status,
+ customPage,
+ ...rest
+}) => {
+ return (
+
+ restricted ? (
+
+ ) : (
+
+
+ )
+ }
+ />
+ );
+};
+
+export default connect(
+ (state) => ({
+ status: state.user.status,
+ }),
+ {}
+)(PrivateRouter);
diff --git a/src/components/Textarea/index.js b/src/components/Textarea/index.js
new file mode 100644
index 0000000..72573ce
--- /dev/null
+++ b/src/components/Textarea/index.js
@@ -0,0 +1,21 @@
+import React from "react";
+import _ from "lodash";
+
+export default function Textarea({ placeholder, theme }) {
+ const light = theme === "light";
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/src/components/Textarea/index.scss b/src/components/Textarea/index.scss
new file mode 100644
index 0000000..5d4858b
--- /dev/null
+++ b/src/components/Textarea/index.scss
@@ -0,0 +1,63 @@
+.custom-textarea {
+ width: 100%;
+ padding: 10px 12px;
+ border-radius: 10px;
+
+ margin-top: 10px;
+ &-light {
+ border: 1px solid $green;
+ background-color: white;
+ color: $gray5;
+ }
+ &-dark {
+ border: 1px solid $gray2;
+ background-color: black;
+ color: white;
+ }
+ &::placeholder {
+ color: #a2a2a2;
+ }
+ &:focus {
+ border: 1px solid $green1;
+ outline: none;
+ &::placeholder {
+ color: $green1;
+ }
+ }
+}
+
+@media screen and (min-width: 1441px) {
+ .custom-textarea {
+ font-size: 16px;
+ &::placeholder {
+ font-size: 16px;
+ }
+ }
+}
+
+@media screen and (min-width: 1008px) and (max-width: 1440px) {
+ .custom-textarea {
+ font-size: calc(100vw / 110);
+ &::placeholder {
+ font-size: calc(100vw / 110);
+ }
+ }
+}
+
+@media screen and (min-width: 641px) and (max-width: 1007px) {
+ .custom-textarea {
+ font-size: calc(100vw / 40);
+ &::placeholder {
+ font-size: calc(100vw / 40);
+ }
+ }
+}
+
+@media screen and (max-width: 640px) {
+ .custom-textarea {
+ font-size: calc(100vw / 30);
+ &::placeholder {
+ font-size: calc(100vw / 30);
+ }
+ }
+}
diff --git a/src/components/Timer/index.js b/src/components/Timer/index.js
new file mode 100644
index 0000000..012062b
--- /dev/null
+++ b/src/components/Timer/index.js
@@ -0,0 +1,84 @@
+import { Component } from "react";
+
+const maxDesktopSize = 1250;
+const maxMobileSize = 550;
+
+const fontSize = {
+ desktop: {
+ div: window.innerWidth > maxDesktopSize ? 12 : window.innerWidth / 95,
+ },
+ mobile: {
+ div: window.innerWidth > maxMobileSize ? 12 : window.innerWidth / 30,
+ },
+};
+export default class Timer extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ time: {
+ h: 0,
+ m: 0,
+ s: 0,
+ },
+ seconds : props.seconds,
+ flag: true,
+ };
+ this.timer = 0;
+ this.startTimer = this.startTimer.bind(this);
+ this.countDown = this.countDown.bind(this);
+ }
+
+ secondsToTime(secs) {
+ let hours = Math.floor(secs / (60 * 60));
+
+ let divisor_for_minutes = secs % (60 * 60);
+ let minutes = Math.floor(divisor_for_minutes / 60);
+
+ let divisor_for_seconds = divisor_for_minutes % 60;
+ let seconds = Math.ceil(divisor_for_seconds);
+
+ let obj = {
+ h: hours,
+ m: minutes,
+ s: seconds,
+ };
+ return obj;
+ }
+
+ componentDidMount() {
+ this.startTimer();
+ let timeLeftVar = this.secondsToTime(this.state.seconds);
+ this.setState({ time: timeLeftVar });
+ }
+
+ startTimer() {
+ if (this.timer === 0 && this.state.seconds > 0) {
+ this.timer = setInterval(this.countDown, 1000);
+ }
+ }
+
+ countDown = async () => {
+ // Remove one second, set state so a re-render happens.
+ let seconds = this.state.seconds - 1;
+ this.setState({
+ time: this.secondsToTime(seconds),
+ seconds: seconds,
+ });
+ if (seconds === 0) {
+ this.props.refresh(true);
+ }
+ };
+
+ componentWillUnmount() {
+ clearInterval(this.timer);
+ }
+ render() {
+ return (
+ <>
+
+ {this.state.time ? this.state.time.m : ''}:{this.state.time ? this.state.time.s : ''}
+
+ >
+ );
+ }
+}
diff --git a/src/components/Timer/index.scss b/src/components/Timer/index.scss
new file mode 100644
index 0000000..f1724eb
--- /dev/null
+++ b/src/components/Timer/index.scss
@@ -0,0 +1,8 @@
+.timer {
+ flex-direction: row;
+ direction: rtl !important;
+ margin-right: 10px;
+ margin-left: 10px;
+ color: $green2;
+ font-family: numeralLight;
+}
diff --git a/src/redux/actions/userFactor.js b/src/redux/actions/userFactor.js
index 16424e9..a46962c 100644
--- a/src/redux/actions/userFactor.js
+++ b/src/redux/actions/userFactor.js
@@ -1,5 +1,29 @@
import proxy from "../proxy";
const userFactor = {
+ //dnvn
+ list:
+ (data = {}) =>
+ async (dispatch) =>
+ await proxy.get("userFactor/list", data, { dispatch }),
+ payment:
+ (data = {}, data2 = {}) =>
+ async (dispatch) => {
+ await proxy.post("userFactor/payment", data, { dispatch });
+ },
+ add:
+ (data = {}, data2 = {}) =>
+ async (dispatch) => {
+ await proxy.post("userFactor/add", data, { dispatch });
+ await proxy.get("userFactor/list", data2, { dispatch });
+ },
+ del:
+ (data = {}, data2 = {}) =>
+ async (dispatch) => {
+ await proxy.delete("userFactor/delete", data);
+ await proxy.get("userFactor/list", data2, { dispatch });
+ },
+
+ //vod
payment:
(data1 = {}, data2 = {}) =>
async (dispatch) => {
diff --git a/src/redux/actions/userProduct.js b/src/redux/actions/userProduct.js
index 677c191..2436d7f 100644
--- a/src/redux/actions/userProduct.js
+++ b/src/redux/actions/userProduct.js
@@ -1,9 +1,33 @@
import proxy from "../proxy";
const userProduct = {
- addVOD:
+ list:
+ (data = {}) =>
+ async (dispatch) => {
+ await proxy.get("userProduct/list", data, { dispatch });
+ },
+ info:
(data = {}) =>
async (dispatch) =>
- await proxy.post("userProduct/addVOD", data, { dispatch }),
+ await proxy.get("userProduct/info", data, { dispatch }),
+ update:
+ (data = {}, data2 = {}) =>
+ async (dispatch) => {
+ await proxy.put("userProduct/update", data);
+ await proxy.get("userProduct/list", data2, { dispatch });
+ },
+ add:
+ (data = {}, data2 = {}, data3 = {}) =>
+ async (dispatch) => {
+ await proxy.post("userProduct/add", data, { dispatch });
+ await proxy.get("userProduct/list", data2, { dispatch });
+ await proxy.get("userFactor/info", data3, { dispatch });
+ },
+ del:
+ (data = {}, data2 = {}) =>
+ async (dispatch) => {
+ await proxy.delete("userProduct/delete", data);
+ await proxy.get("userProduct/list", data2, { dispatch });
+ },
};
-export default userProduct;
\ No newline at end of file
+export default userProduct;
diff --git a/src/redux/reducers/scroll.js b/src/redux/reducers/scroll.js
index cd022e4..5dfe9f0 100644
--- a/src/redux/reducers/scroll.js
+++ b/src/redux/reducers/scroll.js
@@ -24,9 +24,11 @@ const initialState = {
2.5 * height
),
page2VideoPosition:
- prevScroll > 4 * height
+ window.scrollY > 4 * height
? scroll.videoLinearFormula(4 * height)
- : scroll.videoLinearFormula(prevScroll),
+ : window.scrollY > height
+ ? scroll.videoLinearFormula(window.scrollY)
+ : null,
page2VideoTopPosition:
prevScroll > 3 * height
? scroll.linearFormula(3 * height, 70, 50, 2.8 * height, 3 * height)
@@ -154,7 +156,11 @@ export default function scrollAction(state = initialState, action) {
},
};
case "scroll/page3/top":
- return { ...state, page3TopPosition: scroll.homeScrollHandler(4), testTranslateY : -101 };
+ return {
+ ...state,
+ page3TopPosition: scroll.homeScrollHandler(4),
+ testTranslateY: -101,
+ };
case "scroll/page3/testTranslateY":
return {
...state,
@@ -165,10 +171,14 @@ export default function scrollAction(state = initialState, action) {
6.3 * height,
7 * height
),
- page3TopPosition : 0,
+ page3TopPosition: 0,
};
case "scroll/page4/top":
- return { ...state, page4TopPosition: scroll.homeScrollHandler(5), page3TestTranslateY : 100 };
+ return {
+ ...state,
+ page4TopPosition: scroll.homeScrollHandler(5),
+ page3TestTranslateY: 100,
+ };
default:
return state;
}
diff --git a/src/redux/reducers/user.js b/src/redux/reducers/user.js
index b3a072e..ec575ce 100644
--- a/src/redux/reducers/user.js
+++ b/src/redux/reducers/user.js
@@ -1,7 +1,7 @@
import proxy from "../proxy";
import { toast } from "react-toastify";
const initialState = {
- status: proxy.status() || true,
+ status: proxy.status() || false,
loading: false,
error: null,
list: null,
diff --git a/src/redux/reducers/userFactor.js b/src/redux/reducers/userFactor.js
index 88db2ef..ae95fa3 100644
--- a/src/redux/reducers/userFactor.js
+++ b/src/redux/reducers/userFactor.js
@@ -11,16 +11,34 @@ const initialState = {
export default function userFactor(state = initialState, action) {
let { type, data } = action;
switch (type) {
- case "userFactor/myList":
- return { ...state, loading: false, list: data, error: null };
+ //dnvn
+ case "userFactor/list":
+ const checkEmpty = data.filter(
+ (item) => item.condition === 2 && item.product.productType === (1 || 3)
+ );
+ return {
+ ...state,
+ loading: false,
+ list: data,
+ checkEmpty: checkEmpty.length > 0 ? false : true,
+ error: null,
+ };
case "userFactor/info":
return { ...state, loading: false, info: data, error: null };
+ case "userFactor/add":
+ toast.success("درخواست شما با موفقیت انجام شد.");
+ return { ...state, loading: false, error: null, sum: data.payPrice };
+ case "userFactor/delete":
+ return { ...state, loading: false, error: null };
+ case "userFactor/payment":
+ window.location.replace(data);
+ return { ...state, loading: false, error: null };
+ //vod
+ case "userFactor/myList":
+ return { ...state, loading: false, list: data, error: null };
case "userFactor/update":
toast.success("درخواست شما با موفقیت انجام شد.");
return { ...state, loading: false, error: null };
- // case "userFactor/add":
- // toast.success("درخواست شما با موفقیت انجام شد.");
- // return { ...state, loading: false, error: null, sum: data.payPrice };
case "userFactor/deleteUserOffCode":
return { ...state, loading: false, error: null };
case "userFactor/paymentVOD":
diff --git a/src/redux/reducers/userProduct.js b/src/redux/reducers/userProduct.js
index 23cfd01..80ade2d 100644
--- a/src/redux/reducers/userProduct.js
+++ b/src/redux/reducers/userProduct.js
@@ -1,12 +1,43 @@
import { toast } from "react-toastify";
+
const initialState = {
loading: false,
error: null,
+ list: [],
+ info: null,
+ sum: null,
+ checkEmpty: false,
+ hasPhysical: false,
};
export default function userFactor(state = initialState, action) {
let { type, data } = action;
switch (type) {
- case "userProduct/addVOD":
+ case "userProduct/list":
+ const checkEmpty = data.filter(
+ (item) => item.condition === 2 && item.product.productType === (1 || 3)
+ );
+ const hasPhysical =
+ data.filter((item) => item.product.productType === 2).length > 0
+ ? true
+ : false;
+ return {
+ ...state,
+ loading: false,
+ list: data,
+ checkEmpty: checkEmpty.length > 0 ? false : true,
+ error: null,
+ hasPhysical: hasPhysical,
+ };
+ case "userProduct/info":
+ return { ...state, loading: false, info: data, error: null };
+ case "userProduct/update":
+ return { ...state, loading: false, error: null };
+ case "userProduct/add":
+ if (window.location.pathname.indexOf("products") !== -1) {
+ toast.success("درخواست شما با موفقیت انجام شد.");
+ }
+ return { ...state, loading: false, error: null, sum: data.payPrice };
+ case "userProduct/delete":
return { ...state, loading: false, error: null };
case "userProduct/loading":
return { ...state, loading: true };
diff --git a/src/router.js b/src/router.js
index 791bbe0..d6cb73c 100644
--- a/src/router.js
+++ b/src/router.js
@@ -3,31 +3,37 @@ import { BrowserRouter, Routes, Route } from "react-router-dom";
import { connect } from "react-redux";
import Navbar from "./components/Navbar";
import BG from "./components/BG";
+import BottomNavigation from "./components/BottomNavigation";
import _ from "lodash";
import Home from "./views/Home";
+import Auth from "./views/Auth";
import Products from "./views/Products";
import Product from "./views/Product";
import ShoppingCart from "./views/ShoppingCart";
// import VideoTube from "./views/Home/VideoTube";
-function Router({ isDark }) {
+function Router({ isDark, isLogin }) {
return (
+
} />
+ } />
+ } />
+ } />
} />
} />
} />
@@ -48,6 +54,7 @@ function Router({ isDark }) {
const mapStateToProps = (state) => ({
isDark: state.publicApi.isDark,
+ isLogin: state.user.status
});
export default connect(mapStateToProps, {})(Router);
diff --git a/src/utils/onInput.js b/src/utils/onInput.js
new file mode 100644
index 0000000..9f64e8f
--- /dev/null
+++ b/src/utils/onInput.js
@@ -0,0 +1,282 @@
+import { toast } from "react-toastify";
+
+class onInput {
+ persianOnly = (txt) => {
+ let newText = txt;
+ newText = newText.replace(/`/g, "");
+ newText = newText.replace(/0/g, "");
+ newText = newText.replace(/1/g, "");
+ newText = newText.replace(/2/g, "");
+ newText = newText.replace(/3/g, "");
+ newText = newText.replace(/4/g, "");
+ newText = newText.replace(/5/g, "");
+ newText = newText.replace(/6/g, "");
+ newText = newText.replace(/7/g, "");
+ newText = newText.replace(/8/g, "");
+ newText = newText.replace(/9/g, "");
+ newText = newText.replace(/0/g, "");
+ newText = newText.replace(/q/g, "");
+ newText = newText.replace(/w/g, "");
+ newText = newText.replace(/e/g, "");
+ newText = newText.replace(/r/g, "");
+ newText = newText.replace(/t/g, "");
+ newText = newText.replace(/y/g, "");
+ newText = newText.replace(/u/g, "");
+ newText = newText.replace(/i/g, "");
+ newText = newText.replace(/o/g, "");
+ newText = newText.replace(/p/g, "");
+ newText = newText.replace(/\[/g, "");
+ newText = newText.replace(/\]/g, "");
+ newText = newText.replace(/a/g, "");
+ newText = newText.replace(/s/g, "");
+ newText = newText.replace(/d/g, "");
+ newText = newText.replace(/f/g, "");
+ newText = newText.replace(/g/g, "");
+ newText = newText.replace(/h/g, "");
+ newText = newText.replace(/j/g, "");
+ newText = newText.replace(/k/g, "");
+ newText = newText.replace(/l/g, "");
+ newText = newText.replace(/\;/g, "");
+ newText = newText.replace(/\'/g, "");
+ newText = newText.replace(/z/g, "");
+ newText = newText.replace(/x/g, "");
+ newText = newText.replace(/c/g, "");
+ newText = newText.replace(/v/g, "");
+ newText = newText.replace(/b/g, "");
+ newText = newText.replace(/n/g, "");
+ newText = newText.replace(/m/g, "");
+ newText = newText.replace(/\,/g, "");
+ newText = newText.replace(/\./g, "");
+ newText = newText.replace(/\//g, "");
+ newText = newText.replace(/~/g, " ");
+ newText = newText.replace(/Q/g, "");
+ newText = newText.replace(/W/g, "");
+ newText = newText.replace(/E/g, "");
+ newText = newText.replace(/R/g, "");
+ newText = newText.replace(/T/g, "");
+ newText = newText.replace(/Y/g, "");
+ newText = newText.replace(/U/g, "");
+ newText = newText.replace(/I/g, "");
+ newText = newText.replace(/O/g, "");
+ newText = newText.replace(/P/g, "");
+ newText = newText.replace(/A/g, "");
+ newText = newText.replace(/S/g, "");
+ newText = newText.replace(/G/g, "");
+ newText = newText.replace(/H/g, "");
+ newText = newText.replace(/J/g, "");
+ newText = newText.replace(/K/g, "");
+ newText = newText.replace(/L/g, "");
+ newText = newText.replace(/Z/g, "");
+ newText = newText.replace(/X/g, "");
+ newText = newText.replace(/B/g, "");
+ newText = newText.replace(/N/g, "");
+ newText = newText.replace(/M/g, "");
+ newText = newText.replace(/\?/g, "");
+ if (!newText && newText.length !== 0) {
+ toast.info("از کاراکتر فارسی استفاده کنید");
+ }
+ return newText;
+ };
+ englishAndNumberWithoutSpace = (txt) => {
+ let newText = txt;
+ newText = newText.replace(/`/g, "");
+ newText = newText.replace(/0/g, "0");
+ newText = newText.replace(/1/g, "1");
+ newText = newText.replace(/2/g, "2");
+ newText = newText.replace(/3/g, "3");
+ newText = newText.replace(/4/g, "4");
+ newText = newText.replace(/5/g, "5");
+ newText = newText.replace(/6/g, "6");
+ newText = newText.replace(/7/g, "7");
+ newText = newText.replace(/8/g, "8");
+ newText = newText.replace(/9/g, "9");
+ newText = newText.replace(/ا/g, "");
+ newText = newText.replace(/ب/g, "");
+ newText = newText.replace(/پ/g, "");
+ newText = newText.replace(/ت/g, "");
+ newText = newText.replace(/ث/g, "");
+ newText = newText.replace(/ج/g, "");
+ newText = newText.replace(/چ/g, "");
+ newText = newText.replace(/ح/g, "");
+ newText = newText.replace(/خ/g, "");
+ newText = newText.replace(/د/g, "");
+ newText = newText.replace(/\[/g, "");
+ newText = newText.replace(/\]/g, "");
+ newText = newText.replace(/ذ/g, "");
+ newText = newText.replace(/ر/g, "");
+ newText = newText.replace(/ز/g, "");
+ newText = newText.replace(/ژ/g, "");
+ newText = newText.replace(/ط/g, "");
+ newText = newText.replace(/ظ/g, "");
+ newText = newText.replace(/ع/g, "");
+ newText = newText.replace(/غ/g, "");
+ newText = newText.replace(/ف/g, "");
+ newText = newText.replace(/\;/g, "");
+ newText = newText.replace(/\'/g, "");
+ newText = newText.replace(/ق/g, "");
+ newText = newText.replace(/س/g, "");
+ newText = newText.replace(/ش/g, "");
+ newText = newText.replace(/ص/g, "");
+ newText = newText.replace(/ض/g, "");
+ newText = newText.replace(/ک/g, "");
+ newText = newText.replace(/گ/g, "");
+ newText = newText.replace(/\,/g, "");
+ newText = newText.replace(/\./g, "");
+ newText = newText.replace(/\//g, "");
+ newText = newText.replace(/~/g, " ");
+ newText = newText.replace(/ل/g, "");
+ newText = newText.replace(/م/g, "");
+ newText = newText.replace(/ن/g, "");
+ newText = newText.replace(/و/g, "");
+ newText = newText.replace(/ه/g, "");
+ newText = newText.replace(/ی/g, "");
+ newText = newText.replace(/\?/g, "");
+ if (!newText && newText.length !== 0) {
+ toast.info("از کاراکتر انگلیسی واعداداستفاده کنید");
+ }
+ return newText;
+ };
+ numberOnly = (txt) => {
+ let newText = txt;
+ newText = newText.replace(/`/g, "");
+ newText = newText.replace(/0/g, "0");
+ newText = newText.replace(/1/g, "1");
+ newText = newText.replace(/2/g, "2");
+ newText = newText.replace(/3/g, "3");
+ newText = newText.replace(/4/g, "4");
+ newText = newText.replace(/5/g, "5");
+ newText = newText.replace(/6/g, "6");
+ newText = newText.replace(/7/g, "7");
+ newText = newText.replace(/8/g, "8");
+ newText = newText.replace(/9/g, "9");
+ newText = newText.replace(/ا/g, "");
+ newText = newText.replace(/ب/g, "");
+ newText = newText.replace(/پ/g, "");
+ newText = newText.replace(/ت/g, "");
+ newText = newText.replace(/ث/g, "");
+ newText = newText.replace(/ج/g, "");
+ newText = newText.replace(/چ/g, "");
+ newText = newText.replace(/ح/g, "");
+ newText = newText.replace(/خ/g, "");
+ newText = newText.replace(/د/g, "");
+ newText = newText.replace(/\[/g, "");
+ newText = newText.replace(/\]/g, "");
+ newText = newText.replace(/ذ/g, "");
+ newText = newText.replace(/ر/g, "");
+ newText = newText.replace(/ز/g, "");
+ newText = newText.replace(/ژ/g, "");
+ newText = newText.replace(/ط/g, "");
+ newText = newText.replace(/ظ/g, "");
+ newText = newText.replace(/ع/g, "");
+ newText = newText.replace(/غ/g, "");
+ newText = newText.replace(/ف/g, "");
+ newText = newText.replace(/\;/g, "");
+ newText = newText.replace(/\'/g, "");
+ newText = newText.replace(/ق/g, "");
+ newText = newText.replace(/س/g, "");
+ newText = newText.replace(/ش/g, "");
+ newText = newText.replace(/ص/g, "");
+ newText = newText.replace(/ض/g, "");
+ newText = newText.replace(/ک/g, "");
+ newText = newText.replace(/گ/g, "");
+ newText = newText.replace(/\,/g, "");
+ newText = newText.replace(/\./g, "");
+ newText = newText.replace(/\//g, "");
+ newText = newText.replace(/~/g, " ");
+ newText = newText.replace(/ل/g, "");
+ newText = newText.replace(/م/g, "");
+ newText = newText.replace(/ن/g, "");
+ newText = newText.replace(/و/g, "");
+ newText = newText.replace(/ه/g, "");
+ newText = newText.replace(/ی/g, "");
+ newText = newText.replace(/\?/g, "");
+ newText = newText.replace(/q/g, "");
+ newText = newText.replace(/w/g, "");
+ newText = newText.replace(/e/g, "");
+ newText = newText.replace(/r/g, "");
+ newText = newText.replace(/t/g, "");
+ newText = newText.replace(/y/g, "");
+ newText = newText.replace(/u/g, "");
+ newText = newText.replace(/i/g, "");
+ newText = newText.replace(/o/g, "");
+ newText = newText.replace(/p/g, "");
+ newText = newText.replace(/a/g, "");
+ newText = newText.replace(/s/g, "");
+ newText = newText.replace(/d/g, "");
+ newText = newText.replace(/f/g, "");
+ newText = newText.replace(/g/g, "");
+ newText = newText.replace(/h/g, "");
+ newText = newText.replace(/j/g, "");
+ newText = newText.replace(/k/g, "");
+ newText = newText.replace(/l/g, "");
+ newText = newText.replace(/z/g, "");
+ newText = newText.replace(/x/g, "");
+ newText = newText.replace(/c/g, "");
+ newText = newText.replace(/v/g, "");
+ newText = newText.replace(/b/g, "");
+ newText = newText.replace(/n/g, "");
+ newText = newText.replace(/m/g, "");
+ newText = newText.replace(/Q/g, "");
+ newText = newText.replace(/W/g, "");
+ newText = newText.replace(/E/g, "");
+ newText = newText.replace(/R/g, "");
+ newText = newText.replace(/T/g, "");
+ newText = newText.replace(/Y/g, "");
+ newText = newText.replace(/U/g, "");
+ newText = newText.replace(/I/g, "");
+ newText = newText.replace(/O/g, "");
+ newText = newText.replace(/P/g, "");
+ newText = newText.replace(/A/g, "");
+ newText = newText.replace(/S/g, "");
+ newText = newText.replace(/G/g, "");
+ newText = newText.replace(/H/g, "");
+ newText = newText.replace(/J/g, "");
+ newText = newText.replace(/K/g, "");
+ newText = newText.replace(/L/g, "");
+ newText = newText.replace(/Z/g, "");
+ newText = newText.replace(/X/g, "");
+ newText = newText.replace(/B/g, "");
+ newText = newText.replace(/N/g, "");
+ newText = newText.replace(/M/g, "");
+ if (!newText && newText.length !== 0) {
+ toast.info("از اعداداستفاده کنید");
+ }
+ return newText;
+ };
+ dayHandler = (num) => {
+ let newNum = this.numberOnly(num);
+ if (newNum > 31) {
+ toast.error("روز نباید بزرگتر از 31 باشد.");
+ return Math.floor(newNum / 10);
+ }
+ return newNum;
+ };
+ monthHandler = (num) => {
+ let newNum = this.numberOnly(num);
+ if (newNum > 12 || newNum < 0) {
+ toast.error("ماه باید بین 1 تا 12 باشد.");
+ return Math.floor(newNum / 10);
+ }
+ return newNum;
+ };
+ yearHandler = (num) => {
+ let newNum = this.numberOnly(num);
+ if (newNum > 1395) {
+ toast.error("سال باید کوچکتر از 1395 باشد.");
+ return Math.floor(newNum / 10);
+ }
+ return newNum;
+ };
+ phonenumber = (value) => {
+ let formattedValue = value
+ .replace(/[\u0660-\u0669\u06f0-\u06f9]/g, function (c) {
+ return c.charCodeAt(0) & 0xf;
+ })
+ .replace(/[^\d]/, "");
+ return formattedValue;
+ };
+}
+
+const _onInput = new onInput();
+
+export default _onInput;
diff --git a/src/views/Auth/Login/index.js b/src/views/Auth/Login/index.js
new file mode 100644
index 0000000..e361c84
--- /dev/null
+++ b/src/views/Auth/Login/index.js
@@ -0,0 +1,33 @@
+import React, { useState, useRef, useEffect } from "react";
+import { Link } from "react-router-dom";
+import { connect } from "react-redux";
+import onInput from "../../../utils/onInput";
+
+import { user } from "../../../redux/actions";
+import _ from "lodash";
+
+//assets
+
+
+function Login({ login, theme, ...props }) {
+ const [loginFields, setSignUpFiels] = useState(undefined);
+ const onChange = (name, value) => {
+ setSignUpFiels({ ...loginFields, [name]: value });
+ };
+
+ useEffect(() => {}, []);
+ return (
+
+
+
+ );
+}
+
+export default connect(() => ({}), { login: user.login })(Login);
diff --git a/src/views/Auth/Login/index.scss b/src/views/Auth/Login/index.scss
new file mode 100644
index 0000000..6a1b662
--- /dev/null
+++ b/src/views/Auth/Login/index.scss
@@ -0,0 +1,262 @@
+.login {
+
+ &-light {
+ .MuiFormControl-root label{
+ background-color: white !important;
+ }
+ b{
+ color: $gray5 !important;
+ }
+ .login {
+ &__back {
+ a {
+ color: black !important;
+ }
+ }
+ &__options {
+ color: $gray9;
+ a {
+ color: $green4;
+ }
+ }
+ }
+ }
+ &__options {
+ color: #b5b5b5;
+ a {
+ color: $green4;
+ }
+ }
+ button[type="submit"] {
+ margin-top: 25px;
+ background-color: $green4;
+ color: white;
+ padding: 10px 0px;
+ border: 0px;
+ border-radius: 10px;
+ }
+ img {
+ // transform: rotate(-90deg);
+ }
+ .MuiButtonBase-root {
+ padding: 0px !important;
+ }
+ .footer {
+ position: fixed;
+ bottom: 0px;
+ left: 0px;
+ }
+}
+
+@media screen and (min-width: 1441px) {
+ .login {
+ section {
+ width: 410px;
+ b {
+ color: white;
+ font-size: 16px;
+ margin-bottom: 30px;
+ font-weight: 500;
+ p {
+ font-size: 16px;
+ }
+ }
+
+ button {
+ font-size: 17px;
+ }
+ }
+ &__info {
+ width: 350px;
+ margin: 40px auto 0px;
+ text-align: center;
+ color: white;
+ font-size: 14px;
+ a {
+ color: $green4;
+ }
+ }
+ &__back {
+ margin-bottom: 60px;
+ img {
+ transform: rotate(-90deg);
+ }
+ a {
+ color: white;
+ font-size: 13px;
+ }
+ }
+ &__options {
+ div {
+ font-size: 13px;
+ }
+ a {
+ font-size: 13px;
+ }
+ }
+ }
+}
+
+@media screen and (min-width: 1008px) and (max-width: 1440px) {
+ .login {
+ section {
+ width: 350px;
+ transform: scale(0.9);
+ b {
+ color: white;
+ font-size: calc(100vw / 80);
+ margin-bottom: 30px;
+ font-weight: 500;
+ }
+
+ button {
+ font-size: calc(100vw / 80);
+ }
+ }
+ &__info {
+ width: 300px;
+ margin: 40px auto 0px;
+ text-align: center;
+ color: white;
+ font-size: calc(100vw / 110);
+ a {
+ color: $green4;
+ }
+ }
+ &__back {
+ margin-bottom: 40px;
+ img {
+ transform: rotate(-90deg);
+ }
+ a {
+ color: white;
+ font-size: calc(100vw / 110);
+ }
+ }
+ &__options {
+ div {
+ font-size: calc(100vw / 110);
+ }
+ a {
+ font-size: calc(100vw / 110);
+ }
+ }
+ }
+}
+
+@media screen and (min-width: 641px) and (max-width: 1007px) {
+ .login {
+ .footer {
+ display: none !important;
+ }
+ section {
+ // background-color: red;
+ width: 90%;
+ max-width: 700px;
+ height: calc(100% - 60px);
+ justify-content: center;
+ b {
+ color: white;
+ font-size: calc(100vw / 30);
+ margin-bottom: 30px;
+ font-weight: 500;
+ }
+
+ button {
+ font-size: calc(100vw / 30);
+ width: 100%;
+ max-width: 400px;
+ margin: 50px auto 0px;
+ }
+ }
+ &__info {
+ width: 300px;
+ margin: 40px auto 0px;
+ text-align: center;
+ color: white;
+ font-size: calc(100vw / 40);
+ a {
+ color: $green4;
+ }
+ }
+ &__back {
+ position: fixed;
+ top: 100px;
+ margin-bottom: 40px;
+ left: 30px;
+ a {
+ color: white;
+ font-size: calc(100vw / 110);
+ }
+ img {
+ width: 50px;
+ }
+ }
+ &__options {
+ padding-top: 20px;
+ div {
+ font-size: calc(100vw / 40);
+ }
+ a {
+ font-size: calc(100vw / 45);
+ }
+ }
+ }
+}
+
+@media screen and (max-width: 640px) {
+ .login {
+ section {
+ // background-color: red;
+ width: 90%;
+ max-width: 400px;
+ height: calc(100% - 60px);
+ // transform: scale(0.9);
+ justify-content: center;
+ // align-items: center;
+ b {
+ color: white;
+ font-size: calc(100vw / 18);
+ margin-bottom: 30px;
+ font-weight: 500;
+ }
+
+ button {
+ margin-top: 25px;
+ font-size: calc(100vw / 25);
+ }
+ }
+ &__info {
+ width: 300px;
+ margin: 40px auto 0px;
+ text-align: center;
+ color: white;
+ font-size: calc(100vw / 30);
+ a {
+ color: $green4;
+ }
+ }
+ &__back {
+ position: fixed;
+ top: 70px;
+ left: 20px;
+ margin-bottom: 40px;
+ a {
+ color: white;
+ font-size: calc(100vw / 110);
+ }
+ img {
+ width: 40px;
+ // transform: scale()
+ }
+ }
+ &__options {
+ div {
+ font-size: calc(100vw / 30);
+ }
+ a {
+ font-size: calc(100vw / 30);
+ }
+ }
+ }
+}
diff --git a/src/views/Auth/Profile/Birthdate/index.js b/src/views/Auth/Profile/Birthdate/index.js
new file mode 100644
index 0000000..e166e5f
--- /dev/null
+++ b/src/views/Auth/Profile/Birthdate/index.js
@@ -0,0 +1,61 @@
+import React, { useState } from "react";
+import onInput from "../../../../utils/onInput";
+import Input from "../../../../components/Input/index";
+
+import moment from "jalali-moment";
+
+export default function Birthdate({ defaultValue, name, ...props }) {
+ let momentDate = moment(defaultValue[name]);
+ let isvalid = momentDate.isValid();
+ const day = isvalid ? momentDate.format("jDD") : null,
+ month = isvalid ? momentDate.format("jMM") : null,
+ year = isvalid ? momentDate.format("jYYYY") : null;
+ const [state, setState] = useState({ day, month, year });
+ const onChange = (_name, value) => {
+ let _state = { ...state, [_name]: value };
+ setState(_state);
+
+ props.onChange(
+ name,
+ moment
+ .from(`${_state.year}/${_state.month}/${_state.day}`, "fa", "YYYY/M/D")
+ .locale("en")
+ );
+ };
+ return (
+
+ );
+}
diff --git a/src/views/Auth/Profile/Birthdate/index.scss b/src/views/Auth/Profile/Birthdate/index.scss
new file mode 100644
index 0000000..65eb7f0
--- /dev/null
+++ b/src/views/Auth/Profile/Birthdate/index.scss
@@ -0,0 +1,118 @@
+.birthdate {
+ width: 100%;
+ border-radius: 10px;
+ padding: 0px 10px;
+ border: 1px solid $gray1;
+ margin: 10px 0px;
+ label {
+ width: fit-content;
+ color: #ccc;
+ font-weight: 100;
+ }
+ span {
+ color: #bfbfbf;
+ margin: 0px 5px;
+ }
+
+ input {
+ border: none !important;
+ background-color: rgba(204, 204, 204, 0.098);
+ color: $green4;
+ max-width: 40px;
+ text-align: center !important;
+ direction: ltr;
+ margin: 0px 5px !important;
+ border: none;
+ &:focus {
+ outline: 0px;
+ border: 0px;
+ }
+ &::placeholder {
+ color: $gray1;
+ }
+ }
+
+ //INPUT
+
+ .MuiOutlinedInput-notchedOutline {
+ border : none !important;
+ }
+
+ .MuiOutlinedInput-input {
+ padding: 5px !important;
+ &:focus {
+ border: none !important;
+ border-radius: 0px !important;
+ }
+ }
+}
+
+@media screen and (min-width: 1441px) {
+ .birthdate {
+ label {
+ font-size: 14px !important;
+ }
+ span {
+ font-size: 16px;
+ }
+ input {
+ font-size: 16px;
+ &::placeholder {
+ font-size: 16px;
+ }
+ }
+ }
+}
+
+@media screen and (min-width: 1008px) and (max-width: 1440px) {
+ .birthdate {
+ label {
+ font-size: calc(100vw / 120) !important;
+ }
+ span {
+ font-size: calc(100vw / 90);
+ }
+ input {
+ font-size: calc(100vw / 90);
+ &::placeholder {
+ font-size: calc(100vw / 90);
+ }
+ }
+ }
+}
+
+@media screen and (min-width: 640px) and (max-width: 1007px) {
+ .birthdate {
+ label {
+ font-size: calc(100vw / 40) !important;
+ }
+ span {
+ font-size: calc(100vw / 35);
+ }
+ input {
+ font-size: calc(100vw / 20);
+ margin: 0px 5px !important;
+ &::placeholder {
+ font-size: calc(100vw / 30);
+ }
+ }
+ }
+}
+
+@media screen and (max-width: 640px) {
+ .birthdate {
+ label {
+ font-size: calc(100vw / 35) !important;
+ }
+ span {
+ font-size: calc(100vw / 35);
+ }
+ input {
+ font-size: calc(100vw / 20);
+
+ &::placeholder {
+ font-size: calc(100vw / 30);
+ }
+ }
+ }
+}
diff --git a/src/views/Auth/Profile/Document/index.js b/src/views/Auth/Profile/Document/index.js
new file mode 100644
index 0000000..e02f43c
--- /dev/null
+++ b/src/views/Auth/Profile/Document/index.js
@@ -0,0 +1,36 @@
+import React from "react";
+
+export default function Document({ defaultValue, name, onChange }) {
+ return (
+
+ {defaultValue.docFileIds === "" ? (
+ <>
+ onChange(name, e.target.files[0])}
+ />
+ گواهی تدریس خود را آپلود کنید.
+ >
+ ) : (
+ <>
+ onChange(name, e.target.files[0])}
+ />
+
+ {/* {defaultValue.docFileIds.name ||
+ "گواهی تدریس ثبت شده و درحال بررسی می باشد"} */}
+
+ >
+ )}
+
+ );
+}
diff --git a/src/views/Auth/Profile/Document/index.scss b/src/views/Auth/Profile/Document/index.scss
new file mode 100644
index 0000000..9064418
--- /dev/null
+++ b/src/views/Auth/Profile/Document/index.scss
@@ -0,0 +1,52 @@
+.mobile-auth-profile {
+ &__document {
+ margin: 10px auto;
+ width: 100%;
+ height: 50px;
+ border-radius: 10px;
+ border: 2px dashed $gray1;
+ position: relative;
+ input {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ opacity: 0;
+ }
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ border-radius: 50%;
+ }
+ span {
+ color: #afafaf;
+ font-family: numeralLight;
+ }
+ }
+}
+
+@media screen and (min-width: 1441px){
+ span{
+ font-size: 14px;
+ }
+}
+
+@media screen and (min-width: 1008px) and (max-width: 1440px){
+ span{
+ font-size: calc(100vw / 100);
+ }
+}
+
+@media screen and (min-width: 641px) and (max-width: 1007px){
+ span{
+ font-size: calc(100vw / 45);
+ }
+}
+
+@media screen and (max-width: 640px){
+ span{
+ font-size: calc(100vw / 30);
+ }
+}
diff --git a/src/views/Auth/Profile/GenderSwitch/index.js b/src/views/Auth/Profile/GenderSwitch/index.js
new file mode 100644
index 0000000..85f08ca
--- /dev/null
+++ b/src/views/Auth/Profile/GenderSwitch/index.js
@@ -0,0 +1,27 @@
+import React from "react";
+
+
+export default function GenderSwitch({
+ onChange,
+ name,
+ options,
+ selectedOption,
+ label,
+}) {
+ return (
+
+
onChange(name, 2)}
+ >
+ {options[0]}
+
+
onChange(name, 1)}
+ >
+ {options[1]}
+
+
+ );
+}
diff --git a/src/views/Auth/Profile/GenderSwitch/index.scss b/src/views/Auth/Profile/GenderSwitch/index.scss
new file mode 100644
index 0000000..1adbf93
--- /dev/null
+++ b/src/views/Auth/Profile/GenderSwitch/index.scss
@@ -0,0 +1,44 @@
+.gender {
+ width: 100%;
+ margin-bottom: 10px;
+ div {
+ border-radius: 10px;
+ font-family: numeralLight;
+ padding: 13px 0px;
+ width: 45%;
+ text-align: center;
+ cursor: pointer;
+ color: #ccc;
+ background-color: black;
+ border: 1px solid $gray1;
+ }
+ &__active{
+ background-color: $green4 !important;
+ color: white !important;
+ border: none !important;
+ }
+}
+
+@media screen and (min-width: 1441px) {
+ .gender{
+ font-size: 16px;
+ }
+}
+
+@media screen and (min-width: 1008px) and (max-width: 1440px) {
+ .gender{
+ font-size: calc(100vw / 90);
+ }
+}
+
+@media screen and (min-width: 641px) and (max-width: 1007px) {
+ .gender{
+ font-size: calc(100vw / 40);
+ }
+}
+
+@media screen and (max-width: 640px) {
+ .gender{
+ font-size: calc(100vw / 30);
+ }
+}
diff --git a/src/views/Auth/Profile/MultipleSelector/index.js b/src/views/Auth/Profile/MultipleSelector/index.js
new file mode 100644
index 0000000..f58f29a
--- /dev/null
+++ b/src/views/Auth/Profile/MultipleSelector/index.js
@@ -0,0 +1,9 @@
+import React from "react";
+
+
+
+export default function MultipleSelector({align, onChange, selectedOptions, options, defaultValue, label, name,}) {
+ return (
+ <>>
+ );
+}
diff --git a/src/views/Auth/Profile/MultipleSelector/index.scss b/src/views/Auth/Profile/MultipleSelector/index.scss
new file mode 100644
index 0000000..2610c6b
--- /dev/null
+++ b/src/views/Auth/Profile/MultipleSelector/index.scss
@@ -0,0 +1,10 @@
+.mobile-multiple-selector {
+ width: 100%;
+ border-radius: 10px;
+ padding: 9px 10px;
+ border: 1px solid $gray6 !important;
+ margin: 0px !important;
+ .MuiInput-formControl {
+ margin: 9px 0px 8px !important;
+ }
+}
diff --git a/src/views/Auth/Profile/Upload/index.js b/src/views/Auth/Profile/Upload/index.js
new file mode 100644
index 0000000..98c0b09
--- /dev/null
+++ b/src/views/Auth/Profile/Upload/index.js
@@ -0,0 +1,27 @@
+import React from "react";
+
+export default function Upload({ name, value, onChange, label }) {
+ return (
+
+ <>
+ {value === null ? (
+ <>>
+ ) : (
+
+ )}
+
onChange(e.target.name, e.target.files[0])}
+ />
+ >
+
+ );
+}
diff --git a/src/views/Auth/Profile/Upload/index.scss b/src/views/Auth/Profile/Upload/index.scss
new file mode 100644
index 0000000..d2018a3
--- /dev/null
+++ b/src/views/Auth/Profile/Upload/index.scss
@@ -0,0 +1,61 @@
+.profile-upload {
+ width: 100px;
+ height: 100px;
+ border-radius: 50%;
+ margin-top: 15px auto 0px;
+ // border: 2px dotted #ccc;
+ position: relative;
+ cursor: pointer;
+ background-color: $gray8;
+ img{
+ width: 100%;
+ height: 100%;
+ border-radius: 50%;
+ }
+ input {
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ z-index: 50;
+ }
+ span {
+ color: $blue1;
+ font-family: numeralLight;
+ height: 20px;
+ position: absolute;
+ left: 0px;
+ top: calc(50% - 10px);
+ width: 100%;
+ text-align: center;
+ z-index: 10;
+ }
+}
+
+@media screen and (min-width: 1441px) {
+ .profile-upload {
+
+ }
+}
+
+@media screen and (min-width: 1008px) and (max-width: 1440px) {
+ .profile-upload {
+
+ }
+}
+
+@media screen and (min-width: 641px) and (max-width: 1007px) {
+ .profile-upload {
+ width: 80px;
+ height: 80px;
+ }
+}
+
+@media screen and (max-width: 640px) {
+ .profile-upload {
+ width : 80px;
+ height : 80px;
+ }
+}
diff --git a/src/views/Auth/Profile/index.js b/src/views/Auth/Profile/index.js
new file mode 100644
index 0000000..9b8ecf0
--- /dev/null
+++ b/src/views/Auth/Profile/index.js
@@ -0,0 +1,450 @@
+import React, { useState, useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+import onInput from "../../../utils/onInput";
+import { user, file, publicApi } from "../../../redux/actions";
+import { connect } from "react-redux";
+
+import Select from "../../../components/Select";
+import Input from "../../../components/Input";
+import TextArea from "../../../components/Textarea";
+import Upload from "./Upload";
+import Gender from "./GenderSwitch";
+import Birthdate from "./Birthdate";
+import MultipleSelector from "./MultipleSelector";
+import Document from "./Document";
+
+
+function Profile({
+ profile,
+ uploads,
+ getProvince,
+ getCity,
+ setDone,
+ upload,
+ setProfile,
+ province,
+ provinceList,
+ cityList,
+}) {
+ let navigate = useNavigate();
+ const [render, setRender] = useState(false);
+ const [formData, setFormData] = useState({
+ file: uploads["file"] || profile.picFileId || null,
+ picFileId: uploads["file"] || profile.picFileId || null,
+ docFileIds: uploads["docFileIds"] || profile.docFileIds || "",
+ firstName: profile.firstName || "",
+ lastName: profile.lastName || "",
+ password: profile.password || "",
+ username: profile.username || "",
+ address: profile.address || "",
+ email: profile.email || "",
+ birthDate: profile.birthDate || "",
+ gender: profile.gender || 1,
+ status: profile.status || 1,
+ nationalId: profile.nationalId || "",
+ phone: profile.phone || "",
+ schools: profile.schools || null,
+ zoneId: profile.zoneId || "",
+ schoolId: profile.schoolId || "",
+ postalCode: profile.postalCode || "",
+ gradeIds: profile.gradeIds || [],
+ provinceId: profile.provinceId || null,
+ cityId: profile.cityId || null,
+ });
+
+ useEffect(() => {
+ getProvince();
+ getCity({ provinceId: profile.provinceId });
+ }, []);
+
+ useEffect(() => {
+ if (setDone) {
+ navigate("/");
+ }
+ }, [setDone]);
+
+ const grades = [
+ {
+ name: "پیش دبستانی",
+ value: 0,
+ },
+ {
+ name: "اول",
+ value: 1,
+ },
+ {
+ name: "دوم",
+ value: 2,
+ },
+ {
+ name: "سوم",
+ value: 3,
+ },
+ {
+ name: "چهارم",
+ value: 4,
+ },
+ {
+ name: "پنجم",
+ value: 5,
+ },
+ {
+ name: "ششم",
+ value: 6,
+ },
+ {
+ name: "هفتم",
+ value: 7,
+ },
+ {
+ name: "هشتم",
+ value: 8,
+ },
+ {
+ name: "نهم",
+ value: 9,
+ },
+ {
+ name: "دهم",
+ value: 10,
+ },
+ {
+ name: "یازدهم",
+ value: 11,
+ },
+ {
+ name: "دوازدهم",
+ value: 12,
+ },
+ ];
+
+ const onChange = (name, value) => {
+ if (name === "provinceId") {
+ getCity({ provinceId: value });
+ setFormData({ ...formData, cityId: null, [name]: value });
+ } else if (name === "status") {
+ setFormData({
+ ...formData,
+ gradeIds: formData.gradeIds?.slice(0, 1) || [],
+ [name]: value,
+ });
+ } else if (name === "docFileIds") {
+ upload({ file: value, target: name });
+ setFormData({ ...formData, [name]: value });
+ } else if (name === "file") {
+ upload({ file: value, target: name });
+ setFormData({ ...formData, [name]: value });
+ } else {
+ setFormData({ ...formData, [name]: value });
+ }
+ };
+
+ const onSubmit = async () => {
+ const {
+ firstName,
+ lastName,
+ username,
+ //cellphone,
+ password,
+ postalCode,
+ address,
+ email,
+ phone,
+ picFileId,
+ gender,
+ nationalId,
+ birthDate,
+ schools,
+ gradeIds,
+ status,
+ provinceId,
+ cityId,
+ docFileIds,
+ } = formData;
+ const data = {
+ firstName: firstName || profile.firstName,
+ lastName: lastName || profile.lastName,
+ username: username || profile.username,
+ cellphone: profile.cellphone,
+ password: password || profile.password,
+ postalCode: postalCode || profile.postalCode,
+ address: address || profile.address,
+ email: email || profile.email,
+ phone: phone || profile.phone,
+ nationalId: nationalId || profile.nationalId,
+ picFileId: uploads["file"] || picFileId || profile.picFileId,
+ gender: gender || profile.gender,
+ birthDate: birthDate || profile.birthDate,
+ schools: schools || profile.schools,
+ gradeIds: gradeIds || profile.gradeIds,
+ status: status || profile.status,
+ provinceId: provinceId || profile.provinceId,
+ cityId: cityId || profile.cityId,
+ docFileIds: uploads["docFileIds"] || docFileIds || profile.docFileIds,
+ };
+ await setProfile(data);
+ };
+
+ // if (setDone) return ;
+
+ return (
+
+
+
+ onSubmit()}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {formData.status === 1 ? (
+
+
+
+ ) : null}
+ {formData.status === 2 ? (
+
+
+
+ ) : null}
+
+ {formData.status === "دانش آموز" && formData.gradeIds > 9 ? (
+
+
+
+ ) : null}
+ {console.log(province)}
+
+
+
+
+
+
+ {/*
+
+
*/}
+ {formData.status == 1 ? (
+
+
+
+ ) : null}
+ {formData.status == 2 ? (
+
+
+
+ ) : null}
+ {formData.status == 2 ? (
+
+ ) : null}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default connect(
+ (state) => ({
+ profile: state.user.status,
+ setDone: state.user.setDone,
+ loading: state.user.loading,
+ uploading: state.file.loading,
+ uploads: state.file.uploads,
+ provinceList: state.publicApi.province,
+ cityList: state.publicApi.city,
+ }),
+ {
+ getProfile: user.getProfile,
+ setProfile: user.setProfile,
+ upload: file.upload,
+ getProvince: publicApi.getProvince,
+ getCity: publicApi.getCity,
+ }
+)(Profile);
+
+Profile.defaultProps = {
+ user: {
+ name: "اکبر",
+ icon: "",
+ description: "",
+ },
+};
diff --git a/src/views/Auth/Profile/index.scss b/src/views/Auth/Profile/index.scss
new file mode 100644
index 0000000..ce01e3a
--- /dev/null
+++ b/src/views/Auth/Profile/index.scss
@@ -0,0 +1,166 @@
+@import './Birthdate/index.scss';
+@import './Document/index.scss';
+@import './GenderSwitch/index.scss';
+@import './MultipleSelector/index.scss';
+@import './Upload/index.scss';
+
+.MuiOutlinedInput-input {
+ font-family: numeralLight !important;
+}
+
+.profile {
+ scrollbar-width: 0px;
+ padding: 50px 20px 0px;
+ &::-webkit-scrollbar {
+ display: none;
+ }
+ header {
+ margin: 30px 0px;
+ h1 {
+ margin-top: 15px;
+ font-family: numeralMedium;
+ color: white;
+ letter-spacing: -1px;
+ }
+ p {
+ font-family: numeralLight;
+ color: white;
+ text-align: justify;
+ }
+ }
+ &__box {
+ width: 100%;
+ border: 1px solid $gray1;
+ border-radius: 20px;
+ &--section {
+ width: 45%;
+ }
+
+ .MuiMenu-list,
+ .MuiFormControl-root {
+ width: 100%;
+ margin: 10px auto !important;
+ scrollbar-width: 0px !important;
+ &::-webkit-scrollbar {
+ display: none !important;
+ width: 0px !important;
+ }
+ option {
+ font-family: numeralLight !important;
+ }
+ .MuiSelect-iconOutlined {
+ display: none;
+ }
+ .MuiSelect-outlined.MuiSelect-outlined {
+ padding-right: 15px;
+ }
+ color: $gray7 !important;
+ }
+
+ button {
+ margin-top: 20px;
+ margin-bottom: 50px;
+ font-family: numeralLight;
+ border: 0px;
+ background-color: $green3;
+ border-radius: 7px;
+ color: white;
+ padding: 12px 0px;
+ width: 100%;
+ }
+ }
+}
+
+@media screen and (min-width: 1441px) {
+ .profile {
+ h1{
+ font-size: 30px;
+ }
+ p{
+ font-size: 14px;
+ }
+ button {
+ font-size: 21px;
+ }
+ header {
+ }
+ &__box {
+ flex-direction: row;
+ justify-content: space-around;
+ padding: 30px 10px;
+ margin-bottom: 50px;
+ }
+ }
+}
+
+@media screen and (min-width: 1008px) and (max-width: 1440px) {
+ .profile {
+ h1{
+ font-size: calc(100vw / 50);
+ }
+ p{
+ font-size: calc(100vw / 90);
+ }
+ button {
+ font-size: calc(100vw / 70);
+ }
+ &__box {
+ padding: 30px 10px;
+ flex-direction: row;
+ justify-content: space-around;
+ margin-bottom: 50px;
+ }
+ }
+}
+
+@media screen and (min-width: 641px) and (max-width: 1007px) {
+ .profile {
+ padding: 50px 100px 10px;
+ button {
+ font-size: calc(100vw / 40);
+ }
+ header {
+ margin: 0px;
+ margin-top: 30px;
+ h1{
+ font-size: calc(100vw / 35);
+ }
+ p{
+ font-size: calc(100vw / 55);
+ }
+ }
+ &__box {
+ flex-direction: column;
+ border: none;
+ &--section {
+ width: 100%;
+ }
+ }
+ }
+}
+
+@media screen and (max-width: 640px) {
+ .profile {
+ padding: 0px 10px;
+ button {
+ font-size: calc(100vw / 30);
+ }
+ header {
+ margin: 0px;
+ margin-top: 70px;
+ h1{
+ font-size: calc(100vw / 20);
+ }
+ p{
+ font-size: calc(100vw / 35);
+ }
+ }
+ &__box {
+ flex-direction: column;
+ border: none;
+ &--section {
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/src/views/Auth/SignUp/assets/logo.svg b/src/views/Auth/SignUp/assets/logo.svg
new file mode 100644
index 0000000..7198fde
--- /dev/null
+++ b/src/views/Auth/SignUp/assets/logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/views/Auth/SignUp/index.js b/src/views/Auth/SignUp/index.js
new file mode 100644
index 0000000..2e1783d
--- /dev/null
+++ b/src/views/Auth/SignUp/index.js
@@ -0,0 +1,118 @@
+import React, { useState, useRef, useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+import Input from "../../../components/Input";
+import Button from "../../../components/Button";
+import Timer from "../../../components/Timer";
+import onInput from "../../../utils/onInput";
+import { Link } from "react-router-dom";
+
+import { connect } from "react-redux";
+import { user } from "../../../redux/actions";
+import _ from "lodash";
+//assets
+import logoIcon from "./assets/logo.svg";
+
+function SignUp({ sendOtp, sendPhoneNumber, loginFlag, theme }) {
+ const [level, setLevel] = useState("phonenumber");
+ const [signUpFields, setSignUpFiels] = useState(null);
+ const [error, setError] = useState("");
+ const [resend, setResend] = useState(false);
+ const navigate = useNavigate();
+
+ const onChange = (name, value) => {
+ setSignUpFiels({ ...signUpFields, [name]: value });
+ };
+
+ const checkPhoneNumber = () => {
+ if (
+ signUpFields?.cellphone?.slice(0, 2) === "09" &&
+ signUpFields?.cellphone.length === 11
+ ) {
+ setLevel("otp");
+ setResend(false);
+ sendPhoneNumber({ cellphone: signUpFields?.cellphone });
+ setError(undefined);
+ } else {
+ setError("شماره موبایل خود را چک کنید.");
+ }
+ };
+
+ const checkOtp = () => {
+ if (signUpFields?.otp?.length === 4) {
+ sendOtp({
+ cellphone: signUpFields?.cellphone,
+ otp: signUpFields?.otp,
+ userToken: "2",
+ applicationToken: "22",
+ });
+ setError(undefined);
+ } else {
+ setError("کد وارد شده را چک کنید.");
+ }
+ };
+
+ const otpInput = useRef();
+ const numberInput = useRef();
+
+ useEffect(() => {
+ // numberInput.current.focus();
+ }, []);
+
+ useEffect(() => {
+ if (signUpFields?.otp?.length === 4) {
+ sendOtp({
+ cellphone: signUpFields?.cellphone,
+ otp: signUpFields?.otp,
+ userToken: "2",
+ applicationToken: "22",
+ });
+ }
+ }, [signUpFields]);
+
+ useEffect(() => {
+ if (level === "phonenumber") {
+ // numberInput.current.focus();
+ } else {
+ // otpInput.current.focus();
+ }
+ }, [level]);
+
+ useEffect(() => {
+ if (loginFlag) {
+ navigate("/");
+ }
+ }, [loginFlag]);
+ const light = theme === "light";
+ return (
+
+
+
+ سلام
خوش برگشتی!
+
+
+
+ );
+}
+
+export default connect(
+ (state) => ({
+ loginFlag: state.user.setLogin,
+ }),
+ {
+ sendOtp: user.otp_login,
+ sendPhoneNumber: user.otp,
+ }
+)(SignUp);
diff --git a/src/views/Auth/SignUp/index.scss b/src/views/Auth/SignUp/index.scss
new file mode 100644
index 0000000..9821338
--- /dev/null
+++ b/src/views/Auth/SignUp/index.scss
@@ -0,0 +1,320 @@
+.signup {
+ width: 100%;
+ height: 100vh;
+ position: relative;
+ font-family: numeralLight;
+ &__back{
+ img{
+ width: 40px;
+ }
+ }
+ &-light {
+ b {
+ color: $gray5 !important;
+ }
+ input {
+ background-color: white;
+ border: 1px solid $green1;
+ color: $gray5;
+ &::placeholder {
+ color: $gray9;
+ }
+ &:focus {
+ border: 1px solid $green4;
+ &::placeholder {
+ color: $green4;
+ }
+ }
+ }
+ .signup {
+ &__info {
+ color: $gray5;
+ a {
+ color: $green4;
+ }
+ }
+ &__back {
+ a {
+ color: $gray5;
+ font-size: 13px;
+ }
+ }
+ }
+ }
+ &-dark {
+ input {
+ background-color: $gray8;
+ border: 1px solid $gray;
+ color: white;
+ &:focus {
+ border: 1px solid $green4;
+ &::placeholder {
+ color: $green4;
+ }
+ }
+ }
+ .signup {
+ &__info {
+ color: white;
+ a {
+ color: $green4;
+ }
+ }
+ &__back {
+ a {
+ color: white;
+ }
+ }
+ }
+ }
+ img {
+ // transform: rotate(-90deg);
+ }
+ .footer {
+ position: fixed;
+ bottom: 0px;
+ left: 0px;
+ }
+ button[type="submit"] {
+ margin-top: 25px;
+ background-color: $green4;
+ color: white;
+ padding: 10px 0px;
+ border: 0px;
+ border-radius: 10px;
+ }
+}
+
+@media screen and (min-width: 1441px) {
+ .signup {
+ section {
+ width: 410px;
+ b {
+ color: white;
+ font-size: 16px;
+ margin-bottom: 30px;
+ font-weight: 500;
+ line-height: 1.7;
+ p {
+ }
+ }
+ input {
+ text-align: center;
+ border-radius: 8px;
+ font-size: 20px;
+ padding: 8px 0px;
+ direction: ltr;
+ &:focus {
+ &::placeholder {
+ opacity: 0.3;
+ }
+ }
+ }
+ button {
+ margin-top: 25px;
+ font-size: 17px;
+ }
+ }
+ &__info {
+ width: 350px;
+ margin: 30px auto 0px;
+ text-align: center;
+ font-size: 13px;
+ }
+ &__back {
+ margin-bottom: 60px;
+ a {
+ font-size: 13px;
+ }
+ .desktop {
+ img {
+ transform: rotate(-90deg);
+ }
+ }
+ }
+ &__error {
+ margin-top: 10px;
+ color: $red1;
+ font-size: 14px;
+ }
+ }
+}
+
+@media screen and (min-width: 1008px) and (max-width: 1440px) {
+ .signup {
+ section {
+ width: 350px;
+ b {
+ color: white;
+ font-size: calc(100vw / 90);
+ margin-bottom: 30px;
+ font-weight: 500;
+ p {
+ // font-size: calc(100vw / 140) !important;
+ }
+ }
+ input {
+ text-align: center;
+ border-radius: 8px;
+ font-size: calc(100vw / 75);
+ padding: 8px 0px;
+ direction: ltr;
+ &:focus {
+ &::placeholder {
+ opacity: 0.3;
+ }
+ }
+ }
+ button {
+ margin-top: 25px;
+ font-size: calc(100vw / 80);
+ }
+ }
+ &__info {
+ width: 300px;
+ margin: 20px auto 0px;
+ text-align: center;
+ font-size: calc(100vw / 110);
+ }
+ &__back {
+ margin-bottom: 50px;
+ a {
+ font-size: calc(100vw / 110);
+ }
+ .desktop {
+ img {
+ transform: rotate(-90deg);
+ }
+ }
+ }
+ &__error {
+ margin-top: 10px;
+ color: $red1;
+ font-size: calc(100vw / 110);
+ }
+ }
+}
+
+@media screen and (min-width: 641px) and (max-width: 1007px) {
+ .signup {
+ .footer {
+ display: none !important;
+ }
+ section {
+ width: 90%;
+ max-width: 700px;
+ height: calc(100% - 60px);
+ justify-content: center;
+ b {
+ color: white;
+ font-size: calc(100vw / 35);
+ margin-bottom: 70px;
+ font-weight: 500;
+ p {
+ // font-size: calc(100vw / 30) !important;
+ }
+ }
+ input {
+ text-align: center;
+ border-radius: 8px;
+ font-size: calc(100vw / 30);
+ padding: 10px 14px;
+ direction: ltr;
+ &:focus {
+ &::placeholder {
+ opacity: 0.3;
+ }
+ }
+ }
+ button {
+ font-size: calc(100vw / 30);
+ width: 100%;
+ max-width: 400px;
+ margin: 50px auto 0px;
+ }
+ }
+ &__info {
+ width: 400px;
+ margin: 20px auto 0px;
+ text-align: center;
+ font-size: calc(100vw / 40);
+ }
+ &__back {
+ position: fixed;
+ top: 100px;
+ left: 30px;
+ margin-bottom: 50px;
+ a {
+ font-size: calc(100vw / 110);
+ }
+ img {
+ width: 50px;
+ }
+ }
+ &__error {
+ margin-top: 10px;
+ color: $red1;
+ font-size: calc(100vw / 110);
+ }
+ }
+}
+
+@media screen and (max-width: 640px) {
+ .signup {
+ section {
+ width: 90%;
+ max-width: 400px;
+ height: calc(100% - 60px);
+ justify-content: center;
+ b {
+ color: white;
+ font-size: calc(100vw / 25);
+ margin-bottom: 30px;
+ font-weight: 500;
+ p {
+ // font-size: calc(100vw / 30) !important;
+ }
+ }
+ input {
+ text-align: center;
+ border-radius: 8px;
+ font-size: calc(100vw / 22);
+ padding: 10px 14px;
+ direction: ltr;
+ &:focus {
+ &::placeholder {
+ opacity: 0.3;
+ }
+ }
+ }
+ button {
+ margin-top: 20px;
+ font-size: calc(100vw / 24);
+ padding: 12px 0px;
+ border: 0px;
+ border-radius: 10px;
+ }
+ }
+ &__info {
+ width: 300px;
+ margin: 30px auto 0px;
+ text-align: center;
+ font-size: calc(100vw / 30);
+ line-height: 1.5;
+ }
+ &__back {
+ position: fixed;
+ top: 70px;
+ left: 20px;
+ margin-bottom: 50px;
+ a {
+ font-size: calc(100vw / 110);
+ }
+ }
+ &__error {
+ margin-top: 10px;
+ color: $red1;
+ font-size: calc(100vw / 30);
+ }
+ }
+}
diff --git a/src/views/Auth/index.js b/src/views/Auth/index.js
new file mode 100644
index 0000000..8b656df
--- /dev/null
+++ b/src/views/Auth/index.js
@@ -0,0 +1,24 @@
+import React, {useState, useEffect} from 'react';
+import SignUp from './SignUp/index';
+import Profile from './Profile/index';
+import Login from './Login/index';
+import {connect} from 'react-redux';
+
+
+function Auth(props) {
+ const [page, setPage] = useState(props.page);
+ useEffect(() => {
+ setPage(() => props.page);
+ },[props.page]);
+ return (
+ <>
+ { page === 'signup' && }
+ { page === 'login' && }
+ { page === 'profile' && }
+ >
+ )
+}
+
+export default connect((state) => ({
+ theme : state.publicApi.theme,
+}))(Auth);
\ No newline at end of file
diff --git a/src/views/Auth/index.scss b/src/views/Auth/index.scss
new file mode 100644
index 0000000..43f8168
--- /dev/null
+++ b/src/views/Auth/index.scss
@@ -0,0 +1,3 @@
+@import './Login/index.scss';
+@import './Profile/index.scss';
+@import './SignUp/index.scss';
\ No newline at end of file
diff --git a/src/views/Home/Landscape/index.js b/src/views/Home/Landscape/index.js
index aabc71a..a238d68 100644
--- a/src/views/Home/Landscape/index.js
+++ b/src/views/Home/Landscape/index.js
@@ -28,6 +28,7 @@ function Home({
// initialState
useEffect(() => {
+
window.addEventListener("scroll", () => {
const scrollY = window.scrollY;
localStorage.setItem("prevScroll", scrollY);
diff --git a/src/views/Home/Portrait/Private/Blogs/index.js b/src/views/Home/Portrait/Private/Blogs/index.js
index 6432b65..e09398a 100644
--- a/src/views/Home/Portrait/Private/Blogs/index.js
+++ b/src/views/Home/Portrait/Private/Blogs/index.js
@@ -43,8 +43,8 @@ const Blog = ({ blog }) => {
background: `url(https://dnvn.ir/api/v1/file/${blog?.fileIds})`,
backgroundPosition: "contain",
backgroundSize: "100% 100%",
- minWidth: "calc(100vw / 1.3)",
- minHeight: "calc(100vw / 1.3 * 2 / 3)",
+ width: 280,
+ minHeight: 220,
}}
>
diff --git a/src/views/Home/Portrait/Private/Shop/index.js b/src/views/Home/Portrait/Private/Shop/index.js
index 2b358a3..5ca77f0 100644
--- a/src/views/Home/Portrait/Private/Shop/index.js
+++ b/src/views/Home/Portrait/Private/Shop/index.js
@@ -16,9 +16,9 @@ function Shop({ list, getList, grades, isDark }) {
{list.map((book, index) => (
@@ -45,8 +45,8 @@ const Book = ({ book, index }) => {
alt=""
className="rounded-sm"
style={{
- minWidth: "calc(100vh / 3 * 3 / 5)",
- maxHeight: "calc(100vh / 3)",
+ width: 200,
+ height: 303,
}}
/>
) : (
@@ -55,8 +55,8 @@ const Book = ({ book, index }) => {
alt=""
className="rounded-sm"
style={{
- minWidth: "calc(100vh / 6 * 3 / 5)",
- maxHeight: "calc(100vh / 6 - 5px)",
+ width: 100,
+ height: 148,
marginBottom: index % 2 !== 0 ? "8px" : "0px",
}}
/>
diff --git a/src/views/Product/index.js b/src/views/Product/index.js
index 5d715d6..c4d3a62 100644
--- a/src/views/Product/index.js
+++ b/src/views/Product/index.js
@@ -1,13 +1,23 @@
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
-import { book } from "../../redux/actions";
+import { toast } from "react-toastify";
+import { book, userProduct } from "../../redux/actions";
+import proxy from "../../redux/proxy";
import location from "../../utils/location";
import Button from "../../components/Button";
import Header from "../../components/Header";
import Comment from "./Comment";
import Rate from "./Rate";
-export const Product = ({ productType, getInfo, book, grades, isDark }) => {
+export const Product = ({
+ productType,
+ getInfo,
+ book,
+ grades,
+ isDark,
+ userId,
+ pushToCart,
+}) => {
useEffect(() => {
getInfo({ id: location.getId() });
}, []);
@@ -69,6 +79,15 @@ export const Product = ({ productType, getInfo, book, grades, isDark }) => {