113 lines
3.2 KiB
TypeScript
113 lines
3.2 KiB
TypeScript
import React, { useMemo } from 'react'
|
||
import { useParams } from 'react-router-dom'
|
||
import { Box, Heading, Tooltip, Text } from '@chakra-ui/react'
|
||
import dayjs from 'dayjs'
|
||
|
||
import { api } from '../../__data__/api/api'
|
||
import { PageLoader } from '../../components/page-loader/page-loader'
|
||
|
||
export const Attendance = () => {
|
||
const { courseId } = useParams()
|
||
const { data: attendance, isLoading } = api.useLessonListQuery(courseId, {
|
||
selectFromResult: ({ data, isLoading }) => ({
|
||
data: data?.body,
|
||
isLoading,
|
||
}),
|
||
})
|
||
const { data: courseInfo, isLoading: courseInfoIssLoading } =
|
||
api.useGetCourseByIdQuery(courseId)
|
||
|
||
const data = useMemo(() => {
|
||
if (!attendance) return null
|
||
|
||
const studentsMap = new Map()
|
||
|
||
attendance.forEach((lesson) => {
|
||
lesson.students.forEach((student) => {
|
||
const current = studentsMap.get(student.sub) || {}
|
||
|
||
studentsMap.set(student.sub, {
|
||
...student,
|
||
id: student.sub,
|
||
value: current.value || (student.family_name && student.given_name
|
||
? `${student.family_name} ${student.given_name}`
|
||
: student.name || student.email || student.preferred_username || student.family_name || student.given_name),
|
||
})
|
||
})
|
||
})
|
||
|
||
const compare = Intl.Collator('ru').compare
|
||
|
||
const students = [...studentsMap.values()]
|
||
students.sort(({ family_name: name }, { family_name: nname }) =>
|
||
compare(name, nname),
|
||
)
|
||
return {
|
||
students,
|
||
}
|
||
}, [attendance])
|
||
|
||
if (!data || isLoading || courseInfoIssLoading) {
|
||
return <PageLoader />
|
||
}
|
||
|
||
return (
|
||
<Box>
|
||
<Box mt={12} mb={12}>
|
||
<Heading>{courseInfo.name}</Heading>
|
||
</Box>
|
||
<Box>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Дата</th>
|
||
<th>Название занятия</th>
|
||
{data.students.map((student) => (
|
||
<th id={student.id || student.sub} key={student.sub}>{student.name || student.value || 'Имя не определено'}</th>
|
||
))}
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{attendance.map((lesson, index) => (
|
||
<tr key={lesson.name}>
|
||
<td>{dayjs(lesson.date).format('DD.MM.YYYY')}</td>
|
||
<td>{<ShortText text={lesson.name} />}</td>
|
||
|
||
{data.students.map((st) => {
|
||
const wasThere =
|
||
lesson.students.findIndex((u) => u.sub === st.sub) !== -1
|
||
return (
|
||
<td
|
||
style={{
|
||
textAlign: 'center',
|
||
backgroundColor: wasThere ? '#8ef78a' : '#e09797',
|
||
}}
|
||
key={st.sub}
|
||
>
|
||
{wasThere ? '+' : '-'}
|
||
</td>
|
||
)
|
||
})}
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</Box>
|
||
</Box>
|
||
)
|
||
}
|
||
|
||
const ShortText = ({ text }: { text: string }) => {
|
||
const needShortText = text.length > 20
|
||
|
||
if (needShortText) {
|
||
return (
|
||
<Tooltip label="На страницу с лекциями" fontSize="12px" top="16px">
|
||
<Text>{text.slice(0, 20)}...</Text>
|
||
</Tooltip>
|
||
)
|
||
}
|
||
|
||
return text
|
||
}
|