+
+ {"До начала\n" + formatWaitTime(waitTime)}
- {members}
+
+
{members}
+
-
- {statusRegister}
+
+ {
+ statusRegister == "reg" ?
+ <>
{}} text="Регистрация"/>>
+ :
+ <> {}} text="Вы записаны"/>>
+ }
diff --git a/src/views/home/contests/Contests.tsx b/src/views/home/contests/Contests.tsx
index 2d68158..d704521 100644
--- a/src/views/home/contests/Contests.tsx
+++ b/src/views/home/contests/Contests.tsx
@@ -1,128 +1,69 @@
import { useEffect } from "react";
import { SecondaryButton } from "../../../components/button/SecondaryButton";
import { cn } from "../../../lib/cn";
-import { useAppDispatch } from "../../../redux/hooks";
+import { useAppDispatch, useAppSelector } from "../../../redux/hooks";
import ContestsBlock from "./ContestsBlock";
import { setMenuActivePage } from "../../../redux/slices/store";
-
-
-interface Contest {
- id: number;
- name: string;
- authors: string[];
- startAt: string;
- registerAt: string;
- duration: number;
- members: number;
- statusRegister: "reg" | "nonreg";
-}
-
-
+import { fetchContests } from "../../../redux/slices/contests";
const Contests = () => {
-
const dispatch = useAppDispatch();
const now = new Date();
- const contests: Contest[] = [
- // === Прошедшие контесты ===
- {
- id: 1,
- name: "Code Marathon 2025",
- authors: ["tourist", "Petr", "Semen", "Rotar"],
- startAt: "2025-09-15T10:00:00.000Z",
- registerAt: "2025-09-10T10:00:00.000Z",
- duration: 180,
- members: 4821,
- statusRegister: "reg",
- },
- {
- id: 2,
- name: "Autumn Cup 2025",
- authors: ["awoo", "Benq"],
- startAt: "2025-09-25T17:00:00.000Z",
- registerAt: "2025-09-20T17:00:00.000Z",
- duration: 150,
- members: 3670,
- statusRegister: "nonreg",
- },
- // === Контесты, которые сейчас идут ===
- {
- id: 3,
- name: "Halloween Challenge",
- authors: ["Errichto", "Radewoosh"],
- startAt: "2025-10-29T10:00:00.000Z", // начался сегодня
- registerAt: "2025-10-25T10:00:00.000Z",
- duration: 240,
- members: 5123,
- statusRegister: "reg",
- },
- {
- id: 4,
- name: "October Blitz",
- authors: ["neal", "Um_nik"],
- startAt: "2025-10-29T12:00:00.000Z",
- registerAt: "2025-10-24T12:00:00.000Z",
- duration: 300,
- members: 2890,
- statusRegister: "nonreg",
- },
-
- // === Контесты, которые еще не начались ===
- {
- id: 5,
- name: "Winter Warmup",
- authors: ["tourist", "rng_58"],
- startAt: "2025-11-05T18:00:00.000Z",
- registerAt: "2025-11-01T18:00:00.000Z",
- duration: 180,
- members: 2100,
- statusRegister: "reg",
- },
- {
- id: 6,
- name: "Global Coding Cup",
- authors: ["maroonrk", "kostka"],
- startAt: "2025-11-12T15:00:00.000Z",
- registerAt: "2025-11-08T15:00:00.000Z",
- duration: 240,
- members: 1520,
- statusRegister: "nonreg",
- },
- ];
+ // Берём данные из Redux
+ const contests = useAppSelector((state) => state.contests.contests);
+ const loading = useAppSelector((state) => state.contests.status);
+ const error = useAppSelector((state) => state.contests.error);
+ // При загрузке страницы — выставляем активную вкладку и подгружаем контесты
useEffect(() => {
- dispatch(setMenuActivePage("contests"))
+ dispatch(setMenuActivePage("contests"));
+ dispatch(fetchContests({}));
}, []);
- return (
-
-
+ if (loading == "loading") {
+ return
Загрузка контестов...
;
+ }
+ if (error) {
+ return
Ошибка: {error}
;
+ }
+
+ return (
+
+
Контесты
{ }}
+ onClick={() => {}}
text="Создать группу"
className="absolute right-0"
/>
-
+
{
+ const endTime =
+ new Date(contest.endsAt).getTime()
+ return endTime >= now.getTime();
+ })}
+ />
-
- {
- const endTime = new Date(contest.startAt).getTime() + contest.duration * 60 * 1000;
- return endTime >= now.getTime();
- })} />
- {
- const endTime = new Date(contest.startAt).getTime() + contest.duration * 60 * 1000;
- return endTime < now.getTime();
- })} />
+ {
+ const endTime =
+ new Date(contest.endsAt).getTime()
+ return endTime < now.getTime();
+ })}
+ />
);
diff --git a/src/views/home/contests/ContestsBlock.tsx b/src/views/home/contests/ContestsBlock.tsx
index ec14e55..ec9642c 100644
--- a/src/views/home/contests/ContestsBlock.tsx
+++ b/src/views/home/contests/ContestsBlock.tsx
@@ -2,27 +2,19 @@ import { useState, FC } from "react";
import { cn } from "../../../lib/cn";
import { ChevroneDown } from "../../../assets/icons/groups";
import ContestItem from "./ContestItem";
+import { Contest } from "../../../redux/slices/contests";
-interface Contest {
- id: number;
- name: string;
- authors: string[];
- startAt: string;
- registerAt: string;
- duration: number;
- members: number;
- statusRegister: "reg" | "nonreg";
-}
-interface GroupsBlockProps {
+
+interface ContestsBlockProps {
contests: Contest[];
title: string;
className?: string;
}
-const GroupsBlock: FC
= ({ contests, title, className }) => {
+const ContestsBlock: FC = ({ contests, title, className }) => {
const [active, setActive] = useState(title != "Скрытые");
@@ -50,7 +42,14 @@ const GroupsBlock: FC = ({ contests, title, className }) => {
{
- contests.map((v, i) => )
+ contests.map((v, i) => )
}
@@ -60,4 +59,4 @@ const GroupsBlock: FC
= ({ contests, title, className }) => {
);
};
-export default GroupsBlock;
+export default ContestsBlock;