Refactor TaskWorkspace to conditionally display learning materials with a button for user interaction. Update TaskPage to filter task navigation buttons based on accessibility, improving user experience in task management.
Some checks failed
platform/bro-js/challenge-pl/pipeline/head There was a failure building this commit

This commit is contained in:
2025-12-14 15:25:53 +03:00
parent 0092e55b65
commit f7df4c755d
2 changed files with 64 additions and 56 deletions

View File

@@ -76,7 +76,29 @@ export const TaskWorkspace = ({ task, onTaskComplete }: TaskWorkspaceProps) => {
return ( return (
<VStack align="stretch" gap={3}> <VStack align="stretch" gap={3}>
{/* Дополнительные материалы - показываются сверху */}
{task.learningMaterial && showLearningMaterial && (
<LearningMaterialViewer
content={task.learningMaterial}
linesPerPage={30}
/>
)}
<Box borderWidth="1px" borderRadius="md" borderColor="gray.200" p={4} bg="white" shadow="sm"> <Box borderWidth="1px" borderRadius="md" borderColor="gray.200" p={4} bg="white" shadow="sm">
{/* Кнопка для показа дополнительного материала */}
{task.learningMaterial && !showLearningMaterial && (
<HStack justify="center" mb={4}>
<Button
size="sm"
variant="outline"
colorScheme="blue"
onClick={() => setShowLearningMaterial(true)}
>
📚 Прочитать доп. материал
</Button>
</HStack>
)}
<Text fontSize="lg" fontWeight="bold" mb={3} color="gray.800"> <Text fontSize="lg" fontWeight="bold" mb={3} color="gray.800">
{task.title} {task.title}
</Text> </Text>
@@ -249,30 +271,8 @@ export const TaskWorkspace = ({ task, onTaskComplete }: TaskWorkspaceProps) => {
> >
<ReactMarkdown remarkPlugins={[remarkGfm]}>{task.description}</ReactMarkdown> <ReactMarkdown remarkPlugins={[remarkGfm]}>{task.description}</ReactMarkdown>
</Box> </Box>
{/* Кнопка для показа дополнительного материала */}
{task.learningMaterial && !showLearningMaterial && (
<HStack justify="center" mt={4}>
<Button
size="sm"
variant="outline"
colorScheme="blue"
onClick={() => setShowLearningMaterial(true)}
>
📚 Прочитать доп. материал
</Button>
</HStack>
)}
</Box> </Box>
{/* Дополнительные материалы - показываются отдельно */}
{task.learningMaterial && showLearningMaterial && (
<LearningMaterialViewer
content={task.learningMaterial}
linesPerPage={30}
/>
)}
{/* Статус проверки и результат - фиксированное место */} {/* Статус проверки и результат - фиксированное место */}

View File

@@ -79,10 +79,10 @@ export const TaskPage = () => {
const handleTaskComplete = () => { const handleTaskComplete = () => {
if (!chain || currentTaskIndex === -1) return if (!chain || currentTaskIndex === -1) return
const nextTaskIndex = currentTaskIndex + 1 const nextTaskIndex = currentTaskIndex + 1
const nextTask = chain.tasks[nextTaskIndex] const nextTask = chain.tasks[nextTaskIndex]
if (nextTask) { if (nextTask) {
// Обновляем прогресс перед переходом // Обновляем прогресс перед переходом
storage.setFurthestTaskIndex(chain.id, nextTaskIndex) storage.setFurthestTaskIndex(chain.id, nextTaskIndex)
@@ -97,15 +97,15 @@ export const TaskPage = () => {
const handleNavigateToTask = (newTaskId: string) => { const handleNavigateToTask = (newTaskId: string) => {
if (!chain) return if (!chain) return
const newTaskIndex = chain.tasks.findIndex(t => t.id === newTaskId) const newTaskIndex = chain.tasks.findIndex(t => t.id === newTaskId)
if (newTaskIndex === -1) return if (newTaskIndex === -1) return
// Проверяем доступность // Проверяем доступность
if (!isTaskAccessible(newTaskIndex)) { if (!isTaskAccessible(newTaskIndex)) {
return // Не переходим к заблокированному заданию return // Не переходим к заблокированному заданию
} }
// Обновляем прогресс при переходе // Обновляем прогресс при переходе
const newFurthest = Math.max(furthestTaskIndex, newTaskIndex) const newFurthest = Math.max(furthestTaskIndex, newTaskIndex)
if (newFurthest > furthestTaskIndex) { if (newFurthest > furthestTaskIndex) {
@@ -115,6 +115,7 @@ export const TaskPage = () => {
navigate(URLs.task(chain.id, newTaskId)) navigate(URLs.task(chain.id, newTaskId))
} }
// Проверяем доступность текущего задания при загрузке // Проверяем доступность текущего задания при загрузке
useEffect(() => { useEffect(() => {
if (chain && currentTaskIndex >= 0 && !isTaskAccessible(currentTaskIndex)) { if (chain && currentTaskIndex >= 0 && !isTaskAccessible(currentTaskIndex)) {
@@ -138,7 +139,7 @@ export const TaskPage = () => {
return null return null
} }
const taskProgress = `Задание ${currentTaskIndex + 1}` const taskProgress = `Задание`
return ( return (
<> <>
@@ -146,12 +147,12 @@ export const TaskPage = () => {
<Box bg="gray.50" minH="100vh" py={4} 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">
{/* Навигация по заданиям */} {/* Навигация по заданиям */}
<Box <Box
bg="white" bg="white"
borderWidth="1px" borderWidth="1px"
borderColor="gray.200" borderColor="gray.200"
borderRadius="md" borderRadius="md"
p={3} p={3}
mb={4} mb={4}
shadow="sm" shadow="sm"
> >
@@ -160,29 +161,36 @@ export const TaskPage = () => {
<Text fontSize="sm" fontWeight="medium" color="gray.600" mr={2}> <Text fontSize="sm" fontWeight="medium" color="gray.600" mr={2}>
Задания: Задания:
</Text> </Text>
{chain.tasks.map((t, index) => { {chain.tasks
const isAccessible = isTaskAccessible(index) .filter((_, index) => {
const isCurrent = t.id === taskId const isAccessible = isTaskAccessible(index)
// Показываем все доступные + только следующую недоступную
return ( return isAccessible || index === furthestTaskIndex + 1
<Button })
key={t.id} .map((t) => {
size="sm" const taskIndex = chain.tasks.indexOf(t)
variant={isCurrent ? 'solid' : isAccessible ? 'outline' : 'ghost'} const isAccessible = isTaskAccessible(taskIndex)
colorScheme={isCurrent ? 'teal' : 'gray'} const isCurrent = t.id === taskId
// @ts-expect-error Chakra UI v2 uses isDisabled
isDisabled={!isAccessible} return (
onClick={() => isAccessible && handleNavigateToTask(t.id)} <Button
minW="40px" key={t.id}
opacity={isAccessible ? 1 : 0.5} size="sm"
cursor={isAccessible ? 'pointer' : 'not-allowed'} variant={isCurrent ? 'solid' : isAccessible ? 'outline' : 'ghost'}
> colorScheme={isCurrent ? 'teal' : 'gray'}
{isAccessible ? index + 1 : `🔒${index + 1}`} // @ts-expect-error Chakra UI v2 uses isDisabled
</Button> isDisabled={!isAccessible}
) onClick={() => isAccessible && handleNavigateToTask(t.id)}
})} minW="40px"
opacity={isAccessible ? 1 : 0.5}
cursor={isAccessible ? 'pointer' : 'not-allowed'}
>
{isAccessible ? taskIndex + 1 : `🔒${taskIndex + 1}`}
</Button>
)
})}
</HStack> </HStack>
<Button <Button
size="sm" size="sm"
variant="ghost" variant="ghost"