Стилизация формы создания лекции #12
| @ -51,11 +51,11 @@ export const api = createApi({ | ||||
|       query: (courseId) => `/lesson/list/${courseId}`, | ||||
|       providesTags: ['LessonList'] | ||||
|     }), | ||||
|     createLesson: builder.mutation<BaseResponse<Lesson>, Pick<Lesson, 'name'> & { courseId: string }>({ | ||||
|       query: ({ name, courseId }) => ({ | ||||
|     createLesson: builder.mutation<BaseResponse<Lesson>, Pick<Lesson, 'name' | 'date'> & { courseId: string }>({ | ||||
|       query: ({ name, courseId, date }) => ({ | ||||
|         url: '/lesson', | ||||
|         method: 'POST', | ||||
|         body: { name, courseId }, | ||||
|         body: { name, courseId, date }, | ||||
|       }), | ||||
|       invalidatesTags: ['LessonList'] | ||||
|     }), | ||||
|  | ||||
| @ -2,34 +2,44 @@ import React, { useCallback, useEffect, useRef, useState } from 'react' | ||||
| import dayjs from 'dayjs' | ||||
| import { Link, useParams } from 'react-router-dom' | ||||
| import { getNavigationsValue } from '@ijl/cli' | ||||
| import { useForm, Controller } from 'react-hook-form' | ||||
| import { | ||||
|   Breadcrumb, | ||||
|   BreadcrumbItem, | ||||
|   BreadcrumbLink, | ||||
|   Container, | ||||
|   Box, | ||||
|   Card, | ||||
|   CardBody, | ||||
|   CardHeader, | ||||
|   Heading, | ||||
|   Button, | ||||
|   ButtonGroup, | ||||
|   CloseButton, | ||||
|   useToast, | ||||
|   Stack, | ||||
|   VStack, | ||||
|   FormControl, | ||||
|   FormLabel, | ||||
|   FormHelperText, | ||||
|   FormErrorMessage, | ||||
|   Input, | ||||
| } from '@chakra-ui/react' | ||||
| 
 | ||||
| import { | ||||
|   ArrowImg, | ||||
|   IconButton, | ||||
|   InputElement, | ||||
|   InputLabel, | ||||
|   InputWrapper, | ||||
|   StartWrapper, | ||||
|   LessonItem, | ||||
|   Lessonname, | ||||
|   Papper, | ||||
|   ErrorSpan, | ||||
|   Cross, | ||||
|   AddButton, | ||||
|   MainWrapper, | ||||
| } from './style' | ||||
| import { AddIcon } from '@chakra-ui/icons' | ||||
| 
 | ||||
| import { LessonItem, Lessonname, ErrorSpan } from './style' | ||||
| 
 | ||||
| import arrow from '../assets/36-arrow-right.svg' | ||||
| import { keycloak } from '../__data__/kc' | ||||
| import { useAppSelector } from '../__data__/store' | ||||
| import { api } from '../__data__/api/api' | ||||
| import { isTeacher } from '../utils/user' | ||||
| 
 | ||||
| interface NewLessonForm { | ||||
|   name: string | ||||
|   date: string | ||||
| } | ||||
| 
 | ||||
| const LessonList = () => { | ||||
|   const { courseId } = useParams() | ||||
|   const user = useAppSelector((s) => s.user) | ||||
| @ -37,6 +47,20 @@ const LessonList = () => { | ||||
|   const [createLesson, crLQuery] = api.useCreateLessonMutation() | ||||
|   const [value, setValue] = useState('') | ||||
|   const [showForm, setShowForm] = useState(false) | ||||
|   const { | ||||
|     control, | ||||
|     handleSubmit, | ||||
|     reset, | ||||
|     formState: { errors }, | ||||
|     getValues, | ||||
|   } = useForm<NewLessonForm>({ | ||||
|     defaultValues: { | ||||
|       name: '', | ||||
|       date: '', | ||||
|     }, | ||||
|   }) | ||||
|   const toast = useToast() | ||||
|   const toastRef = useRef(null) | ||||
| 
 | ||||
|   const handleChange = useCallback( | ||||
|     (event) => { | ||||
| @ -44,26 +68,38 @@ const LessonList = () => { | ||||
|     }, | ||||
|     [setValue], | ||||
|   ) | ||||
|   const handleSubmit = useCallback( | ||||
|     (event) => { | ||||
|       event.preventDefault() | ||||
|       createLesson({ name: value, courseId }) | ||||
|     }, | ||||
|     [value], | ||||
|   ) | ||||
|   const onSubmit = ({ name, date }) => { | ||||
|     toastRef.current = toast({ | ||||
|       title: 'Отправляем', | ||||
|       status: 'loading', | ||||
|       duration: 9000, | ||||
|     }) | ||||
|     createLesson({ name, courseId, date }) | ||||
|   } | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     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]) | ||||
| 
 | ||||
|   return ( | ||||
|     <MainWrapper> | ||||
|       <StartWrapper> | ||||
|     <Container maxW="container.xl"> | ||||
|       <Breadcrumb> | ||||
|         <BreadcrumbItem> | ||||
|             <BreadcrumbLink as={Link} to={getNavigationsValue('journal.main')}>Журнал</BreadcrumbLink> | ||||
|           <BreadcrumbLink as={Link} to={getNavigationsValue('journal.main')}> | ||||
|             Журнал | ||||
|           </BreadcrumbLink> | ||||
|         </BreadcrumbItem> | ||||
| 
 | ||||
|         <BreadcrumbItem isCurrentPage> | ||||
| @ -72,37 +108,99 @@ const LessonList = () => { | ||||
|       </Breadcrumb> | ||||
| 
 | ||||
|       {isTeacher(user) && ( | ||||
|           <> | ||||
|         <Box mt="15" mb="15"> | ||||
|           {showForm ? ( | ||||
|               <Papper> | ||||
|                 <Cross role="button" onClick={() => setShowForm(false)}> | ||||
|                   X | ||||
|                 </Cross> | ||||
|                 <form onSubmit={handleSubmit}> | ||||
|                   <InputWrapper> | ||||
|                     <InputLabel htmlFor="input"> | ||||
|                       Название новой лекции: | ||||
|                     </InputLabel> | ||||
|                     <InputElement | ||||
|                       value={value} | ||||
|                       onChange={handleChange} | ||||
|                       id="input" | ||||
|                       type="text" | ||||
|                       autoComplete="off" | ||||
|             <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="date" | ||||
|                       rules={{ required: 'Обязательное поле' }} | ||||
|                       render={({ field }) => ( | ||||
|                         <FormControl> | ||||
|                           <FormLabel>Дата</FormLabel> | ||||
|                           <Input | ||||
|                             {...field} | ||||
|                             required={false} | ||||
|                             placeholder="Укажите дату лекции" | ||||
|                             size="md" | ||||
|                             type="datetime-local" | ||||
|                           /> | ||||
|                     <IconButton type="submit"> | ||||
|                       <ArrowImg src={arrow} /> | ||||
|                     </IconButton> | ||||
|                   </InputWrapper> | ||||
|                           {errors.date ? ( | ||||
|                             <FormErrorMessage> | ||||
|                               {errors.date?.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="Название лекции" | ||||
|                             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> | ||||
| 
 | ||||
|                   {crLQuery.error && ( | ||||
|                     <ErrorSpan>{(crLQuery.error as any).error}</ErrorSpan> | ||||
|                   )} | ||||
|                 </form> | ||||
|               </Papper> | ||||
|               </CardBody> | ||||
|             </Card> | ||||
|           ) : ( | ||||
|               <AddButton onClick={() => setShowForm(true)}>Добавить</AddButton> | ||||
|             <Box p="2" m="2"> | ||||
|               <Button | ||||
|                 leftIcon={<AddIcon />} | ||||
|                 colorScheme="green" | ||||
|                 onClick={() => setShowForm(true)} | ||||
|               > | ||||
|                 Добавить | ||||
|               </Button> | ||||
|             </Box> | ||||
|           )} | ||||
|           </> | ||||
|         </Box> | ||||
|       )} | ||||
|       <ul style={{ paddingLeft: 0 }}> | ||||
|         {data?.body?.map((lesson) => ( | ||||
| @ -124,8 +222,7 @@ const LessonList = () => { | ||||
|           </LessonItem> | ||||
|         ))} | ||||
|       </ul> | ||||
|       </StartWrapper> | ||||
|     </MainWrapper> | ||||
|     </Container> | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -592,6 +592,155 @@ | ||||
|                 "email": "sharova@mail.ru" | ||||
|             } | ||||
|              | ||||
|         ], | ||||
|           "date": "2024-03-08T21:18:07.033Z", | ||||
|           "created": "2024-03-05T21:18:07.033Z", | ||||
|           "__v": 22 | ||||
|       }, | ||||
|       { | ||||
|           "_id": "65e78c0fced789d2f6791tt5", | ||||
|           "name": "ВВОДНАЯ ПО JS.ПРИМЕНЕНИЕ И СПОСОБЫ ПОДКЛЮЧЕНИЯ НА СТРАНИЦЕ. LET, CONST. БАЗОВЫЕ ТИПЫ ДАННЫХ, ПРИВЕДЕНИЕ ТИПОВ. ПЕРЕМЕННЫЕ, ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННЫХ", | ||||
|           "students": [ | ||||
|             { | ||||
|                 "sub": "fcde3f22-d9ba-412a-a572-c59e515a290f", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Мария Капитанова", | ||||
|                 "preferred_username": "maryaKapitan@gmail.com", | ||||
|                 "given_name": "Мария", | ||||
|                 "family_name": "Капитанова", | ||||
|                 "email": "maryaKapitan@gmail.com", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocJgIjjOFD2YUSyRF5kH4jaysE6X5p-kq0Cg0CFncfMi=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "5b072deb-33ee-443e-9718-3b5720a3dfb7", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Евгений Кореной", | ||||
|                 "preferred_username": "koren@gmail.com", | ||||
|                 "given_name": "Кореной", | ||||
|                 "family_name": "Евгений", | ||||
|                 "email": "koren@gmail.com", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocJpVhDeG-Rpjjm2Un6r8ACz_s_injuIFKpzXf3qmyCn3Cg=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "7adf0cd1-cf07-4079-88d8-1a5c9b8f42c2", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Ирина Игнатьева", | ||||
|                 "preferred_username": "irign@gmailcom", | ||||
|                 "given_name": "Ирина", | ||||
|                 "family_name": "Игнатьева", | ||||
|                 "email": "irign@gmailcom", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocL45E4Gt8D5oyIl3ipkcGsv4ShWGs3bdlwEMA_1rzGZ=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "95ccc005-95b9-4305-9447-364a32033911", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Иван Петров", | ||||
|                 "preferred_username": "petrov@mail.ru", | ||||
|                 "given_name": "Иван", | ||||
|                 "family_name": "Петров", | ||||
|                 "email": "petrov@mail.ru", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocIgQn5mfDAh2djx-3ofG9z1Em26ZyuUgVPd-6rDOl6z=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "ede1ef2c-6ecf-484a-8fb8-282a77e1caa1", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Константин Тимуров", | ||||
|                 "preferred_username": "konstantK@gmail.com", | ||||
|                 "given_name": "Константин", | ||||
|                 "family_name": "Тимуров", | ||||
|                 "email": "konstantK@gmail.com", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocJjnOfqaoAU_D4STrJPN9fPOeJ8tv60WbWVZu2ZWcHs=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "92cc6a15-805c-4439-b592-b23f32d6d208", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Александра Питерская", | ||||
|                 "preferred_username": "piteralex@gmail.com", | ||||
|                 "given_name": "Александра", | ||||
|                 "family_name": "Питерская", | ||||
|                 "email": "piteralex@gmail.com", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocKhbCbWvBBc_m7bjU5sLCE-dQ-KygBk-aUCSR8XaYtq=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "4a3ba8b8-4120-4877-a160-be9ba4d5b3e3", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Анастасия Светлых", | ||||
|                 "preferred_username": "anastasya@gmail.ocm", | ||||
|                 "given_name": "Анастасия", | ||||
|                 "family_name": "Светлых", | ||||
|                 "email": "anastasya@gmail.ocm", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocJnsM8UGhbH806yLVgWZ17g3-gJFVcG0Uz5kvqT7dvC=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "b4634921-00b3-4082-9284-8ac47f269394", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Эмилия Снежко", | ||||
|                 "preferred_username": "emi@mail.ru", | ||||
|                 "given_name": "Эмилия", | ||||
|                 "family_name": "Снежко", | ||||
|                 "email": "emi@mail.ru", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocI98dzSFQDPr2LXMPFEUX8KLY6bY2m08O_aAj2B5KVNKg=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "bf1a95aa-39a2-4528-9b8d-319409995df5", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Юлия Бобова", | ||||
|                 "preferred_username": "bobova@gmail.com", | ||||
|                 "given_name": "Юлия", | ||||
|                 "family_name": "Бобова", | ||||
|                 "email": "bobova@gmail.com", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocJ_Ud4iI-jgqcJ3QJcWpESbRLX_C1BnB8_7uTTC-4Dn=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "c273a3e3-f7ba-4057-8c57-a1f43b6174a5", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Анна Самоварова", | ||||
|                 "preferred_username": "samovar@gmail.com", | ||||
|                 "given_name": "Анна", | ||||
|                 "family_name": "Самоварова", | ||||
|                 "email": "samovar@gmail.com", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocJOhIMdQkXPd55wTMgTTkUCnqbsu4EncgEPm67iz_mK=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "8555885b-715c-4dee-a7c5-9563a6a05211", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Евгения Жужова", | ||||
|                 "preferred_username": "zhuzhova@gmail.com", | ||||
|                 "given_name": "Евгения", | ||||
|                 "family_name": "Жужова", | ||||
|                 "email": "zhuzhova@gmail.com", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocJUtJBAVBm642AxoGpMDDMV8CPu3MEoLjU3hmO7oisG=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "12dee54f-64e9-4be3-9cb0-02ff07ab24fe", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Эдгар Петренко", | ||||
|                 "preferred_username": "petrenk@mail.ru", | ||||
|                 "given_name": "Эдгар", | ||||
|                 "family_name": "Петренко", | ||||
|                 "email": "petrenk@mail.ru", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocLgKAZag32kpGVHMVbh_GsU-rX_MAtmeVIPoov0ZPBYIA=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "4082b72a-4730-4841-ad68-06a0e19263df", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Елена Вавилон", | ||||
|                 "preferred_username": "elenvavil@mail.ru", | ||||
|                 "given_name": "Елена", | ||||
|                 "family_name": "Вавилон", | ||||
|                 "email": "elenvavil@mail.ru", | ||||
|                 "picture": "https://lh3.googleusercontent.com/a/ACg8ocKXcmzcqRch2--j2Ge2m9e8MIOZ8y1MjsQ0cSEoXOmW=s96-c" | ||||
|             }, | ||||
|             { | ||||
|                 "sub": "9e8a08d8-d76a-4f26-99c5-9a1d3c067104", | ||||
|                 "email_verified": true, | ||||
|                 "name": "Ольга Шарова", | ||||
|                 "preferred_username": "julyashap", | ||||
|                 "given_name": "Ольга", | ||||
|                 "family_name": "Шарова", | ||||
|                 "email": "sharova@mail.ru" | ||||
|             } | ||||
|              | ||||
|         ], | ||||
|           "date": "2024-03-08T21:18:07.033Z", | ||||
|           "created": "2024-03-05T21:18:07.033Z", | ||||
| @ -599,3 +748,4 @@ | ||||
|       } | ||||
|   ] | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user