reza completed home page api

master
RezaAshrafi77 3 years ago
parent e810e8b89d
commit be2401b918
  1. 48
      src/components/GradeFilter/index.tsx
  2. 6
      src/components/HomeSearchBox/index.scss
  3. 63
      src/components/HomeSearchBox/index.tsx
  4. 16
      src/custom.scss
  5. 53
      src/redux/actions-type/book.tsx
  6. 28
      src/redux/actions-type/faq.tsx
  7. 4
      src/redux/actions-type/index.tsx
  8. 33
      src/redux/actions-type/product.tsx
  9. 5
      src/redux/actions/book.tsx
  10. 14
      src/redux/actions/content.tsx
  11. 18
      src/redux/actions/faq.tsx
  12. 6
      src/redux/actions/index.tsx
  13. 27
      src/redux/actions/product.tsx
  14. 2
      src/redux/actions/user.tsx
  15. 14
      src/redux/actions/userFactor.tsx
  16. 10
      src/redux/actions/userProduct.tsx
  17. 96
      src/redux/reducers/book.tsx
  18. 35
      src/redux/reducers/faq.tsx
  19. 4
      src/redux/reducers/index.tsx
  20. 29
      src/redux/reducers/product.tsx
  21. 18
      src/views/Auth/SignUp/index.tsx
  22. 17
      src/views/Faq/index.tsx
  23. 8
      src/views/Home/Books/Book/index.scss
  24. 10
      src/views/Home/Books/index.scss
  25. 16
      src/views/Home/Books/index.tsx
  26. 8
      src/views/Home/Courses/Course/index.scss
  27. 12
      src/views/Home/Courses/Course/index.tsx
  28. 11
      src/views/Home/Courses/index.scss
  29. 5
      src/views/Home/Courses/index.tsx
  30. 111
      src/views/Home/index.tsx
  31. 32
      src/views/Subscription/SubscribeRadio/index.tsx
  32. 30
      src/views/Subscription/index.tsx

@ -1,28 +1,31 @@
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { book } from "../../redux/actions";
import "./index.scss";
import dropdown from "../../assets/icons/dropdown.png";
export default function GradeFilter(props: any) {
function GradeFilter({selectedGrade, gradeFilter, grades}: any) {
const [arrowTop, setArrowTop] = useState(false);
const { grades, grade, setGrade } = props;
useEffect(() => {
setArrowTop(false);
},[grade])
}, [selectedGrade]);
return (
<section className="grade-filter d-flex align-items-center">
<h1 className="d-flex align-items-center">
پایه تحصیلی
{window.innerWidth > 1007 ? <span></span> : null}
<span className="desktop"></span>
</h1>
<div
className="grade-filter__box d-flex"
onClick={() => setArrowTop(!arrowTop)}
>
{
grade ? <h2>{grade}</h2> : <span>پایه تحصیلی خود را انتخاب نمائید</span>
}
{selectedGrade ? (
<h2>{grades[selectedGrade - 1].name}</h2>
) : (
<span>پایه تحصیلی خود را انتخاب نمائید</span>
)}
<img
src={dropdown}
style={{ transform: !arrowTop ? "rotate(180deg)" : "rotate(0deg)" }}
@ -30,35 +33,38 @@ export default function GradeFilter(props: any) {
</div>
{arrowTop ? (
<ul className="grade-filter__list d-flex flex-wrap">
{grades.map((item: String, i: any) => (
{grades.map((item: any, i: any) => (
<li
key={i}
onClick={(e) =>
grade !== item ? setGrade(item) : setGrade(null)
onClick={() =>
gradeFilter(item.value)
}
className={grade === item ? "grade-filter__list--active" : ""}
className={selectedGrade === item.value ? "grade-filter__list--active" : ""}
>
{item}
{item.name}
</li>
))}
</ul>
) : null}
{window.innerWidth > 1007 ? (
<ul className="d-flex align-items-center">
{grades.map((item: String, i: any) => (
<ul className="desktop align-items-center">
{grades.map((item: any, i: any) => (
<li
key={i}
onClick={(e) =>
grade !== item ? setGrade(item) : setGrade(null)
}
className={grade === item ? "grade-filter__active" : ""}
onClick={(e) => gradeFilter(item.value)}
className={selectedGrade === item.value ? "grade-filter__active" : ""}
>
{item}
{item.name}
</li>
))}
</ul>
) : null}
</section>
);
}
export default connect(
(state: any) => ({
selectedGrade: state.book.selectedGrade,
}),
{ gradeFilter: book.gradeFilter }
)(GradeFilter);

@ -103,6 +103,9 @@
&__voice {
display: none;
}
&__searchIcon{
display: none;
}
form {
width: 85%;
input {
@ -147,7 +150,8 @@
&__searchIcon {
position: absolute;
left: 62px;
top: 9px;
top: 50%;
transform: translateY(-50%);
width: 27px;
}
form {

@ -1,25 +1,48 @@
import React, { useState } from "react";
import "./index.scss";
import { connect } from "react-redux";
import { book } from "../../redux/actions";
import search from "../../assets/icons/search.png";
import voice from "../../assets/icons/voice.png";
export default function HomeSearchBox(props: any) {
const { lastItems, setVocal, inputValue, setInputValue } = props;
function HomeSearchBox({
lastItems,
setVocal,
inputValue,
setInputValue,
sortFilter,
selectedSort,
}: any) {
const submitInput = (value: any) => {
setInputValue(value);
sortFilter({ search: value, sort: selectedSort });
};
const submitSort = (value: any) => {
sortFilter({ search: inputValue, sort: value });
};
return (
<section className="home-search-box d-flex flex-column align-items-center">
<form className="d-flex" onSubmit={(e) => e.preventDefault()}>
<input
type="search"
placeholder="نام درس یا دوره را جستجو کنید"
onChange={(e) => setInputValue(e.target.value)}
onChange={(e) => submitInput(e.target.value)}
value={inputValue}
/>
<button type="submit">
<button
type="submit"
onClick={() => sortFilter({ search: inputValue, sort: selectedSort })}
>
<img src={search} />
</button>
{window.innerWidth < 640 ? (
<img className="home-search-box__searchIcon" src={search} />
) : null}
<img
className="mobile home-search-box__searchIcon"
src={search}
onClick={() => sortFilter({ search: inputValue, sort: selectedSort })}
/>
<button
className="home-search-box__voice"
onClick={() => setVocal(true)}
@ -30,8 +53,12 @@ export default function HomeSearchBox(props: any) {
<ul className="d-flex">
{lastItems.map((item: any, i: any) => (
<li key={i} style={{ color: i === 0 ? "#9CDF52" : "" }}>
{item}
<li
key={i}
style={{ color: selectedSort === item.name ? "#9CDF52" : "" }}
onClick={() => sortFilter({ search: inputValue, sort: item.name })}
>
{item.name}
</li>
))}
</ul>
@ -39,6 +66,22 @@ export default function HomeSearchBox(props: any) {
);
}
export default connect(
(state: any) => ({
selectedSort: state.book.selectedSort,
}),
{ sortFilter: book.sortFilter }
)(HomeSearchBox);
HomeSearchBox.defaultProps = {
lastItems: ["دوره علوم تجربی", "دوره علوم انسانی", "تمامی دورهها"],
lastItems: [
{
name: "تمامی دورهها",
icon: "",
},
{
name: "جدیدترینها",
icon: "",
},
],
};

@ -84,7 +84,21 @@
}
.main {
background: black;
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%
);
width: 100%;
overflow-x: hidden;
padding-top: 60px;

@ -1,34 +1,51 @@
interface list {
type : "book/list"
data : any
type: "book/list";
data: any;
}
interface info{
type : "book/info"
data : any
interface info {
type: "book/info";
data: any;
}
interface setLessonActive{
type : "book/lesson/active"
data : any
interface setLessonActive {
type: "book/lesson/active";
data: any;
}
interface setVideoActive{
type : "book/video/active"
data : any
interface setVideoActive {
type: "book/video/active";
data: any;
}
interface error{
type : "book/error"
data : undefined
interface gradeFilter {
type: "book/gradeFilter";
data: any;
}
interface loading{
type : "book/loading"
data : undefined
interface sortFilter {
type: "book/sortFilter";
data: any;
}
interface error {
type: "book/error";
data: undefined;
}
interface loading {
type: "book/loading";
data: undefined;
}
type BookAction = list | info | setVideoActive | setLessonActive | loading | error;
type BookAction =
| list
| info
| setVideoActive
| setLessonActive
| gradeFilter
| sortFilter
| loading
| error;
export default BookAction;

@ -0,0 +1,28 @@
interface list {
type : "faq/list"
data : any
}
interface add {
type : "faq/add"
data : any
}
interface selectFaq{
type : "faq/selectFaq"
data : any
}
interface error{
type : "faq/error"
data : undefined
}
interface loading{
type : "faq/loading"
data : undefined
}
type FaqAction = list | add | selectFaq | loading | error;
export default FaqAction;

@ -3,5 +3,9 @@ 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";
export type { default as productAction } from "./product";
export type { default as FaqAction } from "./faq";

@ -0,0 +1,33 @@
interface ListVOD {
type : "product/listVOD"
data : any
}
interface AddVOD {
type : "product/addVOD"
data : any
}
interface DeleteVOD{
type : "product/deleteVOD"
data : any
}
interface SelectVOD{
type : "product/selectVOD"
data : any
}
interface error{
type : "product/error"
data : undefined
}
interface loading{
type : "product/loading"
data : undefined
}
type productAction = ListVOD | AddVOD | DeleteVOD | SelectVOD | loading | error;
export default productAction;

@ -9,11 +9,14 @@ const book = {
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("book/info", data, { dispatch }),
setLessonActive: (data: undefined) => async (dispatch: Dispatch) =>
await dispatch({ type: "book/lesson/active", data: data }),
setVideoActive: (data: undefined) => async (dispatch: Dispatch) =>
await dispatch({ type: "book/video/active", data: data }),
gradeFilter: (data: undefined) => async (dispatch: Dispatch) =>
await dispatch({ type: "book/gradeFilter", data: data }),
sortFilter: (data: undefined) => async (dispatch: Dispatch) =>
await dispatch({ type: "book/sortFilter", data: data }),
// update:
// (data = {}, data2 = {}) =>
// async (dispatch : Dispatch) => {

@ -0,0 +1,14 @@
import proxy from "../proxy";
import { Dispatch } from "redux";
const content = {
listVOD:
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("content/listVOD", data, { dispatch }),
infoVOD:
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("content/infoVOD", data, { dispatch }),
};
export default content;

@ -0,0 +1,18 @@
import proxy from "../proxy";
import { Dispatch } from "redux";
const faq = {
list:
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("faq/list", data, { dispatch }),
add:
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.post("faq/add", data, { dispatch }),
selectFaq:
(data = {}) =>
async (dispatch: Dispatch) =>
await dispatch({ type: "faq/selectFaq", data: data }),
};
export default faq;

@ -3,6 +3,12 @@ export { default as publicApi } from "./public";
export { default as user } from "./user";
export { default as book } from "./book";
export { default as blog } from "./blog";
export { default as product } from "./product";
export { default as userFactor } from "./userFactor";
export { default as userProduct } from "./userProduct";
export { default as content } from "./content";
export { default as faq } from "./faq";

@ -0,0 +1,27 @@
import proxy from "../proxy";
import { Dispatch } from "redux";
const product = {
listVOD:
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("product/listVOD", data, { dispatch }),
addVOD:
(data = {}, data2 = {}) =>
async (dispatch: Dispatch) => {
await proxy.post("product/addVOD", data);
await proxy.get("product/listVOD", data2, { dispatch });
},
deleteVOD:
(data = {}, data2 = {}) =>
async (dispatch: Dispatch) => {
await proxy.delete("product/deleteVOD", data);
await proxy.get("product/listVOD", data2, { dispatch });
},
selectVOD:
(data = {}) =>
async (dispatch: Dispatch) => {
await dispatch({ type: "product/selectVOD", data });
},
};
export default product;

@ -3,7 +3,7 @@ import {Dispatch} from 'redux';
const user = {
otp: (data : String) => async (dispatch : Dispatch) =>
await proxy.login("public/sendOTP", data, { dispatch }),
await proxy.post("public/sendOTP", data, { dispatch }),
otp_login: (data : Object) => async (dispatch : Dispatch) =>
await proxy.login("user/otp/login", data, { dispatch }),

@ -0,0 +1,14 @@
import proxy from "../proxy";
import { Dispatch } from "redux";
const userFactor = {
payment:
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("userFactor/payment", data, { dispatch }),
verify:
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("userFactor/verify", data, { dispatch }),
};
export default userFactor;

@ -0,0 +1,10 @@
import proxy from "../proxy";
import { Dispatch } from "redux";
const userProduct = {
addVOD:
(data = {}) =>
async (dispatch : Dispatch) =>
await proxy.post("userProduct/addVOD", data, { dispatch }),
};
export default userProduct;

@ -201,19 +201,19 @@ const initialState = {
name: "درس اول",
files: [
{
id : 0,
id: 0,
name: "ماهی های پرورشی و فواید آن ی",
src: sea,
text: "لورم اپیوسرم یک متن آزمایشی است که برای",
},
{
id : 1,
id: 1,
name: "ماهی های پرورشی و فواید آن ذ",
src: sea,
text: "لورم اپیوسرم یک متن آزمایشی است که برای",
},
{
id : 2,
id: 2,
name: "ماهی های پرورشی و فواید آن ن",
src: sea,
text: "لورم اپیوسرم یک متن آزمایشی است که برای",
@ -242,56 +242,60 @@ const initialState = {
],
},
],
attachments : [
attachments: [
{
name : "تمرین بخش اول از درس دوم",
file : ''
name: "تمرین بخش اول از درس دوم",
file: "",
},
{
name : "تمرین بخش اول از درس دوم",
file : ''
name: "تمرین بخش اول از درس دوم",
file: "",
},
{
name : "تمرین بخش اول از درس دوم",
file : ''
name: "تمرین بخش اول از درس دوم",
file: "",
},
{
name : "تمرین بخش اول از درس دوم",
file : ''
name: "تمرین بخش اول از درس دوم",
file: "",
},
{
name : "تمرین بخش اول از درس دوم",
file : ''
name: "تمرین بخش اول از درس دوم",
file: "",
},
{
name : "تمرین بخش اول از درس دوم",
file : ''
name: "تمرین بخش اول از درس دوم",
file: "",
},
]
],
},
selectedVideo : {
selectedVideo: {
name: "ماهی های پرورشی و فواید آن ی",
src: sea,
text: "لورم اپیوسرم یک متن آزمایشی است که برای",
},
comments : [
comments: [
{
id : 0,
imageUrl : user1,
name : 'حمد عظیمی',
text : 'متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد',
repliedTo : null,
date : '1400/07/29',
id: 0,
imageUrl: user1,
name: "حمد عظیمی",
text: "متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد",
repliedTo: null,
date: "1400/07/29",
},
{
id : 1,
imageUrl : user2,
name : 'حمد عظیمی',
text : 'متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد',
repliedTo : null,
date : '1400/07/29',
id: 1,
imageUrl: user2,
name: "حمد عظیمی",
text: "متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد",
repliedTo: null,
date: "1400/07/29",
},
]
],
gradeFilterBooks: null,
sortFilterCourse: null,
selectedGrade: null,
selectedSort: 'تمامی دورهها',
};
const grades = [
@ -354,8 +358,34 @@ export default function book(state = initialState, action: BookAction) {
...state,
loading: false,
error: null,
selectedVideo : data,
selectedVideo: data,
};
case "book/gradeFilter":
if (data === state.selectedGrade) {
return { ...state, gradeFilterBooks: null, selectedGrade: null };
} else {
return {
...state,
gradeFilterBooks: state.list.filter(
(item: any, i: any) => item.gradeId === data
),
selectedGrade: data,
};
}
case "book/sortFilter":
const search = state.list.filter(
(item: any) => item.name.indexOf(data.search) !== -1
);
if (data.sort === "تمامی دورهها") {
return { ...state, sortFilterCourse: search, selectedSort: data.sort };
}
else if(data.sort === 'جدیدترینها'){
return { ...state, sortFilterCourse: search.sort((item1 : any, item2 : any) => {
return item1.publishYear - item2.publishYear;
}), selectedSort: data.sort };
}
return { ...state, sortFilterCourse: search, selectedSort: data.sort };
// case "book/update":
// return { ...state, loading: false, error: null };
// case "book/add":

@ -0,0 +1,35 @@
import { toast } from "react-toastify";
import { FaqAction } from "../actions-type";
const initialState = {
loading: false,
error: null,
list: [],
};
export default function faq(state = initialState, action: FaqAction) {
let { type, data } = action;
switch (type) {
case "faq/list":
return { ...state, loading: false, list: data, error: null };
case "faq/add":
return { ...state, loading: false, error: null };
case "faq/selectFaq":
return {
...state,
loading: false,
error: null,
list: state.list.map((item: any) =>
item.id === data
? { ...item, active: !item.active }
: { ...item, active: false }
),
};
case "faq/loading":
return { ...state, loading: true };
case "faq/error":
toast.error(data.message);
return { ...state, loading: false, error: data.message };
default:
return state;
}
}

@ -3,5 +3,5 @@ export { default as publicApi } from "./public";
export { default as user } from "./user";
export { default as book } from "./book";
export { default as blog } from "./blog";
export { default as product } from "./product";
export { default as faq } from "./faq";

@ -0,0 +1,29 @@
import { toast } from "react-toastify";
import { productAction } from "../actions-type";
const initialState = {
loading: false,
error: null,
listVOD: [],
selectedVOD: null,
};
export default function product(state = initialState, action: productAction) {
let { type, data } = action;
switch (type) {
case "product/listVOD":
return { ...state, loading: false, listVOD: data, error: null };
case "product/addVOD":
return { ...state, loading: false, error: null };
case "product/deleteVOD":
return { ...state, loading: false, error: null };
case "product/selectVOD":
return {...state, selectedVOD : data};
case "product/loading":
return { ...state, loading: true };
case "product/error":
toast.error(data.message);
return { ...state, loading: false, error: data.message };
default:
return state;
}
}

@ -17,8 +17,7 @@ interface SignUpFields {
otp?: String;
}
function SignUp({sendOtp, sendPhoneNumber} : any) {
function SignUp({ sendOtp, sendPhoneNumber }: any) {
const [level, setLevel] = useState("phonenumber");
const [signUpFields, setSignUpFiels] = useState<SignUpFields | undefined>(
undefined
@ -45,7 +44,12 @@ function SignUp({sendOtp, sendPhoneNumber} : any) {
const checkOtp = () => {
if (signUpFields?.otp?.length === 4) {
sendOtp({ cellphone: signUpFields?.cellphone, otp : signUpFields?.otp });
sendOtp({
cellphone: signUpFields?.cellphone,
otp: signUpFields?.otp,
userToken: "2",
applicationToken: "22",
});
setError(undefined);
} else {
setError("کد وارد شده را چک کنید.");
@ -57,15 +61,15 @@ function SignUp({sendOtp, sendPhoneNumber} : any) {
useEffect(() => {
numberInput.current.focus();
},[]);
}, []);
useEffect(() => {
if(level === 'phonenumber'){
if (level === "phonenumber") {
numberInput.current.focus();
}else{
} else {
otpInput.current.focus();
}
},[level])
}, [level]);
return (
<div className="signup d-flex flex-column align-items-center justify-content-center">

@ -5,12 +5,13 @@ import search from "../../assets/icons/search.png";
import dropdown from "../../assets/icons/dropdown.png";
import whiteDropdown from "../../assets/icons/white-dropdown.png";
import { connect } from "react-redux";
import { publicApi } from "../../redux/actions";
import { faq } from "../../redux/actions";
import scroll from "../../util/scroll.js";
import "./index.scss";
function Faq({ list, setFaqActive }: any) {
function Faq({ list, selectFaq, getList }: any) {
useEffect(() => {
getList();
scroll.goToTop();
}, []);
return (
@ -32,13 +33,13 @@ function Faq({ list, setFaqActive }: any) {
</div>
</header>
<ul className="faq__list d-flex flex-column">
{list.map((item: any, i: any) => (
{list?.map((item: any, i: any) => (
<li className="d-flex flex-column" key={i}>
<div
className="faq__list--itemHeader d-flex align-items-center justify-content-between p-4"
onClick={() => setFaqActive(item.id)}
onClick={() => selectFaq(item.id)}
>
<strong>{item.name}</strong>
<strong>{item.title}</strong>
{item.active ? (
<img src={dropdown} alt="" />
) : (
@ -47,7 +48,7 @@ function Faq({ list, setFaqActive }: any) {
</div>
{item.active && (
<div className="faq__list--itemBody d-flex px-4">
<p>{item.value}</p>
<p>{item.description}</p>
</div>
)}
</li>
@ -61,7 +62,7 @@ function Faq({ list, setFaqActive }: any) {
export default connect(
(state: any) => ({
list: state.publicApi.faqList,
list: state.faq.list,
}),
{ setFaqActive: publicApi.setFaqActive }
{ getList: faq.list, selectFaq: faq.selectFaq }
)(Faq);

@ -34,8 +34,7 @@
@media screen and (min-width : 1441px){
.home-books-book{
img{
height: 200px;
width: 170px;
height: 300px;
}
h2{
font-size: 20px;
@ -52,8 +51,8 @@
@media screen and (min-width : 1008px) and (max-width : 1440px){
.home-books-book{
img{
height: 200px;
width: 100%;
height: 250px;
// width: 100%;
}
h2{
font-size: calc(100vw / 80);
@ -71,7 +70,6 @@
.home-books-book{
img{
height: 200px;
width : calc(100vw / 4);
border-bottom-left-radius: 25px !important;
}
h2{

@ -25,6 +25,13 @@
padding-right: 5px;
color: green;
}
&__list{
scrollbar-width: 0px;
&::-webkit-scrollbar{
display: none;
width: 0px;
}
}
}
@media screen and (min-width: 1441px) {
@ -75,6 +82,9 @@
&__more{
font-size: calc(100vw / 90);
}
&__list{
overflow-x: scroll;
}
}
}

@ -5,7 +5,7 @@ import Book from "./Book/index";
import { book } from "../../../redux/actions";
import "./index.scss";
function Books({list, number, getList}: any) {
function Books({list, number}: any) {
const slideNumberHandler = () => {
if (window.innerWidth >= 1440) {
return 5;
@ -18,17 +18,12 @@ function Books({list, number, getList}: any) {
}
};
console.log(list);
useEffect(() => {
getList();
}, []);
return (
<section
className="home-books d-flex flex-column"
onClick={() => getList()}
>
{window.innerWidth > 1007 && list?.length > 0 ? (
{window.innerWidth > 1007 ? (
<Carousel
itemsToShow={slideNumberHandler()}
isRTL={true}
@ -36,13 +31,13 @@ function Books({list, number, getList}: any) {
showArrows={true}
pagination={false}
>
{list?.map((item: Object, i: Number) => (
{list.map((item: Object, i: Number) => (
<Book data={item} key={i} />
))}
</Carousel>
) : (
<div className="home-books__list d-flex">
{list?.map((item: Object, i: Number) => (
{list.map((item: Object, i: Number) => (
<Book data={item} key={i} />
))}
</div>
@ -53,7 +48,6 @@ function Books({list, number, getList}: any) {
export default connect(
( state : any) => ({
list : state.book.list,
}),
{ getList: book.list }
{ }
)(Books);

@ -33,7 +33,7 @@
@media screen and (min-width : 1441px){
.home-courses-course{
img{
height: 200px;
height: 300px;
}
h2{
font-size: 20px;
@ -50,7 +50,7 @@
@media screen and (min-width : 1008px) and (max-width : 1440px){
.home-courses-course{
img{
width: 180px;
height: 280px;
}
h2{
font-size: calc(100vw / 80);
@ -67,7 +67,7 @@
@media screen and (min-width : 641px) and (max-width : 1007px){
.home-courses-course{
img{
height: 200px;
height: 220px;
}
h2{
font-size: calc(100vw / 60);
@ -84,7 +84,7 @@
@media screen and (max-width : 640px){
.home-courses-course{
img{
width: calc(100vw / 1.9);
height: 250px;
// height: calc(100vw / 2.2);
}
h2{

@ -8,18 +8,18 @@ export default function Course(props: any) {
const { data } = props;
return (
<Link to={`/courses/${data.id}`} className="home-courses-course 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">
<Avatar src={data.user} style={{ width: 40, height: 40 }} />
<Avatar src={`https://dnvn.ir/api/v1/file/${data.fileIds}`} style={{ width: 40, height: 40 }} />
<div className="home-courses-course__info d-flex flex-column">
<h2>{data.name}</h2>
{window.innerWidth > 1007 ? (
{/* {window.innerWidth > 1007 ? (
<p>{data.text.slice(0, 100)}</p>
) : (
<p>{data.text.slice(0, 50)}</p>
)}
)} */}
<ul className="d-flex flex-wrap">
{/* <ul className="d-flex flex-wrap">
{data.tags.length <= 2
? data.tags.map((item: String, i: any) => <li key={i}>{item}</li>)
: null}
@ -30,7 +30,7 @@ export default function Course(props: any) {
<li key={3}>+</li>
</>
) : null}
</ul>
</ul> */}
</div>
</footer>
</Link>

@ -33,6 +33,13 @@
color: #9CDF52;
}
}
&__list{
scrollbar-width: 0px;
&::-webkit-scrollbar{
display: none;
width: 0px;
}
}
}
@media screen and (min-width: 1441px) {
@ -83,7 +90,11 @@
&__more{
font-size: calc(100vw / 90);
}
&__list{
overflow-x: scroll;
}
}
}
@media screen and (max-width: 640px) {

@ -1,11 +1,11 @@
import React from "react";
import React, {useEffect} from "react";
import Carousel from "react-elastic-carousel";
import Course from "./Course/index";
import { Link } from "react-router-dom";
import ExpandMoreRoundedIcon from "@mui/icons-material/ExpandMoreRounded";
import "./index.scss";
export default function Courses(props: any) {
export default function Courses({number, courses} : any) {
const slideNumberHandler = () => {
if (window.innerWidth >= 1440) {
return 4;
@ -17,7 +17,6 @@ export default function Courses(props: any) {
return 2;
}
};
const { number, courses } = props;
return (
<section className="home-courses d-flex flex-column">
<header className="d-flex justify-content-between">

@ -11,6 +11,8 @@ import Header from "./Header/index";
import AppDownload from "./AppDownload/index";
import Vocal from "../../components/Vocal/Vocal";
import scroll from "../../util/scroll";
import { connect } from "react-redux";
import { book } from "../../redux/actions";
import olum7 from "../../assets/images/olum7.jpg";
import olum8 from "../../assets/images/olum8.jpg";
@ -20,17 +22,29 @@ import blog1 from "../../assets/images/blog1.png";
import blog2 from "../../assets/images/blog2.png";
import blog3 from "../../assets/images/blog3.png";
export default function Home({ courses, grades, headerData, blogs }: any) {
function Home({
courseList,
getCourseList,
grades,
headerData,
blogs,
gradeFilterBooks,
sortFilterCourse,
selectedSort,
sortFilter
}: any) {
const [grade, setGrade] = useState(null);
const [vocal, setVocal] = useState(false);
const [inputValue, setInputValue] = useState("");
useEffect(() => {
if (inputValue) {
sortFilter({search : inputValue, sort : selectedSort});
setVocal(false);
}
}, [inputValue]);
useEffect(() => {
getCourseList();
scroll.goToTop();
}, []);
return (
@ -48,9 +62,9 @@ export default function Home({ courses, grades, headerData, blogs }: any) {
inputValue={inputValue}
setInputValue={setInputValue}
/>
<Courses courses={courses} />
<Courses courses={sortFilterCourse ? sortFilterCourse : courseList} />
<GradeFilter grades={grades} grade={grade} setGrade={setGrade} />
<Books courses={courses} />
<Books list={gradeFilterBooks ? gradeFilterBooks : courseList} />
<Blogs blogs={blogs} />
<AppDownload />
<Footer />
@ -62,64 +76,65 @@ export default function Home({ courses, grades, headerData, blogs }: any) {
);
}
export default connect(
(state: any) => ({
courseList: state.book.list,
gradeFilterBooks: state.book.gradeFilterBooks,
sortFilterCourse: state.book.sortFilterCourse,
selectedSort: state.book.selectedSort,
}),
{ getCourseList: book.list, sortFilter: book.sortFilter }
)(Home);
Home.defaultProps = {
courses: [
grades: [
{
id: 0,
name: "فیزیک کوانتوم و موارد مشابه",
text: "لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.",
imageUrl: olum7,
tags: ["دوره جدید", "تخفیفهای هفتگی", "پایه هفتم"],
name: "اول",
value: 1,
},
{
id: 1,
name: "فیزیک کوانتوم و موارد مشابه",
text: "لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.",
imageUrl: olum8,
tags: ["دوره جدید", "تخفیفهای هفتگی", "پایه هفتم"],
name: "دوم",
value: 2,
},
{
id: 2,
name: "فیزیک کوانتوم و موارد مشابه",
text: "لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.",
imageUrl: olum9,
tags: ["دوره جدید", "تخفیفهای هفتگی", "پایه هفتم"],
name: "سوم",
value: 3,
},
{
id: 3,
name: "فیزیک کوانتوم و موارد مشابه",
text: "لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.",
imageUrl: olum7,
tags: ["دوره جدید", "تخفیفهای هفتگی", "پایه هفتم"],
name: "چهارم",
value: 4,
},
{
id: 4,
name: "فیزیک کوانتوم و موارد مشابه",
text: "لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.",
imageUrl: olum8,
tags: ["دوره جدید", "تخفیفهای هفتگی", "پایه هفتم"],
name: "پنجم",
value: 5,
},
{
id: 5,
name: "فیزیک کوانتوم و موارد مشابه",
text: "لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.",
imageUrl: olum9,
tags: ["دوره جدید", "تخفیفهای هفتگی", "پایه هفتم"],
name: "ششم",
value: 6,
},
{
name: "هفتم",
value: 7,
},
{
name: "هشتم",
value: 8,
},
{
name: "نهم",
value: 9,
},
{
name: "دهم",
value: 10,
},
{
name: "یازدهم",
value: 11,
},
{
name: "دوازدهم",
value: 12,
},
],
grades: [
"اول",
"دوم",
"سوم",
"چهارم",
"پنجم",
"ششم",
"هفتم",
"هشتم",
"نهم",
"دهم",
"یازدهم",
"دوازدهم",
],
headerData: [
{

@ -4,20 +4,20 @@ import CustomCheckbox from "../../../components/CustomCheckbox";
import CircleRoundedIcon from "@mui/icons-material/CircleRounded";
import RadioButtonUncheckedRoundedIcon from "@mui/icons-material/RadioButtonUncheckedRounded";
import { connect } from "react-redux";
import { publicApi } from "../../../redux/actions";
import {product } from "../../../redux/actions";
function SubscribeRadio({ data, selectedSubscribe, setSubscribe }: any) {
function SubscribeRadio({ data, selectedVOD, selectVOD }: any) {
return (
<div
className={
"subscribe-radio d-flex" +
" " +
(selectedSubscribe.id === data.id ? "subscribe-radio-active" : "")
(selectedVOD?.id === data.id ? "subscribe-radio-active" : "")
}
onClick={() =>
selectedSubscribe.id === data.id
? setSubscribe({})
: setSubscribe(data)
selectedVOD?.id === data.id
? selectVOD(null)
: selectVOD(data)
}
>
<div className="subscribe-radio__name d-flex align-items-center">
@ -32,27 +32,27 @@ function SubscribeRadio({ data, selectedSubscribe, setSubscribe }: any) {
style={{ color: "white", fontSize: 40, padding: 0 }}
/>
}
checked={selectedSubscribe.id === data.id}
checked={selectedVOD?.id === data.id}
/>
<h2>{data.name}</h2>
</div>
<div className="subscribe-radio__factor d-flex flex-column justify-content-center">
{data.offPercent !== 0 && (
{/* {data.offPercent !== 0 && ( */}
<div className="subscribe-radio__factor--off d-flex align-items-center">
<b>
{data.off}
{data.offerPrice}
<span></span>
</b>
<i>تومان</i>
</div>
)}
{/* )} */}
<div className="subscribe-radio__factor--finalPrice d-flex align-items-center">
<strong>{data.finalPrice}</strong>
<strong>{data.price}</strong>
<i>تومان</i>
</div>
{data.offPercent !== 0 && (
<span className="subscribe-radio__factor--tag">{`${data.offPercent}% تخفیف ویژه`}</span>
)}
{/* {data.offPercent !== 0 && ( */}
{/* <span className="subscribe-radio__factor--tag">{`${30}% تخفیف ویژه`}</span> */}
{/* )} */}
</div>
</div>
);
@ -60,7 +60,7 @@ function SubscribeRadio({ data, selectedSubscribe, setSubscribe }: any) {
export default connect(
(state: any) => ({
selectedSubscripe: state.publicApi.selectedSubscripe,
selectedVOD: state.product.selectedVOD,
}),
{ setSubscribe: publicApi.setSubscribe }
{ selectVOD: product.selectVOD }
)(SubscribeRadio);

@ -1,16 +1,18 @@
import React, {useEffect} from "react";
import React, { useEffect } from "react";
import Navbar from "../../components/Navbar/index";
import Footer from "../../views/Home/Footer/index";
import SubscribeRadio from "./SubscribeRadio/index";
import DiscountCode from "./DiscountCode/index";
import {connect} from 'react-redux';
import scroll from '../../util/scroll';
import { connect } from "react-redux";
import { product } from "../../redux/actions";
import scroll from "../../util/scroll";
import "./index.scss";
function Subscription({subscribes, selectedSubscribe} : any) {
function Subscription({ listVOD, getList }: any) {
useEffect(() => {
getList();
scroll.goToTop();
},[])
}, []);
return (
<div className="subscription main d-flex flex-column">
<Navbar />
@ -21,11 +23,9 @@ function Subscription({subscribes, selectedSubscribe} : any) {
از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و
سطرآنچنان که لازم است و برای شرایط{" "}
</p>
{
subscribes?.map((subscribe : any , i : any) => (
<SubscribeRadio data={subscribe} selectedSubscribe={selectedSubscribe} />
))
}
{listVOD?.map((subscribe: any, i: any) => (
<SubscribeRadio data={subscribe} />
))}
<DiscountCode />
<div className="d-flex justify-content-end py-4">
<button className="submit submit-large">تایید و پرداخت</button>
@ -36,7 +36,9 @@ function Subscription({subscribes, selectedSubscribe} : any) {
);
}
export default connect((state : any) => ({
subscribes : state.publicApi.mockSubscribes,
selectedSubscribe : state.publicApi.selectedSubscribe
}), {})(Subscription);
export default connect(
(state: any) => ({
listVOD: state.product.listVOD,
}),
{ getList: product.listVOD }
)(Subscription);

Loading…
Cancel
Save