feat: problem detail page
This commit is contained in:
parent
5049330fde
commit
aedf2bbf17
@ -10,6 +10,7 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ant-design/icons": "^5.1.4",
|
||||||
"@sentry/react": "^7.58.1",
|
"@sentry/react": "^7.58.1",
|
||||||
"@sentry/vite-plugin": "^2.4.0",
|
"@sentry/vite-plugin": "^2.4.0",
|
||||||
"antd": "^5.7.0",
|
"antd": "^5.7.0",
|
||||||
|
@ -5,6 +5,9 @@ settings:
|
|||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@ant-design/icons':
|
||||||
|
specifier: ^5.1.4
|
||||||
|
version: 5.1.4(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@sentry/react':
|
'@sentry/react':
|
||||||
specifier: ^7.58.1
|
specifier: ^7.58.1
|
||||||
version: 7.58.1(react@18.2.0)
|
version: 7.58.1(react@18.2.0)
|
||||||
|
@ -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 Markdown from "../components/markdown.tsx";
|
||||||
import { useLoaderData } from "react-router-dom";
|
import { DetailsResp, ProblemApi } from "../api/problem.ts";
|
||||||
|
|
||||||
interface LoaderProps {
|
export async function ProblemLoader({ params }: { params: { id: string } }) {
|
||||||
params: {
|
const id = parseInt(params.id);
|
||||||
id: string;
|
if (isNaN(id)) {
|
||||||
};
|
throw new Error("invalid problem id");
|
||||||
}
|
}
|
||||||
|
return await ProblemApi.Details({ pid: id });
|
||||||
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 };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ProblemPage() {
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<Row justify="center" align="top" gutter={[16, 16]}>
|
<Row justify="center" align="top" gutter={[16, 16]}>
|
||||||
<Col span={18}>
|
<Col span={18}>{ProblemStatement}</Col>
|
||||||
<Markdown markdown={text} />
|
<Col span={6}>{MiscPanel}</Col>
|
||||||
</Col>
|
|
||||||
<Col span={6}>
|
|
||||||
<Card title="卡片标题">
|
|
||||||
<Space>
|
|
||||||
<Button type="primary">Primary</Button>
|
|
||||||
<Button type="primary">Primary</Button>
|
|
||||||
</Space>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user