import React, { useState, useRef, useEffect } from 'react'; import { useParams } from 'react-router-dom'; import { Task, TaskType, Solution } from '@/shared/types/task'; import { useQuery } from '@tanstack/react-query'; import { getTaskSolutionHistory } from '@/shared/api/session'; import SolutionStatus from './components/SolutionStatus'; import InputSolution from './components/InputSolution'; import FileSolution from './components/FileSolution'; import CodeSolution from './components/CodeSolution'; import ActionButtons from './components/ActionButtons'; import SolutionHistorySheet from './components/SolutionHistorySheet'; interface TaskSolutionProps { task: Task; answer: string; setAnswer: (value: string) => void; selectedFile: File | null; setSelectedFile: (file: File | null) => void; onSubmit: () => void; isSubmitting?: boolean; } const TaskSolution: React.FC = ({ task, answer, setAnswer, selectedFile, setSelectedFile, onSubmit, isSubmitting = false }) => { const fileInputRef = useRef(null); const [isHistoryOpen, setIsHistoryOpen] = useState(false); const [selectedSolutionUrl, setSelectedSolutionUrl] = useState(null); const [displayedSolution, setDisplayedSolution] = useState(null); const { id: competitionId } = useParams<{ id: string }>(); const prevTaskIdRef = useRef(null); const solutionsQuery = useQuery({ queryKey: ['solutionHistory', competitionId, task.id], queryFn: () => getTaskSolutionHistory(competitionId || '', task.id), enabled: !!(competitionId && task.id), }); const solutionHistory = solutionsQuery.data || []; const maxAttempts = task.max_attempts || -1; const submissionsUsed = solutionHistory.length; const submissionsLeft = Math.max(0, maxAttempts - submissionsUsed); const hasSubmissionsLeft = submissionsLeft > 0; useEffect(() => { if (solutionHistory.length > 0 && !displayedSolution) { const latestSolution = solutionHistory[solutionHistory.length - 1]; setDisplayedSolution(latestSolution); } }, [solutionHistory]); useEffect(() => { if (prevTaskIdRef.current !== task.id) { setDisplayedSolution(null); setSelectedSolutionUrl(null); if (solutionHistory.length > 0) { const latestSolution = solutionHistory[solutionHistory.length - 1]; setDisplayedSolution(latestSolution); } prevTaskIdRef.current = task.id; } }, [task.id, solutionHistory]); useEffect(() => { const loadSolutionContent = async () => { if (!displayedSolution || !displayedSolution.content) return; try { if (task.type === TaskType.FILE) { setAnswer(""); setSelectedFile(null); setSelectedSolutionUrl(displayedSolution.content); } else { setSelectedFile(null); setSelectedSolutionUrl(null); const response = await fetch(displayedSolution.content); if (!response.ok) { throw new Error(`Failed to fetch solution content: ${response.status}`); } const text = await response.text(); setAnswer(text); } } catch (error) { console.error('Error loading solution content:', error); } }; loadSolutionContent(); }, [displayedSolution, setAnswer, setSelectedFile]); const handleOpenHistory = () => { setIsHistoryOpen(true); }; const handleSolutionSelect = (solution: Solution) => { setDisplayedSolution(solution); }; const handleClearExistingFile = () => { setSelectedSolutionUrl(null); }; return (
{displayedSolution ? ( <> ) : (
Решение еще не отправлено
)} {task.type === TaskType.INPUT && ( )} {task.type === TaskType.FILE && ( )} {task.type === TaskType.CODE && ( )}
{hasSubmissionsLeft ? ( <> Осталось посылок: {submissionsLeft === Infinity ? '∞' : submissionsLeft} {maxAttempts !== -1 && ( (из {maxAttempts}) )} ) : ( Вы использовали все посылки )}
); }; export default TaskSolution;