124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import {
|
|
chevroneLeft,
|
|
chevroneRight,
|
|
arrowLeft,
|
|
} from '../../../assets/icons/header';
|
|
import { Logo } from '../../../assets/logos';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
|
|
import { useQuery } from '../../../hooks/useQuery';
|
|
import { fetchMyAttemptsInContest } from '../../../redux/slices/contests';
|
|
|
|
interface HeaderProps {
|
|
missionId: number;
|
|
back?: string;
|
|
}
|
|
|
|
const Header: React.FC<HeaderProps> = ({ missionId, back }) => {
|
|
const navigate = useNavigate();
|
|
const dispatch = useAppDispatch();
|
|
|
|
const query = useQuery();
|
|
const contestId = Number(query.get('contestId') ?? undefined);
|
|
|
|
const attempt = useAppSelector(
|
|
(state) => state.contests.fetchMyAttemptsInContest.attempts[0],
|
|
);
|
|
|
|
const [time, setTime] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (!contestId) return;
|
|
const calc = (time: string) => {
|
|
return time != '' && new Date() <= new Date(time);
|
|
};
|
|
if (attempt) {
|
|
if (!calc(attempt.expiresAt)) {
|
|
navigate('/home/contests');
|
|
}
|
|
const diffMs =
|
|
new Date(attempt.expiresAt).getTime() - new Date().getTime();
|
|
|
|
const seconds = Math.floor(diffMs / 1000);
|
|
|
|
setTime(seconds);
|
|
|
|
const interval = setInterval(() => {
|
|
setTime((t) => {
|
|
if (t <= 1) {
|
|
clearInterval(interval);
|
|
navigate('/home/contests');
|
|
return 0;
|
|
}
|
|
return t - 1;
|
|
});
|
|
}, 1000);
|
|
|
|
return () => clearInterval(interval);
|
|
}
|
|
}, [attempt]);
|
|
|
|
useEffect(() => {
|
|
if (contestId) {
|
|
dispatch(fetchMyAttemptsInContest(contestId));
|
|
}
|
|
}, [contestId]);
|
|
|
|
const minutes = String(Math.floor(time / 60)).padStart(2, '0');
|
|
const seconds = String(time % 60).padStart(2, '0');
|
|
|
|
return (
|
|
<header className="w-full h-[60px] flex items-center px-4 gap-[20px]">
|
|
<img
|
|
src={Logo}
|
|
alt="Logo"
|
|
className="h-[28px] w-auto cursor-pointer"
|
|
onClick={() => {
|
|
navigate('/home');
|
|
}}
|
|
/>
|
|
|
|
<img
|
|
src={arrowLeft}
|
|
alt="back"
|
|
className="h-[24px] w-[24px] cursor-pointer"
|
|
onClick={() => {
|
|
if (back) navigate(back);
|
|
else navigate('/home/missions');
|
|
}}
|
|
/>
|
|
|
|
<div className="flex gap-[10px]">
|
|
<img
|
|
src={chevroneLeft}
|
|
alt="back"
|
|
className="h-[24px] w-[24px] cursor-pointer"
|
|
onClick={() => {
|
|
if (missionId <= 1) return;
|
|
if (back)
|
|
navigate(`/mission/${missionId - 1}?back=${back}`);
|
|
else navigate(`/mission/${missionId - 1}`);
|
|
}}
|
|
/>
|
|
<span>{missionId}</span>
|
|
<img
|
|
src={chevroneRight}
|
|
alt="back"
|
|
className="h-[24px] w-[24px] cursor-pointer"
|
|
onClick={() => {
|
|
if (back)
|
|
navigate(`/mission/${missionId + 1}?back=${back}`);
|
|
else navigate(`/mission/${missionId + 1}`);
|
|
}}
|
|
/>
|
|
</div>
|
|
{!!contestId && !!attempt && (
|
|
<div className="">{`${minutes}:${seconds}`}</div>
|
|
)}
|
|
</header>
|
|
);
|
|
};
|
|
|
|
export default Header;
|