feat: problem detail page

This commit is contained in:
Paul Pan 2023-07-16 20:50:34 +08:00
parent 5049330fde
commit aedf2bbf17
3 changed files with 107 additions and 49 deletions

View File

@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@ant-design/icons": "^5.1.4",
"@sentry/react": "^7.58.1",
"@sentry/vite-plugin": "^2.4.0",
"antd": "^5.7.0",

View File

@ -5,6 +5,9 @@ settings:
excludeLinksFromLockfile: false
dependencies:
'@ant-design/icons':
specifier: ^5.1.4
version: 5.1.4(react-dom@18.2.0)(react@18.2.0)
'@sentry/react':
specifier: ^7.58.1
version: 7.58.1(react@18.2.0)

View File

@ -1,61 +1,115 @@
import { Row, Col, Card, Button, Space } from "antd";
import {
Row,
Col,
Collapse,
CollapseProps,
Descriptions,
Tag,
Space,
Typography,
Button,
} from "antd";
import { PlayCircleOutlined, SearchOutlined } from "@ant-design/icons";
import { Link, useLoaderData, useNavigate } from "react-router-dom";
import Markdown from "../components/markdown.tsx";
import { useLoaderData } from "react-router-dom";
import { DetailsResp, ProblemApi } from "../api/problem.ts";
interface LoaderProps {
params: {
id: string;
};
}
interface ProblemProps {
text: string;
}
export async function ProblemLoader({ params }: LoaderProps) {
console.log(params.id);
const text = `
# Problem 1
| Time Limit | Memory Limit |
| ---------- | ------------ |
| 1s | 256MB |
\`\`\`cpp
#include<iostream>
using namespace std;
int main() {
cout << "hello world" << endl;
return 0;
}
\`\`\`
I'm a paragraph.
inline \`code\` test
`;
return { text: text };
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 });
}
function ProblemPage() {
const { text } = useLoaderData() as ProblemProps;
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}`}>
<Typography.Link>
{details.problem.provider.nick_name}
</Typography.Link>
</Link>
</Descriptions.Item>
<Descriptions.Item label="Supported Languages">
<Space size={[0, 8]} wrap>
{details.context.Languages.map((l) => (
<Tag>{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
icon={<PlayCircleOutlined />}
onClick={() =>
navigate(`/problem/${details.problem.meta.ID}/submit`)
}
>
Submit
</Button>
<Button
icon={<SearchOutlined />}
onClick={() =>
navigate(`/problem/${details.problem.meta.ID}/status`)
}
>
Status
</Button>
</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"]} />
);
return (
<>
<Row justify="center" align="top" gutter={[16, 16]}>
<Col span={18}>
<Markdown markdown={text} />
</Col>
<Col span={6}>
<Card title="卡片标题">
<Space>
<Button type="primary">Primary</Button>
<Button type="primary">Primary</Button>
</Space>
</Card>
</Col>
<Col span={18}>{ProblemStatement}</Col>
<Col span={6}>{MiscPanel}</Col>
</Row>
</>
);