сделал создание и просмотр лекции
This commit is contained in:
parent
87a14f0eb1
commit
4ec6e96525
@ -1,6 +1,8 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from app.domain.entities.users import UserRead
|
||||||
|
|
||||||
|
|
||||||
class LessonBase(BaseModel):
|
class LessonBase(BaseModel):
|
||||||
title: str = Field(..., max_length=250)
|
title: str = Field(..., max_length=250)
|
||||||
@ -10,7 +12,7 @@ class LessonBase(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class LessonCreate(LessonBase):
|
class LessonCreate(LessonBase):
|
||||||
course_id: int
|
pass
|
||||||
|
|
||||||
|
|
||||||
class LessonUpdate(BaseModel):
|
class LessonUpdate(BaseModel):
|
||||||
@ -25,5 +27,7 @@ class LessonRead(LessonBase):
|
|||||||
course_id: int
|
course_id: int
|
||||||
creator_id: int
|
creator_id: int
|
||||||
|
|
||||||
|
creator: UserRead
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|||||||
@ -18,6 +18,6 @@ class Lesson(RootTable):
|
|||||||
creator_id: Mapped[int] = mapped_column(ForeignKey('users.id'), nullable=False)
|
creator_id: Mapped[int] = mapped_column(ForeignKey('users.id'), nullable=False)
|
||||||
|
|
||||||
course: Mapped['Course'] = relationship('Course', back_populates='lessons')
|
course: Mapped['Course'] = relationship('Course', back_populates='lessons')
|
||||||
creator: Mapped['User'] = relationship('User', back_populates='created_lessons')
|
creator: Mapped['User'] = relationship('User', back_populates='created_lessons', lazy='joined')
|
||||||
|
|
||||||
files: Mapped[List['LessonFile']] = relationship('LessonFile', back_populates='lesson')
|
files: Mapped[List['LessonFile']] = relationship('LessonFile', back_populates='lesson')
|
||||||
|
|||||||
@ -48,7 +48,6 @@ def require_admin(user: User = Depends(require_auth_user)):
|
|||||||
|
|
||||||
|
|
||||||
def require_teacher(user: User = Depends(require_auth_user)):
|
def require_teacher(user: User = Depends(require_auth_user)):
|
||||||
print(user.role.title, user.role.title not in [UserRoles.TEACHER, Settings().root_role_name], [UserRoles.TEACHER, Settings().root_role_name])
|
|
||||||
if user.role.title not in [UserRoles.TEACHER, Settings().root_role_name]:
|
if user.role.title not in [UserRoles.TEACHER, Settings().root_role_name]:
|
||||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail='Ошибка доступа')
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail='Ошибка доступа')
|
||||||
|
|
||||||
|
|||||||
@ -1,77 +1,68 @@
|
|||||||
import useCreateLessonModalForm from "./useCreateLessonModalForm.js";
|
import useCreateLessonModalForm from "./useCreateLessonModalForm.js";
|
||||||
import {Button, Form, Input, InputNumber, Modal, Upload} from "antd";
|
import {Button, Form, Input, InputNumber, Modal, Upload} from "antd";
|
||||||
import JoditEditor from "jodit-react";
|
import JoditEditor from "jodit-react";
|
||||||
import {UploadOutlined} from "@ant-design/icons";
|
|
||||||
|
|
||||||
|
const {TextArea} = Input;
|
||||||
|
|
||||||
const CreateLessonModalForm = () => {
|
const CreateLessonModalForm = ({courseId}) => {
|
||||||
const {
|
const {
|
||||||
isModalOpen,
|
isModalOpen,
|
||||||
handleCancel,
|
handleCancel,
|
||||||
|
handleOk,
|
||||||
form,
|
form,
|
||||||
joditConfig,
|
joditConfig,
|
||||||
editorRef,
|
editorRef,
|
||||||
} = useCreateLessonModalForm();
|
isLoading,
|
||||||
|
} = useCreateLessonModalForm({courseId});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
title="Создание лекционного материала"
|
||||||
open={isModalOpen}
|
open={isModalOpen}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
footer={null}
|
width={1000}
|
||||||
title={"Создание лекционного материала"}
|
footer={[
|
||||||
style={{
|
<Button key="cancel" onClick={handleCancel}>
|
||||||
minWidth: "70%",
|
Отмена
|
||||||
minHeight: "80%",
|
</Button>,
|
||||||
}}
|
<Button
|
||||||
|
key="submit"
|
||||||
|
type="primary"
|
||||||
|
loading={isLoading}
|
||||||
|
onClick={handleOk}
|
||||||
|
>
|
||||||
|
Создать лекцию
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
destroyOnHidden
|
||||||
>
|
>
|
||||||
<Form
|
<Form form={form} layout="vertical" preserve={false}>
|
||||||
name={"lesson"}
|
|
||||||
form={form}
|
|
||||||
layout={"vertical"}
|
|
||||||
>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="title"
|
name="title"
|
||||||
label="Название"
|
label="Название лекции"
|
||||||
rules={[{required: true, message: "Пожалуйста, введите название"}]}
|
rules={[{required: true, message: "Введите название лекции"}]}
|
||||||
>
|
>
|
||||||
<Input/>
|
<Input size="large" placeholder="Введение в JavaScript"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
name="description"
|
<Form.Item name="description" label="Краткое описание">
|
||||||
label="Описание"
|
<TextArea rows={2} placeholder="О чём эта лекция..."/>
|
||||||
>
|
|
||||||
<Input/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
name="text"
|
<Form.Item name="number" label="Порядковый номер" initialValue={1}>
|
||||||
label="Текстовый материал"
|
<InputNumber min={1} style={{width: "100%"}}/>
|
||||||
>
|
</Form.Item>
|
||||||
<div className="jodit-container">
|
|
||||||
|
<Form.Item label="Содержание лекции">
|
||||||
|
<div style={{border: "1px solid #d9d9d9", borderRadius: 6}}>
|
||||||
<JoditEditor
|
<JoditEditor
|
||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
config={joditConfig}
|
config={joditConfig}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
name="number"
|
|
||||||
label="Порядковый номер отображения"
|
|
||||||
>
|
|
||||||
<InputNumber min={1} defaultValue={1}/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="files" label="Прикрепить файлы">
|
|
||||||
<Upload
|
|
||||||
multiple
|
|
||||||
>
|
|
||||||
<Button icon={<UploadOutlined/>}>Выбрать файлы</Button>
|
|
||||||
</Upload>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item>
|
|
||||||
<Button type="primary" htmlType="submit">Сохранить</Button>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CreateLessonModalForm;
|
export default CreateLessonModalForm;
|
||||||
@ -2,22 +2,62 @@ import {useDispatch, useSelector} from "react-redux";
|
|||||||
import {setOpenModalCreateLesson} from "../../../../../Redux/Slices/lessonsSlice.js";
|
import {setOpenModalCreateLesson} from "../../../../../Redux/Slices/lessonsSlice.js";
|
||||||
import {Form, notification} from "antd";
|
import {Form, notification} from "antd";
|
||||||
import {useMemo, useRef} from "react";
|
import {useMemo, useRef} from "react";
|
||||||
|
import {useCreateLessonMutation} from "../../../../../Api/lessonsApi.js";
|
||||||
|
|
||||||
|
|
||||||
const useCreateLessonModalForm = () => {
|
const useCreateLessonModalForm = ({courseId}) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const {
|
const {
|
||||||
openModalCreateLesson
|
openModalCreateLesson
|
||||||
} = useSelector((state) => state.lessons);
|
} = useSelector((state) => state.lessons);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
const [createLesson, {isLoading}] = useCreateLessonMutation();
|
||||||
|
|
||||||
const isModalOpen = openModalCreateLesson;
|
const isModalOpen = openModalCreateLesson;
|
||||||
const editorRef = useRef(null);
|
const editorRef = useRef(null);
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
form.resetFields();
|
||||||
|
if (editorRef.current) {
|
||||||
|
editorRef.current.value = "";
|
||||||
|
}
|
||||||
dispatch(setOpenModalCreateLesson(false));
|
dispatch(setOpenModalCreateLesson(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
const values = await form.validateFields();
|
||||||
|
const content = editorRef.current?.value || "";
|
||||||
|
|
||||||
|
const lessonData = {
|
||||||
|
title: values.title,
|
||||||
|
description: values.description || null,
|
||||||
|
text: content,
|
||||||
|
number: values.number || 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
await createLesson({
|
||||||
|
courseId,
|
||||||
|
lessonData,
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
notification.success({
|
||||||
|
title: "Успех",
|
||||||
|
description: "Лекция успешно создана!",
|
||||||
|
placement: "topRight",
|
||||||
|
});
|
||||||
|
|
||||||
|
handleCancel();
|
||||||
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
|
title: "Ошибка",
|
||||||
|
description: error?.data?.detail || "Не удалось создать лекцию",
|
||||||
|
placement: "topRight",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const joditConfig = useMemo(
|
const joditConfig = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
readonly: false,
|
readonly: false,
|
||||||
@ -89,6 +129,7 @@ const useCreateLessonModalForm = () => {
|
|||||||
form,
|
form,
|
||||||
joditConfig,
|
joditConfig,
|
||||||
editorRef,
|
editorRef,
|
||||||
|
handleOk,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,85 @@
|
|||||||
|
import useViewLessonModal from "./useViewLessonModal.js";
|
||||||
|
import {Avatar, Button, Col, Divider, Modal, Space, Typography} from "antd";
|
||||||
|
import {CloseOutlined, UserOutlined} from "@ant-design/icons";
|
||||||
|
|
||||||
|
|
||||||
|
const {Title, Text, Paragraph} = Typography;
|
||||||
|
|
||||||
|
const ViewLessonModal = () => {
|
||||||
|
const {
|
||||||
|
selectedLessonToView,
|
||||||
|
modalIsOpen,
|
||||||
|
handleClose,
|
||||||
|
} = useViewLessonModal();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={modalIsOpen}
|
||||||
|
onCancel={handleClose}
|
||||||
|
footer={null}
|
||||||
|
width={1000}
|
||||||
|
closeIcon={<CloseOutlined style={{fontSize: 20}}/>}
|
||||||
|
title={null}
|
||||||
|
centered
|
||||||
|
destroyOnHidden
|
||||||
|
>
|
||||||
|
<Space align="start" style={{marginBottom: 16}}>
|
||||||
|
<Col>
|
||||||
|
<Title level={2} style={{margin: 0, flex: 1}}>
|
||||||
|
{selectedLessonToView?.title}
|
||||||
|
</Title>
|
||||||
|
<Avatar
|
||||||
|
size="small"
|
||||||
|
icon={<UserOutlined/>}
|
||||||
|
style={{backgroundColor: "#1890ff"}}
|
||||||
|
>
|
||||||
|
{selectedLessonToView?.creator?.first_name?.[0] || "У"}
|
||||||
|
</Avatar>
|
||||||
|
<Text type="secondary">
|
||||||
|
Создал: <strong>{selectedLessonToView?.creator?.first_name} {selectedLessonToView?.creator?.last_name}</strong>
|
||||||
|
{selectedLessonToView?.creator?.patronymic && ` ${selectedLessonToView?.creator.patronymic}`}
|
||||||
|
</Text>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
{selectedLessonToView?.description && (
|
||||||
|
<>
|
||||||
|
<Title level={4} style={{margin: "16px 0 8px"}}>
|
||||||
|
Описание
|
||||||
|
</Title>
|
||||||
|
<Paragraph type="secondary" style={{fontSize: 16, marginBottom: 24}}>
|
||||||
|
{selectedLessonToView?.description}
|
||||||
|
</Paragraph>
|
||||||
|
<Divider style={{margin: "24px 0"}}/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{selectedLessonToView?.text ? (
|
||||||
|
<div
|
||||||
|
className="lesson-content"
|
||||||
|
dangerouslySetInnerHTML={{__html: selectedLessonToView?.text}}
|
||||||
|
style={{
|
||||||
|
fontSize: "16px",
|
||||||
|
lineHeight: "1.7",
|
||||||
|
color: "#333",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Paragraph italic type="secondary">
|
||||||
|
Текстовый материал отсутствует
|
||||||
|
</Paragraph>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Divider/>
|
||||||
|
|
||||||
|
<div style={{textAlign: "right"}}>
|
||||||
|
<Button onClick={handleClose}>
|
||||||
|
Закрыть
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ViewLessonModal;
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
|
import {setSelectedLessonToView} from "../../../../../Redux/Slices/lessonsSlice.js";
|
||||||
|
|
||||||
|
|
||||||
|
const useViewLessonModal = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const {
|
||||||
|
selectedLessonToView
|
||||||
|
} = useSelector((state) => state.lessons);
|
||||||
|
|
||||||
|
const modalIsOpen = selectedLessonToView !== null;
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
dispatch(setSelectedLessonToView(null));
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectedLessonToView,
|
||||||
|
modalIsOpen,
|
||||||
|
handleClose,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useViewLessonModal;
|
||||||
@ -1,24 +1,50 @@
|
|||||||
import useCourseDetailPage from "./useCourseDetailPage.js";
|
import useCourseDetailPage from "./useCourseDetailPage.js";
|
||||||
import {Button, Col, FloatButton, Result, Row, Tooltip, Typography} from "antd";
|
import {
|
||||||
import {ArrowLeftOutlined, BookOutlined, FormOutlined, PlusOutlined} from "@ant-design/icons";
|
Avatar,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Col,
|
||||||
|
Empty,
|
||||||
|
FloatButton,
|
||||||
|
Popconfirm,
|
||||||
|
Result,
|
||||||
|
Row,
|
||||||
|
Space,
|
||||||
|
Tag,
|
||||||
|
Tooltip,
|
||||||
|
Typography
|
||||||
|
} from "antd";
|
||||||
|
import {
|
||||||
|
ArrowLeftOutlined,
|
||||||
|
BookOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
FormOutlined,
|
||||||
|
PlusOutlined
|
||||||
|
} from "@ant-design/icons";
|
||||||
import {useNavigate, useParams} from "react-router-dom";
|
import {useNavigate, useParams} from "react-router-dom";
|
||||||
import {ROLES} from "../../../Core/constants.js";
|
import {ROLES} from "../../../Core/constants.js";
|
||||||
import CONFIG from "../../../Core/сonfig.js";
|
import CONFIG from "../../../Core/сonfig.js";
|
||||||
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||||||
import CreateLessonModalForm from "./Components/CreateLessonModalForm/CreateLessonModalForm.jsx";
|
import CreateLessonModalForm from "./Components/CreateLessonModalForm/CreateLessonModalForm.jsx";
|
||||||
|
import ViewLessonModal from "./Components/ViewLessonModalForm/ViewLessonModal.jsx";
|
||||||
|
|
||||||
|
|
||||||
const {Title} = Typography;
|
const {Title, Text} = Typography;
|
||||||
|
|
||||||
const CourseDetailPage = () => {
|
const CourseDetailPage = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const {courseId} = useParams();
|
const {courseId} = useParams();
|
||||||
const {
|
const {
|
||||||
|
isTeacherOrAdmin,
|
||||||
|
lessonsData,
|
||||||
userData,
|
userData,
|
||||||
courseData,
|
courseData,
|
||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
handleCreateLesson,
|
handleCreateLesson,
|
||||||
|
handleOpenLesson,
|
||||||
|
handleEditLesson,
|
||||||
} = useCourseDetailPage(courseId);
|
} = useCourseDetailPage(courseId);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
@ -46,7 +72,92 @@ const CourseDetailPage = () => {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<CreateLessonModalForm/>
|
{lessonsData.length === 0 ? (
|
||||||
|
<Empty
|
||||||
|
description="Пока нет лекций"
|
||||||
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
|
style={{ margin: "60px 0" }}
|
||||||
|
>
|
||||||
|
{isTeacherOrAdmin && (
|
||||||
|
<Button type="primary" size="large" onClick={handleCreateLesson}>
|
||||||
|
Добавить первую лекцию
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Empty>
|
||||||
|
) : (
|
||||||
|
<Row gutter={[24, 24]}>
|
||||||
|
{lessonsData.map((lesson, index) => (
|
||||||
|
<Col xs={24} sm={12} lg={8} xl={6} key={lesson.id}>
|
||||||
|
<Card
|
||||||
|
hoverable
|
||||||
|
style={{ height: "100%", cursor: "pointer" }}
|
||||||
|
onClick={() => handleOpenLesson(lesson)}
|
||||||
|
title={
|
||||||
|
<Space>
|
||||||
|
<Text strong>{lesson.number}. {lesson.title}</Text>
|
||||||
|
{lesson.text && lesson.text.length > 100 && (
|
||||||
|
<Tag color="blue">Есть текст</Tag>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
extra={
|
||||||
|
isTeacherOrAdmin && (
|
||||||
|
<Space onClick={(e) => e.stopPropagation()}>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleEditLesson(lesson);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Popconfirm
|
||||||
|
title="Удалить лекцию?"
|
||||||
|
description="Это действие нельзя отменить"
|
||||||
|
// onConfirm={(e) => {
|
||||||
|
// e?.stopPropagation();
|
||||||
|
// handleDeleteLesson(lesson.id);
|
||||||
|
// }}
|
||||||
|
okText="Удалить"
|
||||||
|
cancelText="Отмена"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
/>
|
||||||
|
</Popconfirm>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div style={{ marginBottom: 16 }}>
|
||||||
|
{lesson.description ? (
|
||||||
|
<Text type="secondary">{lesson.description}</Text>
|
||||||
|
) : (
|
||||||
|
<Text type="secondary" italic>Описание отсутствует</Text>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ marginTop: 16, display: "flex", alignItems: "center", gap: 8 }}>
|
||||||
|
<Avatar size="small" style={{ backgroundColor: "#1890ff" }}>
|
||||||
|
{userData?.first_name?.[0] || "У"}
|
||||||
|
</Avatar>
|
||||||
|
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||||
|
Создал: {lesson.creator?.first_name} {lesson.creator?.last_name}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<CreateLessonModalForm
|
||||||
|
courseId={courseId}
|
||||||
|
/>
|
||||||
|
<ViewLessonModal/>
|
||||||
{[CONFIG.ROOT_ROLE_NAME, ROLES.TEACHER].includes(userData.role.title) && (
|
{[CONFIG.ROOT_ROLE_NAME, ROLES.TEACHER].includes(userData.role.title) && (
|
||||||
<FloatButton.Group
|
<FloatButton.Group
|
||||||
placement={"left"}
|
placement={"left"}
|
||||||
|
|||||||
@ -2,7 +2,14 @@ import {useGetAuthenticatedUserDataQuery} from "../../../Api/usersApi.js";
|
|||||||
import {useGetCourseByIdQuery} from "../../../Api/coursesApi.js";
|
import {useGetCourseByIdQuery} from "../../../Api/coursesApi.js";
|
||||||
import {useEffect} from "react";
|
import {useEffect} from "react";
|
||||||
import {useDispatch} from "react-redux";
|
import {useDispatch} from "react-redux";
|
||||||
import {setOpenModalCreateLesson} from "../../../Redux/Slices/lessonsSlice.js";
|
import {
|
||||||
|
setOpenModalCreateLesson,
|
||||||
|
setSelectedLessonToUpdate,
|
||||||
|
setSelectedLessonToView
|
||||||
|
} from "../../../Redux/Slices/lessonsSlice.js";
|
||||||
|
import {useGetLessonsByCourseIdQuery} from "../../../Api/lessonsApi.js";
|
||||||
|
import {ROLES} from "../../../Core/constants.js";
|
||||||
|
import CONFIG from "../../../Core/сonfig.js";
|
||||||
|
|
||||||
|
|
||||||
const useCourseDetailPage = (courseId) => {
|
const useCourseDetailPage = (courseId) => {
|
||||||
@ -13,7 +20,7 @@ const useCourseDetailPage = (courseId) => {
|
|||||||
isLoading: isUserLoading,
|
isLoading: isUserLoading,
|
||||||
isError: isUserError,
|
isError: isUserError,
|
||||||
} = useGetAuthenticatedUserDataQuery(undefined, {
|
} = useGetAuthenticatedUserDataQuery(undefined, {
|
||||||
pollingInterval: 60000,
|
pollingInterval: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -21,7 +28,15 @@ const useCourseDetailPage = (courseId) => {
|
|||||||
isLoading: isCourseLoading,
|
isLoading: isCourseLoading,
|
||||||
isError: isCourseError,
|
isError: isCourseError,
|
||||||
} = useGetCourseByIdQuery(courseId, {
|
} = useGetCourseByIdQuery(courseId, {
|
||||||
pollingInterval: 60000,
|
pollingInterval: 10000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: lessonsData,
|
||||||
|
isLoading: isLessonsLoading,
|
||||||
|
isError: isLessonsError,
|
||||||
|
} = useGetLessonsByCourseIdQuery(courseId, {
|
||||||
|
pollingInterval: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -32,12 +47,26 @@ const useCourseDetailPage = (courseId) => {
|
|||||||
dispatch(setOpenModalCreateLesson(true))
|
dispatch(setOpenModalCreateLesson(true))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isTeacherOrAdmin = [CONFIG.ROOT_ROLE_NAME, ROLES.TEACHER].includes(userData?.role?.title);
|
||||||
|
|
||||||
|
const handleOpenLesson = (lesson) => {
|
||||||
|
dispatch(setSelectedLessonToView(lesson))
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditLesson = (lesson) => {
|
||||||
|
dispatch(setSelectedLessonToUpdate(lesson))
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
isTeacherOrAdmin,
|
||||||
|
lessonsData,
|
||||||
userData,
|
userData,
|
||||||
courseData,
|
courseData,
|
||||||
isLoading: isUserLoading || isCourseLoading,
|
isLoading: isUserLoading || isCourseLoading || isLessonsLoading,
|
||||||
isError: isUserError || isCourseError,
|
isError: isUserError || isCourseError || isLessonsError,
|
||||||
handleCreateLesson,
|
handleCreateLesson,
|
||||||
|
handleOpenLesson,
|
||||||
|
handleEditLesson,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {createSlice} from "@reduxjs/toolkit";
|
|||||||
const initialState = {
|
const initialState = {
|
||||||
selectedLessonToUpdate: null,
|
selectedLessonToUpdate: null,
|
||||||
openModalCreateLesson: false,
|
openModalCreateLesson: false,
|
||||||
|
selectedLessonToView: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const lessonSlice = createSlice({
|
const lessonSlice = createSlice({
|
||||||
@ -16,9 +17,16 @@ const lessonSlice = createSlice({
|
|||||||
setOpenModalCreateLesson(state, action) {
|
setOpenModalCreateLesson(state, action) {
|
||||||
state.openModalCreateLesson = action.payload;
|
state.openModalCreateLesson = action.payload;
|
||||||
},
|
},
|
||||||
|
setSelectedLessonToView(state, action) {
|
||||||
|
state.selectedLessonToView = action.payload;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {setSelectedLessonToUpdate, setOpenModalCreateLesson} = lessonSlice.actions;
|
export const {
|
||||||
|
setSelectedLessonToUpdate,
|
||||||
|
setOpenModalCreateLesson,
|
||||||
|
setSelectedLessonToView,
|
||||||
|
} = lessonSlice.actions;
|
||||||
|
|
||||||
export default lessonSlice.reducer;
|
export default lessonSlice.reducer;
|
||||||
Loading…
x
Reference in New Issue
Block a user