formatting
This commit is contained in:
@@ -1,71 +1,78 @@
|
||||
import { cn } from "../../../lib/cn";
|
||||
import { IconError, IconSuccess } from "../../../assets/icons/missions";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { cn } from '../../../lib/cn';
|
||||
import { IconError, IconSuccess } from '../../../assets/icons/missions';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export interface MissionItemProps {
|
||||
id: number;
|
||||
authorId: number;
|
||||
name: string;
|
||||
difficulty: "Easy" | "Medium" | "Hard";
|
||||
difficulty: 'Easy' | 'Medium' | 'Hard';
|
||||
tags: string[];
|
||||
timeLimit: number;
|
||||
memoryLimit: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
type: "first" | "second";
|
||||
status: "empty" | "success" | "error";
|
||||
type: 'first' | 'second';
|
||||
status: 'empty' | 'success' | 'error';
|
||||
}
|
||||
|
||||
export function formatMilliseconds(ms: number): string {
|
||||
const rounded = Math.round(ms) / 1000;
|
||||
const formatted = rounded.toString().replace(/\.?0+$/, '');
|
||||
return `${formatted} c`;
|
||||
const rounded = Math.round(ms) / 1000;
|
||||
const formatted = rounded.toString().replace(/\.?0+$/, '');
|
||||
return `${formatted} c`;
|
||||
}
|
||||
|
||||
export function formatBytesToMB(bytes: number): string {
|
||||
const megabytes = Math.floor(bytes / (1024 * 1024));
|
||||
return `${megabytes} МБ`;
|
||||
const megabytes = Math.floor(bytes / (1024 * 1024));
|
||||
return `${megabytes} МБ`;
|
||||
}
|
||||
|
||||
const MissionItem: React.FC<MissionItemProps> = ({
|
||||
id, name, difficulty, timeLimit, memoryLimit, type, status
|
||||
id,
|
||||
name,
|
||||
difficulty,
|
||||
timeLimit,
|
||||
memoryLimit,
|
||||
type,
|
||||
status,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div className={cn("h-[44px] w-full relative rounded-[10px] text-liquid-white",
|
||||
type == "first" ? "bg-liquid-lighter" : "bg-liquid-background",
|
||||
"grid grid-cols-[80px,1fr,1fr,60px,24px] grid-flow-col gap-[20px] px-[20px] box-border items-center",
|
||||
status == "error" && "border-l-[11px] border-l-liquid-red pl-[9px]",
|
||||
status == "success" && "border-l-[11px] border-l-liquid-green pl-[9px]",
|
||||
"cursor-pointer brightness-100 hover:brightness-125 transition-all duration-300",
|
||||
)}
|
||||
onClick={() => {navigate(`/mission/${id}`)}}
|
||||
<div
|
||||
className={cn(
|
||||
'h-[44px] w-full relative rounded-[10px] text-liquid-white',
|
||||
type == 'first' ? 'bg-liquid-lighter' : 'bg-liquid-background',
|
||||
'grid grid-cols-[80px,1fr,1fr,60px,24px] grid-flow-col gap-[20px] px-[20px] box-border items-center',
|
||||
status == 'error' &&
|
||||
'border-l-[11px] border-l-liquid-red pl-[9px]',
|
||||
status == 'success' &&
|
||||
'border-l-[11px] border-l-liquid-green pl-[9px]',
|
||||
'cursor-pointer brightness-100 hover:brightness-125 transition-all duration-300',
|
||||
)}
|
||||
onClick={() => {
|
||||
navigate(`/mission/${id}`);
|
||||
}}
|
||||
>
|
||||
<div className="text-[18px] font-bold">
|
||||
#{id}
|
||||
</div>
|
||||
<div className="text-[18px] font-bold">
|
||||
{name}
|
||||
</div>
|
||||
<div className="text-[18px] font-bold">#{id}</div>
|
||||
<div className="text-[18px] font-bold">{name}</div>
|
||||
<div className="text-[12px] text-right">
|
||||
стандартный ввод/вывод {formatMilliseconds(timeLimit)}, {formatBytesToMB(memoryLimit)}
|
||||
стандартный ввод/вывод {formatMilliseconds(timeLimit)},{' '}
|
||||
{formatBytesToMB(memoryLimit)}
|
||||
</div>
|
||||
<div className={cn(
|
||||
"text-center text-[18px]",
|
||||
difficulty == "Hard" && "text-liquid-red",
|
||||
difficulty == "Medium" && "text-liquid-orange",
|
||||
difficulty == "Easy" && "text-liquid-green",
|
||||
)}>
|
||||
<div
|
||||
className={cn(
|
||||
'text-center text-[18px]',
|
||||
difficulty == 'Hard' && 'text-liquid-red',
|
||||
difficulty == 'Medium' && 'text-liquid-orange',
|
||||
difficulty == 'Easy' && 'text-liquid-green',
|
||||
)}
|
||||
>
|
||||
{difficulty}
|
||||
</div>
|
||||
<div className="h-[24px] w-[24px]">
|
||||
{
|
||||
status == "error" && <img src={IconError}/>
|
||||
}
|
||||
{
|
||||
status == "success" && <img src={IconSuccess}/>
|
||||
}
|
||||
{status == 'error' && <img src={IconError} />}
|
||||
{status == 'success' && <img src={IconSuccess} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import MissionItem from "./MissionItem";
|
||||
import { SecondaryButton } from "../../../components/button/SecondaryButton";
|
||||
import { useAppDispatch, useAppSelector } from "../../../redux/hooks";
|
||||
import { useEffect, useState } from "react";
|
||||
import { setMenuActivePage } from "../../../redux/slices/store";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { fetchMissions } from "../../../redux/slices/missions";
|
||||
import ModalCreate from "./ModalCreate";
|
||||
|
||||
import MissionItem from './MissionItem';
|
||||
import { SecondaryButton } from '../../../components/button/SecondaryButton';
|
||||
import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { setMenuActivePage } from '../../../redux/slices/store';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { fetchMissions } from '../../../redux/slices/missions';
|
||||
import ModalCreate from './ModalCreate';
|
||||
|
||||
export interface Mission {
|
||||
id: number;
|
||||
authorId: number;
|
||||
name: string;
|
||||
difficulty: "Easy" | "Medium" | "Hard";
|
||||
difficulty: 'Easy' | 'Medium' | 'Hard';
|
||||
tags: string[];
|
||||
timeLimit: number;
|
||||
memoryLimit: number;
|
||||
@@ -21,60 +20,60 @@ export interface Mission {
|
||||
}
|
||||
|
||||
const Missions = () => {
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const [modalActive, setModalActive] = useState<boolean>(false);
|
||||
|
||||
const missions = useAppSelector((state) => state.missions.missions);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setMenuActivePage("missions"))
|
||||
dispatch(fetchMissions({}))
|
||||
dispatch(setMenuActivePage('missions'));
|
||||
dispatch(fetchMissions({}));
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<div className=" h-full w-full box-border p-[20px] pt-[20px]">
|
||||
<div className="h-full box-border">
|
||||
|
||||
<div className="relative flex items-center mb-[20px]">
|
||||
<div className="h-[50px] text-[40px] font-bold text-liquid-white flex items-center">
|
||||
Задачи
|
||||
</div>
|
||||
<SecondaryButton
|
||||
onClick={() => {setModalActive(true)}}
|
||||
<SecondaryButton
|
||||
onClick={() => {
|
||||
setModalActive(true);
|
||||
}}
|
||||
text="Добавить задачу"
|
||||
className="absolute right-0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="bg-liquid-lighter h-[50px] mb-[20px]">
|
||||
|
||||
</div>
|
||||
<div className="bg-liquid-lighter h-[50px] mb-[20px]"></div>
|
||||
|
||||
<div>
|
||||
|
||||
{missions.map((v, i) => (
|
||||
<MissionItem
|
||||
key={i}
|
||||
id={v.id}
|
||||
authorId={v.authorId}
|
||||
name={v.name}
|
||||
difficulty={"Easy"}
|
||||
tags={v.tags}
|
||||
timeLimit={1000}
|
||||
memoryLimit={256 * 1024 * 1024}
|
||||
createdAt={v.createdAt}
|
||||
updatedAt={v.updatedAt}
|
||||
type={i % 2 == 0 ? "first" : "second"}
|
||||
status={i == 0 || i == 3 || i == 7 ? "success" : (i == 2 || i == 4 || i == 9 ? "error" : "empty")}/>
|
||||
))}
|
||||
{missions.map((v, i) => (
|
||||
<MissionItem
|
||||
key={i}
|
||||
id={v.id}
|
||||
authorId={v.authorId}
|
||||
name={v.name}
|
||||
difficulty={'Easy'}
|
||||
tags={v.tags}
|
||||
timeLimit={1000}
|
||||
memoryLimit={256 * 1024 * 1024}
|
||||
createdAt={v.createdAt}
|
||||
updatedAt={v.updatedAt}
|
||||
type={i % 2 == 0 ? 'first' : 'second'}
|
||||
status={
|
||||
i == 0 || i == 3 || i == 7
|
||||
? 'success'
|
||||
: i == 2 || i == 4 || i == 9
|
||||
? 'error'
|
||||
: 'empty'
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
pages
|
||||
</div>
|
||||
<div>pages</div>
|
||||
</div>
|
||||
|
||||
<ModalCreate setActive={setModalActive} active={modalActive} />
|
||||
|
||||
@@ -59,6 +59,10 @@ const ModalCreate: FC<ModalCreateProps> = ({ active, setActive }) => {
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setMissionsStatus({ key: 'upload', status: 'idle' }));
|
||||
}, [active]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="bg-liquid-background border-liquid-lighter border-[2px] p-[25px] rounded-[20px] text-liquid-white"
|
||||
@@ -152,6 +156,8 @@ const ModalCreate: FC<ModalCreateProps> = ({ active, setActive }) => {
|
||||
text="Отмена"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{status == 'failed' && <div>error</div>}
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user