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
Some checks failed
platform/bro-js/challenge-pl/pipeline/head There was a failure building this commit
This commit is contained in:
parent
bb31cc5c6c
commit
79e3dc9864
@ -3,7 +3,12 @@ import { Box, Button, Flex, Heading, Text } from '@chakra-ui/react'
|
|||||||
|
|
||||||
import { useChallenge } from '../context/ChallengeContext'
|
import { useChallenge } from '../context/ChallengeContext'
|
||||||
|
|
||||||
export const Header = () => {
|
interface HeaderProps {
|
||||||
|
chainName?: string
|
||||||
|
taskProgress?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Header = ({ chainName, taskProgress }: HeaderProps) => {
|
||||||
const { nickname, logout } = useChallenge()
|
const { nickname, logout } = useChallenge()
|
||||||
|
|
||||||
if (!nickname) return null
|
if (!nickname) return null
|
||||||
@ -13,11 +18,21 @@ export const Header = () => {
|
|||||||
<Flex maxW="1200px" mx="auto" justify="space-between" align="center">
|
<Flex maxW="1200px" mx="auto" justify="space-between" align="center">
|
||||||
<Box>
|
<Box>
|
||||||
<Heading size="md" color="teal.600">
|
<Heading size="md" color="teal.600">
|
||||||
Challenge Platform
|
{chainName || 'Challenge Platform'}
|
||||||
</Heading>
|
</Heading>
|
||||||
<Text fontSize="sm" color="gray.600" mt={1}>
|
<Flex gap={3} align="center" mt={1}>
|
||||||
{nickname}
|
<Text fontSize="sm" color="gray.600">
|
||||||
</Text>
|
{nickname}
|
||||||
|
</Text>
|
||||||
|
{taskProgress && (
|
||||||
|
<>
|
||||||
|
<Text fontSize="sm" color="gray.400">•</Text>
|
||||||
|
<Text fontSize="sm" color="gray.600">
|
||||||
|
{taskProgress}
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
<Button onClick={logout} variant="ghost" size="sm">
|
<Button onClick={logout} variant="ghost" size="sm">
|
||||||
Выйти
|
Выйти
|
||||||
|
|||||||
@ -36,109 +36,102 @@ export const TaskWorkspace = ({ task, onTaskComplete }: TaskWorkspaceProps) => {
|
|||||||
}, [finalSubmission, refreshStats])
|
}, [finalSubmission, refreshStats])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack align="stretch" gap={4}>
|
<VStack align="stretch" gap={3}>
|
||||||
<Box borderWidth="1px" borderRadius="lg" borderColor="gray.200" p={4} bg={descriptionBg}>
|
<Box borderWidth="1px" borderRadius="md" borderColor="gray.200" p={3} bg={descriptionBg}>
|
||||||
<Text fontSize="lg" fontWeight="semibold" mb={2}>
|
<Text fontSize="md" fontWeight="semibold" mb={1}>
|
||||||
{task.title}
|
{task.title}
|
||||||
</Text>
|
</Text>
|
||||||
<Text whiteSpace="pre-line" color="gray.700">
|
<Text whiteSpace="pre-line" color="gray.700" fontSize="sm">
|
||||||
{task.description}
|
{task.description}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Статус проверки */}
|
{/* Статус проверки */}
|
||||||
{queueStatus && !finalSubmission && (
|
{queueStatus && !finalSubmission && (
|
||||||
<Box borderWidth="1px" borderRadius="lg" borderColor="blue.200" bg="blue.50" p={4}>
|
<Box borderWidth="1px" borderRadius="md" borderColor="blue.200" bg="blue.50" p={2}>
|
||||||
<HStack>
|
<HStack gap={2}>
|
||||||
<Spinner size="md" color="blue.500" />
|
<Spinner size="sm" color="blue.500" />
|
||||||
<VStack align="flex-start" gap={1}>
|
<Text fontSize="sm" fontWeight="medium" color="blue.700">
|
||||||
<Text fontWeight="semibold" color="blue.700">
|
{queueStatus.status === 'waiting' ? 'Ожидание в очереди...' : 'Проверяем решение...'}
|
||||||
{queueStatus.status === 'waiting' ? 'Ожидание в очереди...' : 'Проверяем решение...'}
|
{typeof queueStatus.position === 'number' && queueStatus.position > 0 && ` (позиция: ${queueStatus.position})`}
|
||||||
</Text>
|
</Text>
|
||||||
{typeof queueStatus.position === 'number' && queueStatus.position > 0 && (
|
|
||||||
<Text fontSize="sm" color="blue.600">
|
|
||||||
Позиция в очереди: {queueStatus.position}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</VStack>
|
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Результат проверки - успех */}
|
{/* Результат проверки - успех */}
|
||||||
{isAccepted && (
|
{isAccepted && (
|
||||||
<Box borderWidth="2px" borderRadius="lg" borderColor="green.300" bg="green.50" p={4}>
|
<Box borderWidth="1px" borderRadius="md" borderColor="green.300" bg="green.50" p={3}>
|
||||||
<VStack gap={3}>
|
<HStack justify="space-between" align="start">
|
||||||
<Text fontSize="3xl">✅</Text>
|
<HStack align="start" gap={2} flex={1}>
|
||||||
<Text fontSize="xl" fontWeight="bold" color="green.700">
|
<Text fontSize="xl">✅</Text>
|
||||||
Задание принято!
|
<Box>
|
||||||
</Text>
|
<Text fontSize="md" fontWeight="bold" color="green.700">
|
||||||
{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}
|
|
||||||
</Text>
|
</Text>
|
||||||
|
{finalSubmission?.feedback && (
|
||||||
|
<Text fontSize="sm" color="gray.700" mt={1}>
|
||||||
|
{finalSubmission.feedback}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
</HStack>
|
||||||
<Button onClick={onTaskComplete} colorScheme="green" size="lg">
|
<Button onClick={onTaskComplete} colorScheme="green" size="sm">
|
||||||
Следующее задание →
|
Следующее →
|
||||||
</Button>
|
</Button>
|
||||||
</VStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Результат проверки - требуется доработка */}
|
{/* Результат проверки - требуется доработка */}
|
||||||
{needsRevision && (
|
{needsRevision && (
|
||||||
<Box borderWidth="2px" borderRadius="lg" borderColor="orange.300" bg="orange.50" p={4}>
|
<Box borderWidth="1px" borderRadius="md" borderColor="orange.300" bg="orange.50" p={3}>
|
||||||
<VStack gap={3}>
|
<HStack align="start" gap={2}>
|
||||||
<Text fontSize="3xl">⚠️</Text>
|
<Text fontSize="xl">⚠️</Text>
|
||||||
<Text fontSize="xl" fontWeight="bold" color="orange.700">
|
<Box flex={1}>
|
||||||
Требуется доработка
|
<HStack>
|
||||||
</Text>
|
<Text fontSize="md" fontWeight="bold" color="orange.700">
|
||||||
{finalSubmission?.feedback && (
|
Требуется доработка
|
||||||
<Box w="100%" bg="white" borderRadius="md" p={3} borderWidth="1px" borderColor="orange.200">
|
|
||||||
<Text fontWeight="medium" color="orange.800" mb={1}>
|
|
||||||
Комментарий проверяющего:
|
|
||||||
</Text>
|
</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}
|
{finalSubmission.feedback}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
)}
|
||||||
)}
|
</Box>
|
||||||
<Text fontSize="sm" color="gray.600">
|
</HStack>
|
||||||
Попытка №{finalSubmission?.attemptNumber}
|
|
||||||
</Text>
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fontWeight="medium" mb={2}>
|
<Text fontWeight="medium" mb={1} fontSize="sm">
|
||||||
Ваше решение
|
Ваше решение
|
||||||
</Text>
|
</Text>
|
||||||
<Textarea
|
<Textarea
|
||||||
value={result}
|
value={result}
|
||||||
onChange={(event) => setResult(event.target.value)}
|
onChange={(event) => setResult(event.target.value)}
|
||||||
placeholder="Напишите ваше решение..."
|
placeholder="Напишите ваше решение..."
|
||||||
rows={14}
|
rows={8}
|
||||||
bg="white"
|
bg="white"
|
||||||
|
fontSize="sm"
|
||||||
// @ts-expect-error Chakra UI v2 uses isDisabled
|
// @ts-expect-error Chakra UI v2 uses isDisabled
|
||||||
isDisabled={isChecking || isAccepted}
|
isDisabled={isChecking || isAccepted}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<HStack justify="flex-end" gap={3}>
|
<HStack justify="flex-end" gap={2}>
|
||||||
{!isAccepted && (
|
{!isAccepted && (
|
||||||
<>
|
<>
|
||||||
{/* @ts-expect-error Chakra UI v2 uses isDisabled */}
|
{/* @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>
|
</Button>
|
||||||
{/* @ts-expect-error Chakra UI v2 uses isLoading/isDisabled */}
|
{/* @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 ? 'Отправить снова' : 'Отправить на проверку'}
|
{needsRevision ? 'Отправить снова' : 'Отправить на проверку'}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
import React, { useEffect, useRef, useState } from 'react'
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
|
||||||
Flex,
|
|
||||||
Heading,
|
|
||||||
Text,
|
Text,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { Alert } from '@chakra-ui/react/alert'
|
import { Alert } from '@chakra-ui/react/alert'
|
||||||
@ -44,11 +41,6 @@ export const MainPage = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleBackToChains = () => {
|
|
||||||
setSelectedChain(null)
|
|
||||||
setSelectedTask(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = eventEmitter.on('submission_completed', (event) => {
|
const unsubscribe = eventEmitter.on('submission_completed', (event) => {
|
||||||
const submission = (event.data as { submission?: { status: string; attemptNumber: number } })?.submission
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header chainName={selectedChain.name} taskProgress={taskProgress} />
|
||||||
<Box bg="gray.50" minH="100vh" py={8} px={{ base: 4, md: 8 }}>
|
<Box bg="gray.50" minH="100vh" py={4} px={{ base: 4, md: 8 }}>
|
||||||
<Box maxW="1200px" mx="auto">
|
<Box maxW="1200px" mx="auto">
|
||||||
{notification && (
|
{notification && (
|
||||||
<Alert.Root status={notification.status} borderRadius="md" mb={4}>
|
<Alert.Root status={notification.status} borderRadius="md" mb={4}>
|
||||||
@ -123,20 +117,6 @@ export const MainPage = () => {
|
|||||||
</Alert.Root>
|
</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 && (
|
{selectedTask && (
|
||||||
<TaskWorkspace task={selectedTask} onTaskComplete={handleTaskComplete} />
|
<TaskWorkspace task={selectedTask} onTaskComplete={handleTaskComplete} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user