Стилизация формы создания лекции #12

Merged
alexredux merged 3 commits from feature/#11-styled-form-add-lesson into master 2024-03-31 11:44:45 +03:00
2 changed files with 153 additions and 84 deletions
Showing only changes of commit 0f796fd9bc - Show all commits

View File

@ -51,7 +51,7 @@ const CoursesList = () => {
string | null string | null
>(null) >(null)
const toastRef = useRef(null) const toastRef = useRef(null)
const { const {
control, control,
handleSubmit, handleSubmit,

View File

@ -2,34 +2,44 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { Link, useParams } from 'react-router-dom' import { Link, useParams } from 'react-router-dom'
import { getNavigationsValue } from '@ijl/cli' import { getNavigationsValue } from '@ijl/cli'
import { useForm, Controller } from 'react-hook-form'
import { import {
Breadcrumb, Breadcrumb,
BreadcrumbItem, BreadcrumbItem,
BreadcrumbLink, BreadcrumbLink,
Container,
Box,
Card,
CardBody,
CardHeader,
Heading,
Button,
ButtonGroup,
CloseButton,
useToast,
Stack,
VStack,
FormControl,
FormLabel,
FormHelperText,
FormErrorMessage,
Input,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { import { AddIcon } from '@chakra-ui/icons'
ArrowImg,
IconButton, import { LessonItem, Lessonname, ErrorSpan } from './style'
InputElement,
InputLabel,
InputWrapper,
StartWrapper,
LessonItem,
Lessonname,
Papper,
ErrorSpan,
Cross,
AddButton,
MainWrapper,
} from './style'
import arrow from '../assets/36-arrow-right.svg'
import { keycloak } from '../__data__/kc' import { keycloak } from '../__data__/kc'
import { useAppSelector } from '../__data__/store' import { useAppSelector } from '../__data__/store'
import { api } from '../__data__/api/api' import { api } from '../__data__/api/api'
import { isTeacher } from '../utils/user' import { isTeacher } from '../utils/user'
interface NewLessonForm {
name: string
}
const LessonList = () => { const LessonList = () => {
const { courseId } = useParams() const { courseId } = useParams()
const user = useAppSelector((s) => s.user) const user = useAppSelector((s) => s.user)
@ -37,6 +47,19 @@ const LessonList = () => {
const [createLesson, crLQuery] = api.useCreateLessonMutation() const [createLesson, crLQuery] = api.useCreateLessonMutation()
const [value, setValue] = useState('') const [value, setValue] = useState('')
const [showForm, setShowForm] = useState(false) const [showForm, setShowForm] = useState(false)
const {
control,
handleSubmit,
reset,
formState: { errors },
getValues,
} = useForm<NewLessonForm>({
defaultValues: {
name: '',
},
})
const toast = useToast()
const toastRef = useRef(null)
const handleChange = useCallback( const handleChange = useCallback(
(event) => { (event) => {
@ -44,88 +67,134 @@ const LessonList = () => {
}, },
[setValue], [setValue],
) )
const handleSubmit = useCallback( const onSubmit = ({ name }) => {
(event) => { toastRef.current = toast({
event.preventDefault() title: 'Отправляем',
createLesson({ name: value, courseId }) status: 'loading',
}, duration: 9000,
[value], })
) createLesson({ name, courseId })
}
useEffect(() => { useEffect(() => {
if (crLQuery.isSuccess) { if (crLQuery.isSuccess) {
setValue('') const values = getValues()
if (toastRef.current) {
toast.update(toastRef.current, {
title: 'Лекция создана',
description: `Лекция ${values.name} успешно создана`,
status: 'success',
duration: 9000,
isClosable: true,
})
}
reset()
} }
}, [crLQuery.isSuccess]) }, [crLQuery.isSuccess])
return ( return (
<MainWrapper> <Container maxW="container.xl">
<StartWrapper> <Breadcrumb>
<Breadcrumb> <BreadcrumbItem>
<BreadcrumbItem> <BreadcrumbLink as={Link} to={getNavigationsValue('journal.main')}>
<BreadcrumbLink as={Link} to={getNavigationsValue('journal.main')}>Журнал</BreadcrumbLink> Журнал
</BreadcrumbItem> </BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem isCurrentPage> <BreadcrumbItem isCurrentPage>
<BreadcrumbLink href="#">Курс</BreadcrumbLink> <BreadcrumbLink href="#">Курс</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
</Breadcrumb> </Breadcrumb>
{isTeacher(user) && ( {isTeacher(user) && (
<> <Box mt="15" mb="15">
{showForm ? ( {showForm ? (
<Papper> <Card align="left">
<Cross role="button" onClick={() => setShowForm(false)}> <CardHeader display="flex">
X <Heading as="h2" mt="0">
</Cross> Создание лекции
<form onSubmit={handleSubmit}> </Heading>
<InputWrapper> <CloseButton ml="auto" onClick={() => setShowForm(false)} />
<InputLabel htmlFor="input"> </CardHeader>
Название новой лекции: <CardBody>
</InputLabel> <form onSubmit={handleSubmit(onSubmit)}>
<InputElement <VStack spacing="10" align="left">
value={value} <Controller
onChange={handleChange} control={control}
id="input" name="name"
type="text" rules={{ required: 'Обязательное поле' }}
autoComplete="off" render={({ field }) => (
<FormControl
isRequired
isInvalid={Boolean(errors.name)}
>
<FormLabel>Название новой лекции:</FormLabel>
<Input
{...field}
required={false}
placeholder="Название лекции"
size="md"
/>
{errors.name && (
<FormErrorMessage>
{errors.name.message}
</FormErrorMessage>
)}
</FormControl>
)}
/> />
<IconButton type="submit"> <Box mt="10">
<ArrowImg src={arrow} /> <Button
</IconButton> size="lg"
</InputWrapper> type="submit"
leftIcon={<AddIcon />}
colorScheme="blue"
>
Создать
</Button>
</Box>
</VStack>
{crLQuery.error && ( {crLQuery.error && (
<ErrorSpan>{(crLQuery.error as any).error}</ErrorSpan> <ErrorSpan>{(crLQuery.error as any).error}</ErrorSpan>
)} )}
</form> </form>
</Papper> </CardBody>
) : ( </Card>
<AddButton onClick={() => setShowForm(true)}>Добавить</AddButton> ) : (
)} <Box p="2" m="2">
</> <Button
)} leftIcon={<AddIcon />}
<ul style={{ paddingLeft: 0 }}> colorScheme="green"
{data?.body?.map((lesson) => ( onClick={() => setShowForm(true)}
<LessonItem key={lesson._id}>
<Link
to={
isTeacher(user)
? `${getNavigationsValue('journal.main')}/lesson/${courseId}/${lesson._id}`
: ''
}
style={{ display: 'flex' }}
> >
<Lessonname>{lesson.name}</Lessonname> Добавить
<span>{dayjs(lesson.date).format('DD MMMM YYYYг.')}</span> </Button>
<span style={{ marginLeft: 'auto' }}> </Box>
Участников - {lesson.students.length} )}
</span> </Box>
</Link> )}
</LessonItem> <ul style={{ paddingLeft: 0 }}>
))} {data?.body?.map((lesson) => (
</ul> <LessonItem key={lesson._id}>
</StartWrapper> <Link
</MainWrapper> to={
isTeacher(user)
? `${getNavigationsValue('journal.main')}/lesson/${courseId}/${lesson._id}`
: ''
}
style={{ display: 'flex' }}
>
<Lessonname>{lesson.name}</Lessonname>
<span>{dayjs(lesson.date).format('DD MMMM YYYYг.')}</span>
<span style={{ marginLeft: 'auto' }}>
Участников - {lesson.students.length}
</span>
</Link>
</LessonItem>
))}
</ul>
</Container>
) )
} }