From 664ded152a8112abbe47a983ce8c9417e393e444 Mon Sep 17 00:00:00 2001 From: rngsurrounded Date: Mon, 3 Mar 2025 22:04:25 +0900 Subject: [PATCH 1/5] test fix --- .../components/CompetitionHeader/index.tsx | 1 - .../modules/TaskSolution/index.tsx | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx b/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx index d4bab74..086abb1 100644 --- a/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx @@ -24,7 +24,6 @@ const CompetitionHeader: React.FC = ({ const handleTaskSelect = (taskId: string) => { setAnswer(""); setSelectedFile(null); - console.log("SETTER ERROR") navigate(`/competition/${competitionId}/tasks/${taskId}`); } diff --git a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx index 5267dbb..8d4051e 100644 --- a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx @@ -81,13 +81,24 @@ const TaskSolution: React.FC = ({ useEffect(() => { const loadSolutionContent = async () => { + // Clear previous inputs when task changes + if (prevTaskIdRef.current !== task.id) { + setAnswer(""); + setSelectedFile(null); + setSelectedSolutionUrl(null); + prevTaskIdRef.current = task.id; + } + if (!displayedSolution || !displayedSolution.content) return; try { + // Only load content for the appropriate task type if (task.type === TaskType.FILE) { + // For file tasks, we just set the URL - don't touch the answer field setSelectedFile(null); setSelectedSolutionUrl(displayedSolution.content); - } else { + } else if (task.type === TaskType.CODE || task.type === TaskType.INPUT) { + // For non-file tasks, fetch and set the answer text - don't touch file fields const response = await fetch(displayedSolution.content); if (!response.ok) { throw new Error(`Failed to fetch solution content: ${response.status}`); @@ -99,9 +110,9 @@ const TaskSolution: React.FC = ({ console.error('Error loading solution content:', error); } }; - + loadSolutionContent(); - }, [displayedSolution, task.type, setAnswer, setSelectedFile]); + }, [displayedSolution, task.id, task.type, setAnswer, setSelectedFile]); const handleOpenHistory = () => { setIsHistoryOpen(true); From 757c1d80230bd4a44dcda42c799abcaf67925a15 Mon Sep 17 00:00:00 2001 From: rngsurrounded Date: Mon, 3 Mar 2025 22:16:59 +0900 Subject: [PATCH 2/5] input hot fix --- .../modules/TaskSolution/index.tsx | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx index 8d4051e..5faf95e 100644 --- a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx @@ -81,24 +81,16 @@ const TaskSolution: React.FC = ({ useEffect(() => { const loadSolutionContent = async () => { - // Clear previous inputs when task changes - if (prevTaskIdRef.current !== task.id) { - setAnswer(""); - setSelectedFile(null); - setSelectedSolutionUrl(null); - prevTaskIdRef.current = task.id; - } - if (!displayedSolution || !displayedSolution.content) return; try { - // Only load content for the appropriate task type if (task.type === TaskType.FILE) { - // For file tasks, we just set the URL - don't touch the answer field + setAnswer(""); setSelectedFile(null); setSelectedSolutionUrl(displayedSolution.content); - } else if (task.type === TaskType.CODE || task.type === TaskType.INPUT) { - // For non-file tasks, fetch and set the answer text - don't touch file fields + } else { + setSelectedFile(null); + setSelectedSolutionUrl(null); const response = await fetch(displayedSolution.content); if (!response.ok) { throw new Error(`Failed to fetch solution content: ${response.status}`); @@ -112,7 +104,7 @@ const TaskSolution: React.FC = ({ }; loadSolutionContent(); - }, [displayedSolution, task.id, task.type, setAnswer, setSelectedFile]); + }, [displayedSolution, task.type, setAnswer, setSelectedFile]); const handleOpenHistory = () => { setIsHistoryOpen(true); From d053d20825753e0b98eeefa7597ea7d07a8252ae Mon Sep 17 00:00:00 2001 From: rngsurrounded Date: Mon, 3 Mar 2025 22:23:15 +0900 Subject: [PATCH 3/5] competition timer test --- .../components/CompetitionHeader/index.tsx | 92 +++++++++++++++++-- .../src/pages/CompetitionSession/index.tsx | 5 + 2 files changed, 89 insertions(+), 8 deletions(-) diff --git a/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx b/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx index 086abb1..ba486e4 100644 --- a/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; +import React, { useState, useEffect } from 'react'; +import { Link, useNavigate } from 'react-router-dom'; import { Task } from '@/shared/types/task'; -import { ArrowLeft } from 'lucide-react'; -import { useNavigate } from 'react-router-dom'; +import { ArrowLeft, Clock } from 'lucide-react'; +import { CompetitionType } from '@/shared/types/task'; interface CompetitionHeaderProps { title: string; @@ -10,6 +10,9 @@ interface CompetitionHeaderProps { competitionId: string; setAnswer: (value: string) => void; setSelectedFile: (file: File | null) => void; + competitionType?: CompetitionType; + startDate?: Date; + endDate?: Date; } const CompetitionHeader: React.FC = ({ @@ -17,16 +20,66 @@ const CompetitionHeader: React.FC = ({ tasks, competitionId, setAnswer, - setSelectedFile + setSelectedFile, + competitionType, + startDate, + endDate }) => { const navigate = useNavigate(); - + const [timeLeft, setTimeLeft] = useState(''); + const handleTaskSelect = (taskId: string) => { setAnswer(""); setSelectedFile(null); navigate(`/competition/${competitionId}/tasks/${taskId}`); } - + + const formatDate = (date?: Date) => { + if (!date) return ''; + + const dateObj = typeof date === 'string' ? new Date(date) : date; + return dateObj.toLocaleString('ru-RU', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + }; + + useEffect(() => { + if (!endDate || competitionType !== CompetitionType.COMPETITIVE) return; + + const endDateObj = typeof endDate === 'string' ? new Date(endDate) : endDate; + + const updateTimer = () => { + const now = new Date(); + const diff = endDateObj.getTime() - now.getTime(); + + // If time is up, redirect to competition page + if (diff <= 0) { + navigate(`/competition/${competitionId}`); + return; + } + + // Calculate hours, minutes, seconds + const hours = Math.floor(diff / (1000 * 60 * 60)); + const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((diff % (1000 * 60)) / 1000); + + // Format time left + setTimeLeft(`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`); + }; + + // Update timer every second + updateTimer(); + const timerInterval = setInterval(updateTimer, 1000); + + return () => clearInterval(timerInterval); + }, [endDate, competitionId, navigate, competitionType]); + + const showTimeSection = competitionType === CompetitionType.COMPETITIVE && (startDate || endDate); + return (
@@ -42,7 +95,30 @@ const CompetitionHeader: React.FC = ({ {title} -
+ {showTimeSection ? ( +
+ +
+ {startDate && ( + + Начало: {formatDate(startDate)} + + )} + {endDate && ( + + Конец: {formatDate(endDate)} + + )} + {timeLeft && ( + + Осталось: {timeLeft} + + )} +
+
+ ) : ( +
+ )}
diff --git a/services/frontend/src/pages/CompetitionSession/index.tsx b/services/frontend/src/pages/CompetitionSession/index.tsx index eb80913..4297e8e 100644 --- a/services/frontend/src/pages/CompetitionSession/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/index.tsx @@ -8,6 +8,7 @@ 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"; +import { CompetitionType } from "@/shared/types/task"; const CompetitionSession = () => { const { id, taskId } = useParams<{ id: string; taskId?: string }>(); @@ -97,6 +98,9 @@ const CompetitionSession = () => { competitionId={competitionId} setAnswer={setAnswer} setSelectedFile={setSelectedFile} + competitionType={competition?.type} + startDate={competition?.start_date} + endDate={competition?.end_date} />
@@ -120,6 +124,7 @@ const CompetitionSession = () => { selectedFile={selectedFile} setSelectedFile={setSelectedFile} onSubmit={handleSubmit} + isSubmitting={submitMutation.isPending} />
) : ( From a31e5b63d3873a700b0fca8cc0d47a0989b46fcd Mon Sep 17 00:00:00 2001 From: rngsurrounded Date: Mon, 3 Mar 2025 22:29:11 +0900 Subject: [PATCH 4/5] timer fix --- .../components/CompetitionHeader/index.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx b/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx index ba486e4..87f93fe 100644 --- a/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { Task } from '@/shared/types/task'; import { ArrowLeft, Clock } from 'lucide-react'; -import { CompetitionType } from '@/shared/types/task'; +import { CompetitionType } from '@/shared/types/competition'; interface CompetitionHeaderProps { title: string; @@ -56,22 +56,18 @@ const CompetitionHeader: React.FC = ({ const now = new Date(); const diff = endDateObj.getTime() - now.getTime(); - // If time is up, redirect to competition page if (diff <= 0) { navigate(`/competition/${competitionId}`); return; } - // Calculate hours, minutes, seconds const hours = Math.floor(diff / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((diff % (1000 * 60)) / 1000); - // Format time left setTimeLeft(`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`); }; - // Update timer every second updateTimer(); const timerInterval = setInterval(updateTimer, 1000); From bc0c24fa5ab2b1ae95d1b40dc0a8e81edc1596a2 Mon Sep 17 00:00:00 2001 From: rngsurrounded Date: Mon, 3 Mar 2025 22:47:44 +0900 Subject: [PATCH 5/5] test --- .../components/CompetitionHeader/index.tsx | 24 ++++++++++--------- .../modules/TaskSolution/index.tsx | 8 ++++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx b/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx index 87f93fe..d912f1a 100644 --- a/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/components/CompetitionHeader/index.tsx @@ -80,20 +80,22 @@ const CompetitionHeader: React.FC = ({
- - - - -

- {title} -

+
+ + + + +

+ {title} +

+
+ {showTimeSection ? (
-
{startDate && ( diff --git a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx index 5faf95e..5441408 100644 --- a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx @@ -82,13 +82,14 @@ const TaskSolution: React.FC = ({ useEffect(() => { const loadSolutionContent = async () => { if (!displayedSolution || !displayedSolution.content) return; - + console.log(displayedSolution, solutionHistory, "CHECK") try { if (task.type === TaskType.FILE) { setAnswer(""); setSelectedFile(null); setSelectedSolutionUrl(displayedSolution.content); - } else { + } + else { setSelectedFile(null); setSelectedSolutionUrl(null); const response = await fetch(displayedSolution.content); @@ -96,6 +97,7 @@ const TaskSolution: React.FC = ({ throw new Error(`Failed to fetch solution content: ${response.status}`); } const text = await response.text(); + setAnswer(text); } } catch (error) { @@ -104,7 +106,7 @@ const TaskSolution: React.FC = ({ }; loadSolutionContent(); - }, [displayedSolution, task.type, setAnswer, setSelectedFile]); + }, [displayedSolution, setAnswer, setSelectedFile]); const handleOpenHistory = () => { setIsHistoryOpen(true);