CRUD лекции #17
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,6 +9,8 @@ pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
*prom.json
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
|
@ -35,6 +35,7 @@ import { useAppSelector } from '../__data__/store'
|
||||
import { api } from '../__data__/api/api'
|
||||
import { isTeacher } from '../utils/user'
|
||||
import { AddIcon, ArrowDownIcon, ArrowUpIcon, LinkIcon } from '@chakra-ui/icons'
|
||||
import { Course } from '../__data__/model'
|
||||
|
||||
interface NewCourseForm {
|
||||
startDt: string
|
||||
@ -226,7 +227,15 @@ const CoursesList = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const CourseCard = ({ course, isOpened, openDetails }) => {
|
||||
const CourseCard = ({
|
||||
course,
|
||||
isOpened,
|
||||
openDetails,
|
||||
}: {
|
||||
course: Course
|
||||
isOpened: boolean
|
||||
openDetails: () => void
|
||||
}) => {
|
||||
const [getLessonList, lessonList] = api.useLazyLessonListQuery()
|
||||
useEffect(() => {
|
||||
if (isOpened) {
|
||||
@ -262,6 +271,7 @@ const CourseCard = ({ course, isOpened, openDetails }) => {
|
||||
{lessonList.data?.body?.map((lesson) => (
|
||||
<Link
|
||||
as={ConnectedLink}
|
||||
key={lesson._id}
|
||||
to={
|
||||
isTeacher(user)
|
||||
? `${getNavigationsValue('journal.main')}/lesson/${course._id}/${lesson._id}`
|
||||
|
@ -20,6 +20,7 @@ import {
|
||||
Lessonname,
|
||||
AddMissedButton,
|
||||
UnorderList,
|
||||
BreadcrumbsWrapper,
|
||||
} from './style'
|
||||
import { api } from '../__data__/api/api'
|
||||
import { User } from '../__data__/model'
|
||||
@ -86,8 +87,8 @@ const LessonDetail = () => {
|
||||
}, [accessCode?.body, AllStudents.data])
|
||||
|
||||
return (
|
||||
<Container maxW="container.xl" centerContent px="200">
|
||||
<VStack align="left">
|
||||
<>
|
||||
<BreadcrumbsWrapper>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink as={Link} to={getNavigationsValue('journal.main')}>
|
||||
@ -108,41 +109,45 @@ const LessonDetail = () => {
|
||||
<BreadcrumbLink href="#">Лекция</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
</Breadcrumb>
|
||||
<Heading as='h3' mt='4' mb='3'>
|
||||
Тема занятия:
|
||||
</Heading>
|
||||
<Box as="span">
|
||||
{accessCode?.body?.lesson?.name}
|
||||
</Box>
|
||||
<Box as='span'>
|
||||
{dayjs(accessCode?.body?.lesson?.date).format('DD MMMM YYYYг.')}{' '}
|
||||
Отмечено - {accessCode?.body?.lesson?.students?.length}{' '}
|
||||
{AllStudents.isSuccess ? `/ ${AllStudents?.data?.body?.length}` : ''}{' '}
|
||||
человек
|
||||
</Box>
|
||||
</VStack>
|
||||
<HStack spacing="8">
|
||||
<a href={userUrl}>
|
||||
<QRCanvas ref={canvRef} />
|
||||
</a>
|
||||
<UnorderList>
|
||||
{studentsArr.map((student) => (
|
||||
<LessonItem key={student.sub} warn={!student.present}>
|
||||
<Lessonname>
|
||||
{student.name || student.preferred_username}{' '}
|
||||
{!student.present && (
|
||||
<AddMissedButton
|
||||
onClick={() => manualAdd({ lessonId, user: student })}
|
||||
>
|
||||
add
|
||||
</AddMissedButton>
|
||||
)}
|
||||
</Lessonname>
|
||||
</LessonItem>
|
||||
))}
|
||||
</UnorderList>
|
||||
</HStack>
|
||||
</Container>
|
||||
</BreadcrumbsWrapper>
|
||||
<Container maxW="container.xl" centerContent px="200">
|
||||
<VStack align="left">
|
||||
<Heading as="h3" mt="4" mb="3">
|
||||
Тема занятия:
|
||||
</Heading>
|
||||
<Box as="span">{accessCode?.body?.lesson?.name}</Box>
|
||||
<Box as="span">
|
||||
{dayjs(accessCode?.body?.lesson?.date).format('DD MMMM YYYYг.')}{' '}
|
||||
Отмечено - {accessCode?.body?.lesson?.students?.length}{' '}
|
||||
{AllStudents.isSuccess
|
||||
? `/ ${AllStudents?.data?.body?.length}`
|
||||
: ''}{' '}
|
||||
человек
|
||||
</Box>
|
||||
</VStack>
|
||||
<HStack spacing="8">
|
||||
<a href={userUrl}>
|
||||
<QRCanvas ref={canvRef} />
|
||||
</a>
|
||||
<UnorderList>
|
||||
{studentsArr.map((student) => (
|
||||
<LessonItem key={student.sub} warn={!student.present}>
|
||||
<Lessonname>
|
||||
{student.name || student.preferred_username}{' '}
|
||||
{!student.present && (
|
||||
<AddMissedButton
|
||||
onClick={() => manualAdd({ lessonId, user: student })}
|
||||
>
|
||||
add
|
||||
</AddMissedButton>
|
||||
)}
|
||||
</Lessonname>
|
||||
</LessonItem>
|
||||
))}
|
||||
</UnorderList>
|
||||
</HStack>
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -24,16 +24,24 @@ import {
|
||||
FormHelperText,
|
||||
FormErrorMessage,
|
||||
Input,
|
||||
TableContainer,
|
||||
Table,
|
||||
Thead,
|
||||
Tr,
|
||||
Th,
|
||||
Tbody,
|
||||
Td,
|
||||
} from '@chakra-ui/react'
|
||||
|
||||
import { AddIcon } from '@chakra-ui/icons'
|
||||
|
||||
import { LessonItem, Lessonname, ErrorSpan } from './style'
|
||||
import { LessonItem, Lessonname, ErrorSpan, BreadcrumbsWrapper } from './style'
|
||||
|
||||
import { keycloak } from '../__data__/kc'
|
||||
import { useAppSelector } from '../__data__/store'
|
||||
import { api } from '../__data__/api/api'
|
||||
import { isTeacher } from '../utils/user'
|
||||
import { qrCode } from '../assets'
|
||||
|
||||
interface NewLessonForm {
|
||||
name: string
|
||||
@ -94,135 +102,171 @@ const LessonList = () => {
|
||||
}, [crLQuery.isSuccess])
|
||||
|
||||
return (
|
||||
<Container maxW="container.xl">
|
||||
<Breadcrumb>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink as={Link} to={getNavigationsValue('journal.main')}>
|
||||
Журнал
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<>
|
||||
<BreadcrumbsWrapper>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink as={Link} to={getNavigationsValue('journal.main')}>
|
||||
Журнал
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
|
||||
<BreadcrumbItem isCurrentPage>
|
||||
<BreadcrumbLink href="#">Курс</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
</Breadcrumb>
|
||||
<BreadcrumbItem isCurrentPage>
|
||||
<BreadcrumbLink href="#">Курс</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
</Breadcrumb>
|
||||
</BreadcrumbsWrapper>
|
||||
<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="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>
|
||||
)}
|
||||
/>
|
||||
|
||||
{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="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)}
|
||||
<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"
|
||||
>
|
||||
<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>
|
||||
Создать
|
||||
</Button>
|
||||
</Box>
|
||||
</VStack>
|
||||
|
||||
{crLQuery.error && (
|
||||
<ErrorSpan>{(crLQuery.error as any).error}</ErrorSpan>
|
||||
)}
|
||||
</form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
) : (
|
||||
<Box p="2" m="2">
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
colorScheme="green"
|
||||
onClick={() => setShowForm(true)}
|
||||
{crLQuery.error && (
|
||||
<ErrorSpan>{(crLQuery.error as any).error}</ErrorSpan>
|
||||
)}
|
||||
</form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
) : (
|
||||
<Box p="2" m="2">
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
colorScheme="green"
|
||||
onClick={() => setShowForm(true)}
|
||||
>
|
||||
Добавить
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
<TableContainer whiteSpace="wrap">
|
||||
<Table variant="striped" colorScheme="cyan">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th align="center">ссылка</Th>
|
||||
<Th>Дата</Th>
|
||||
<Th>into</Th>
|
||||
<Th isNumeric>Участников</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{data?.body?.map((lesson) => (
|
||||
<Tr key={lesson._id}>
|
||||
<Td>
|
||||
<Link
|
||||
to={
|
||||
isTeacher(user)
|
||||
? `${getNavigationsValue('journal.main')}/lesson/${courseId}/${lesson._id}`
|
||||
: ''
|
||||
}
|
||||
style={{ display: 'flex' }}
|
||||
>
|
||||
<img width={24} src={qrCode} />
|
||||
</Link>
|
||||
</Td>
|
||||
<Td>{dayjs(lesson.date).format('H:mm DD.MM.YY')}</Td>
|
||||
<Td>{lesson.name}</Td>
|
||||
<Td isNumeric>{lesson.students.length}</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
{/* <ul style={{ paddingLeft: 0 }}>
|
||||
{data?.body?.map((lesson) => (
|
||||
<LessonItem key={lesson._id}>
|
||||
<Link
|
||||
to={
|
||||
isTeacher(user)
|
||||
? `${getNavigationsValue('journal.main')}/lesson/${courseId}/${lesson._id}`
|
||||
: ''
|
||||
}
|
||||
style={{ display: 'flex' }}
|
||||
>
|
||||
Добавить
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
<ul style={{ paddingLeft: 0 }}>
|
||||
{data?.body?.map((lesson) => (
|
||||
<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>
|
||||
<span style={{ marginLeft: 'auto' }}>
|
||||
Участников - {lesson.students.length}
|
||||
</span>
|
||||
</Link>
|
||||
</LessonItem>
|
||||
))}
|
||||
</ul>
|
||||
</Container>
|
||||
<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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,9 @@ import {
|
||||
Card
|
||||
} from '@chakra-ui/react'
|
||||
|
||||
export const BreadcrumbsWrapper = styled.div`
|
||||
padding: 12px;
|
||||
`;
|
||||
|
||||
export const MainWrapper = styled.main`
|
||||
display: flex;
|
||||
|
Loading…
Reference in New Issue
Block a user