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; } const TaskSolution: React.FC = ({ task, answer, setAnswer, selectedFile, setSelectedFile, onSubmit, }) => { const fileInputRef = useRef(null); const [isHistoryOpen, setIsHistoryOpen] = useState(false); const [selectedSolutionUrl, setSelectedSolutionUrl] = useState(null); const [currentSolution, setCurrentSolution] = useState(null); const { id: competitionId } = useParams<{ id: string }>(); const taskIdRef = useRef(null); const solutionsQuery = useQuery({ queryKey: ['solutionHistory', competitionId, task.id], queryFn: () => getTaskSolutionHistory(competitionId || '', task.id), enabled: !!(competitionId && task.id), }); // Get the solution history - already sorted from oldest to newest const solutionHistory = solutionsQuery.data || []; // Handle task changes useEffect(() => { // If task changed, reset everything and load the latest solution if (taskIdRef.current !== task.id) { setCurrentSolution(null); setSelectedSolutionUrl(null); setAnswer(""); setSelectedFile(null); taskIdRef.current = task.id; // Wait for the query to complete if (!solutionsQuery.isLoading && solutionHistory.length > 0) { // Get the most recent solution (last in the array) const latestSolution = solutionHistory[solutionHistory.length - 1]; setCurrentSolution(latestSolution); } } }, [task.id, solutionHistory, solutionsQuery.isLoading, setAnswer, setSelectedFile]); // Refresh current solution when the solution history changes (after a new submission) useEffect(() => { if (!solutionsQuery.isLoading && solutionHistory.length > 0) { // If we don't have a current solution or there's a new submission // (which would be the last item in the array) if (!currentSolution || currentSolution.id !== solutionHistory[solutionHistory.length - 1].id) { // Set to the latest solution (last in the array) setCurrentSolution(solutionHistory[solutionHistory.length - 1]); } } }, [solutionHistory, currentSolution, solutionsQuery.isLoading]); // Load solution content when current solution changes useEffect(() => { const loadSolutionContent = async () => { if (!currentSolution || !currentSolution.content) return; try { if (task.type === TaskType.FILE) { setSelectedFile(null); setSelectedSolutionUrl(currentSolution.content); } else { const response = await fetch(currentSolution.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(); }, [currentSolution, task.type, setAnswer, setSelectedFile]); const handleOpenHistory = () => { setIsHistoryOpen(true); }; const handleSolutionSelect = (solution: Solution) => { setCurrentSolution(solution); setIsHistoryOpen(false); }; const handleClearExistingFile = () => { setSelectedSolutionUrl(null); }; const handleSubmitWrapper = () => { onSubmit(); setAnswer(""); setSelectedFile(null); setSelectedSolutionUrl(null); }; return (
{currentSolution ? ( ) : (
Решение еще не отправлено
)} {task.type === TaskType.INPUT && ( )} {task.type === TaskType.FILE && ( )} {task.type === TaskType.CODE && ( )}
); }; export default TaskSolution;