import { FC, useEffect, useState } from 'react'; import { Modal } from '../../../components/modal/Modal'; import { PrimaryButton } from '../../../components/button/PrimaryButton'; import { SecondaryButton } from '../../../components/button/SecondaryButton'; import { Input } from '../../../components/input/Input'; import { useAppDispatch, useAppSelector } from '../../../redux/hooks'; import { createContest, setContestStatus, } from '../../../redux/slices/contests'; import { CreateContestBody } from '../../../redux/slices/contests'; import { useNavigate } from 'react-router-dom'; import { NumberInput } from '../../../components/input/NumberInput'; import { DropDownList, DropDownListItem, } from '../../../components/input/DropDownList'; import DateInput from '../../../components/input/DateInput'; import { cn } from '../../../lib/cn'; import { fetchMyGroups } from '../../../redux/slices/groups'; function toUtc(localDateTime?: string): string { if (!localDateTime) return ''; // Создаём дату (она автоматически считается как локальная) const date = new Date(localDateTime); // Возвращаем ISO-строку с 'Z' (всегда в UTC) return date.toISOString(); } interface ModalCreateContestProps { active: boolean; setActive: (value: boolean) => void; } const ModalCreateContest: FC = ({ active, setActive, }) => { const dispatch = useAppDispatch(); const navigate = useNavigate(); const status = useAppSelector( (state) => state.contests.createContest.status, ); const visibilityItems: DropDownListItem[] = [ { value: 'Public', text: 'Публичный' }, { value: 'GroupPrivate', text: 'Для группы' }, ]; const scheduleTypeItems: DropDownListItem[] = [ { value: 'AlwaysOpen', text: 'Всегда открыт' }, { value: 'FixedWindow', text: 'Фиксированое окно' }, { value: 'RollingWindow', text: 'Скользящее окно' }, ]; const now = new Date(); const plus60 = new Date(now.getTime() + 60 * 60 * 1000); const toLocal = (d: Date) => { const off = d.getTimezoneOffset(); const local = new Date(d.getTime() - off * 60000); return local.toISOString().slice(0, 16); }; const [form, setForm] = useState({ name: '', description: '', scheduleType: 'AlwaysOpen', visibility: 'Public', startsAt: toLocal(now), endsAt: toLocal(plus60), attemptDurationMinutes: 60, maxAttempts: 1, allowEarlyFinish: false, missionIds: [], articleIds: [], }); const contest = useAppSelector( (state) => state.contests.createContest.contest, ); const myname = useAppSelector((state) => state.auth.username); const myGroups = useAppSelector( (state) => state.groups.fetchMyGroups.groups, ).filter((group) => group.members.some( (member) => member.username === myname && member.role.includes('Administrator'), ), ); useEffect(() => { if (status === 'successful') { dispatch( setContestStatus({ key: 'createContest', status: 'idle' }), ); navigate( `/contest/create?back=/home/account/contests&contestId=${contest.id}`, ); } }, [status]); useEffect(() => { if (active) { dispatch(fetchMyGroups()); } }, [active]); const handleChange = (key: keyof CreateContestBody, value: any) => { setForm((prev) => ({ ...prev, [key]: value })); }; const handleSubmit = () => { dispatch( createContest({ ...form, endsAt: toUtc(form.endsAt), startsAt: toUtc(form.startsAt), }), ); }; const groupItems = myGroups.map((v) => { return { value: '' + v.id, text: v.name, }; }); const groupIdDefaultState = myGroups.find((g) => g.id == form?.groupId) ?? myGroups[0] ?? undefined; console.log(groupItems, myGroups, groupIdDefaultState); return (
Создать контест
handleChange('name', v)} /> handleChange('description', v)} />
{ handleChange('scheduleType', v); }} weight="w-full" />
{ handleChange('visibility', v); }} weight="w-full" />
{groupIdDefaultState ? (
{ handleChange('groupId', Number(v)); }} weight="w-full" />
) : (
У вас нет группы вкоторой вы являетесь Администратором!
)}
{/* Даты */}
handleChange('startsAt', v)} /> handleChange('endsAt', v)} />
{/* Продолжительность и лимиты */}
handleChange('attemptDurationMinutes', Number(v)) } /> handleChange('maxAttempts', Number(v))} />
{/* Разрешить раннее завершение */} {/*
handleChange('allowEarlyFinish', e.target.checked) } />
*/} {/* Кнопки */}
{ handleSubmit(); }} text="Создать" disabled={status === 'loading'} /> setActive(false)} text="Отмена" />
); }; export default ModalCreateContest;