182 lines
5.7 KiB
TypeScript
182 lines
5.7 KiB
TypeScript
import React, { useMemo, useRef, useState, useEffect } from "react";
|
|
import { Button } from "@heroui/react";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
import ContestsTable from "../components/ContestsTable";
|
|
import ContestCreateForm from "../components/ContestCreateForm";
|
|
import RoundsTable from "@/components/RoundsTable";
|
|
import RoundCreateForm from "@/components/RoundCreateForm";
|
|
import { useContestStore } from "@/stores/contestStore";
|
|
import { useContestRefreshStore } from "@/stores/contestRefreshStore";
|
|
|
|
type FormMode = "none" | "create" | "edit";
|
|
type RoundFormMode = "none" | "create" | "edit";
|
|
|
|
export default function AdminContestsPage() {
|
|
const { t } = useTranslation("common");
|
|
|
|
const [formMode, setFormMode] = useState<FormMode>("none");
|
|
const [roundFormMode, setRoundFormMode] = useState<RoundFormMode>("none");
|
|
const contestFormRef = useRef<HTMLDivElement | null>(null);
|
|
const roundFormRef = useRef<HTMLDivElement | null>(null);
|
|
|
|
const selectedContest = useContestStore((s) => s.selectedContest);
|
|
const setSelectedContest = useContestStore((s) => s.setSelectedContest);
|
|
const selectedRound = useContestStore((s) => s.selectedRound);
|
|
const setSelectedRound = useContestStore((s) => s.setSelectedRound);
|
|
|
|
const triggerRefresh = useContestRefreshStore((s) => s.triggerRefresh);
|
|
|
|
const isFormVisible = formMode !== "none";
|
|
const isRoundFormVisible = roundFormMode !== "none";
|
|
|
|
const formTitle = useMemo(() => {
|
|
if (formMode === "create") return t("contest_new");
|
|
if (formMode === "edit") return t("contest_edit");
|
|
return "";
|
|
}, [formMode, t]);
|
|
|
|
const roundFormTitle = useMemo(() => {
|
|
if (roundFormMode === "create") return t("round_new");
|
|
if (roundFormMode === "edit") return t("round_edit");
|
|
return "";
|
|
}, [roundFormMode, t]);
|
|
|
|
useEffect(() => {
|
|
if (formMode !== "none" && contestFormRef.current) {
|
|
contestFormRef.current.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
}
|
|
}, [formMode]);
|
|
|
|
useEffect(() => {
|
|
if (roundFormMode !== "none" && roundFormRef.current) {
|
|
roundFormRef.current.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
}
|
|
}, [roundFormMode]);
|
|
|
|
return (
|
|
<>
|
|
<ContestsTable
|
|
selectOnRowClick
|
|
showTests
|
|
onRowSelect={(contest) => {
|
|
setSelectedContest(contest);
|
|
setSelectedRound(null);
|
|
setFormMode("none");
|
|
setRoundFormMode("none");
|
|
}}
|
|
onEditContest={(contest) => {
|
|
setSelectedContest(contest);
|
|
setSelectedRound(null);
|
|
setRoundFormMode("none");
|
|
setFormMode("edit");
|
|
}}
|
|
/>
|
|
|
|
<div style={{ display: "flex", gap: 12, marginTop: 16 }}>
|
|
<Button
|
|
onPress={() => {
|
|
setSelectedContest(null);
|
|
setSelectedRound(null);
|
|
setFormMode("create");
|
|
setRoundFormMode("none");
|
|
}}
|
|
>
|
|
{t("contest_add_new") ?? "Přidat nový závod"}
|
|
</Button>
|
|
<Button
|
|
onPress={() => {
|
|
if (!selectedContest) return;
|
|
setFormMode("none");
|
|
setRoundFormMode("create");
|
|
setSelectedRound(null);
|
|
}}
|
|
isDisabled={!selectedContest}
|
|
>
|
|
{t("round_add_new") ?? "Přidat nové kolo"}
|
|
</Button>
|
|
|
|
{(isFormVisible || isRoundFormVisible) && (
|
|
<Button
|
|
variant="light"
|
|
onPress={() => {
|
|
setFormMode("none");
|
|
setRoundFormMode("none");
|
|
setSelectedRound(null);
|
|
}}
|
|
>
|
|
{t("admin_form_close") ?? "Zavřít formulář"}
|
|
</Button>
|
|
)}
|
|
</div>
|
|
|
|
{isFormVisible && (
|
|
<div style={{ marginTop: 16 }} ref={contestFormRef}>
|
|
{formTitle && <h2 style={{ fontSize: 18, fontWeight: 600 }}>{formTitle}</h2>}
|
|
|
|
{formMode === "edit" && selectedContest && (
|
|
<ContestCreateForm
|
|
mode="edit"
|
|
contest={selectedContest}
|
|
onUpdated={() => {
|
|
setFormMode("none");
|
|
triggerRefresh();
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
{formMode === "create" && (
|
|
<ContestCreateForm
|
|
mode="create"
|
|
onCreated={(contest) => {
|
|
setSelectedContest(contest);
|
|
setFormMode("none");
|
|
triggerRefresh();
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{isRoundFormVisible && selectedContest && (
|
|
<div style={{ marginTop: 16 }} ref={roundFormRef}>
|
|
{roundFormTitle && <h2 style={{ fontSize: 18, fontWeight: 600 }}>{roundFormTitle}</h2>}
|
|
<RoundCreateForm
|
|
mode={roundFormMode === "edit" ? "edit" : "create"}
|
|
round={roundFormMode === "edit" ? (selectedRound as any) : undefined}
|
|
contestId={selectedContest.id}
|
|
onCreated={() => {
|
|
setRoundFormMode("none");
|
|
triggerRefresh();
|
|
}}
|
|
onUpdated={() => {
|
|
setRoundFormMode("none");
|
|
triggerRefresh();
|
|
}}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{ selectedContest && (
|
|
<RoundsTable
|
|
contestId={selectedContest ? selectedContest.id : null}
|
|
enableEdit
|
|
showContestColumn={false}
|
|
showTests
|
|
onSelectRound={(round) => {
|
|
setSelectedRound(round);
|
|
setFormMode("none");
|
|
setRoundFormMode("edit");
|
|
}}
|
|
title={
|
|
selectedContest
|
|
? (t("contest_rounds_title_named", { name: selectedContest.name }) ??
|
|
`Kola závodu "${selectedContest.name}":`)
|
|
: ""
|
|
}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
}
|