Добавлена группировка курсов по годам в компонент CoursesList с использованием useMemo для оптимизации производительности. Обновлен интерфейс для отображения курсов, сгруппированных по годам, с соответствующими заголовками и разделителями. Обновлены тестовые данные в success.json для поддержки новых курсов.

This commit is contained in:
2025-03-23 13:13:58 +03:00
parent c7f9e3f2bf
commit 4416a53bc1
2 changed files with 229 additions and 10 deletions

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react'
import React, { useEffect, useRef, useState, useMemo } from 'react'
import dayjs from 'dayjs'
import {
Box,
@@ -19,7 +19,9 @@ import {
useColorMode,
useBreakpointValue,
Flex,
Stack
Stack,
Divider,
Text
} from '@chakra-ui/react'
import { useForm, Controller } from 'react-hook-form'
import { AddIcon } from '@chakra-ui/icons'
@@ -93,6 +95,29 @@ export const CoursesList = () => {
}
}, [crucQuery.isSuccess, t])
// Группировка курсов по годам
const groupedCourses = useMemo(() => {
if (!data?.body?.length) return {}
const grouped: Record<string, typeof data.body> = {}
// Сортируем курсы по дате начала (от новых к старым)
const sortedCourses = [...data.body].sort((a, b) =>
dayjs(b.startDt).valueOf() - dayjs(a.startDt).valueOf()
)
// Группируем по годам
sortedCourses.forEach(course => {
const year = dayjs(course.startDt).format('YYYY')
if (!grouped[year]) {
grouped[year] = []
}
grouped[year].push(course)
})
return grouped
}, [data?.body])
if (isLoading) {
return (
<PageLoader />
@@ -217,14 +242,33 @@ export const CoursesList = () => {
)}
</Box>
)}
<VStack as="ul" align="stretch" spacing={{ base: 3, md: 4 }}>
{data?.body?.map((c) => (
<CourseCard
key={c.id}
course={c}
/>
))}
</VStack>
{Object.keys(groupedCourses).length > 0 ? (
Object.entries(groupedCourses)
.sort(([yearA], [yearB]) => Number(yearB) - Number(yearA)) // Сортируем годы по убыванию
.map(([year, courses]) => (
<Box key={year} mb={6}>
<Flex align="center" mb={3}>
<Heading size="md" color={colorMode === 'dark' ? 'blue.300' : 'blue.600'}>
{year}
</Heading>
<Divider ml={4} flex="1" />
</Flex>
<VStack as="ul" align="stretch" spacing={{ base: 3, md: 4 }}>
{courses.map((c) => (
<CourseCard
key={c.id}
course={c}
/>
))}
</VStack>
</Box>
))
) : (
<Box textAlign="center" py={10}>
<Text color="gray.500">{t('journal.pl.course.noCourses')}</Text>
</Box>
)}
</Container>
)
}