Files
DataRush/services/frontend/src/pages/Competitions/index.tsx
T
2025-03-03 18:58:14 +03:00

128 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;