import React, { useEffect, useRef, useState } from 'react' import { Box, Text, } from '@chakra-ui/react' import { Alert } from '@chakra-ui/react/alert' import type { ChallengeChain, ChallengeTask } from '../../__data__/types' import { useChallenge } from '../../context/ChallengeContext' import { TaskWorkspace } from '../../components/personal' import { Header } from '../../components/Header' import { LoginForm } from '../../components/LoginForm' import { ChainSelector } from '../../components/ChainSelector' export const MainPage = () => { const { nickname, eventEmitter } = useChallenge() const [selectedChain, setSelectedChain] = useState(null) const [selectedTask, setSelectedTask] = useState(null) const [isOffline, setIsOffline] = useState(() => typeof navigator !== 'undefined' ? !navigator.onLine : false, ) const [notification, setNotification] = useState<{ status: 'success' | 'warning'; title: string; description?: string } | null>(null) const notificationTimeoutRef = useRef(null) const handleSelectChain = (chain: ChallengeChain) => { setSelectedChain(chain) setSelectedTask(chain.tasks[0]) } const handleTaskComplete = () => { if (!selectedChain) return const currentIndex = selectedChain.tasks.findIndex((item) => item.id === selectedTask?.id) const nextTask = currentIndex >= 0 ? selectedChain.tasks[currentIndex + 1] : null if (nextTask) { setSelectedTask(nextTask) } else { // Цепочка завершена, возвращаемся к выбору setSelectedChain(null) setSelectedTask(null) } } useEffect(() => { const unsubscribe = eventEmitter.on('submission_completed', (event) => { const submission = (event.data as { submission?: { status: string; attemptNumber: number } })?.submission const accepted = submission?.status === 'accepted' const title = accepted ? 'Задание принято' : 'Задание требует доработки' const description = submission ? `Попытка №${submission.attemptNumber}` : undefined if (notificationTimeoutRef.current) { window.clearTimeout(notificationTimeoutRef.current) } setNotification({ status: accepted ? 'success' : 'warning', title, description }) notificationTimeoutRef.current = window.setTimeout(() => setNotification(null), 4000) }) return () => { unsubscribe() if (notificationTimeoutRef.current) { window.clearTimeout(notificationTimeoutRef.current) } } }, [eventEmitter]) useEffect(() => { const handleOnline = () => setIsOffline(false) const handleOffline = () => setIsOffline(true) window.addEventListener('online', handleOnline) window.addEventListener('offline', handleOffline) return () => { window.removeEventListener('online', handleOnline) window.removeEventListener('offline', handleOffline) } }, []) // Если пользователь не авторизован, показываем форму входа if (!nickname) { return } // Если цепочка не выбрана, показываем селектор цепочек if (!selectedChain) { return ( <>
) } const taskProgress = `Задание ${selectedChain.tasks.findIndex(t => t.id === selectedTask?.id) + 1} из ${selectedChain.tasks.length}` // Показываем выбранную цепочку и задания return ( <>
{notification && ( {notification.title} {notification.description && {notification.description}} )} {isOffline && ( Вы находитесь офлайн. Черновики сохраняются локально и будут отправлены после восстановления связи. )} {selectedTask && ( )} ) }