import { ArrowLeftOutlined, CheckCircleTwoTone, CloseCircleTwoTone, EditOutlined, PlayCircleOutlined, } from '@ant-design/icons' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' 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, TestListItem, testsApi } from '../../api/tests' import TestForm, { TestFormValues } from '../../components/TestForm' const { Title, Text } = Typography export default function TestEdit() { const { id } = useParams<{ id: string }>() const navigate = useNavigate() const queryClient = useQueryClient() const [editMode, setEditMode] = useState(false) const { data: test, isLoading } = useQuery({ queryKey: ['tests', id], 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: activateVersion, isPending: isActivating } = useMutation({ mutationFn: (versionId: number) => testsApi.activate(versionId).then((r) => r.data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['tests'] }) queryClient.invalidateQueries({ queryKey: ['tests', id, 'versions'] }) queryClient.invalidateQueries({ queryKey: ['tests', id] }) message.success('Активная версия изменена') }, onError: () => message.error('Не удалось изменить активную версию'), }) const { mutate: updateTest, isPending } = useMutation({ mutationFn: (data: CreateTestDto) => testsApi.update(Number(id), data).then((r) => r.data), onSuccess: (result) => { queryClient.invalidateQueries({ queryKey: ['tests'] }) if (result.is_new_version) { message.success(`Создана новая версия теста (v${result.test.version})`) navigate(`/tests/${result.test.id}/edit`) } else { message.success('Тест обновлён') queryClient.invalidateQueries({ queryKey: ['tests', id] }) setEditMode(false) } }, onError: (error: unknown) => { const err = error as { response?: { data?: { detail?: string } } } message.error(err.response?.data?.detail || 'Ошибка при сохранении теста') }, }) if (isLoading) { return } if (!test) return null // Режим редактирования — показываем форму с предзаполненными данными if (editMode) { const initialValues: TestFormValues = { title: test.title, description: test.description ?? undefined, passing_score: test.passing_score, has_timer: test.time_limit !== null, time_limit: test.time_limit ?? undefined, allow_navigation_back: test.allow_navigation_back, questions: test.questions.map((q) => ({ text: q.text, answers: q.answers.map((a) => ({ text: a.text, is_correct: a.is_correct })), })), } const onSubmit = (values: TestFormValues) => { updateTest({ title: values.title, description: values.description, passing_score: values.passing_score, time_limit: values.has_timer ? values.time_limit : undefined, allow_navigation_back: values.allow_navigation_back ?? true, questions: values.questions, }) } return ( setEditMode(false)} onBack={() => setEditMode(false)} backLabel="К просмотру теста" /> ) } // Режим просмотра (вид автора) return (
{versions.length > 1 && (!test.is_active || versions.some(v => v.id !== test.id && v.is_active)) && ( )} {test.title} {test.description && ( {test.description} )} {test.questions.length} {test.passing_score}% {test.time_limit ? `${test.time_limit} мин` : 'Без ограничений'} {test.allow_navigation_back ? ( Разрешён ) : ( Запрещён )} {test.version} {new Date(test.created_at).toLocaleDateString('ru-RU')} {versions.length > 1 && ( <> История версий dataSource={versions} rowKey="id" size="small" pagination={false} style={{ marginBottom: 24 }} rowClassName={(record) => (record.id === test.id ? 'ant-table-row-selected' : '')} columns={ [ { title: 'Версия', dataIndex: 'version', width: 70, render: (v: number) => v{v}, }, { title: 'Статус', dataIndex: 'is_active', width: 130, render: (active: boolean) => active ? ( Активная ) : ( Неактивная ), }, { 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', render: (_: unknown, record: TestListItem) => ( {record.id !== test.id && ( )} {(record.id !== test.id || !record.is_active) && ( )} ), }, ] as ColumnsType } /> )} Вопросы ({test.questions.length}) {test.questions.map((question, index) => ( {index + 1}. {question.text} ( {answer.is_correct ? ( ) : ( )} {answer.text} )} /> ))}
) }