Initial commit
This commit is contained in:
181
resources/js/pages/AdminContestsPage.tsx
Normal file
181
resources/js/pages/AdminContestsPage.tsx
Normal file
@@ -0,0 +1,181 @@
|
||||
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}":`)
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user