reza added redux to home and completed desktop login

master
RezaAshrafi77 3 years ago
parent 9d3223090f
commit 924177ecc2
  1. 51
      src/components/Input/index.js
  2. 18
      src/redux/actions-type/blog.tsx
  3. 24
      src/redux/actions-type/book.tsx
  4. 4
      src/redux/actions-type/index.tsx
  5. 2
      src/redux/actions-type/public.tsx
  6. 28
      src/redux/actions/blog.tsx
  7. 38
      src/redux/actions/book.tsx
  8. 4
      src/redux/actions/index.tsx
  9. 29
      src/redux/reducers/blog.tsx
  10. 129
      src/redux/reducers/book.tsx
  11. 4
      src/redux/reducers/index.tsx
  12. 14
      src/util/onInput.js
  13. 280
      src/views/Auth/Login/index.scss
  14. 89
      src/views/Auth/Login/index.tsx
  15. 70
      src/views/Auth/SignUp/index.scss
  16. 84
      src/views/Auth/SignUp/index.tsx
  17. 6
      src/views/Auth/index.tsx
  18. 6
      src/views/Home/Blogs/Blog/index.tsx
  19. 68
      src/views/Home/Blogs/index.tsx
  20. 5
      src/views/Home/Books/Book/index.scss
  21. 4
      src/views/Home/Books/Book/index.tsx
  22. 4
      src/views/Home/Books/index.scss
  23. 31
      src/views/Home/Books/index.tsx

@ -0,0 +1,51 @@
import React from "react";
import TextField from "@material-ui/core/TextField";
import { makeStyles } from "@material-ui/core/styles";
export default function FormPropsTextFields(props) {
const useStyles = makeStyles((theme) => ({
root: {
"& .MuiTextField-root": {
width: "100%",
position: "relative",
marginRight: 10,
"& input": {
textAlign: props.align,
direction: props.align === "right" ? "rtl" : "ltr",
},
fontFamily: "numeralLight",
},
},
}));
const classes = useStyles();
const { defaultValue, maxLength, inputMode, onInput, variant, onChange } =
props;
return (
<form className={classes.root} noValidate autoComplete="off">
<div>
<TextField
id="outlined-basic"
name={props.name}
label={props.label}
variant={variant || "outlined"}
onChange={(e) => onChange(e.target.name, e.target.value)}
defaultValue={defaultValue[props.name] || ""}
inputProps={{ maxLength }}
onInput={
onInput
? (e) => (e.target.value = onInput(e.target.value))
: () => {}
}
/>
</div>
</form>
);
}
FormPropsTextFields.defaultProps = {
align: "right",
maxLength: "",
inputMode: "numeric",
defaultValue: "",
};

@ -0,0 +1,18 @@
interface list {
type : "public/blogList"
data : any
}
interface error{
type : "blog/error"
data : undefined
}
interface loading{
type : "blog/loading"
data : undefined
}
type BlogAction = list | loading | error;
export default BlogAction;

@ -0,0 +1,24 @@
interface list {
type : "book/list"
data : any
}
interface info{
type : "book/info"
data : any
}
interface error{
type : "book/error"
data : undefined
}
interface loading{
type : "book/loading"
data : undefined
}
type BookAction = list | info | loading | error;
export default BookAction;

@ -1,3 +1,7 @@
// @create-index
export type { default as PublicAction } from "./public";
export type { default as UserAction } from "./user";
export type { default as BookAction } from "./book";
export type { default as BlogAction } from "./blog";

@ -28,6 +28,6 @@ interface loading{
// }
type PublicAction =getBlogList | getBlogInfo | getHomeData | loading | error;
type PublicAction = getBlogList | getBlogInfo | getHomeData | loading | error;
export default PublicAction;

@ -0,0 +1,28 @@
import proxy from "../proxy";
import { Dispatch } from "redux";
const blog = {
list:
(data = {}) =>
async (dispatch : Dispatch) =>
await proxy.get("public/blogList", data, { dispatch }),
// update:
// (data = {}, data2 = {}) =>
// async (dispatch : Dispatch) => {
// await proxy.put("blog/update", data);
// await proxy.get("blog/list", data2, { dispatch });
// },
// add:
// (data = {}, data2 = {}) =>
// async (dispatch : Dispatch) => {
// await proxy.post("blog/add", data);
// await proxy.get("blog/list", data2, { dispatch });
// },
// del:
// (data = {}, data2 = {}) =>
// async (dispatch : Dispatch) => {
// await proxy.delete("blog/delete", data);
// await proxy.get("blog/list", data2, { dispatch });
// },
};
export default blog;

@ -0,0 +1,38 @@
import proxy from "../proxy";
import { Dispatch } from "redux";
const book = {
list:
(data = {}) =>
async (dispatch : Dispatch) =>
await proxy.get("book/list", data, { dispatch }),
info:
(data = {}) =>
async (dispatch : Dispatch) =>
await proxy.get("book/info", data, { dispatch }),
// update:
// (data = {}, data2 = {}) =>
// async (dispatch : Dispatch) => {
// await proxy.put("book/update", data);
// await proxy.get("book/list", data2, { dispatch });
// },
// add:
// (data = {}, data2 = {}) =>
// async (dispatch) => {
// await proxy.post("book/add", data);
// await proxy.get("book/list", data2, { dispatch });
// },
// del:
// (data = {}, data2 = {}) =>
// async (dispatch) => {
// await proxy.delete("book/delete", data);
// await proxy.get("book/list", data2, { dispatch });
// },
// searchBook: (data) => async (dispatch) => {
// dispatch({ type: "book/search", data: data });
// },
// filterBook: (data) => async (dispatch) => {
// dispatch({ type: "book/filter", data: data });
// },
};
export default book;

@ -1,4 +1,8 @@
// @create-index
export { default as publicApi } from "./public";
export { default as user } from "./user";
export { default as book } from "./book";
export { default as blog } from "./blog";

@ -0,0 +1,29 @@
import { toast } from "react-toastify";
import {BlogAction} from '../actions-type';
const initialState = {
loading: false,
error: null,
list: [],
};
export default function blog(state = initialState, action : BlogAction) {
let { type, data } = action;
switch (type) {
case "public/blogList":
return { ...state, loading: false, list: data, error: null };
// case "blog/update":
// return { ...state, loading: false, error: null };
// case "blog/add":
// return { ...state, loading: false, error: null };
// case "blog/delete":
// return { ...state, loading: false, error: null };
/////////////
case "blog/loading":
return { ...state, loading: true };
case "blog/error":
toast.error(data.message);
return { ...state, loading: false, error: data.message };
default:
return state;
}
}

@ -0,0 +1,129 @@
import { toast } from "react-toastify";
import { BookAction } from "../actions-type";
const initialState = {
loading: false,
error: null,
list: [],
info: null,
searchResult: [],
filterResult: [],
subjects: [],
levels: [],
sortFilters: ["مرتب سازی", "محبوب ترین", "جدیدترین"],
};
const grades = [
"پیش دبستان",
"اول",
"دوم",
"سوم",
"چهارم",
"پنجم",
"ششم",
"هفتم",
"هشتم",
"نهم",
"دهم",
"یازدهم",
"دوازدهم",
];
export default function book(state = initialState, action : BookAction) {
let { type, data } = action;
switch (type) {
case "book/list":
let itemsSubject = (Array.isArray(data) ? data : []).map(
(item, index) => item.name
);
if (window.innerWidth < 1000) {
itemsSubject.unshift("نام کتاب");
}
let itemsLevel = (Array.isArray(data) ? data : [])
.map((item) => item.gradeId * 1)
.sort((a, b) => a - b)
.map((e) => grades[e]);
if (window.innerWidth < 1000) {
itemsLevel.unshift("پایه تحصیلی");
}
return {
...state,
loading: false,
list: data,
subjects: Array.from(new Set(itemsSubject)),
levels: Array.from(new Set(itemsLevel)),
filterResult: data,
error: null,
};
case "book/info":
return { ...state, loading: false, info: data, error: null };
// case "book/update":
// return { ...state, loading: false, error: null };
// case "book/add":
// return { ...state, loading: false, error: null };
// case "book/delete":
// return { ...state, loading: false, error: null };
// case "book/search":
// return { ...state };
// case "book/filter":
// const realList = state.list;
// const level = data.level;
// const subject = data.subject;
// const sort = data.sort;
// const search = data.search;
// if (level.length > 0 || subject.length > 0 || sort || search) {
// localStorage.setItem("filter", "ON");
// }
// let finalSort;
// let byLevelFilter = [];
// if (level.length > 0) {
// level.map((item1) => {
// for (let i = 0; i < realList.length; i++) {
// if (grades[realList[i].gradeId] === item1) {
// byLevelFilter.push(realList[i]);
// }
// }
// });
// } else {
// byLevelFilter = realList;
// }
// let bySubjectFilter = [];
// if (subject.length > 0) {
// subject.map((item1) => {
// for (let i = 0; i < byLevelFilter.length; i++) {
// if (byLevelFilter[i].name === item1) {
// bySubjectFilter.push(byLevelFilter[i]);
// }
// }
// });
// } else {
// bySubjectFilter = byLevelFilter;
// }
// const bySearchFilter = search
// ? bySubjectFilter.filter((item1) => item1.name.indexOf(search) !== -1)
// : bySubjectFilter;
// if (sort === "گران ترین") {
// finalSort = bySearchFilter.sort((item1, item2) => {
// return item1.product[0].price - item2.product[0].price;
// });
// } else {
// finalSort = bySearchFilter;
// }
// return {
// ...state,
// loading: false,
// error: null,
// filterResult: finalSort,
// };
case "book/loading":
return { ...state, loading: true };
case "book/error":
toast.error(data.message);
return { ...state, loading: false, error: data.message };
default:
return state;
}
}

@ -1,3 +1,7 @@
// @create-index
export { default as publicApi } from "./public";
export { default as user } from "./user";
export { default as book } from "./book";
export { default as blog } from "./blog";

@ -72,7 +72,7 @@ class onInput {
newText = newText.replace(/N/g, "");
newText = newText.replace(/M/g, "");
newText = newText.replace(/\?/g, "");
if (!newText) {
if (!newText && newText.length !== 0) {
toast.info("از کاراکتر فارسی استفاده کنید");
}
return newText;
@ -131,7 +131,7 @@ class onInput {
newText = newText.replace(/ه/g, "");
newText = newText.replace(/ی/g, "");
newText = newText.replace(/\?/g, "");
if (!newText) {
if (!newText && newText.length !== 0) {
toast.info("از کاراکتر انگلیسی واعداداستفاده کنید");
}
return newText;
@ -238,7 +238,7 @@ class onInput {
newText = newText.replace(/B/g, "");
newText = newText.replace(/N/g, "");
newText = newText.replace(/M/g, "");
if (!newText) {
if (!newText && newText.length !== 0) {
toast.info("از اعداداستفاده کنید");
}
return newText;
@ -267,6 +267,14 @@ class onInput {
}
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();

@ -0,0 +1,280 @@
.login {
width: 100%;
height: 100vh;
position: relative;
font-family: numeralLight;
&__options{
color: #B5B5B5;
a {
color: #84de56;
}
}
img {
transform: rotate(-90deg);
}
.MuiButtonBase-root{
padding: 0px !important;
}
background: linear-gradient(
135deg,
hsla(0, 0%, 31%, 1) 0%,
hsla(0, 0%, 0%, 1) 100%
);
background: -moz-linear-gradient(
135deg,
hsla(0, 0%, 31%, 1) 0%,
hsla(0, 0%, 0%, 1) 100%
);
background: -webkit-linear-gradient(
135deg,
hsla(0, 0%, 31%, 1) 0%,
hsla(0, 0%, 0%, 1) 100%
);
.footer {
position: fixed;
bottom: 0px;
left: 0px;
}
}
@media screen and (min-width: 1441px) {
.login {
section {
width: 410px;
b {
color: white;
font-size: 20px;
margin-bottom: 30px;
font-weight: 500;
p {
font-size: 16px;
}
}
button {
margin-top: 25px;
background-color: #84de56;
color: white;
font-size: 20px;
padding: 10px 0px;
border: 0px;
border-radius: 10px;
}
}
&__info {
width: 350px;
margin: 40px auto 0px;
text-align: center;
color: white;
font-size: 14px;
a {
color: #84de56;
}
}
&__back {
margin-bottom: 60px;
a {
color: white;
font-size: 13px;
}
}
&__options{
div{
font-size: 13px;
}
a{
font-size: 15px;
}
}
.MuiFormControl-root {
width: 100%;
margin: 10px auto !important;
.MuiSelect-iconOutlined {
display: none;
}
.MuiSelect-outlined.MuiSelect-outlined {
padding-right: 15px;
}
color: #797979 !important;
}
.MuiOutlinedInput-notchedOutline {
top: 0px !important;
}
.MuiOutlinedInput-notchedOutline {
border-color: #666666 !important;
border-width: 1px !important;
color: green !important;
border-radius: 10px !important;
}
.MuiOutlinedInput-input {
padding: 15px 14px !important;
font-family: numeralLight;
font-size: 20px;
&:focus{
border: 0.2px solid #84de56 !important;
border-radius: 10px;
transform : translateY(0.5px);
}
}
.MuiInputLabel-outlined {
font-family: numeralLight !important;
display: inline !important;
position: absolute;
text-align: right !important;
right: 15px;
top: 22px;
padding: 0px !important;
transform: translate(0px, 0px) scale(1) !important;
}
.MuiInputLabel-shrink {
text-align: center !important;
display: inline;
position: absolute;
right: 0px;
top: -8px;
transform: translate(0px, 0px) scale(0.85) !important;
padding: 0px 10px !important;
}
label {
background-color: #2F2F2F;
width: fit-content;
text-align: center;
color: #B5B5B5 !important;
letter-spacing: -1px;
font-size: 16px;
}
.Mui-focused {
color: rgba(0, 0, 0, 1) !important;
border-color: #84de56 !important;
// background-color: white;
color: #84de56 !important;
}
.MuiInputBase-input {
height: auto !important;
}
}
}
@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 {
margin-top: 25px;
background-color: #84de56;
color: white;
font-size: calc(100vw / 80);
padding: 10px 0px;
border: 0px;
border-radius: 10px;
}
}
&__info {
width: 300px;
margin: 40px auto 0px;
text-align: center;
color: white;
font-size: calc(100vw / 110);
a {
color: #84de56;
}
}
&__back {
margin-bottom: 40px;
a {
color: white;
font-size: calc(100vw / 110);
}
}
&__options{
div{
font-size: calc(100vw / 110);
}
a{
font-size: calc(100vw / 110);
}
}
.MuiFormControl-root {
width: 100%;
margin: 10px auto !important;
.MuiSelect-iconOutlined {
display: none;
}
.MuiSelect-outlined.MuiSelect-outlined {
padding-right: 15px;
}
color: #797979 !important;
}
.MuiOutlinedInput-notchedOutline {
top: 0px !important;
}
.MuiOutlinedInput-notchedOutline {
border-color: #666666 !important;
border-width: 1px !important;
color: green !important;
border-radius: 10px !important;
}
.MuiOutlinedInput-input {
padding: 10px 14px !important;
font-family: numeralLight;
font-size: calc(100vw / 80);
&:focus{
border: 0.2px solid #84de56 !important;
border-radius: 10px;
transform : translateY(0px);
z-index: 100;
}
}
.MuiInputLabel-outlined {
font-family: numeralLight !important;
display: inline !important;
position: absolute;
text-align: right !important;
right: 15px;
top: calc(50%);
padding: 0px !important;
transform: translate(0px, -50%) scale(1) !important;
}
.MuiInputLabel-shrink {
text-align: center !important;
display: inline;
position: absolute;
right: 0px;
top: -8px;
transform: translate(0px, 0px) scale(0.85) !important;
padding: 0px 10px !important;
}
label {
background-color: #2F2F2F;
width: fit-content;
text-align: center;
color: #B5B5B5 !important;
letter-spacing: -1px;
font-size: calc(100vw / 100);
z-index: 110;
}
.Mui-focused {
color: rgba(0, 0, 0, 1) !important;
border-color: #84de56 !important;
// background-color: white;
color: #84de56 !important;
}
.MuiInputBase-input {
height: auto !important;
}
}
}

@ -1,9 +1,88 @@
import React from 'react'
import React, { useState } from "react";
import Navbar from "../../../components/Navbar/index";
import Footer from "../../../views/Home/Footer/index";
import Input from "../../../components/Input/index";
import Checkbox from "@material-ui/core/Checkbox";
import CheckBoxOutlineBlankTwoToneIcon from "@material-ui/icons/CheckBoxOutlineBlankTwoTone";
import CheckBoxRoundedIcon from "@material-ui/icons/CheckBoxRounded";
export default function Login() {
import { Link } from "react-router-dom";
import arrow from "../../../assets/icons/dropdown.png";
import onInput from "../../../util/onInput";
import { connect, useSelector } from "react-redux";
import { user } from "../../../redux/actions";
import "./index.scss";
interface LoginFields {
username?: string;
password?: string;
}
function Login(props: any) {
const [loginFields, setSignUpFiels] = useState<LoginFields | undefined>(
undefined
);
const onChange = (name: string, value: string) => {
setSignUpFiels({ ...loginFields, [name]: value });
};
return (
<div>
<div className="login d-flex flex-column align-items-center justify-content-center">
<Navbar />
<section className="d-flex flex-column">
<div className="login__back d-flex justify-content-end">
<Link to="/sign-up" className="d-flex align-items-center">
بازگشت به صفحه قبل
<img src={arrow} />
</Link>
</div>
<b>
سلام
<br />
خوش برگشتی!
</b>
<Input
name="username"
label="نام کاربری"
align="left"
onInput={onInput.englishAndNumberWithoutSpace}
onChange={onChange}
/>
<Input
name="password"
label="رمز عبور"
align="left"
onInput={onInput.englishAndNumberWithoutSpace}
onChange={onChange}
/>
<div className="login__options d-flex justify-content-between align-items-center">
<div className="d-flex align-items-center">
<Checkbox
icon={
<CheckBoxOutlineBlankTwoToneIcon
style={{ color: "#666666", fontSize: 30, padding: 0 }}
/>
}
checkedIcon={
<CheckBoxRoundedIcon
style={{ color: "#84DE56", fontSize: 30, padding: 0 }}
/>
}
/>
مرا به خاطر بسپار
</div>
<Link to="/forget">رمز عبور خود را فراموش کردهاید؟</Link>
</div>
<button type="submit" onClick={() => props.login(loginFields)}>
ورود
</button>
<p className="login__info" onClick={() => props.setPage("signup")}>
<Link to="/sign-up">ساخت حساب کاربری</Link>
</p>
</section>
<Footer />
</div>
)
);
}
export default connect(() => ({}), { login: user.otp_login })(Login);

@ -85,5 +85,75 @@
font-size: 13px;
}
}
&__error{
margin-top: 10px;
color: rgb(255, 115, 115);
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;
background-color: #2a2a2a;
border: 1px solid #a2a2a2;
border-radius: 8px;
font-size: calc(100vw / 75);
padding: 8px 0px;
color: white;
direction: ltr;
&:focus {
border: 1px solid #84de56;
&::placeholder {
color: #84de56;
opacity: 0.3;
}
}
}
button {
margin-top: 25px;
background-color: #84de56;
color: white;
font-size: calc(100vw / 80);
padding: 10px 0px;
border: 0px;
border-radius: 10px;
}
}
&__info {
width: 300px;
margin: 20px auto 0px;
text-align: center;
color: white;
font-size: calc(100vw / 110);
a {
color: #84de56;
}
}
&__back {
margin-bottom: 50px;
a {
color: white;
font-size: calc(100vw / 110);
}
}
&__error{
margin-top: 10px;
color: rgb(255, 115, 115);
font-size: calc(100vw / 110);
}
}
}

@ -1,40 +1,82 @@
import React, { useState } from "react";
import Navbar from "../../../components/Navbar/index";
import Footer from "../../../views/Home/Footer/index";
import onInput from "../../../util/onInput";
import { Link } from "react-router-dom";
import arrow from "../../../assets/icons/dropdown.png";
import "./index.scss";
import { connect, useSelector } from "react-redux";
import { user } from "../../../redux/actions";
interface SignUpFields {
phonenumber?: String;
cellphone?: String;
otp?: String;
}
export default function SignUp() {
const [level, setLevel] = useState("otp");
const [signUpFiels, setSignUpFiels] = useState<SignUpFields | undefined>(
function SignUp(props : any) {
const [level, setLevel] = useState("phonenumber");
const [signUpFields, setSignUpFiels] = useState<SignUpFields | undefined>(
undefined
);
const [error, setError] = useState<string | undefined>(undefined);
const onChange = (name: string, value: string) => {
setSignUpFiels({ ...signUpFields, [name]: value });
};
const submitPhoneNumber = () => {
if(signUpFields?.cellphone?.slice(0,2) === '09' && signUpFields?.cellphone.length === 11){
setLevel("otp");
props.submitOtp({cellphone : signUpFields?.cellphone});
setError(undefined);
}else{
setError('شماره موبایل خود را چک کنید.');
}
}
const submitOTP = () => {
if( signUpFields?.otp?.length === 4){
props.submitOtp({cellphone : signUpFields?.cellphone});
setError(undefined);
}else{
setError('کد وارد شده را چک کنید.');
}
}
return (
<div className="signup d-flex flex-column align-items-center justify-content-center">
<Navbar />
{level === "phonenumber" && (
<section className="d-flex flex-column">
<div className="signup__back d-flex justify-content-end">
{/* <div className="signup__back d-flex justify-content-end">
<Link to="/sign-up" className="d-flex align-items-center">
بازگشت به صفحه قبل
<img src={arrow} />
</Link>
</div>
</div> */}
<b>
ثبت نام
<br />
لطفا شماره موبایل خود را وارد کنید.
</b>
<input type="text" inputMode="numeric" placeholder="09123456789" />
<button type="submit">ادامه</button>
<input
type="text"
name="cellphone"
inputMode="numeric"
placeholder="09123456789"
maxLength={11}
onChange={(e) => onChange(e.target.name, e.target.value)}
onInput={({ target }) =>
((target as HTMLInputElement).value = onInput.phonenumber(
(target as HTMLInputElement).value
))
}
/>
<span className="signup__error">{error}</span>
<button type="submit" onClick={() => submitPhoneNumber()}> ادامه</button>
<p className="signup__info">
با ثبت نام در سرویس ویدئویی دانوین قوانین
<Link to="/"> شرایط استفاده و حریم خصوصی </Link>
@ -44,7 +86,7 @@ export default function SignUp() {
)}
{level === "otp" && (
<section className="d-flex flex-column">
<div className="signup__back d-flex justify-content-end">
<div className="signup__back d-flex justify-content-end" onClick={() => setLevel('phonenumber')}>
<Link to="/sign-up" className="d-flex align-items-center">
بازگشت به صفحه قبل
<img src={arrow} />
@ -54,17 +96,29 @@ export default function SignUp() {
تاییدیه شماره موبایل
<br />
<p>
کد ارسال شده به شماره {signUpFiels?.phonenumber} را وارد کنید.
کد ارسال شده به شماره {signUpFields?.cellphone} را وارد کنید.
</p>
</b>
<input type="text" inputMode="numeric" />
<button type="submit">ادامه</button>
<p className="signup__info">
</p>
<input
type="text"
inputMode="numeric"
name="otp"
onChange={(e) => onChange(e.target.name, e.target.value)}
onInput={({ target }) =>
((target as HTMLInputElement).value = onInput.numberOnly(
(target as HTMLInputElement).value
))
}
/>
<span className="signup__error">{error}</span>
<button type="submit" onClick={() => submitOTP()}>ادامه</button>
<p className="signup__info"></p>
</section>
)}
<Footer />
</div>
);
}
export default connect(() => ({
}), {submitSignUp : user.otp_login, submitOtp : user.otp})(SignUp);

@ -1,14 +1,14 @@
import React from 'react';
import React, {useState} from 'react';
import SignUp from './SignUp/index';
import Profile from './Profile/index';
import Login from './Login/index';
export default function Auth(props : any) {
const {page} = props;
const [page, setPage] = useState(props.page);
return (
<>
{ page === 'signup' && <SignUp /> }
{ page === 'login' && <Login /> }
{ page === 'login' && <Login setPage={setPage} /> }
{ page === 'profile' && <Profile /> }
</>
)

@ -7,15 +7,15 @@ export default function Blog(props: any) {
return (
<Link to={'/'}
className="home-blogs-blog d-flex align-items-end"
style={{ background: `url(${data.imageUrl})` }}
style={{ background: `url(https://dnvn.ir/api/v1/file/${data.fileIds})` }}
draggable={'false'}
>
{/* <img src={data.imageUrl} alt={data.name} /> */}
<div className="home-blogs-blog__cover"></div>
<footer className="d-flex">
<div className="home-blogs-blog__info d-flex flex-column">
<h2>{data.name}</h2>
<p>{data.text.slice(0, 49)}</p>
<h2>{data.title}</h2>
{/* <p>{data.text.slice(0, 49)}</p> */}
</div>
</footer>
</Link>

@ -1,12 +1,13 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import Carousell from "react-elastic-carousel";
import {Carousel} from "3d-react-carousal";
import { Carousel } from "3d-react-carousal";
import Blog from "./Blog/index";
import { Link } from "react-router-dom";
import { connect, useSelector } from "react-redux";
import { blog } from "../../../redux/actions";
import "./index.scss";
export default function Blogs(props: any) {
function Blogs(props: any) {
const slideNumberHandler = () => {
if (window.innerWidth >= 1440) {
return 3;
@ -19,28 +20,43 @@ export default function Blogs(props: any) {
}
};
const { number, blogs } = props;
const list = useSelector((state: any) => state.blog.list);
useEffect(() => {
props.getList();
}, []);
return (
<section className="home-blogs d-flex flex-column">
<header className="d-flex flex-column">
<h1>پیشنهادی برای شما</h1>
</header>
{window.innerWidth > 1007 ? (
<Carousell
itemsToShow={slideNumberHandler()}
isRTL={true}
enableTilt={false}
showArrows={false}
pagination={false}
>
{blogs.map((item: Object, i: Number) => (
<Blog data={item} key={i} />
))}
</Carousell>
) : (
<Carousel autoplay={false} arrows={false} slides={blogs.map((item: Object, i: Number) => (
<Blog data={item} key={i} />
))} />
)}
</section>
<section className="home-blogs d-flex flex-column">
<header className="d-flex flex-column">
<h1>پیشنهادی برای شما</h1>
</header>
{window.innerWidth > 1007 ? (
<Carousell
itemsToShow={slideNumberHandler()}
isRTL={true}
enableTilt={false}
showArrows={false}
pagination={false}
>
{list.map((item: Object, i: Number) => (
<Blog data={item} key={i} />
))}
</Carousell>
) : (
<Carousel
autoplay={false}
arrows={false}
slides={list.map((item: Object, i: Number) => (
<Blog data={item} key={i} />
))}
/>
)}
</section>
);
}
export default connect(
({ blog }: any) => ({
blog,
}),
{ getList: blog.list }
)(Blogs);

@ -1,6 +1,7 @@
.home-books-book{
padding: 0px 10px;
cursor: pointer;
border-bottom: 1px solid #424242;
img{
border-radius: 8px;
}
@ -9,7 +10,6 @@
}
&__info{
border-bottom: 1px solid #424242;
padding-bottom: 15px;
margin-right: 10px;
p {
@ -35,6 +35,7 @@
.home-books-book{
img{
height: 200px;
width: 170px;
}
h2{
font-size: 20px;
@ -52,7 +53,7 @@
.home-books-book{
img{
height: 200px;
width: 95%;
width: 100%;
}
h2{
font-size: calc(100vw / 80);

@ -6,11 +6,11 @@ export default function Book(props: any) {
const { data } = props;
return (
<Link to={'/'} className="home-books-book d-flex flex-column" draggable={'false'}>
<img src={data.imageUrl} alt={data.name} draggable={'false'} />
<img src={`https://dnvn.ir/api/v1/file/${data.fileIds}`} alt={data.name} draggable={'false'} />
<footer className="d-flex">
<div className="home-books-book__info d-flex flex-column">
<h2>{data.name}</h2>
<p>{data.text.slice(0, 50)}</p>
<p>{'لورم ایپسوم و اینجور چیزا'}</p>
</div>
</footer>
</Link>

@ -29,7 +29,7 @@
@media screen and (min-width: 1441px) {
.home-books {
max-width: 1250px;
max-width: 1350px;
header{
h1{
font-size: 20px;
@ -46,7 +46,7 @@
@media screen and (min-width: 1008px) and (max-width: 1440px) {
.home-books {
max-width: 1350px;
max-width: 1250px;
header{
h1{
font-size: calc(100vw / 60);

@ -1,11 +1,11 @@
import React from "react";
import React, { useEffect } from "react";
import { useSelector, connect } from "react-redux";
import Carousel from "react-elastic-carousel";
import Book from "./Book/index";
import { Link } from "react-router-dom";
import ExpandMoreRoundedIcon from "@material-ui/icons/ExpandMoreRounded";
import { book } from "../../../redux/actions";
import "./index.scss";
export default function Courses(props: any) {
function Books(props: any) {
const slideNumberHandler = () => {
if (window.innerWidth >= 1440) {
return 5;
@ -18,9 +18,19 @@ export default function Courses(props: any) {
}
};
const { number, courses } = props;
const list = useSelector((state: any) => state.book.list);
console.log(list);
useEffect(() => {
props.getList();
}, []);
return (
<section className="home-books d-flex flex-column">
{window.innerWidth > 1007 ? (
<section
className="home-books d-flex flex-column"
onClick={() => props.getList()}
>
{window.innerWidth > 1007 && list.length > 0 ? (
<Carousel
itemsToShow={slideNumberHandler()}
isRTL={true}
@ -28,7 +38,7 @@ export default function Courses(props: any) {
showArrows={true}
pagination={false}
>
{courses.map((item: Object, i: Number) => (
{list.map((item: Object, i: Number) => (
<Book data={item} key={i} />
))}
</Carousel>
@ -42,3 +52,10 @@ export default function Courses(props: any) {
</section>
);
}
export default connect(
({ book }: any) => ({
book,
}),
{ getList: book.list }
)(Books);

Loading…
Cancel
Save