diff --git a/services/frontend/src/pages/CompetitionSession/index.tsx b/services/frontend/src/pages/CompetitionSession/index.tsx index 09fc40c..4d0c5f8 100644 --- a/services/frontend/src/pages/CompetitionSession/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/index.tsx @@ -4,6 +4,7 @@ import CompetitionHeader from "./components/CompetitionHeader"; import TaskContent from "./components/TaskContent"; import TaskSolution from "./modules/TaskSolution"; import { getCompetitionTasks, submitTaskSolution } from "@/shared/api/session"; +import { getCompetition } from "@/shared/api/competitions"; import { Loader2 } from "lucide-react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { TaskType } from "@/shared/types/task"; @@ -15,6 +16,12 @@ const CompetitionSession = () => { const competitionId = id || ""; const queryClient = useQueryClient(); + const competitionQuery = useQuery({ + queryKey: ["competition", competitionId], + queryFn: () => getCompetition(competitionId), + enabled: !!competitionId, + }); + const tasksQuery = useQuery({ queryKey: ["competitionTasks", competitionId], queryFn: () => getCompetitionTasks(competitionId), @@ -46,9 +53,12 @@ const CompetitionSession = () => { } }); + const competition = competitionQuery.data; const tasks = tasksQuery.data || []; - const isLoading = tasksQuery.isLoading; - const error = tasksQuery.error ? "Не удалось загрузить задания. Пожалуйста, попробуйте позже." : null; + const isLoading = tasksQuery.isLoading || competitionQuery.isLoading; + const error = tasksQuery.error || competitionQuery.error + ? "Не удалось загрузить данные. Пожалуйста, попробуйте позже." + : null; const currentTask = tasks.find((t) => t.id === taskId) || null; @@ -77,10 +87,12 @@ const CompetitionSession = () => { submitMutation.mutate(); }; + const competitionTitle = competition?.title || "Загрузка соревнования..."; + return (
diff --git a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/components/FileSolution/index.tsx b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/components/FileSolution/index.tsx index 8f97216..b7d351b 100644 --- a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/components/FileSolution/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/components/FileSolution/index.tsx @@ -99,7 +99,7 @@ const FileSolution: React.FC = ({ )} - {selectedFile ? ( + {selectedFile || existingFileUrl ? ( - ) : existingFileUrl ? ( -
- - -
) : null}
diff --git a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx index fb8324b..20fdda1 100644 --- a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx @@ -30,7 +30,9 @@ const TaskSolution: React.FC = ({ 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 previousTaskIdRef = useRef(null); const solutionsQuery = useQuery({ queryKey: ['solutionHistory', competitionId, task.id], @@ -39,18 +41,46 @@ const TaskSolution: React.FC = ({ }); const solutionHistory = solutionsQuery.data || []; - const latestSolution = solutionHistory && solutionHistory.length > 0 ? solutionHistory[0] : null; useEffect(() => { - const loadLatestSolution = async () => { - if (!latestSolution || !latestSolution.content) return; + if (solutionHistory.length > 0 && !currentSolution) { + setCurrentSolution(solutionHistory[solutionHistory.length - 1]); + } + }, [solutionHistory, currentSolution]); + + useEffect(() => { + if (solutionHistory.length > 0 && currentSolution && + solutionHistory[0].id !== currentSolution.id) { + setCurrentSolution(solutionHistory[solutionHistory.length - 1]); + } + }, [solutionHistory, currentSolution]); + + useEffect(() => { + if (previousTaskIdRef.current !== task.id) { + setCurrentSolution(null); + setSelectedSolutionUrl(null); + + setAnswer(""); + setSelectedFile(null); + + if (solutionHistory.length > 0 && !solutionsQuery.isLoading) { + setCurrentSolution(solutionHistory[solutionHistory.length - 1]); + } + + previousTaskIdRef.current = task.id; + } + }, [task.id, solutionHistory, solutionsQuery.isLoading, setAnswer, setSelectedFile]); + + useEffect(() => { + const loadSolutionContent = async () => { + if (!currentSolution || !currentSolution.content) return; try { if (task.type === TaskType.FILE) { setSelectedFile(null); - setSelectedSolutionUrl(latestSolution.content); + setSelectedSolutionUrl(currentSolution.content); } else { - const response = await fetch(latestSolution.content); + const response = await fetch(currentSolution.content); if (!response.ok) { throw new Error(`Failed to fetch solution content: ${response.status}`); } @@ -58,38 +88,20 @@ const TaskSolution: React.FC = ({ setAnswer(text); } } catch (error) { - console.error('Error loading latest solution content:', error); - } finally { + console.error('Error loading solution content:', error); } }; - if (latestSolution && !solutionsQuery.isLoading && !solutionsQuery.isError) { - loadLatestSolution(); - } - }, [latestSolution, task.id, task.type, setAnswer, setSelectedFile]); + loadSolutionContent(); + }, [currentSolution, task.type, setAnswer, setSelectedFile]); const handleOpenHistory = () => { setIsHistoryOpen(true); }; - const handleSolutionSelect = async (solution: Solution) => { - if (!solution.content) return; - - try { - if (task.type === TaskType.FILE) { - setSelectedFile(null); - setSelectedSolutionUrl(solution.content); - } else { - const response = await fetch(solution.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); - } + const handleSolutionSelect = (solution: Solution) => { + setCurrentSolution(solution); + setIsHistoryOpen(false); }; const handleClearExistingFile = () => { @@ -98,8 +110,8 @@ const TaskSolution: React.FC = ({ return (
- {latestSolution ? ( - + {currentSolution ? ( + ) : (
Решение еще не отправлено @@ -109,7 +121,7 @@ const TaskSolution: React.FC = ({ {task.type === TaskType.INPUT && ( )} @@ -126,7 +138,7 @@ const TaskSolution: React.FC = ({ {task.type === TaskType.CODE && ( )} @@ -141,6 +153,7 @@ const TaskSolution: React.FC = ({ solutions={solutionHistory} maxPoints={task.points} onSolutionSelect={handleSolutionSelect} + currentSolutionId={currentSolution?.id} />
);