contests update

This commit is contained in:
Виталий Лавшонок
2025-11-06 18:27:28 +03:00
parent 1b39b8c77f
commit 6c92c789d0
5 changed files with 136 additions and 108 deletions

View File

@@ -6,48 +6,71 @@ import { useAppDispatch, useAppSelector } from '../redux/hooks';
import {
createContest,
CreateContestBody,
deleteContest,
fetchContestById,
setContestStatus,
updateContest,
} from '../redux/slices/contests';
import DateRangeInput from '../components/input/DateRangeInput';
import { useQuery } from '../hooks/useQuery';
import { useNavigate } from 'react-router-dom';
import { fetchMissionById, Mission } from '../redux/slices/missions';
import { Navigate, useNavigate } from 'react-router-dom';
import { fetchMissionById } from '../redux/slices/missions';
import { ReverseButton } from '../components/button/ReverseButton';
interface Mission {
id: number;
name: string;
}
/**
* Страница создания / редактирования контеста
*/
const ContestEditor = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const status = useAppSelector(
(state) => state.contests.createContest.status,
);
const [missionIdInput, setMissionIdInput] = useState<string>('');
const query = useQuery();
const back = query.get('back') ?? undefined;
const contestId = Number(query.get('contestId') ?? undefined);
const refactor = !!contestId;
if (!refactor){
return <Navigate to="/home/account/acontest" />
}
const status = useAppSelector(
(state) => state.contests.createContest.status,
);
const [missionIdInput, setMissionIdInput] = useState<string>('');
const [contest, setContest] = useState<CreateContestBody>({
name: '',
description: '',
scheduleType: 'AlwaysOpen',
visibility: 'Public',
startsAt: null,
endsAt: null,
attemptDurationMinutes: null,
maxAttempts: null,
allowEarlyFinish: false,
groupId: null,
startsAt: '',
endsAt: '',
attemptDurationMinutes: 60,
maxAttempts: 1,
allowEarlyFinish: true,
groupIds: [],
missionIds: [],
articleIds: [],
});
const [missions, setMissions] = useState<Mission[]>([]);
const statusDelete = useAppSelector((state) => state.contests.deleteContest.status)
const { contest: contestById, status: contestByIdstatus } = useAppSelector(
(state) => state.contests.fetchContestById,
);
@@ -61,9 +84,15 @@ const ContestEditor = () => {
setContest((prev) => ({ ...prev, [key]: value }));
};
const handleSubmit = () => {
dispatch(createContest(contest));
const handleUpdateContest = () => {
dispatch(updateContest({...contest, contestId}));
};
const handleDeleteContest = () => {
dispatch(deleteContest(contestId));
};
const addMission = () => {
const id = Number(missionIdInput.trim());
@@ -91,6 +120,13 @@ const ContestEditor = () => {
setMissions(missions.filter((v) => v.id != removeId));
};
useEffect(() => {
if (statusDelete == "successful"){
dispatch(setContestStatus({key: "deleteContest", status: "idle"}))
navigate('/home/account/contests')
}
}, [statusDelete])
useEffect(() => {
if (refactor) {
dispatch(fetchContestById(contestId));
@@ -101,10 +137,14 @@ const ContestEditor = () => {
if (refactor && contestByIdstatus == 'successful' && contestById) {
setContest({
...contestById,
missionIds: [],
// groupIds: contestById.groups.map(group => group.groupId),
groupIds: [],
missionIds: contestById.missions?.map(mission => mission.id),
articleIds: contestById.articles?.map(article => article.articleId),
visibility: 'Public',
scheduleType: 'AlwaysOpen',
});
setMissions(contestById.missions ?? []);
}
}, [contestById]);
@@ -253,27 +293,19 @@ const ContestEditor = () => {
{/* Кнопки */}
<div className="flex flex-row w-full items-center justify-end mt-[20px] gap-[20px]">
{refactor ? (
<>
<PrimaryButton
onClick={handleSubmit}
onClick={handleUpdateContest}
text="Сохранить"
disabled={status === 'loading'}
/>
<ReverseButton
color="error"
onClick={handleSubmit}
onClick={handleDeleteContest}
text="Удалить"
disabled={status === 'loading'}
disabled={statusDelete === 'loading'}
/>
</>
) : (
<PrimaryButton
onClick={handleSubmit}
text="Создать"
disabled={status === 'loading'}
/>
)}
</div>
</div>
</div>