Browse Source
- /tests/:id — employee view, answers shown without correct/incorrect markers - /tests/:id/edit — author view, correct answers highlighted + edit button (disabled until Sprint 4) - TestList: add 'Изменить' button linking to author view Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>master
4 changed files with 130 additions and 10 deletions
@ -0,0 +1,118 @@
|
||||
import { |
||||
ArrowLeftOutlined, |
||||
CheckCircleTwoTone, |
||||
CloseCircleTwoTone, |
||||
EditOutlined, |
||||
PlayCircleOutlined, |
||||
} from '@ant-design/icons' |
||||
import { useQuery } from '@tanstack/react-query' |
||||
import { Alert, Button, Card, Descriptions, List, Space, Spin, Tag, Typography } from 'antd' |
||||
import { useNavigate, useParams } from 'react-router-dom' |
||||
|
||||
import { Answer, testsApi } from '../../api/tests' |
||||
|
||||
const { Title, Text } = Typography |
||||
|
||||
export default function TestEdit() { |
||||
const { id } = useParams<{ id: string }>() |
||||
const navigate = useNavigate() |
||||
|
||||
const { data: test, isLoading } = useQuery({ |
||||
queryKey: ['tests', id], |
||||
queryFn: () => testsApi.get(Number(id)).then((r) => r.data), |
||||
}) |
||||
|
||||
if (isLoading) { |
||||
return <Spin size="large" style={{ display: 'block', margin: '48px auto' }} /> |
||||
} |
||||
|
||||
if (!test) return null |
||||
|
||||
return ( |
||||
<div style={{ maxWidth: 820, margin: '0 auto', padding: 24 }}> |
||||
<Space style={{ width: '100%', justifyContent: 'space-between', marginBottom: 16 }}> |
||||
<Button icon={<ArrowLeftOutlined />} onClick={() => navigate('/')}> |
||||
К списку тестов |
||||
</Button> |
||||
<Space> |
||||
<Button |
||||
icon={<EditOutlined />} |
||||
disabled |
||||
title="Редактирование будет доступно в следующем спринте" |
||||
> |
||||
Редактировать |
||||
</Button> |
||||
<Button |
||||
type="primary" |
||||
icon={<PlayCircleOutlined />} |
||||
onClick={() => navigate(`/tests/${test.id}/take`)} |
||||
> |
||||
Пройти тест |
||||
</Button> |
||||
</Space> |
||||
</Space> |
||||
|
||||
<Alert |
||||
type="warning" |
||||
showIcon |
||||
message="Вид автора — правильные ответы отмечены" |
||||
style={{ marginBottom: 16 }} |
||||
/> |
||||
|
||||
<Title level={2}>{test.title}</Title> |
||||
|
||||
{test.description && ( |
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 16 }}> |
||||
{test.description} |
||||
</Text> |
||||
)} |
||||
|
||||
<Card style={{ marginBottom: 24 }}> |
||||
<Descriptions column={3}> |
||||
<Descriptions.Item label="Вопросов">{test.questions.length}</Descriptions.Item> |
||||
<Descriptions.Item label="Порог зачёта">{test.passing_score}%</Descriptions.Item> |
||||
<Descriptions.Item label="Таймер"> |
||||
{test.time_limit ? `${test.time_limit} мин` : 'Без ограничений'} |
||||
</Descriptions.Item> |
||||
<Descriptions.Item label="Возврат к вопросу"> |
||||
{test.allow_navigation_back ? ( |
||||
<Tag color="green">Разрешён</Tag> |
||||
) : ( |
||||
<Tag color="red">Запрещён</Tag> |
||||
)} |
||||
</Descriptions.Item> |
||||
<Descriptions.Item label="Версия">{test.version}</Descriptions.Item> |
||||
<Descriptions.Item label="Создан"> |
||||
{new Date(test.created_at).toLocaleDateString('ru-RU')} |
||||
</Descriptions.Item> |
||||
</Descriptions> |
||||
</Card> |
||||
|
||||
<Title level={3}>Вопросы ({test.questions.length})</Title> |
||||
|
||||
{test.questions.map((question, index) => ( |
||||
<Card key={question.id} style={{ marginBottom: 12 }}> |
||||
<Text strong> |
||||
{index + 1}. {question.text} |
||||
</Text> |
||||
<List |
||||
style={{ marginTop: 10 }} |
||||
dataSource={question.answers} |
||||
renderItem={(answer: Answer) => ( |
||||
<List.Item style={{ padding: '4px 0' }}> |
||||
<Space> |
||||
{answer.is_correct ? ( |
||||
<CheckCircleTwoTone twoToneColor="#52c41a" /> |
||||
) : ( |
||||
<CloseCircleTwoTone twoToneColor="#d9d9d9" /> |
||||
)} |
||||
<Text>{answer.text}</Text> |
||||
</Space> |
||||
</List.Item> |
||||
)} |
||||
/> |
||||
</Card> |
||||
))} |
||||
</div> |
||||
) |
||||
} |
||||
Loading…
Reference in new issue