toggle exam
This commit is contained in:
200
src/pages/course-list/course-list.tsx
Normal file
200
src/pages/course-list/course-list.tsx
Normal file
@@ -0,0 +1,200 @@
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import {
|
||||
Box,
|
||||
CardHeader,
|
||||
CardBody,
|
||||
Button,
|
||||
Card,
|
||||
Heading,
|
||||
Container,
|
||||
VStack,
|
||||
Input,
|
||||
CloseButton,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
FormHelperText,
|
||||
FormErrorMessage,
|
||||
useToast,
|
||||
} from '@chakra-ui/react'
|
||||
import { useForm, Controller } from 'react-hook-form'
|
||||
|
||||
import { ErrorSpan } from '../style'
|
||||
|
||||
import { useAppSelector } from '../../__data__/store'
|
||||
import { api } from '../../__data__/api/api'
|
||||
import { isTeacher } from '../../utils/user'
|
||||
import { AddIcon } from '@chakra-ui/icons'
|
||||
import { PageLoader } from '../../components/page-loader/page-loader'
|
||||
import { CourseCard } from './course-card'
|
||||
|
||||
interface NewCourseForm {
|
||||
startDt: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export const CoursesList = () => {
|
||||
const toast = useToast()
|
||||
const user = useAppSelector((s) => s.user)
|
||||
const { data, isLoading } = api.useCoursesListQuery()
|
||||
const [createUpdateCourse, crucQuery] = api.useCreateUpdateCourseMutation()
|
||||
const [showForm, setShowForm] = useState(false)
|
||||
const toastRef = useRef(null)
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors },
|
||||
getValues,
|
||||
} = useForm<NewCourseForm>({
|
||||
defaultValues: {
|
||||
startDt: dayjs().format('YYYY-MM-DD'),
|
||||
name: 'Название',
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = ({ startDt, name }) => {
|
||||
toastRef.current = toast({
|
||||
title: 'Отправляем',
|
||||
status: 'loading',
|
||||
duration: 9000,
|
||||
})
|
||||
createUpdateCourse({ name, startDt })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (crucQuery.isSuccess) {
|
||||
const values = getValues()
|
||||
if (toastRef.current) {
|
||||
toast.update(toastRef.current, {
|
||||
title: 'Курс создан.',
|
||||
description: `Курс ${values.name} успешно создан`,
|
||||
status: 'success',
|
||||
duration: 9000,
|
||||
isClosable: true,
|
||||
})
|
||||
}
|
||||
reset()
|
||||
}
|
||||
}, [crucQuery.isSuccess])
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<PageLoader />
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Container maxW="container.xl">
|
||||
{isTeacher(user) && (
|
||||
<Box mt="15" mb="15">
|
||||
{showForm ? (
|
||||
<Card align="left">
|
||||
<CardHeader display="flex">
|
||||
<Heading as="h2" mt="0">
|
||||
Создание курса
|
||||
</Heading>
|
||||
<CloseButton ml="auto" onClick={() => setShowForm(false)} />
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<VStack spacing={10} align="left">
|
||||
<Controller
|
||||
control={control}
|
||||
name="startDt"
|
||||
rules={{ required: 'Обязательное поле' }}
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
isRequired
|
||||
isInvalid={Boolean(errors.startDt)}
|
||||
>
|
||||
<FormLabel>Дата начала</FormLabel>
|
||||
<Input
|
||||
{...field}
|
||||
required={false}
|
||||
placeholder="Select Date and Time"
|
||||
size="md"
|
||||
type="date"
|
||||
/>
|
||||
{errors.startDt ? (
|
||||
<FormErrorMessage>
|
||||
{errors.startDt?.message}
|
||||
</FormErrorMessage>
|
||||
) : (
|
||||
<FormHelperText>
|
||||
Укажите дату начала курса
|
||||
</FormHelperText>
|
||||
)}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
rules={{
|
||||
required: 'Обязательное поле',
|
||||
}}
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
isRequired
|
||||
isInvalid={Boolean(errors.name)}
|
||||
>
|
||||
<FormLabel>Название новой лекции:</FormLabel>
|
||||
<Input
|
||||
{...field}
|
||||
required={false}
|
||||
placeholder="КФУ-24-2"
|
||||
size="md"
|
||||
/>
|
||||
{errors.name && (
|
||||
<FormErrorMessage>
|
||||
{errors.name.message}
|
||||
</FormErrorMessage>
|
||||
)}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Box mt={10}>
|
||||
<Button
|
||||
size="lg"
|
||||
type="submit"
|
||||
leftIcon={<AddIcon />}
|
||||
colorScheme="blue"
|
||||
>
|
||||
Создать
|
||||
</Button>
|
||||
</Box>
|
||||
</VStack>
|
||||
|
||||
{crucQuery?.error && (
|
||||
<ErrorSpan>{(crucQuery?.error as any).error}</ErrorSpan>
|
||||
)}
|
||||
</form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
) : (
|
||||
<Box p="2" m="2">
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
colorScheme="green"
|
||||
onClick={() => setShowForm(true)}
|
||||
>
|
||||
Добавить
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
<VStack as="ul" align="stretch">
|
||||
{data?.body?.map((c) => (
|
||||
<CourseCard
|
||||
key={c._id}
|
||||
course={c}
|
||||
/>
|
||||
))}
|
||||
</VStack>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user