229 lines
6.0 KiB
TypeScript
229 lines
6.0 KiB
TypeScript
import React, { useEffect, useRef, useState } from 'react'
|
|
import { formatDate } from '../../../utils/dayjs-config'
|
|
import { Link } from 'react-router-dom'
|
|
import { getNavigationValue, getFeatures } from '@brojs/cli'
|
|
import {
|
|
Button,
|
|
Tr,
|
|
Td,
|
|
Menu,
|
|
MenuButton,
|
|
MenuItem,
|
|
MenuList,
|
|
useToast,
|
|
Flex,
|
|
Text,
|
|
useColorMode,
|
|
Box,
|
|
Image,
|
|
} from '@chakra-ui/react'
|
|
import { EditIcon } from '@chakra-ui/icons'
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { qrCode } from '../../../assets'
|
|
|
|
import { LessonForm } from './lessons-form'
|
|
import { api } from '../../../__data__/api/api'
|
|
|
|
const features = getFeatures('journal')
|
|
const groupByDate = features?.['group.by.date']
|
|
|
|
type ItemProps = {
|
|
id: string
|
|
date: string
|
|
name: string
|
|
isTeacher: boolean
|
|
courseId: string
|
|
setlessonToDelete(): void
|
|
setEditLesson?: () => void
|
|
students: unknown[]
|
|
isMobile?: boolean
|
|
}
|
|
|
|
export const Item: React.FC<ItemProps> = ({
|
|
id,
|
|
date,
|
|
name,
|
|
isTeacher,
|
|
courseId,
|
|
setlessonToDelete,
|
|
setEditLesson,
|
|
students,
|
|
isMobile = false,
|
|
}) => {
|
|
const [edit, setEdit] = useState(false)
|
|
const toastRef = useRef(null)
|
|
const toast = useToast()
|
|
const [updateLesson, updateLessonRqst] = api.useUpdateLessonMutation()
|
|
const createdLessonRef = useRef(null)
|
|
const { t } = useTranslation()
|
|
const { colorMode } = useColorMode()
|
|
|
|
// QR-код с применением фильтра инверсии для тёмной темы
|
|
const QRCodeImage = () => (
|
|
<Box
|
|
display="flex"
|
|
justifyContent="center"
|
|
filter={colorMode === 'dark' ? 'invert(1)' : 'none'}
|
|
>
|
|
<img
|
|
width={isMobile ? 20 : 24}
|
|
src={qrCode}
|
|
alt="QR код"
|
|
style={{ margin: '0 auto' }}
|
|
/>
|
|
</Box>
|
|
)
|
|
|
|
const onSubmit = (lessonData) => {
|
|
toastRef.current = toast({
|
|
title: t('journal.pl.common.sending'),
|
|
status: 'loading',
|
|
duration: 9000,
|
|
})
|
|
createdLessonRef.current = lessonData
|
|
if (navigator.onLine) {
|
|
updateLesson(lessonData)
|
|
} else {
|
|
toast.update(toastRef.current, {
|
|
title: t('journal.pl.lesson.noInternet'),
|
|
status: 'error',
|
|
duration: 3000
|
|
})
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (updateLessonRqst.isSuccess) {
|
|
const toastProps = {
|
|
title: t('journal.pl.lesson.updated'),
|
|
description: t('journal.pl.lesson.updateMessage', { name: createdLessonRef.current?.name }),
|
|
status: 'success' as const,
|
|
duration: 9000,
|
|
isClosable: true,
|
|
}
|
|
if (toastRef.current) toast.update(toastRef.current, toastProps)
|
|
else toast(toastProps)
|
|
setEdit(false)
|
|
}
|
|
}, [updateLessonRqst.isSuccess])
|
|
|
|
if (edit && isTeacher) {
|
|
return (
|
|
<Tr>
|
|
<Td colSpan={5}>
|
|
<LessonForm
|
|
isLoading={updateLessonRqst.isLoading}
|
|
error={(updateLessonRqst.error as any)?.error}
|
|
onSubmit={onSubmit}
|
|
onCancel={() => {
|
|
setEdit(false)
|
|
}}
|
|
lesson={{ _id: id, id, name, date }}
|
|
title={t('journal.pl.lesson.editTitle')}
|
|
nameButton={t('journal.pl.save')}
|
|
/>
|
|
</Td>
|
|
</Tr>
|
|
)
|
|
}
|
|
|
|
if (isMobile) {
|
|
return (
|
|
<>
|
|
<Flex justify="space-between" align="center" mb={2}>
|
|
<Text fontWeight="medium">{name}</Text>
|
|
<Text fontSize="sm">{formatDate(date, groupByDate ? 'HH:mm' : 'HH:mm DD.MM.YY')}</Text>
|
|
</Flex>
|
|
|
|
<Flex justify="space-between" align="center">
|
|
{isTeacher && (
|
|
<Link
|
|
to={`${getNavigationValue('journal.main')}/lesson/${courseId}/${id}`}
|
|
style={{ display: 'flex' }}
|
|
>
|
|
<QRCodeImage />
|
|
</Link>
|
|
)}
|
|
|
|
<Flex align="center">
|
|
<Text fontSize="sm" mr={2}>
|
|
{t('journal.pl.common.marked')}: {students.length}
|
|
</Text>
|
|
|
|
{isTeacher && !edit && (
|
|
<Menu>
|
|
<MenuButton as={Button} size="sm">
|
|
<EditIcon />
|
|
</MenuButton>
|
|
<MenuList>
|
|
<MenuItem
|
|
onClick={() => {
|
|
if (setEditLesson) {
|
|
setEditLesson();
|
|
} else {
|
|
setEdit(true);
|
|
}
|
|
}}
|
|
>
|
|
{t('journal.pl.edit')}
|
|
</MenuItem>
|
|
<MenuItem onClick={setlessonToDelete}>{t('journal.pl.delete')}</MenuItem>
|
|
</MenuList>
|
|
</Menu>
|
|
)}
|
|
{edit && <Button size="sm" onClick={setlessonToDelete}>{t('journal.pl.save')}</Button>}
|
|
</Flex>
|
|
</Flex>
|
|
</>
|
|
)
|
|
}
|
|
|
|
// Стандартное отображение
|
|
return (
|
|
<Tr>
|
|
{isTeacher && (
|
|
<Td>
|
|
<Link
|
|
to={`${getNavigationValue('journal.main')}/lesson/${courseId}/${id}`}
|
|
style={{ display: 'flex' }}
|
|
>
|
|
<QRCodeImage />
|
|
</Link>
|
|
</Td>
|
|
)}
|
|
<Td textAlign="center">
|
|
{formatDate(date, groupByDate ? 'HH:mm' : 'HH:mm DD.MM.YY')}
|
|
</Td>
|
|
<Td>{name}</Td>
|
|
{isTeacher && (
|
|
<Td>
|
|
{!edit && (
|
|
<Menu>
|
|
<MenuButton as={Button}>
|
|
<EditIcon />
|
|
</MenuButton>
|
|
<MenuList>
|
|
<MenuItem
|
|
onClick={() => {
|
|
if (setEditLesson) {
|
|
setEditLesson();
|
|
} else {
|
|
setEdit(true);
|
|
}
|
|
}}
|
|
>
|
|
{t('journal.pl.edit')}
|
|
</MenuItem>
|
|
<MenuItem onClick={setlessonToDelete}>{t('journal.pl.delete')}</MenuItem>
|
|
</MenuList>
|
|
</Menu>
|
|
)}
|
|
{edit && <Button onClick={setlessonToDelete}>{t('journal.pl.save')}</Button>}
|
|
</Td>
|
|
)}
|
|
<Td isNumeric>{students.length}</Td>
|
|
</Tr>
|
|
)
|
|
}
|