reza completed available api

master
RezaAshrafi77 3 years ago
parent 6c512ebdcf
commit 8c8be6e2e6
  1. 6
      src/redux/actions-type/book.tsx
  2. 24
      src/redux/actions-type/public.tsx
  3. 2
      src/redux/actions/book.tsx
  4. 8
      src/redux/actions/public.tsx
  5. 7
      src/redux/reducers/book.tsx
  6. 61
      src/redux/reducers/public.tsx
  7. 44
      src/views/Course/Lesson/index.tsx
  8. 37
      src/views/Course/index.tsx
  9. 31
      src/views/Courses/Course/index.scss
  10. 13
      src/views/Courses/Course/index.tsx
  11. 1
      src/views/Courses/index.scss
  12. 11
      src/views/Courses/index.tsx
  13. 7
      src/views/VideoTube/Book/index.scss
  14. 5
      src/views/VideoTube/Book/index.tsx
  15. 20
      src/views/VideoTube/LessonPlayList/index.tsx
  16. 1
      src/views/VideoTube/index.scss
  17. 56
      src/views/VideoTube/index.tsx

@ -8,11 +8,6 @@ interface setLessonActive {
data: any;
}
interface setVideoActive {
type: "book/video/active";
data: any;
}
interface gradeFilter {
type: "book/gradeFilter";
data: any;
@ -35,7 +30,6 @@ interface loading {
type BookAction =
| list
| setVideoActive
| setLessonActive
| gradeFilter
| sortFilter

@ -8,9 +8,24 @@ interface getBlogList {
data: any;
}
interface setVideoActive {
type: "active/video";
data: any;
}
interface activeCategory {
type: "active/category";
data: any;
}
interface bookInfo {
type: "public/vod/bookCourse"
data: any
type: "public/vod/bookCourse";
data: any;
}
interface bookSection {
type: "public/vod/bookSection";
data: any;
}
interface getBlogInfo {
@ -48,7 +63,7 @@ interface selectMenu {
data: any;
}
interface getHeader{
interface getHeader {
type: "public/VOD/homePage";
data: any;
}
@ -68,9 +83,12 @@ interface loading {
// }
type PublicAction =
| activeCategory
| setVideoActive
| getBlogList
| getBlogInfo
| bookInfo
| bookSection
| setSubscribe
| getHomeData
| setFaqActive

@ -7,8 +7,6 @@ const book = {
await proxy.get("book/list", 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) =>

@ -10,6 +10,10 @@ const publicApi = {
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("public/vod/bookCourse", data, { dispatch }),
bookSection:
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("public/vod/bookSection", data, { dispatch }),
getContactData:
(data = {}) =>
async (dispatch: Dispatch) =>
@ -36,6 +40,10 @@ const publicApi = {
(data = {}) =>
async (dispatch: Dispatch) =>
await proxy.get("public/VOD/homePage", data, { dispatch }),
activeCategory: (data: Object) => async (dispatch: Dispatch) =>
await dispatch({ type: "active/category", data: data }),
setVideoActive: (data: undefined) => async (dispatch: Dispatch) =>
await dispatch({ type: "active/video", data: data }),
};
export default publicApi;

@ -347,13 +347,6 @@ export default function book(state = initialState, action: BookAction) {
: { ...item, active: false }
),
};
case "book/video/active":
return {
...state,
loading: false,
error: null,
selectedVideo: data,
};
case "book/gradeFilter":
if (data === state.selectedGrade) {
return { ...state, gradeFilterBooks: null, selectedGrade: null };

@ -1,5 +1,5 @@
import { PublicAction } from "../actions-type";
import proxy from '../proxy';
import proxy from "../proxy";
const initialState = {
homeData: [],
newProducts: [],
@ -10,8 +10,8 @@ const initialState = {
arList: [],
blogList: [],
blog: null,
province : null,
city : null,
province: null,
city: null,
departmans: [
{
id: 0,
@ -26,11 +26,14 @@ const initialState = {
name: "برنامه نویسی",
},
],
header : [],
selectedMenu : null,
header: [],
selectedMenu: null,
contactData: null,
selectedVideo: null,
bookInfo : null,
bookInfo: null,
activeCategory: null,
categories: null,
bookSection : null,
};
const grades = [
@ -51,13 +54,49 @@ const grades = [
export default function publicApi(state = initialState, action: PublicAction) {
let { type, data } = action;
switch (type) {
case "active/video":
return {
...state,
loading: false,
error: null,
selectedVideo: data,
};
case "active/category":
return {
...state,
loading: false,
activeCategory: state.activeCategory === data ? null : data,
error: null,
};
case "public/vod/bookSection":
return {
...state,
loading: false,
bookSection: data,
error: null,
selectedVideo : data?.vods[0]
};
case "public/vod/bookCourse":
let allCats;
allCats = Array.from(
new Set(
data.vods.map((item: any) => item.categoryId && item.categoryId)
)
);
return {
...state,
loading: false,
bookInfo: data,
selectedVideo: data.vods[0],
bookInfo: {
...data,
vods: data.vods.map((item: any) => {
return { ...item, active: false };
}),
},
error: null,
categories: allCats.map((item: any) =>
data.vods.filter((item1: any) => item1.categoryId === item)
),
};
case "public/homePage":
let itemsLevel;
@ -179,15 +218,15 @@ export default function publicApi(state = initialState, action: PublicAction) {
case "public/blogInfo":
return { ...state, loading: false, error: null, blog: data };
case "public/setSubscribe":
return { ...state, loading: false, error: null, selectedSubscribe : data };
return { ...state, loading: false, error: null, selectedSubscribe: data };
case "public/province":
return { ...state, loading: false, error: null, province: data };
case "public/city":
return { ...state, loading: false, error: null, city: data };
case "public/selectMenu":
return { ...state, loading: false, error: null, selectedMenu : data };
return { ...state, loading: false, error: null, selectedMenu: data };
case "public/VOD/homePage":
return { ...state, loading: false, error: null, header : data };
return { ...state, loading: false, error: null, header: data };
case "loading":
return { ...state, loading: true };
case "error":

@ -2,23 +2,25 @@ import React from "react";
import whiteDropdown from "../../../assets/icons/white-dropdown.png";
import whitePlay from "../../../assets/icons/white-play.png";
import document from "../../../assets/icons/document.png";
import lock from "../../../assets/icons/lock.png";
import "./index.scss";
import { connect } from "react-redux";
import { book } from "../../../redux/actions";
import LessonPlayList from "../../VideoTube/LessonPlayList";
import { book, publicApi } from "../../../redux/actions";
function Lesson(props: any) {
const { lesson } = props;
function Lesson({toggle, lesson, activeCategory} : any) {
const duration = (value : number) => {
const minute = value % 60;
const hour = Math.round(value / 60);
return (hour > 0 ? (hour + ' ' + 'ساعت') : '') + ' ' + minute + ' ' + 'دقیقه';
}
return (
<div className="lesson d-flex flex-column">
<header
className="desktop justify-content-between align-items-center"
onClick={() => props.toggle(lesson.id)}
onClick={() => toggle(lesson[0].categoryId)}
>
<div className="d-flex align-items-center">
<img src={whiteDropdown} alt="" />
<h4>{lesson.title}</h4>
<h4>{lesson[0].categoryId}</h4>
</div>
<div className="lesson__duration d-flex">
مدت زمان درس {lesson.duration}
@ -30,10 +32,10 @@ function Lesson(props: any) {
" " +
(!lesson.active && "lesson__active")
}
onClick={() => props.toggle(lesson.id)}
onClick={() => toggle(lesson[0].categoryId)}
>
<div className="d-flex flex-column">
<h4>{lesson.title}</h4>
<h4>{lesson[0].categoryId}</h4>
<span> مدت زمان درس {lesson.duration}</span>
</div>
<div className="lesson__duration d-flex">
@ -44,32 +46,32 @@ function Lesson(props: any) {
className={
"lesson__files d-flex flex-column justify-content-around" +
" " +
(lesson.active && "lesson__files--active")
((lesson[0].categoryId === activeCategory) && "lesson__files--active")
}
style={{
height: lesson.active
? lesson.files.length *
height: lesson[0].categoryId === activeCategory
? lesson.length *
(window.innerWidth > 1007
? window.innerWidth / 33 + 20
: window.innerWidth / 33 + 45)
: "0px",
}}
>
{lesson.map((data: any, i: any) => (
{lesson?.map((data: any, i: any) => (
<li
className="lesson__files--sample justify-content-between align-items-center"
style={{
display: lesson.active ? "flex" : "none",
display: lesson[0].categoryId === activeCategory ? "flex" : "none",
}}
>
<div className="d-flex align-items-center">
{data.type === "video" && <img src={whitePlay} alt="" />}
{data.type === "document" && <img src={document} alt="" />}
{data.type === "pdf" && <img src={document} alt="" />}
<h5>{data.name}</h5>
</div>
<ul className="d-flex">
<li>{data.type !== "document" && data.duration}</li>
<li>{data.view && "مشاهده"}</li>
<li>{data.type !== "pdf" && duration(data.duration)}</li>
<li>{data.isFree && "مشاهده"}</li>
{/* <li>{data.download ? "دانلود" : <img src={lock} alt="" />}</li> */}
</ul>
</li>
@ -79,6 +81,8 @@ function Lesson(props: any) {
);
}
export default connect((state: any) => ({}), { toggle: book.setLessonActive })(
Lesson
);
export default connect((state: any) => ({
activeCategory : state.publicApi.activeCategory
}), {
toggle : publicApi.activeCategory,
})(Lesson);

@ -13,8 +13,9 @@ import StyledRating from "../../components/StyledRating";
import { connect } from "react-redux";
import { publicApi } from "../../redux/actions";
import scroll from "../../util/scroll";
import Loader from "../../components/Loader";
function Course({ lessons, getInfo, info }: any) {
function Course({ getInfo, info, categories, loading }: any) {
const [links, setLinks] = useState([
{ link: "/", name: "صفحه اصلی" },
{ link: "/courses", name: "دورهها" },
@ -31,18 +32,17 @@ function Course({ lessons, getInfo, info }: any) {
// ),
});
}, []);
let allCats;
let cats = [];
if (info?.vods) {
allCats = Array.from(
new Set(info?.vods.map((item: any) => item.categoryId && item.categoryId))
);
cats = allCats.map((item: any) =>
info?.vods.filter((item1: any) => item1.categoryId === item)
);
}
const checkFreeCat = () => {
const freeCat = info?.vods.filter((item: any) => item?.isFreeVOD)[0];
localStorage.setItem("free", 1 + "," + freeCat?.categoryId);
};
return (
<div className="course main d-flex flex-column">
<div
className="course main d-flex flex-column"
style={{ filter: loading ? "blur(8px)" : "" }}
>
<Navbar />
<main>
<header className="course__header desktop align-items-end">
@ -58,12 +58,13 @@ function Course({ lessons, getInfo, info }: any) {
<BreadCrumbs links={links} />
<h1>{info?.name}</h1>
<p>{info?.text}</p>
<i>{info?.vodTeacher}</i>
</div>
<div className="d-flex justify-content-between">
<div className="course-info-items d-flex align-items-center justify-content-around">
<img src={slide} alt="" />
<div className="d-flex flex-column">
<i>{240} ساعت درس </i>
<i>{info?.vodDuration} ساعت درس </i>
<p>در این قسمت توضیحی</p>
</div>
</div>
@ -96,6 +97,7 @@ function Course({ lessons, getInfo, info }: any) {
<Link
to="/video-tube"
className="course__options--button d-flex align-items-center justify-content-between"
onClick={() => checkFreeCat()}
>
مشاهده پیشنمایش دوره
<img src={play} alt="" />
@ -154,12 +156,17 @@ function Course({ lessons, getInfo, info }: any) {
<h2>سر فصل دوره</h2>
<p>در این قسمت شاید یک متن جهت زیباسازی قرار بگیرد </p>
</header>
{cats?.map((lesson: any, i: any) => (
{categories?.map((lesson: any, i: any) => (
<Lesson key={i} lesson={lesson} />
))}
</section>
</main>
<Footer />
{loading && (
<div className="full-loader">
<Loader size={50} />
</div>
)}
</div>
);
}
@ -168,6 +175,8 @@ export default connect(
(state: any) => ({
lessons: state.book.mockLessons,
info: state.publicApi.bookInfo,
categories: state.publicApi.categories,
loading: state.publicApi.loading,
}),
{ getInfo: publicApi.bookInfo }
)(Course);

@ -3,6 +3,7 @@
padding: 10px;
border-bottom: 1px solid #212121;
transition: all 0.5s;
position: relative;
* {
transition: all 0.5s;
color: #aaa;
@ -16,6 +17,11 @@
}
p {
}
span {
position: absolute;
left: 10px;
top: 10px;
}
}
@media screen and (min-width: 1441px) {
@ -44,6 +50,9 @@
font-size: 13px;
width: 80%;
}
span {
font-size: 13px;
}
}
}
@ -69,14 +78,20 @@
h1 {
font-size: calc(100vw / 70);
}
h2{
font-size: calc(100vw / 90);
}
p {
font-size: calc(100vw / 100);
font-size: calc(100vw / 110);
width: 80%;
}
span {
font-size: calc(100vw / 120);
}
}
}
@media screen and (min-width : 641px) and (max-width: 1007px) {
@media screen and (min-width: 641px) and (max-width: 1007px) {
.courses-course {
margin-top: 20px;
background-color: #aaaaaa21;
@ -89,10 +104,16 @@
font-size: calc(100vw / 45);
color: #84de56;
}
h2{
font-size: calc(100vw / 52);
}
p {
font-size: calc(100vw / 65);
width: 80%;
}
span {
font-size: calc(100vw / 70);
}
}
}
@ -109,9 +130,15 @@
font-size: calc(100vw / 24);
color: #84de56;
}
h2{
font-size: calc(100vw / 28);
}
p {
font-size: calc(100vw / 40);
width: 80%;
}
span {
font-size: calc(100vw / 45);
}
}
}

@ -4,17 +4,26 @@ import { Link } from "react-router-dom";
import location from "../../../util/location";
export default function Course({ data }: any) {
const duration = () => {
const minute = data.vodDuration % 60;
const hour = Math.round(data.vodDuration / 60);
return (hour > 0 ? (hour + ' ' + 'ساعت') : '') + ' ' + minute + ' ' + 'دقیقه';
}
return (
<Link to={"/courses/" + location.getId()} className="courses-course d-flex">
<img src={`https://dnvn.ir/api/v1/file/${data.fileIds}`} alt="" />
<div className="d-flex flex-column justify-content-center px-3">
<div className="d-flex flex-column justify-content-between px-3">
<div className="d-flex flex-column">
<h1>{data.name}</h1>
<h2>نام نویسنده</h2>
</div>
<p>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده
از طراحان گرافیک است چاپگرها و متون بلکه روزنامه و مجله در ستون و
</p>
<i></i>
</div>
<span>{duration()}</span>
</Link>
);
}

@ -1,4 +1,5 @@
.courses {
position: relative;
main {
margin-top: 30px;
header {

@ -7,8 +7,9 @@ import { connect } from "react-redux";
import location from "../../util/location";
import Course from "./Course";
import BreadCrumbs from "../../components/BreadCrumbs";
import Loader from "../../components/Loader";
function Courses({ getList, list, selectedMenu }: any) {
function Courses({ getList, list, selectedMenu, loading }: any) {
const [links, setLinks] = useState([
{ link: "/", name: "صفحه اصلی" },
{ link: "/courses", name: "دورهها" },
@ -19,7 +20,7 @@ function Courses({ getList, list, selectedMenu }: any) {
}, []);
return (
<div className="courses main d-flex flex-column">
<div className="courses main d-flex flex-column" style={{ filter: (loading) ? "blur(8px)" : "" }}>
<Navbar />
<main className="d-flex flex-column">
<header className="d-flex">
@ -36,6 +37,11 @@ function Courses({ getList, list, selectedMenu }: any) {
))}
</main>
<Footer />
{
loading && <div className="full-loader">
<Loader size={50} />
</div>
}
</div>
);
}
@ -44,6 +50,7 @@ export default connect(
(state: any) => ({
list: state.book.list,
selectedMenu: state.publicApi.selectedMenu,
loading : state.book.loading
}),
{ getList: book.list }
)(Courses);

@ -6,6 +6,13 @@
border-bottom-right-radius: 10px;
border-bottom-left-radius: 24px;
margin-bottom: 10px;
transition: all 0.5s;
}
&:hover{
color: white;
img{
transform: translateY(-10px);
}
}
}

@ -1,13 +1,14 @@
import React from 'react';
import {Link} from 'react-router-dom';
import './index.scss';
export default function Book({data} : any) {
return (
<div className="video-tube-suggest d-flex flex-column">
<Link to={'/courses/' + data.id} className="video-tube-suggest d-flex flex-column">
<img src={`https://dnvn.ir/api/v1/file/${data.fileIds}`} alt="" />
<h4>{data.name}</h4>
<p>{'لورم ایپسوم و اینجور چیزا'}</p>
</div>
</Link>
)
}

@ -1,24 +1,19 @@
import React from "react";
import "./index.scss";
import { connect } from "react-redux";
import { book } from "../../../redux/actions";
import { publicApi } from "../../../redux/actions";
function LessonPlayList({ video, selectedVideo, setVideoActive, num }: any) {
return (
<>
{1 && (
{
video.isFreeVOD &&
<div className="lesson-playlist d-flex flex-column">
<header className="d-flex align-items-center">
<h3>{'بخش 1'}</h3>
<span></span>
</header>
{/* {lesson.files.map((file: any, i: any) => ( */}
<div
className={
"lesson-playlist__item d-flex align-items-center" +
" " +
(video.id === selectedVideo.id &&
"lesson-playlist__item--active")
(video.id === selectedVideo.id && "lesson-playlist__item--active")
}
// key={i}
onClick={() => setVideoActive(video)}
@ -35,18 +30,17 @@ function LessonPlayList({ video, selectedVideo, setVideoActive, num }: any) {
{/* <p>{file.text}</p> */}
</div>
</div>
{/* ))} */}
</div>
)}
}
</>
);
}
export default connect(
(state: any) => ({
selectedVideo: state.book.selectedVideo,
selectedVideo: state.publicApi.selectedVideo,
}),
{
setVideoActive: book.setVideoActive,
setVideoActive: publicApi.setVideoActive,
}
)(LessonPlayList);

@ -70,6 +70,7 @@
}
}
&___list {
padding-top: 10px;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 8px;

@ -1,4 +1,4 @@
import React, { useEffect } from "react";
import React, { useState, useEffect } from "react";
import Navbar from "../../components/Navbar";
import Footer from "../Home/Footer";
import LessonPlayList from "./LessonPlayList";
@ -13,18 +13,12 @@ import listIcon from "../../assets/icons/list.png";
import { connect } from "react-redux";
import scroll from "../../util/scroll.js";
import { book, publicApi } from "../../redux/actions";
import Loader from "../../components/Loader";
function VodTube({
videoList,
getBookList,
list,
selectedVideo,
comments,
info,
getInfo,
}: any) {
function VodTube({ selectedVideo, info, bookSection, loading }: any) {
useEffect(() => {
getBookList();
const free: any = localStorage.getItem("free")?.split(",");
scroll.goToTop();
// getInfo({
// bookId: 1,
// // window.location.pathname.slice(
@ -32,11 +26,15 @@ function VodTube({
// // window.location.pathname.length
// // ),
// });
scroll.goToTop();
bookSection({ bookId: free[0], categoryId: free[1] });
}, []);
return (
<div className="video-tube main d-flex flex-column">
<>
<div
className="video-tube main d-flex flex-column"
style={{ filter: loading ? "blur(8px)" : "" }}
>
<Navbar />
<main className="d-flex">
<div className="video-tube__content d-flex flex-column">
@ -55,7 +53,7 @@ function VodTube({
<button>بستن نظرات</button>
</header>
<div className="video-tube__content-comments___list d-flex flex-column">
{comments?.map((comment: any, i: any) => (
{info?.comments?.map((comment: any, i: any) => (
<Comment comment={comment} key={i} />
))}
</div>
@ -68,7 +66,7 @@ function VodTube({
<section className="video-tube__sidebar--playlist d-flex flex-column">
<header className="d-flex justify-content-between align-items-center">
<div className="d-flex flex-column">
<h2>{videoList.name}</h2>
<h2>لیست فیلمها</h2>
<p>در این قسمت توضیحی کوتاه قرار می گیرد</p>
</div>
<img src={listIcon} alt="" />
@ -79,6 +77,7 @@ function VodTube({
))}
</div>
</section>
{info?.attachments.length > 0 && (
<section className="video-tube__sidebar--attachments d-flex flex-column">
<header className="d-flex align-items-center">
<div className="d-flex flex-column">
@ -87,18 +86,19 @@ function VodTube({
</div>
</header>
<div className="video-tube__sidebar--attachments___list d-flex flex-column">
{videoList.attachments?.map((file: any, i: any) => (
{info?.attachments?.map((file: any, i: any) => (
<Attachments file={file} key={i} />
))}
</div>
</section>
)}
<section className="video-tube__sidebar--suggests d-flex flex-column">
<header className="d-flex justify-content-between align-items-center">
<h2>پیشنهاد دانوین برای شما</h2>
<span>تا 50% تخفیف </span>
</header>
<div className="video-tube__sidebar--suggests___list d-flex justify-content-between align-items-center">
{list?.slice(0, 3).map((item: any, i: any) => (
{info?.related?.map((item: any, i: any) => (
<Book data={item} key={i} />
))}
</div>
@ -109,7 +109,7 @@ function VodTube({
<button>بستن نظرات</button>
</header>
<div className="video-tube__content-comments___list d-flex flex-column">
{comments?.map((comment: any, i: any) => (
{info?.comments?.map((comment: any, i: any) => (
<Comment comment={comment} key={i} />
))}
</div>
@ -121,16 +121,24 @@ function VodTube({
</main>
<Footer />
</div>
{loading && (
<div className="full-loader">
<Loader size={50} />
</div>
)}
</>
);
}
export default connect(
(state: any) => ({
videoList: state.book.mockVideoList,
selectedVideo: state.book.selectedVideo,
list: state.book.list,
comments: state.book.comments,
info: state.book.info,
selectedVideo: state.publicApi.selectedVideo,
info: state.publicApi.bookSection,
loading: state.publicApi.loading,
}),
{ getInfo: publicApi.bookInfo, getBookList : book.list }
{
getInfo: publicApi.bookInfo,
getBookList: book.list,
bookSection: publicApi.bookSection,
}
)(VodTube);

Loading…
Cancel
Save