feat: add version history section to test edit page

- GET /api/tests/{id}/versions — returns full version chain from oldest to newest
- TestEdit: shows 'История версий' table when multiple versions exist,
  current version highlighted, links to navigate between versions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Aleksey Razorvin
2026-03-21 13:35:53 +05:00
parent b2a3bda01b
commit 6b52bca55f
3 changed files with 108 additions and 2 deletions
+69 -2
View File
@@ -6,11 +6,12 @@ import {
PlayCircleOutlined,
} from '@ant-design/icons'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Alert, Button, Card, Descriptions, List, Space, Spin, Tag, Typography, message } from 'antd'
import { Alert, Button, Card, Descriptions, List, Space, Spin, Table, Tag, Typography, message } from 'antd'
import type { ColumnsType } from 'antd/es/table'
import { useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { Answer, CreateTestDto, testsApi } from '../../api/tests'
import { Answer, CreateTestDto, TestListItem, testsApi } from '../../api/tests'
import TestForm, { TestFormValues } from '../../components/TestForm'
const { Title, Text } = Typography
@@ -26,6 +27,12 @@ export default function TestEdit() {
queryFn: () => testsApi.get(Number(id)).then((r) => r.data),
})
const { data: versions = [] } = useQuery({
queryKey: ['tests', id, 'versions'],
queryFn: () => testsApi.versions(Number(id)).then((r) => r.data),
enabled: !editMode,
})
const { mutate: updateTest, isPending } = useMutation({
mutationFn: (data: CreateTestDto) => testsApi.update(Number(id), data).then((r) => r.data),
onSuccess: (result) => {
@@ -174,6 +181,66 @@ export default function TestEdit() {
/>
</Card>
))}
{versions.length > 1 && (
<>
<Title level={3} style={{ marginTop: 32 }}>
История версий
</Title>
<Table<TestListItem>
dataSource={versions}
rowKey="id"
size="small"
pagination={false}
rowClassName={(record) => (record.id === test.id ? 'ant-table-row-selected' : '')}
columns={
[
{
title: 'Версия',
dataIndex: 'version',
width: 90,
render: (v: number, record: TestListItem) => (
<Space>
<Tag color={record.id === test.id ? 'blue' : 'default'}>v{v}</Tag>
{record.id === test.id && <Text type="secondary">(текущая)</Text>}
</Space>
),
},
{
title: 'Дата',
dataIndex: 'created_at',
width: 120,
render: (d: string) => new Date(d).toLocaleDateString('ru-RU'),
},
{
title: 'Вопросов',
dataIndex: 'questions_count',
width: 100,
align: 'center' as const,
},
{
title: 'Порог зачёта',
dataIndex: 'passing_score',
width: 120,
align: 'center' as const,
render: (s: number) => `${s}%`,
},
{
title: '',
key: 'action',
width: 100,
render: (_: unknown, record: TestListItem) =>
record.id !== test.id ? (
<Button size="small" onClick={() => navigate(`/tests/${record.id}/edit`)}>
Открыть
</Button>
) : null,
},
] as ColumnsType<TestListItem>
}
/>
</>
)}
</div>
)
}