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

This commit is contained in:
Primakov Alexandr Alexandrovich 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>
)
}

View File

@ -46,6 +46,181 @@
"startDt": "2024-03-02T15:37:05.907Z",
"created": "2024-03-02T15:37:05.908Z",
"__v": 2
},
{
"id": "66f84d32def890e3g789239a",
"name": "МГУ-24-1",
"teachers": [
{
"sub": "a72905c2-f334-50db-920f-d9e85c7248d2",
"name": "Елена Иванова",
"preferred_username": "ivanova",
"email": "ivanova@example.com"
}
],
"lessons": [
"66e3f6gcec37fec650f28490",
"66e312d5ec37fec650f2abff",
"66e79cfcced789d2f6791416"
],
"creator": {
"sub": "a72905c2-f334-50db-920f-d9e85c7248d2",
"email_verified": true,
"name": "Елена Иванова",
"preferred_username": "ivanova",
"given_name": "Елена",
"family_name": "Иванова",
"email": "ivanova@example.com"
},
"startDt": "2024-04-15T10:30:00.000Z",
"endDt": "2024-06-30T18:00:00.000Z",
"created": "2024-04-10T09:25:33.112Z",
"__v": 1
},
{
"id": "66g95e43fef901f4h890340b",
"name": "СПБГУ-24-3",
"teachers": [
{
"sub": "b83016d3-g445-61ec-931g-e0f96d8359e3",
"name": "Михаил Петров",
"preferred_username": "petrov",
"email": "petrov@example.com"
},
{
"sub": "c94127e4-h556-72fd-042h-f1g07e9460f4",
"name": "Анна Сидорова",
"preferred_username": "sidorova",
"email": "sidorova@example.com"
}
],
"lessons": [
"67f4g7hdec37fec650f28501",
"67f423e6ec37fec650f2acgg",
"67f80dgdced789d2f6791527",
"67f80e1gced789d2f679152d"
],
"creator": {
"sub": "b83016d3-g445-61ec-931g-e0f96d8359e3",
"email_verified": true,
"name": "Михаил Петров",
"preferred_username": "petrov",
"given_name": "Михаил",
"family_name": "Петров",
"email": "petrov@example.com"
},
"startDt": "2024-05-20T09:00:00.000Z",
"examWithJury": "67dg4e4g5748e531e7382562",
"created": "2024-05-15T14:22:45.500Z",
"capacity": 30,
"enrolled": 28,
"__v": 3
},
{
"id": "67h06f54gfg012g5i901451c",
"name": "HSE-24-2",
"teachers": [
{
"sub": "d05238f5-i667-83ge-153i-g2h18f0571g5",
"name": "Сергей Кузнецов",
"preferred_username": "kuznetsov",
"email": "kuznetsov@example.com"
}
],
"lessons": [
"68g5h8iec37fec650f28612",
"68g534f7ec37fec650f2adhi",
"68g91eigced789d2f6791638"
],
"creator": {
"sub": "d05238f5-i667-83ge-153i-g2h18f0571g5",
"email_verified": true,
"name": "Сергей Кузнецов",
"preferred_username": "kuznetsov",
"given_name": "Сергей",
"family_name": "Кузнецов",
"email": "kuznetsov@example.com"
},
"startDt": "2024-06-10T13:15:00.000Z",
"endDt": "2024-08-25T17:45:00.000Z",
"created": "2024-06-01T11:08:30.750Z",
"location": "Онлайн",
"tags": ["программирование", "алгоритмы", "анализ данных"],
"__v": 0
},
{
"id": "54c62b10bdc678a1d5680127e",
"name": "МФТИ-23-1",
"teachers": [
{
"sub": "e16349g6-j778-94hf-264j-h3i29g1682h6",
"name": "Дмитрий Соколов",
"preferred_username": "sokolov",
"email": "sokolov@example.com"
}
],
"lessons": [
"54b2d4eadb26edb541e17378",
"54b2e2c3db26edb541e18489",
"54b3d5efdb26edb541e19590"
],
"creator": {
"sub": "e16349g6-j778-94hf-264j-h3i29g1682h6",
"email_verified": true,
"name": "Дмитрий Соколов",
"preferred_username": "sokolov",
"given_name": "Дмитрий",
"family_name": "Соколов",
"email": "sokolov@example.com"
},
"startDt": "2023-09-01T08:00:00.000Z",
"endDt": "2023-12-25T16:00:00.000Z",
"created": "2023-08-15T10:42:18.320Z",
"status": "completed",
"completionRate": 92,
"__v": 5
},
{
"id": "78i17g65hgh123h6j012562d",
"name": "УрФУ-25-4",
"teachers": [
{
"sub": "f27450h7-k889-05ig-375k-i4j30h2793i7",
"name": "Ольга Морозова",
"preferred_username": "morozova",
"email": "morozova@example.com"
},
{
"sub": "g38561i8-l990-16jh-486l-j5k41i3804j8",
"name": "Константин Волков",
"preferred_username": "volkov",
"email": "volkov@example.com"
}
],
"lessons": [
"79h6i9jfdb26edb541e20601",
"79h7j0kgdb26edb541e21712",
"79h8k1lhdb26edb541e22823",
"79h9l2midb26edb541e23934"
],
"creator": {
"sub": "f27450h7-k889-05ig-375k-i4j30h2793i7",
"email_verified": true,
"name": "Ольга Морозова",
"preferred_username": "morozova",
"given_name": "Ольга",
"family_name": "Морозова",
"email": "morozova@example.com"
},
"startDt": "2025-02-10T09:30:00.000Z",
"endDt": "2025-07-05T15:30:00.000Z",
"created": "2024-11-20T14:55:40.670Z",
"status": "scheduled",
"maxCapacity": 50,
"registrationDeadline": "2025-01-30T23:59:59.999Z",
"location": "Гибрид",
"tags": ["машинное обучение", "компьютерное зрение", "нейронные сети"],
"__v": 0
}
]
}