diff --git a/services/frontend/src/pages/CompetitionSession/index.tsx b/services/frontend/src/pages/CompetitionSession/index.tsx index fd8ec50..0b4a490 100644 --- a/services/frontend/src/pages/CompetitionSession/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/index.tsx @@ -1,5 +1,5 @@ -import { useState } from "react"; -import { useParams, Navigate } from "react-router-dom"; +import { useState, useEffect } from "react"; +import { useParams, Navigate, useNavigate } from "react-router-dom"; import CompetitionHeader from "./components/CompetitionHeader"; import TaskContent from "./components/TaskContent"; import TaskSolution from "./modules/TaskSolution"; @@ -13,8 +13,10 @@ const CompetitionSession = () => { const { id, taskId } = useParams<{ id: string; taskId?: string }>(); const [answer, setAnswer] = useState(""); const [selectedFile, setSelectedFile] = useState(null); + const [submissionSuccess, setSubmissionSuccess] = useState(false); const competitionId = id || ""; const queryClient = useQueryClient(); + const navigate = useNavigate(); const competitionQuery = useQuery({ queryKey: ["competition", competitionId], @@ -45,14 +47,37 @@ const CompetitionSession = () => { queryKey: ['solutionHistory', competitionId, taskId] }); - setAnswer(""); - setSelectedFile(null); + setSubmissionSuccess(true); // Set flag to trigger the timeout }, onError: (error) => { console.error("Error submitting solution:", error); } }); + // Effect to handle the page reload after successful submission + useEffect(() => { + let timeoutId: number; + + if (submissionSuccess) { + timeoutId = window.setTimeout(() => { + // Reload the current page + window.location.reload(); + + // Alternative: Use React Router's navigate to refresh + // navigate(`/competition/${competitionId}/tasks/${taskId}`, { replace: true }); + + setSubmissionSuccess(false); + }, 5000); // 5 seconds timeout + } + + // Clean up timeout when component unmounts or when submissionSuccess changes + return () => { + if (timeoutId) { + window.clearTimeout(timeoutId); + } + }; + }, [submissionSuccess, competitionId, taskId, navigate]); + const competition = competitionQuery.data; const tasks = tasksQuery.data || []; const isLoading = tasksQuery.isLoading || competitionQuery.isLoading; @@ -125,6 +150,16 @@ const CompetitionSession = () => { onSubmit={handleSubmit} isSubmitting={submitMutation.isPending} /> + {submissionSuccess && ( +
+
+ +

+ Решение отправлено! Страница обновится через несколько секунд... +

+
+
+ )} ) : (
diff --git a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx index cd7906b..8113fba 100644 --- a/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx +++ b/services/frontend/src/pages/CompetitionSession/modules/TaskSolution/index.tsx @@ -70,14 +70,6 @@ const TaskSolution: React.FC = ({ } }, [task.id, solutionHistory]); - // useEffect(() => { - // if (solutionHistory.length > 0 && - // (!displayedSolution || - // (solutionHistory[solutionHistory.length - 1].id !== displayedSolution.id))) { - // setDisplayedSolution(solutionHistory[solutionHistory.length - 1]); - // } - // }, [solutionHistory, displayedSolution]); - useEffect(() => { const loadSolutionContent = async () => { if (!displayedSolution || !displayedSolution.content) return; @@ -122,9 +114,6 @@ const TaskSolution: React.FC = ({
{displayedSolution ? ( <> -
- Результат последней посылки: -
) : ( diff --git a/services/frontend/src/pages/Review/modules/review-header.tsx b/services/frontend/src/pages/Review/modules/review-header.tsx index d27e9e8..a7e14c5 100644 --- a/services/frontend/src/pages/Review/modules/review-header.tsx +++ b/services/frontend/src/pages/Review/modules/review-header.tsx @@ -1,13 +1,22 @@ import { buttonVariants } from "@/components/ui/button"; import { DataRushReview } from "@/components/ui/icons/datarush-review"; import { Reviewer } from "@/shared/types/review"; -import { Link } from "react-router"; +import { useUserStore } from "@/shared/stores/user"; +import { useNavigate } from "react-router-dom"; interface ReviewHeaderProps { reviewer: Reviewer; } export const ReviewHeader = ({ reviewer }: ReviewHeaderProps) => { + const clearUser = useUserStore((state) => state.clearUser); + const navigate = useNavigate(); + + const handleLogout = () => { + clearUser(); + navigate("/"); + }; + return (
@@ -15,13 +24,13 @@ export const ReviewHeader = ({ reviewer }: ReviewHeaderProps) => {

{reviewer.name} {reviewer.surname}

- Выйти - +
); -}; +}; \ No newline at end of file diff --git a/services/frontend/src/pages/UserProfile/index.tsx b/services/frontend/src/pages/UserProfile/index.tsx deleted file mode 100644 index ec9d1d1..0000000 --- a/services/frontend/src/pages/UserProfile/index.tsx +++ /dev/null @@ -1,398 +0,0 @@ -import React from "react"; -import { User } from "lucide-react"; -import { useUserStore } from "@/shared/stores/user"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; - -const UserProfile = () => { - const user = useUserStore((state) => state.user); - - return ( -
-
-
- {user?.avatar ? ( - {user.username} - ) : ( - - )} -
-
-

{user?.username}

-

- {user?.role || "Участник"} • На платформе с{" "} - {new Date(user?.createdAt || Date.now()).toLocaleDateString("ru-RU", { - year: "numeric", - month: "long", - })} -

-
-
- - - - - Информация - - - Статистика - - - Достижения - - - - - - - - - - - - - - - -
- ); -}; - -const UserInfo = () => { - const user = useUserStore((state) => state.user); - - return ( - - - Личная информация - - -
-
-

- Полное имя -

-

- {user?.fullName || "Не указано"} -

-
- -
-

- Email -

-

{user?.email || "Не указано"}

-
- -
-

- Учебное заведение -

-

- {user?.university || "Не указано"} -

-
- -
-

- Специализация -

-

- {user?.specialization || "Не указано"} -

-
-
- -
-

- О себе -

-

- {user?.bio || "Пользователь пока не добавил информацию о себе."} -

-
-
-
- ); -}; - -const UserStatistics = () => { - // Mock statistics data - const statistics = { - totalCompetitions: 12, - completedCompetitions: 8, - totalScore: 756, - averageScore: 94.5, - bestResult: { - competition: "Олимпиада DANO 2024", - place: 3, - score: 97, - }, - totalTasks: 86, - solvedTasks: 72, - tasksByStatus: { - correct: 58, - partial: 14, - wrong: 9, - unattempted: 5, - }, - }; - - return ( -
-
- - - - -
- -
- - - Лучший результат - - -
-

- {statistics.bestResult.competition} -

-
- Место - - {statistics.bestResult.place} - -
-
- Баллы - - {statistics.bestResult.score} - -
-
-
-
- - - - Решение задач - - -
-
- Всего задач - - {statistics.totalTasks} - -
-
- Решено задач - - {statistics.solvedTasks} - -
-
- -
-

- Статусы решений -

-
-
-
-
-
-
-
-
-
-
-
- - Верно ({statistics.tasksByStatus.correct}) - -
-
-
- - Частично ({statistics.tasksByStatus.partial}) - -
-
-
- - Неверно ({statistics.tasksByStatus.wrong}) - -
-
-
-
-
-
-
- ); -}; - - -const StatCard = ({ title, value }: { title: string; value: number | string }) => ( - - -

{title}

-

{value}

-
-
-); - -const UserAchievements = () => { - const achievements = [ - { - id: 1, - name: "Первые шаги", - description: "Участие в первом соревновании", - imageUrl: "/achievements/first-steps.png", - unlocked: true, - }, - { - id: 2, - name: "Восходящая звезда", - description: "Победа в соревновании", - imageUrl: "/achievements/rising-star.png", - unlocked: true, - }, - { - id: 3, - name: "Мастер кода", - description: "Решите 50 задач на программирование", - imageUrl: "/achievements/code-master.png", - unlocked: true, - }, - { - id: 4, - name: "Бронзовый призер", - description: "Займите 3 место в соревновании", - imageUrl: "/achievements/bronze.png", - unlocked: true, - }, - { - id: 5, - name: "Серебряный призер", - description: "Займите 2 место в соревновании", - imageUrl: "/achievements/silver.png", - unlocked: false, - }, - { - id: 6, - name: "Золотой призер", - description: "Займите 1 место в соревновании", - imageUrl: "/achievements/gold.png", - unlocked: false, - }, - { - id: 7, - name: "Марафонец", - description: "Участвуйте в 10 соревнованиях", - imageUrl: "/achievements/marathon.png", - unlocked: false, - }, - { - id: 8, - name: "Идеальное решение", - description: "Получите максимальные баллы за все задачи в соревновании", - imageUrl: "/achievements/perfect.png", - unlocked: false, - }, - ]; - - return ( -
-

- Разблокировано {achievements.filter(a => a.unlocked).length} из {achievements.length} -

- -
- {achievements.map((achievement) => ( -
-
- {achievement.imageUrl ? ( -
-
-
- ) : ( -
- - {achievement.name.substring(0, 1)} - -
- )} -
-

- {achievement.name} -

-

- {achievement.description} -

-
- ))} -
-
- ); -}; - -export default UserProfile; \ No newline at end of file diff --git a/services/frontend/src/pages/UserProfile/modules/UserAchievements/index.tsx b/services/frontend/src/pages/UserProfile/modules/UserAchievements/index.tsx deleted file mode 100644 index a713aa0..0000000 --- a/services/frontend/src/pages/UserProfile/modules/UserAchievements/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -const UserAchievements = () => { - return ( -
-

- Разблокировано {achievements.filter(a => a.unlocked).length} из {achievements.length} -

- -
- {achievements.map((achievement) => ( -
-
- {achievement.imageUrl ? ( -
-
-
- ) : ( -
- - {achievement.name.substring(0, 1)} - -
- )} -
-

- {achievement.name} -

-

- {achievement.description} -

-
- ))} -
-
- ); -}; - -export default UserAchievements \ No newline at end of file diff --git a/services/frontend/src/pages/UserProfile/modules/UserStatistics/index.tsx b/services/frontend/src/pages/UserProfile/modules/UserStatistics/index.tsx deleted file mode 100644 index e69de29..0000000