chore: refactor problem page
This commit is contained in:
parent
2dfdec85ed
commit
4ee1b98699
9
src/api/loader.ts
Normal file
9
src/api/loader.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ProblemApi } from "./problem.ts";
|
||||
|
||||
export async function ProblemLoader({ params }: { params: { id: string } }) {
|
||||
const id = parseInt(params.id);
|
||||
if (isNaN(id)) {
|
||||
throw new Error("invalid problem id");
|
||||
}
|
||||
return await ProblemApi.Details({ pid: id });
|
||||
}
|
71
src/components/problem-details.tsx
Normal file
71
src/components/problem-details.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import React from "react";
|
||||
import { Link, useLoaderData } from "react-router-dom";
|
||||
import { Collapse, CollapseProps, Descriptions, Space, Tag } from "antd";
|
||||
|
||||
import { DetailsResp } from "../api/problem.ts";
|
||||
|
||||
interface ProblemDetailsProps {
|
||||
action: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function ProblemDetails(props: ProblemDetailsProps) {
|
||||
const details = useLoaderData() as DetailsResp;
|
||||
|
||||
const problemInfo = (
|
||||
<Descriptions bordered column={1} size="small">
|
||||
<Descriptions.Item label="Provider">
|
||||
<Link to={`/user/${details.problem.provider.meta.ID}`}>
|
||||
{details.problem.provider.nick_name}
|
||||
</Link>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Supported Languages">
|
||||
<Space size={[0, 8]} wrap>
|
||||
{details.context.Languages.map((l) => (
|
||||
<Tag key={l.Lang}>{l.Lang}</Tag>
|
||||
))}
|
||||
</Space>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Task Nums">
|
||||
{details.context.Tasks.length}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
);
|
||||
|
||||
const runtimeLimit = (
|
||||
<Descriptions bordered column={1} size="small">
|
||||
<Descriptions.Item label="Time Limit">
|
||||
{details.context.Runtime.TimeLimit} ms
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Memory Limit">
|
||||
{details.context.Runtime.MemoryLimit} MB
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Process Limit">
|
||||
{details.context.Runtime.NProcLimit}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
);
|
||||
|
||||
const miscItems: CollapseProps["items"] = [
|
||||
{
|
||||
key: "1",
|
||||
label: "Problem Info",
|
||||
children: problemInfo,
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
label: "Runtime Limit",
|
||||
children: runtimeLimit,
|
||||
},
|
||||
{
|
||||
key: "3",
|
||||
label: "Action",
|
||||
children: props.action,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Collapse items={miscItems} defaultActiveKey={["1", "2", "3"]} />
|
||||
</>
|
||||
);
|
||||
}
|
@ -11,7 +11,7 @@ const ErrorPage = () => {
|
||||
|
||||
const convertError = (error: unknown): string => {
|
||||
if (isRouteErrorResponse(error)) {
|
||||
return error.error?.message || error.statusText;
|
||||
return `${error.status} ${error.statusText}`;
|
||||
} else if (error instanceof Error) {
|
||||
return error.message;
|
||||
} else if (typeof error === "string") {
|
||||
|
@ -2,5 +2,5 @@ export { Root } from "./root";
|
||||
export { ErrorPage } from "./error-page";
|
||||
|
||||
export { HomePage } from "./home";
|
||||
export { ProblemLoader, ProblemPage } from "./problem";
|
||||
export { ProblemPage } from "./problem";
|
||||
export { SearchPage } from "./search";
|
||||
|
@ -1,63 +1,15 @@
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
Collapse,
|
||||
CollapseProps,
|
||||
Descriptions,
|
||||
Tag,
|
||||
Space,
|
||||
Button,
|
||||
} from "antd";
|
||||
import { Row, Col, Space, Button } from "antd";
|
||||
import { PlayCircleOutlined, SearchOutlined } from "@ant-design/icons";
|
||||
import { Link, useLoaderData, useNavigate } from "react-router-dom";
|
||||
import { useLoaderData, useNavigate } from "react-router-dom";
|
||||
|
||||
import Markdown from "../components/markdown.tsx";
|
||||
import { DetailsResp, ProblemApi } from "../api/problem.ts";
|
||||
|
||||
export async function ProblemLoader({ params }: { params: { id: string } }) {
|
||||
const id = parseInt(params.id);
|
||||
if (isNaN(id)) {
|
||||
throw new Error("invalid problem id");
|
||||
}
|
||||
return await ProblemApi.Details({ pid: id });
|
||||
}
|
||||
import { DetailsResp } from "../api/problem.ts";
|
||||
import ProblemDetails from "../components/problem-details.tsx";
|
||||
|
||||
export function ProblemPage() {
|
||||
const details = useLoaderData() as DetailsResp;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const problemInfo = (
|
||||
<Descriptions bordered column={1} size="small">
|
||||
<Descriptions.Item label="Provider">
|
||||
<Link to={`/user/${details.problem.provider.meta.ID}`}>
|
||||
{details.problem.provider.nick_name}
|
||||
</Link>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Supported Languages">
|
||||
<Space size={[0, 8]} wrap>
|
||||
{details.context.Languages.map((l) => (
|
||||
<Tag key={l.Lang}>{l.Lang}</Tag>
|
||||
))}
|
||||
</Space>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Task Nums">
|
||||
{details.context.Tasks.length}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
);
|
||||
const runtimeLimit = (
|
||||
<Descriptions bordered column={1} size="small">
|
||||
<Descriptions.Item label="Time Limit">
|
||||
{details.context.Runtime.TimeLimit} ms
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Memory Limit">
|
||||
{details.context.Runtime.MemoryLimit} MB
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Process Limit">
|
||||
{details.context.Runtime.NProcLimit}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
);
|
||||
const actionBtn = (
|
||||
<Space wrap>
|
||||
<Button
|
||||
@ -79,28 +31,8 @@ export function ProblemPage() {
|
||||
</Space>
|
||||
);
|
||||
|
||||
const miscItems: CollapseProps["items"] = [
|
||||
{
|
||||
key: "1",
|
||||
label: "Problem Info",
|
||||
children: problemInfo,
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
label: "Runtime Limit",
|
||||
children: runtimeLimit,
|
||||
},
|
||||
{
|
||||
key: "3",
|
||||
label: "Action",
|
||||
children: actionBtn,
|
||||
},
|
||||
];
|
||||
|
||||
const ProblemStatement = <Markdown markdown={details.problem.statement} />;
|
||||
const MiscPanel = (
|
||||
<Collapse items={miscItems} defaultActiveKey={["1", "2", "3"]} />
|
||||
);
|
||||
const MiscPanel = <ProblemDetails action={actionBtn} />;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
Reference in New Issue
Block a user