mirror of
https://gitlab.com/megazordpobeda/DataRush.git
synced 2026-05-23 06:17:10 +00:00
128 lines
3.7 KiB
TypeScript
128 lines
3.7 KiB
TypeScript
import React, { useState } from "react";
|
||
import { CompetitionGrid } from "./modules/CompetitionsGrid";
|
||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||
import { useQuery } from "@tanstack/react-query";
|
||
import { getCompetitions } from "@/shared/api/competitions";
|
||
import {
|
||
NoActiveCompetitions,
|
||
NoCompetitions,
|
||
NoCompletedCompetitions,
|
||
} from "./modules/NoCompetitions";
|
||
import { TabsContent } from "@radix-ui/react-tabs";
|
||
import { Loading } from "@/components/ui/loading";
|
||
import { CompetitionState } from "@/shared/types/competition";
|
||
|
||
enum CompetitionTab {
|
||
ONGOING = "ongoing",
|
||
COMPLETED = "completed",
|
||
}
|
||
|
||
const CompetitionsPage = () => {
|
||
const [activeTab, setActiveTab] = useState<string>(CompetitionTab.ONGOING);
|
||
|
||
const activeCompetitionsQuery = useQuery({
|
||
queryKey: ["active-competitions"],
|
||
queryFn: async () => getCompetitions(true),
|
||
retry: 1,
|
||
});
|
||
|
||
const inactiveCompetitionsQuery = useQuery({
|
||
queryKey: ["inactive-competitions"],
|
||
queryFn: async () => getCompetitions(false),
|
||
retry: 1,
|
||
});
|
||
|
||
const startedCompetitions = React.useMemo(
|
||
() =>
|
||
(activeCompetitionsQuery.data ?? []).filter(
|
||
(comp) => comp.state === CompetitionState.STARTED,
|
||
),
|
||
[activeCompetitionsQuery.data],
|
||
);
|
||
|
||
const finishedCompetitions = React.useMemo(
|
||
() =>
|
||
(activeCompetitionsQuery.data ?? []).filter(
|
||
(comp) => comp.state === CompetitionState.FINISHED,
|
||
),
|
||
[activeCompetitionsQuery.data],
|
||
);
|
||
|
||
if (
|
||
activeCompetitionsQuery.isLoading ||
|
||
inactiveCompetitionsQuery.isLoading
|
||
) {
|
||
return <Loading />;
|
||
}
|
||
|
||
return (
|
||
<div className="flex flex-col gap-6 sm:gap-8">
|
||
{(activeCompetitionsQuery.data ?? []).length > 0 && (
|
||
<Tabs value={activeTab} onValueChange={setActiveTab} asChild>
|
||
<Section>
|
||
<SectionHeader>
|
||
<SectionTitle>Мои события</SectionTitle>
|
||
|
||
<TabsList>
|
||
<TabsTrigger value={CompetitionTab.ONGOING}>
|
||
Прохожу
|
||
</TabsTrigger>
|
||
<TabsTrigger value={CompetitionTab.COMPLETED}>
|
||
Завершено
|
||
</TabsTrigger>
|
||
</TabsList>
|
||
</SectionHeader>
|
||
|
||
<TabsContent value={CompetitionTab.ONGOING} asChild>
|
||
{startedCompetitions.length > 0 ? (
|
||
<CompetitionGrid competitions={startedCompetitions} />
|
||
) : (
|
||
<NoActiveCompetitions />
|
||
)}
|
||
</TabsContent>
|
||
|
||
<TabsContent value={CompetitionTab.COMPLETED} asChild>
|
||
{finishedCompetitions.length > 0 ? (
|
||
<CompetitionGrid competitions={finishedCompetitions} />
|
||
) : (
|
||
<NoCompletedCompetitions />
|
||
)}
|
||
</TabsContent>
|
||
</Section>
|
||
</Tabs>
|
||
)}
|
||
|
||
<Section>
|
||
<SectionHeader>
|
||
<SectionTitle>События</SectionTitle>
|
||
</SectionHeader>
|
||
{(inactiveCompetitionsQuery.data ?? []).length > 0 ? (
|
||
<CompetitionGrid
|
||
competitions={inactiveCompetitionsQuery.data ?? []}
|
||
/>
|
||
) : (
|
||
<NoCompetitions />
|
||
)}
|
||
</Section>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
const Section = ({ children }: { children: React.ReactNode }) => {
|
||
return <div className="flex flex-col gap-6 sm:gap-8">{children}</div>;
|
||
};
|
||
|
||
const SectionHeader = ({ children }: { children: React.ReactNode }) => {
|
||
return (
|
||
<div className="flex min-h-[58px] flex-col items-center justify-center gap-4 sm:flex-row sm:gap-2">
|
||
{children}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
const SectionTitle = ({ children }: { children: React.ReactNode }) => {
|
||
return <h1 className="w-full text-3xl font-semibold">{children}</h1>;
|
||
};
|
||
|
||
export default CompetitionsPage;
|