130 lines
4.0 KiB
TypeScript
130 lines
4.0 KiB
TypeScript
import SubmissionItem from "./SubmissionItem";
|
||
import { useAppDispatch, useAppSelector } from "../../../redux/hooks";
|
||
import { FC, useEffect } from "react";
|
||
import {
|
||
Contest,
|
||
fetchMySubmissions,
|
||
setContestStatus,
|
||
} from "../../../redux/slices/contests";
|
||
import { arrowLeft } from "../../../assets/icons/header";
|
||
import { useNavigate } from "react-router-dom";
|
||
|
||
export interface Mission {
|
||
id: number;
|
||
authorId: number;
|
||
name: string;
|
||
difficulty: "Easy" | "Medium" | "Hard";
|
||
tags: string[];
|
||
timeLimit: number;
|
||
memoryLimit: number;
|
||
createdAt: string;
|
||
updatedAt: string;
|
||
}
|
||
|
||
interface SubmissionsProps {
|
||
contest: Contest;
|
||
}
|
||
|
||
const Submissions: FC<SubmissionsProps> = ({ contest }) => {
|
||
const dispatch = useAppDispatch();
|
||
const navigate = useNavigate();
|
||
|
||
const { submissions, status } = useAppSelector(
|
||
(state) => state.contests.fetchMySubmissions
|
||
);
|
||
|
||
useEffect(() => {
|
||
if (contest && contest.id) dispatch(fetchMySubmissions(contest.id));
|
||
}, [contest]);
|
||
|
||
useEffect(() => {
|
||
if (status == "successful") {
|
||
dispatch(setContestStatus({ key: "fetchMySubmissions", status: "idle" }));
|
||
}
|
||
}, [status]);
|
||
|
||
const checkStatus = (status: string) => {
|
||
if (status == "IncorrectAnswer") return "wronganswer";
|
||
if (status == "TimeLimitError") return "timelimit";
|
||
return undefined;
|
||
};
|
||
|
||
const solvedCount = (contest.missions ?? []).filter((mission) =>
|
||
submissions.some(
|
||
(s) =>
|
||
s.solution.missionId === mission.id &&
|
||
s.solution.status === "Accepted: All tests passed"
|
||
)
|
||
).length;
|
||
|
||
const totalCount = contest.missions?.length ?? 0;
|
||
|
||
return (
|
||
<div className="h-full w-[calc(100%+250px)] box-border overflow-y-scroll overflow-x-hidden thin-scrollbar p-[20px] flex flex-col gap-[20px]">
|
||
<div className="">
|
||
<div className="h-[50px] text-[40px] text-liquid-white font-bold">
|
||
{contest.name}
|
||
</div>
|
||
<div className="flex justify-between h-[24px] items-center gap-[10px]">
|
||
<div className="flex items-center">
|
||
<img
|
||
src={arrowLeft}
|
||
className="cursor-pointer"
|
||
onClick={() => {
|
||
navigate(`/contest/${contest.id}`);
|
||
}}
|
||
/>
|
||
<span className="text-liquid-light font-bold text-[18px]">
|
||
Контест #{contest.id}
|
||
</span>
|
||
</div>
|
||
<div className="text-liquid-white text-[16px] font-bold">{`${solvedCount}/${totalCount} Решено`}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<div className="grid grid-cols-7 text-center items-center h-[43px] mb-[10px] text-[16px] font-bold text-liquid-white">
|
||
<div>Посылка</div>
|
||
<div>Когда</div>
|
||
<div>Задача</div>
|
||
<div>Язык</div>
|
||
<div>Вердикт</div>
|
||
<div>Время</div>
|
||
<div>Память</div>
|
||
</div>
|
||
|
||
{!submissions || submissions.length == 0 ? (
|
||
<div className="text-liquid-brightmain text-[16px] font-medium text-center mt-[50px]">Вы еще ничего не отсылали</div>
|
||
) : (
|
||
<>
|
||
{submissions.map((v, i) => (
|
||
<SubmissionItem
|
||
key={i}
|
||
id={v.id ?? 0}
|
||
datetime={v.solution.time}
|
||
missionId={v.solution.missionId}
|
||
language={v.solution.language}
|
||
verdict={
|
||
v.solution.testerMessage?.includes("Compilation failed")
|
||
? "Compilation failed"
|
||
: v.solution.testerMessage
|
||
}
|
||
duration={1000}
|
||
memory={256 * 1024 * 1024}
|
||
type={i % 2 ? "second" : "first"}
|
||
status={
|
||
v.solution.testerMessage == "All tests passed"
|
||
? "success"
|
||
: checkStatus(v.solution.testerErrorCode)
|
||
}
|
||
/>
|
||
))}
|
||
</>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default Submissions;
|