158 lines
5.0 KiB
TypeScript
158 lines
5.0 KiB
TypeScript
import type React from "react";
|
|
import { useEffect, useState } from "react";
|
|
import {
|
|
Accordion,
|
|
AccordionButton,
|
|
AccordionIcon,
|
|
AccordionItem,
|
|
AccordionPanel,
|
|
Box,
|
|
Link,
|
|
Select,
|
|
Table,
|
|
Tag,
|
|
Tbody,
|
|
Td,
|
|
Tr,
|
|
Wrap,
|
|
WrapItem,
|
|
} from "@chakra-ui/react";
|
|
import { Link as ReactRouterLink } from "react-router-dom";
|
|
import type { DetailResponse, RuntimeInfo } from "../app/services/problem";
|
|
|
|
const TitleItem = ({ word }: { word: string }) => (
|
|
<h2>
|
|
<AccordionButton>
|
|
<Box as="span" flex="1" textAlign="left">
|
|
{word}
|
|
</Box>
|
|
<AccordionIcon />
|
|
</AccordionButton>
|
|
</h2>
|
|
);
|
|
|
|
interface ProblemInfoMenuProps {
|
|
data?: DetailResponse;
|
|
onLanguageSelect?: (lang: string) => void;
|
|
action?: React.ReactNode;
|
|
}
|
|
|
|
const EmptyRuntime: RuntimeInfo = {
|
|
TimeLimit: 0,
|
|
MemoryLimit: 0,
|
|
NProcLimit: 0,
|
|
};
|
|
|
|
export default function ProblemInfoMenu(props: ProblemInfoMenuProps) {
|
|
const [lang, setLang] = useState(props.data?.context.Languages[0]?.Lang || "c");
|
|
const runtime = props.data?.context.Languages.find((x) => x.Lang === lang)?.Runtime.Run || EmptyRuntime;
|
|
useEffect(() => {
|
|
props.onLanguageSelect && props.onLanguageSelect(lang);
|
|
}, [lang, props]);
|
|
|
|
const problemInfo = (
|
|
<Table variant="striped" size="sm">
|
|
<Tbody>
|
|
<Tr>
|
|
<Td>Title</Td>
|
|
<Td>{props.data?.problem.title || "..."}</Td>
|
|
</Tr>
|
|
<Tr>
|
|
<Td>Author</Td>
|
|
<Td>
|
|
<Link
|
|
as={ReactRouterLink}
|
|
color="blue.500"
|
|
to={`/profile/${props.data?.problem.provider.meta.ID || 0}`}
|
|
>
|
|
{props.data?.problem.provider.nick_name || "..."}
|
|
</Link>
|
|
</Td>
|
|
</Tr>
|
|
<Tr>
|
|
<Td>Languages</Td>
|
|
<Td>
|
|
<Wrap>
|
|
{props.data?.context.Languages.map((l) => (
|
|
<WrapItem key={l.Lang}>
|
|
<Tag variant="outline" size="sm" colorScheme="pink">
|
|
{l.Lang}
|
|
</Tag>
|
|
</WrapItem>
|
|
))}
|
|
</Wrap>
|
|
</Td>
|
|
</Tr>
|
|
<Tr>
|
|
<Td>Tags</Td>
|
|
<Td>
|
|
<Wrap>
|
|
{props.data?.problem.tags.Elements.map((t) => (
|
|
<WrapItem key={t}>
|
|
<Tag variant="outline" size="sm" colorScheme="orange">
|
|
{t}
|
|
</Tag>
|
|
</WrapItem>
|
|
))}
|
|
</Wrap>
|
|
</Td>
|
|
</Tr>
|
|
</Tbody>
|
|
</Table>
|
|
);
|
|
|
|
const taskInfo = (
|
|
<Table variant="striped" size="sm">
|
|
<Tbody>
|
|
<Tr>
|
|
<Td>Time Limit</Td>
|
|
<Td>{runtime.TimeLimit} ms</Td>
|
|
</Tr>
|
|
<Tr>
|
|
<Td>Memory Limit</Td>
|
|
<Td>{runtime.MemoryLimit} MB</Td>
|
|
</Tr>
|
|
<Tr>
|
|
<Td>Process Limit</Td>
|
|
<Td>{runtime.NProcLimit}</Td>
|
|
</Tr>
|
|
<Tr>
|
|
<Td>Select</Td>
|
|
<Td>
|
|
<Select size="sm" onChange={(e) => setLang(e.target.value)} value={lang}>
|
|
{props.data?.context.Languages.map((l) => (
|
|
<option key={l.Lang} value={l.Lang}>
|
|
{l.Lang}
|
|
</option>
|
|
))}
|
|
</Select>
|
|
</Td>
|
|
</Tr>
|
|
</Tbody>
|
|
</Table>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<Accordion defaultIndex={[0, 1, ...(props.action ? [2] : [])]} allowMultiple>
|
|
<AccordionItem>
|
|
<TitleItem word="Problem Info" />
|
|
<AccordionPanel pb={4}>{problemInfo}</AccordionPanel>
|
|
</AccordionItem>
|
|
|
|
<AccordionItem>
|
|
<TitleItem word="Task Info" />
|
|
<AccordionPanel pb={4}>{taskInfo}</AccordionPanel>
|
|
</AccordionItem>
|
|
|
|
{props.action && (
|
|
<AccordionItem>
|
|
<TitleItem word="Action" />
|
|
<AccordionPanel pb={4}>{props.action}</AccordionPanel>
|
|
</AccordionItem>
|
|
)}
|
|
</Accordion>
|
|
</>
|
|
);
|
|
}
|