101 lines
2.9 KiB
TypeScript
101 lines
2.9 KiB
TypeScript
import React, { useEffect } from "react";
|
|
import { useParams } from "react-router-dom";
|
|
import { useContestStore } from "@/stores/contestStore";
|
|
import { useLanguageStore } from "@/stores/languageStore";
|
|
import ContestsOverview from "@/components/ContestsOverview";
|
|
import RoundsOverview from "@/components/RoundsOverview";
|
|
import axios from "axios";
|
|
|
|
|
|
export default function ContestsLeftPanel() {
|
|
const { contestId } = useParams<{ contestId?: string }>();
|
|
const { roundId } = useParams();
|
|
const cId = contestId ? Number(contestId) : null;
|
|
const rId = roundId ? Number(roundId) : null;
|
|
const selectedContest = useContestStore((s) => s.selectedContest);
|
|
const setSelectedContest = useContestStore((s) => s.setSelectedContest);
|
|
const clearSelection = useContestStore((s) => s.clearSelection);
|
|
const locale = useLanguageStore((s) => s.locale);
|
|
|
|
// pokud je contestId v URL, načti a ulož do storu
|
|
useEffect(() => {
|
|
const numericId = contestId ? Number(contestId) : null;
|
|
if (!numericId) {
|
|
clearSelection();
|
|
return;
|
|
}
|
|
|
|
if (selectedContest && selectedContest.id === numericId) {
|
|
// už máme data v store, nefetchuj
|
|
return;
|
|
}
|
|
|
|
let active = true;
|
|
(async () => {
|
|
try {
|
|
const res = await axios.get(`/api/contests/${numericId}`, {
|
|
headers: { Accept: "application/json" },
|
|
params: { lang: locale },
|
|
withCredentials: true,
|
|
});
|
|
|
|
if (!active) return;
|
|
|
|
const data = res.data;
|
|
const rounds = Array.isArray(data.rounds)
|
|
? data.rounds.map((r: any) => ({
|
|
id: r.id,
|
|
contest_id: r.contest_id,
|
|
name: r.name,
|
|
description: r.description ?? null,
|
|
is_active: r.is_active,
|
|
is_test: r.is_test,
|
|
is_sixhr: r.is_sixhr,
|
|
start_time: r.start_time ?? null,
|
|
end_time: r.end_time ?? null,
|
|
logs_deadline: r.logs_deadline ?? null,
|
|
}))
|
|
: [];
|
|
setSelectedContest({
|
|
id: data.id,
|
|
name: data.name,
|
|
description: data.description ?? null,
|
|
is_active: data.is_active,
|
|
is_mcr: data.is_mcr,
|
|
is_sixhr: data.is_sixhr,
|
|
start_time: data.start_time ?? null,
|
|
duration: data.duration ?? 0,
|
|
rounds,
|
|
});
|
|
} catch {
|
|
// při chybě jen nevybere nic
|
|
}
|
|
})();
|
|
|
|
return () => {
|
|
active = false;
|
|
};
|
|
}, [contestId, locale, clearSelection, setSelectedContest]);
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div>
|
|
<ContestsOverview
|
|
onlyActive={true}
|
|
showTests={false}
|
|
/>
|
|
</div>
|
|
|
|
{rId && (
|
|
<div>
|
|
<RoundsOverview
|
|
contestId={cId}
|
|
roundsFromStore={selectedContest ? selectedContest.rounds : null}
|
|
showTests={false}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|