Refactor Header and TaskWorkspace components to enhance UI and user feedback. Header now accepts chainName and taskProgress props for improved context display. TaskWorkspace updates include styling adjustments, conditional rendering for queue status, and feedback messages, streamlining user interaction during task processing.
Some checks failed
platform/bro-js/challenge-pl/pipeline/head There was a failure building this commit

This commit is contained in:
Primakov Alexandr Alexandrovich 2025-11-04 11:55:09 +03:00
parent bb31cc5c6c
commit 79e3dc9864
3 changed files with 73 additions and 85 deletions

View File

@ -3,7 +3,12 @@ import { Box, Button, Flex, Heading, Text } from '@chakra-ui/react'
import { useChallenge } from '../context/ChallengeContext'
export const Header = () => {
interface HeaderProps {
chainName?: string
taskProgress?: string
}
export const Header = ({ chainName, taskProgress }: HeaderProps) => {
const { nickname, logout } = useChallenge()
if (!nickname) return null
@ -13,11 +18,21 @@ export const Header = () => {
<Flex maxW="1200px" mx="auto" justify="space-between" align="center">
<Box>
<Heading size="md" color="teal.600">
Challenge Platform
{chainName || 'Challenge Platform'}
</Heading>
<Text fontSize="sm" color="gray.600" mt={1}>
{nickname}
</Text>
<Flex gap={3} align="center" mt={1}>
<Text fontSize="sm" color="gray.600">
{nickname}
</Text>
{taskProgress && (
<>
<Text fontSize="sm" color="gray.400"></Text>
<Text fontSize="sm" color="gray.600">
{taskProgress}
</Text>
</>
)}
</Flex>
</Box>
<Button onClick={logout} variant="ghost" size="sm">
Выйти

View File

@ -36,109 +36,102 @@ export const TaskWorkspace = ({ task, onTaskComplete }: TaskWorkspaceProps) => {
}, [finalSubmission, refreshStats])
return (
<VStack align="stretch" gap={4}>
<Box borderWidth="1px" borderRadius="lg" borderColor="gray.200" p={4} bg={descriptionBg}>
<Text fontSize="lg" fontWeight="semibold" mb={2}>
<VStack align="stretch" gap={3}>
<Box borderWidth="1px" borderRadius="md" borderColor="gray.200" p={3} bg={descriptionBg}>
<Text fontSize="md" fontWeight="semibold" mb={1}>
{task.title}
</Text>
<Text whiteSpace="pre-line" color="gray.700">
<Text whiteSpace="pre-line" color="gray.700" fontSize="sm">
{task.description}
</Text>
</Box>
{/* Статус проверки */}
{queueStatus && !finalSubmission && (
<Box borderWidth="1px" borderRadius="lg" borderColor="blue.200" bg="blue.50" p={4}>
<HStack>
<Spinner size="md" color="blue.500" />
<VStack align="flex-start" gap={1}>
<Text fontWeight="semibold" color="blue.700">
{queueStatus.status === 'waiting' ? 'Ожидание в очереди...' : 'Проверяем решение...'}
</Text>
{typeof queueStatus.position === 'number' && queueStatus.position > 0 && (
<Text fontSize="sm" color="blue.600">
Позиция в очереди: {queueStatus.position}
</Text>
)}
</VStack>
<Box borderWidth="1px" borderRadius="md" borderColor="blue.200" bg="blue.50" p={2}>
<HStack gap={2}>
<Spinner size="sm" color="blue.500" />
<Text fontSize="sm" fontWeight="medium" color="blue.700">
{queueStatus.status === 'waiting' ? 'Ожидание в очереди...' : 'Проверяем решение...'}
{typeof queueStatus.position === 'number' && queueStatus.position > 0 && ` (позиция: ${queueStatus.position})`}
</Text>
</HStack>
</Box>
)}
{/* Результат проверки - успех */}
{isAccepted && (
<Box borderWidth="2px" borderRadius="lg" borderColor="green.300" bg="green.50" p={4}>
<VStack gap={3}>
<Text fontSize="3xl"></Text>
<Text fontSize="xl" fontWeight="bold" color="green.700">
Задание принято!
</Text>
{finalSubmission?.feedback && (
<Box w="100%" bg="white" borderRadius="md" p={3} borderWidth="1px" borderColor="green.200">
<Text fontWeight="medium" color="green.800" mb={1}>
Комментарий:
</Text>
<Text whiteSpace="pre-wrap" color="gray.700">
{finalSubmission.feedback}
<Box borderWidth="1px" borderRadius="md" borderColor="green.300" bg="green.50" p={3}>
<HStack justify="space-between" align="start">
<HStack align="start" gap={2} flex={1}>
<Text fontSize="xl"></Text>
<Box>
<Text fontSize="md" fontWeight="bold" color="green.700">
Задание принято!
</Text>
{finalSubmission?.feedback && (
<Text fontSize="sm" color="gray.700" mt={1}>
{finalSubmission.feedback}
</Text>
)}
</Box>
)}
<Button onClick={onTaskComplete} colorScheme="green" size="lg">
Следующее задание
</HStack>
<Button onClick={onTaskComplete} colorScheme="green" size="sm">
Следующее
</Button>
</VStack>
</HStack>
</Box>
)}
{/* Результат проверки - требуется доработка */}
{needsRevision && (
<Box borderWidth="2px" borderRadius="lg" borderColor="orange.300" bg="orange.50" p={4}>
<VStack gap={3}>
<Text fontSize="3xl"></Text>
<Text fontSize="xl" fontWeight="bold" color="orange.700">
Требуется доработка
</Text>
{finalSubmission?.feedback && (
<Box w="100%" bg="white" borderRadius="md" p={3} borderWidth="1px" borderColor="orange.200">
<Text fontWeight="medium" color="orange.800" mb={1}>
Комментарий проверяющего:
<Box borderWidth="1px" borderRadius="md" borderColor="orange.300" bg="orange.50" p={3}>
<HStack align="start" gap={2}>
<Text fontSize="xl"></Text>
<Box flex={1}>
<HStack>
<Text fontSize="md" fontWeight="bold" color="orange.700">
Требуется доработка
</Text>
<Text whiteSpace="pre-wrap" color="gray.700">
<Text fontSize="xs" color="gray.600">
(попытка {finalSubmission?.attemptNumber})
</Text>
</HStack>
{finalSubmission?.feedback && (
<Text fontSize="sm" color="gray.700" mt={1}>
{finalSubmission.feedback}
</Text>
</Box>
)}
<Text fontSize="sm" color="gray.600">
Попытка {finalSubmission?.attemptNumber}
</Text>
</VStack>
)}
</Box>
</HStack>
</Box>
)}
<Box>
<Text fontWeight="medium" mb={2}>
<Text fontWeight="medium" mb={1} fontSize="sm">
Ваше решение
</Text>
<Textarea
value={result}
onChange={(event) => setResult(event.target.value)}
placeholder="Напишите ваше решение..."
rows={14}
rows={8}
bg="white"
fontSize="sm"
// @ts-expect-error Chakra UI v2 uses isDisabled
isDisabled={isChecking || isAccepted}
/>
</Box>
<HStack justify="flex-end" gap={3}>
<HStack justify="flex-end" gap={2}>
{!isAccepted && (
<>
{/* @ts-expect-error Chakra UI v2 uses isDisabled */}
<Button onClick={reset} variant="ghost" isDisabled={isChecking}>
<Button onClick={reset} variant="ghost" size="sm" isDisabled={isChecking}>
Сбросить
</Button>
{/* @ts-expect-error Chakra UI v2 uses isLoading/isDisabled */}
<Button onClick={submit} colorScheme="teal" isLoading={isChecking} isDisabled={!result.trim() || isChecking}>
<Button onClick={submit} colorScheme="teal" size="sm" isLoading={isChecking} isDisabled={!result.trim() || isChecking}>
{needsRevision ? 'Отправить снова' : 'Отправить на проверку'}
</Button>
</>

View File

@ -1,9 +1,6 @@
import React, { useEffect, useRef, useState } from 'react'
import {
Box,
Button,
Flex,
Heading,
Text,
} from '@chakra-ui/react'
import { Alert } from '@chakra-ui/react/alert'
@ -44,11 +41,6 @@ export const MainPage = () => {
}
}
const handleBackToChains = () => {
setSelectedChain(null)
setSelectedTask(null)
}
useEffect(() => {
const unsubscribe = eventEmitter.on('submission_completed', (event) => {
const submission = (event.data as { submission?: { status: string; attemptNumber: number } })?.submission
@ -100,11 +92,13 @@ export const MainPage = () => {
)
}
const taskProgress = `Задание ${selectedChain.tasks.findIndex(t => t.id === selectedTask?.id) + 1} из ${selectedChain.tasks.length}`
// Показываем выбранную цепочку и задания
return (
<>
<Header />
<Box bg="gray.50" minH="100vh" py={8} px={{ base: 4, md: 8 }}>
<Header chainName={selectedChain.name} taskProgress={taskProgress} />
<Box bg="gray.50" minH="100vh" py={4} px={{ base: 4, md: 8 }}>
<Box maxW="1200px" mx="auto">
{notification && (
<Alert.Root status={notification.status} borderRadius="md" mb={4}>
@ -123,20 +117,6 @@ export const MainPage = () => {
</Alert.Root>
)}
<Flex justify="space-between" align="center" mb={8}>
<Box>
<Heading size="lg" mb={1}>
{selectedChain.name}
</Heading>
<Text color="gray.600">
Задание {selectedChain.tasks.findIndex(t => t.id === selectedTask?.id) + 1} из {selectedChain.tasks.length}
</Text>
</Box>
<Button onClick={handleBackToChains} variant="outline">
Вернуться к цепочкам
</Button>
</Flex>
{selectedTask && (
<TaskWorkspace task={selectedTask} onTaskComplete={handleTaskComplete} />
)}