Обновлены компоненты для учета только прошедших лекций в статистике посещаемости. Добавлено мобильное отображение в компонентах LessonItems и Item, улучшена логика фильтрации лекций. Реализовано отображение QR-кода с учетом темы оформления.
This commit is contained in:
@@ -11,6 +11,11 @@ import {
|
||||
MenuItem,
|
||||
MenuList,
|
||||
useToast,
|
||||
Flex,
|
||||
Text,
|
||||
useColorMode,
|
||||
Box,
|
||||
Image,
|
||||
} from '@chakra-ui/react'
|
||||
import { EditIcon } from '@chakra-ui/icons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -32,6 +37,7 @@ type ItemProps = {
|
||||
setlessonToDelete(): void
|
||||
setEditLesson?: () => void
|
||||
students: unknown[]
|
||||
isMobile?: boolean
|
||||
}
|
||||
|
||||
export const Item: React.FC<ItemProps> = ({
|
||||
@@ -43,6 +49,7 @@ export const Item: React.FC<ItemProps> = ({
|
||||
setlessonToDelete,
|
||||
setEditLesson,
|
||||
students,
|
||||
isMobile = false,
|
||||
}) => {
|
||||
const [edit, setEdit] = useState(false)
|
||||
const toastRef = useRef(null)
|
||||
@@ -50,6 +57,23 @@ export const Item: React.FC<ItemProps> = ({
|
||||
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({
|
||||
@@ -104,6 +128,58 @@ export const Item: React.FC<ItemProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<>
|
||||
<Flex justify="space-between" align="center" mb={2}>
|
||||
<Text fontWeight="medium">{name}</Text>
|
||||
<Text fontSize="sm">{dayjs(date).format(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 && (
|
||||
@@ -112,7 +188,7 @@ export const Item: React.FC<ItemProps> = ({
|
||||
to={`${getNavigationValue('journal.main')}/lesson/${courseId}/${id}`}
|
||||
style={{ display: 'flex' }}
|
||||
>
|
||||
<img width={24} src={qrCode} style={{ margin: '0 auto' }} />
|
||||
<QRCodeImage />
|
||||
</Link>
|
||||
</Td>
|
||||
)}
|
||||
|
||||
@@ -3,6 +3,10 @@ import dayjs from 'dayjs'
|
||||
import {
|
||||
Tr,
|
||||
Td,
|
||||
Box,
|
||||
Flex,
|
||||
Text,
|
||||
useBreakpointValue,
|
||||
} from '@chakra-ui/react'
|
||||
|
||||
import { Lesson } from '../../../__data__/model'
|
||||
@@ -25,24 +29,70 @@ export const LessonItems: React.FC<LessonItemProps> = ({
|
||||
courseId,
|
||||
setlessonToDelete,
|
||||
setEditLesson,
|
||||
}) => (
|
||||
<>
|
||||
{date && (
|
||||
<Tr>
|
||||
<Td colSpan={isTeacher ? 5 : 3}>
|
||||
{dayjs(date).format('DD MMMM YYYY')}
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
{lessons.map((lesson) => (
|
||||
<Item
|
||||
key={lesson.id}
|
||||
{...lesson}
|
||||
setlessonToDelete={() => setlessonToDelete(lesson)}
|
||||
setEditLesson={setEditLesson ? () => setEditLesson(lesson) : undefined}
|
||||
courseId={courseId}
|
||||
isTeacher={isTeacher}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}) => {
|
||||
// Использование useBreakpointValue для определения мобильного отображения
|
||||
const isMobile = useBreakpointValue({ base: true, md: false })
|
||||
|
||||
// Мобильное отображение
|
||||
if (isMobile) {
|
||||
return (
|
||||
<>
|
||||
{date && (
|
||||
<Box
|
||||
p={3}
|
||||
mb={2}
|
||||
bg="gray.100"
|
||||
borderRadius="md"
|
||||
_dark={{ bg: "gray.700" }}
|
||||
>
|
||||
<Text fontWeight="bold">{dayjs(date).format('DD MMMM YYYY')}</Text>
|
||||
</Box>
|
||||
)}
|
||||
{lessons.map((lesson) => (
|
||||
<Box
|
||||
key={lesson.id}
|
||||
p={3}
|
||||
mb={2}
|
||||
borderRadius="md"
|
||||
boxShadow="sm"
|
||||
borderLeft="4px solid"
|
||||
borderLeftColor="cyan.500"
|
||||
>
|
||||
<Item
|
||||
{...lesson}
|
||||
setlessonToDelete={() => setlessonToDelete(lesson)}
|
||||
setEditLesson={setEditLesson ? () => setEditLesson(lesson) : undefined}
|
||||
courseId={courseId}
|
||||
isTeacher={isTeacher}
|
||||
isMobile={true}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// Стандартное отображение для планшетов и больших экранов
|
||||
return (
|
||||
<>
|
||||
{date && (
|
||||
<Tr>
|
||||
<Td colSpan={isTeacher ? 5 : 3}>
|
||||
{dayjs(date).format('DD MMMM YYYY')}
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
{lessons.map((lesson) => (
|
||||
<Item
|
||||
key={lesson.id}
|
||||
{...lesson}
|
||||
setlessonToDelete={() => setlessonToDelete(lesson)}
|
||||
setEditLesson={setEditLesson ? () => setEditLesson(lesson) : undefined}
|
||||
courseId={courseId}
|
||||
isTeacher={isTeacher}
|
||||
isMobile={false}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogOverlay,
|
||||
useBreakpointValue,
|
||||
} from '@chakra-ui/react'
|
||||
import { AddIcon } from '@chakra-ui/icons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -257,6 +258,9 @@ const LessonList = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Добавляем определение размера экрана
|
||||
const isMobile = useBreakpointValue({ base: true, md: false })
|
||||
|
||||
if (isLoading) {
|
||||
return <XlSpinner />
|
||||
}
|
||||
@@ -352,38 +356,54 @@ const LessonList = () => {
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<TableContainer whiteSpace="wrap" pb={13}>
|
||||
<Table variant="striped" colorScheme="cyan">
|
||||
<Thead>
|
||||
<Tr>
|
||||
{isTeacher(user) && (
|
||||
<Th align="center" width={1}>
|
||||
{t('journal.pl.lesson.link')}
|
||||
{isMobile ? (
|
||||
<Box pb={13}>
|
||||
{lessonCalc?.map(({ data: lessons, date }) => (
|
||||
<LessonItems
|
||||
courseId={courseId}
|
||||
date={date}
|
||||
isTeacher={isTeacher(user)}
|
||||
lessons={lessons}
|
||||
setlessonToDelete={setlessonToDelete}
|
||||
setEditLesson={handleEditLesson}
|
||||
key={date}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
) : (
|
||||
<TableContainer whiteSpace="wrap" pb={13}>
|
||||
<Table variant="striped" colorScheme="cyan">
|
||||
<Thead>
|
||||
<Tr>
|
||||
{isTeacher(user) && (
|
||||
<Th align="center" width={1}>
|
||||
{t('journal.pl.lesson.link')}
|
||||
</Th>
|
||||
)}
|
||||
<Th textAlign="center" width={1}>
|
||||
{groupByDate ? t('journal.pl.lesson.time') : t('journal.pl.common.date')}
|
||||
</Th>
|
||||
)}
|
||||
<Th textAlign="center" width={1}>
|
||||
{groupByDate ? t('journal.pl.lesson.time') : t('journal.pl.common.date')}
|
||||
</Th>
|
||||
<Th width="100%">{t('journal.pl.common.name')}</Th>
|
||||
{isTeacher(user) && <Th>{t('journal.pl.lesson.action')}</Th>}
|
||||
<Th isNumeric>{t('journal.pl.common.marked')}</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{lessonCalc?.map(({ data: lessons, date }) => (
|
||||
<LessonItems
|
||||
courseId={courseId}
|
||||
date={date}
|
||||
isTeacher={isTeacher(user)}
|
||||
lessons={lessons}
|
||||
setlessonToDelete={setlessonToDelete}
|
||||
setEditLesson={handleEditLesson}
|
||||
key={date}
|
||||
/>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<Th width="100%">{t('journal.pl.common.name')}</Th>
|
||||
{isTeacher(user) && <Th>{t('journal.pl.lesson.action')}</Th>}
|
||||
<Th isNumeric>{t('journal.pl.common.marked')}</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{lessonCalc?.map(({ data: lessons, date }) => (
|
||||
<LessonItems
|
||||
courseId={courseId}
|
||||
date={date}
|
||||
isTeacher={isTeacher(user)}
|
||||
lessons={lessons}
|
||||
setlessonToDelete={setlessonToDelete}
|
||||
setEditLesson={handleEditLesson}
|
||||
key={date}
|
||||
/>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user