fix: поправил автоподстановку даты в форму редактирования лекции [#29]
All checks were successful
platform/bro/pipeline/head This commit looks good
All checks were successful
platform/bro/pipeline/head This commit looks good
This commit is contained in:
parent
2d98b55bbc
commit
87c08e18bd
1
src/components/xl-spinner/index.ts
Normal file
1
src/components/xl-spinner/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { XlSpinner } from './xl-spinner';
|
20
src/components/xl-spinner/xl-spinner.tsx
Normal file
20
src/components/xl-spinner/xl-spinner.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
Container,
|
||||
Center,
|
||||
Spinner,
|
||||
} from '@chakra-ui/react'
|
||||
|
||||
export const XlSpinner = () => (
|
||||
<Container maxW="container.xl">
|
||||
<Center h="300px">
|
||||
<Spinner
|
||||
thickness="4px"
|
||||
speed="0.65s"
|
||||
emptyColor="gray.200"
|
||||
color="blue.500"
|
||||
size="xl"
|
||||
/>
|
||||
</Center>
|
||||
</Container>
|
||||
)
|
@ -61,8 +61,8 @@ const CoursesList = () => {
|
||||
getValues,
|
||||
} = useForm<NewCourseForm>({
|
||||
defaultValues: {
|
||||
startDt: '',
|
||||
name: '',
|
||||
startDt: dayjs().format('YYYY-MM-DD'),
|
||||
name: 'Название',
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
export const CourseListPage = lazy(/* chank-name="course-details" */() => import('./course-list'));
|
||||
|
||||
export const LessonDetailsPage = lazy(/* chank-name="course-details" */() => import('./lesson-details'));
|
||||
export const LessonListPage = lazy(/* chank-name="course-details" */() => import('./lesson-list'));
|
||||
|
||||
export const UserPage = lazy(/* chank-name="course-details" */() => import('./user-page'));
|
||||
export const CourseListPage = lazy(() => import(/* webpackChunkName: "course-list" */ './course-list'));
|
||||
export const LessonDetailsPage = lazy(() => import(/* webpackChunkName: "lesson-details" */ './lesson-details'));
|
||||
export const LessonListPage = lazy(() => import(/* webpackChunkName: "lesson-list" */ './lesson-list'));
|
||||
export const UserPage = lazy(() => import(/* webpackChunkName: "user-page" */ './user-page'));
|
||||
|
28
src/pages/lesson-list/components/bar.tsx
Normal file
28
src/pages/lesson-list/components/bar.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React from 'react'
|
||||
import { ResponsiveBar } from '@nivo/bar'
|
||||
|
||||
export const Bar = ({ data }) => (
|
||||
<ResponsiveBar
|
||||
data={data}
|
||||
keys={['count']}
|
||||
indexBy="lessonIndex"
|
||||
margin={{ top: 50, right: 130, bottom: 50, left: 60 }}
|
||||
padding={0.3}
|
||||
valueScale={{ type: 'linear' }}
|
||||
indexScale={{ type: 'band', round: true }}
|
||||
colors={{ scheme: 'set3' }}
|
||||
axisTop={null}
|
||||
axisRight={null}
|
||||
labelSkipWidth={12}
|
||||
labelSkipHeight={12}
|
||||
labelTextColor={{
|
||||
from: 'color',
|
||||
modifiers: [['brighter', 1.4]],
|
||||
}}
|
||||
role="application"
|
||||
ariaLabel="График посещаемости лекций"
|
||||
barAriaLabel={(e) =>
|
||||
e.id + ': ' + e.formattedValue + ' on lection: ' + e.indexValue
|
||||
}
|
||||
/>
|
||||
)
|
137
src/pages/lesson-list/components/lessons-form.tsx
Normal file
137
src/pages/lesson-list/components/lessons-form.tsx
Normal file
@ -0,0 +1,137 @@
|
||||
import React from 'react'
|
||||
import { useForm, Controller } from 'react-hook-form'
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
CardBody,
|
||||
CardHeader,
|
||||
Heading,
|
||||
Button,
|
||||
CloseButton,
|
||||
VStack,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
FormHelperText,
|
||||
FormErrorMessage,
|
||||
Input,
|
||||
} from '@chakra-ui/react'
|
||||
import { AddIcon } from '@chakra-ui/icons'
|
||||
|
||||
import { dateToCalendarFormat } from '../../../utils/time'
|
||||
import { Lesson } from '../../../__data__/model'
|
||||
import { ErrorSpan } from '../style'
|
||||
|
||||
interface NewLessonForm {
|
||||
name: string;
|
||||
date: string;
|
||||
}
|
||||
|
||||
interface LessonFormProps {
|
||||
lesson?: Partial<Lesson>
|
||||
isLoading: boolean
|
||||
onCancel: () => void
|
||||
onSubmit: (lesson: Lesson) => void
|
||||
error?: string
|
||||
title: string
|
||||
nameButton: string
|
||||
}
|
||||
|
||||
export const LessonForm = ({
|
||||
lesson,
|
||||
isLoading,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
error,
|
||||
title,
|
||||
nameButton,
|
||||
}: LessonFormProps) => {
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = useForm<NewLessonForm>({
|
||||
defaultValues: (lesson && { ...lesson, date: dateToCalendarFormat(lesson.date) }) || {
|
||||
name: '',
|
||||
date: dateToCalendarFormat(),
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Card align="left">
|
||||
<CardHeader display="flex">
|
||||
<Heading as="h2" mt="0">
|
||||
{title}
|
||||
</Heading>
|
||||
<CloseButton
|
||||
ml="auto"
|
||||
onClick={() => {
|
||||
reset()
|
||||
onCancel()
|
||||
}}
|
||||
/>
|
||||
</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"
|
||||
/>
|
||||
{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"
|
||||
isLoading={isLoading}
|
||||
>
|
||||
{nameButton}
|
||||
</Button>
|
||||
</Box>
|
||||
</VStack>
|
||||
|
||||
{error && <ErrorSpan>{error}</ErrorSpan>}
|
||||
</form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)
|
||||
}
|
3
src/pages/lesson-list/index.ts
Normal file
3
src/pages/lesson-list/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import LessonsList from './lesson-list';
|
||||
|
||||
export default LessonsList;
|
@ -4,31 +4,18 @@ import React, {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { ResponsiveBar } from '@nivo/bar'
|
||||
import dayjs from 'dayjs'
|
||||
import { Link, useParams } from 'react-router-dom'
|
||||
import { getNavigationsValue, getFeatures } from '@brojs/cli'
|
||||
import { useForm, Controller } from 'react-hook-form'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
Container,
|
||||
Box,
|
||||
Card,
|
||||
CardBody,
|
||||
CardHeader,
|
||||
Heading,
|
||||
Button,
|
||||
CloseButton,
|
||||
useToast,
|
||||
VStack,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Toast,
|
||||
FormHelperText,
|
||||
FormErrorMessage,
|
||||
Input,
|
||||
TableContainer,
|
||||
Table,
|
||||
Thead,
|
||||
@ -41,8 +28,6 @@ import {
|
||||
MenuItem,
|
||||
Text,
|
||||
MenuList,
|
||||
Center,
|
||||
Spinner,
|
||||
AlertDialog,
|
||||
AlertDialogBody,
|
||||
AlertDialogContent,
|
||||
@ -52,134 +37,22 @@ import {
|
||||
} from '@chakra-ui/react'
|
||||
import { AddIcon, EditIcon } from '@chakra-ui/icons'
|
||||
|
||||
import { useAppSelector } from '../__data__/store'
|
||||
import { api } from '../__data__/api/api'
|
||||
import { isTeacher } from '../utils/user'
|
||||
import { qrCode } from '../assets'
|
||||
import { Lesson } from '../__data__/model'
|
||||
import { useAppSelector } from '../../__data__/store'
|
||||
import { api } from '../../__data__/api/api'
|
||||
import { isTeacher } from '../../utils/user'
|
||||
import { qrCode } from '../../assets'
|
||||
import { Lesson } from '../../__data__/model'
|
||||
import { XlSpinner } from '../../components/xl-spinner'
|
||||
|
||||
import { ErrorSpan, BreadcrumbsWrapper } from './style'
|
||||
import { LessonForm } from './components/lessons-form'
|
||||
import { BreadcrumbsWrapper } from './style'
|
||||
import { Bar } from './components/bar'
|
||||
|
||||
const features = getFeatures('journal')
|
||||
|
||||
const barFeature = features?.['lesson.bar']
|
||||
const groupByDate = features?.['group.by.date']
|
||||
|
||||
interface NewLessonForm {
|
||||
name: string
|
||||
date: string
|
||||
}
|
||||
|
||||
interface LessonFormProps {
|
||||
lesson?: Partial<Lesson>
|
||||
isLoading: boolean
|
||||
onCancel: () => void
|
||||
onSubmit: (lesson: Lesson) => void
|
||||
error?: string
|
||||
title: string
|
||||
nameButton: string
|
||||
}
|
||||
|
||||
const LessonForm = ({
|
||||
lesson,
|
||||
isLoading,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
error,
|
||||
title,
|
||||
nameButton,
|
||||
}: LessonFormProps) => {
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = useForm<NewLessonForm>({
|
||||
defaultValues: lesson || {
|
||||
name: '',
|
||||
date: '',
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Card align="left">
|
||||
<CardHeader display="flex">
|
||||
<Heading as="h2" mt="0">
|
||||
{title}
|
||||
</Heading>
|
||||
<CloseButton
|
||||
ml="auto"
|
||||
onClick={() => {
|
||||
reset()
|
||||
onCancel()
|
||||
}}
|
||||
/>
|
||||
</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"
|
||||
/>
|
||||
{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"
|
||||
isLoading={isLoading}
|
||||
>
|
||||
{nameButton}
|
||||
</Button>
|
||||
</Box>
|
||||
</VStack>
|
||||
|
||||
{error && <ErrorSpan>{error}</ErrorSpan>}
|
||||
</form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
const LessonList = () => {
|
||||
const { courseId } = useParams()
|
||||
const user = useAppSelector((s) => s.user)
|
||||
@ -201,7 +74,6 @@ const LessonList = () => {
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
if (!groupByDate) {
|
||||
return [{ date: '', data: sorted }]
|
||||
}
|
||||
@ -308,19 +180,7 @@ const LessonList = () => {
|
||||
}, [updateLessonRqst.isSuccess])
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Container maxW="container.xl">
|
||||
<Center h="300px">
|
||||
<Spinner
|
||||
thickness="4px"
|
||||
speed="0.65s"
|
||||
emptyColor="gray.200"
|
||||
color="blue.500"
|
||||
size="xl"
|
||||
/>
|
||||
</Center>
|
||||
</Container>
|
||||
)
|
||||
return <XlSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -494,29 +354,3 @@ const LessonList = () => {
|
||||
}
|
||||
|
||||
export default LessonList
|
||||
|
||||
const Bar = ({ data }) => (
|
||||
<ResponsiveBar
|
||||
data={data}
|
||||
keys={['count']}
|
||||
indexBy="lessonIndex"
|
||||
margin={{ top: 50, right: 130, bottom: 50, left: 60 }}
|
||||
padding={0.3}
|
||||
valueScale={{ type: 'linear' }}
|
||||
indexScale={{ type: 'band', round: true }}
|
||||
colors={{ scheme: 'set3' }}
|
||||
axisTop={null}
|
||||
axisRight={null}
|
||||
labelSkipWidth={12}
|
||||
labelSkipHeight={12}
|
||||
labelTextColor={{
|
||||
from: 'color',
|
||||
modifiers: [['brighter', 1.4]],
|
||||
}}
|
||||
role="application"
|
||||
ariaLabel="График посещаемости лекций"
|
||||
barAriaLabel={(e) =>
|
||||
e.id + ': ' + e.formattedValue + ' on lection: ' + e.indexValue
|
||||
}
|
||||
/>
|
||||
)
|
13
src/pages/lesson-list/style.ts
Normal file
13
src/pages/lesson-list/style.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const BreadcrumbsWrapper = styled.div`
|
||||
padding: 12px;
|
||||
`;
|
||||
|
||||
export const ErrorSpan = styled.span`
|
||||
color: #f9e2e2;
|
||||
display: block;
|
||||
padding: 16px;
|
||||
background-color: #d32f0b;
|
||||
border-radius: 11px;
|
||||
`
|
@ -9,10 +9,8 @@ import {
|
||||
Box,
|
||||
Center,
|
||||
Container,
|
||||
Heading,
|
||||
Spinner,
|
||||
Text,
|
||||
Stack,
|
||||
} from '@chakra-ui/react'
|
||||
import { UserCard } from '../components/user-card'
|
||||
|
||||
|
3
src/utils/time.ts
Normal file
3
src/utils/time.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export const dateToCalendarFormat = (date?: string) => dayjs(date).format('YYYY-MM-DDTHH:mm')
|
Loading…
Reference in New Issue
Block a user