feat: add SubmitPage

This commit is contained in:
Paul Pan 2024-03-16 18:46:13 +08:00
parent 0be3286bb3
commit 9274b3314d
6 changed files with 126 additions and 2 deletions

View File

@ -2,3 +2,5 @@ node_modules/
/dist/ /dist/
/pnpm-lock.yaml /pnpm-lock.yaml
/postcss.config.cjs /postcss.config.cjs
src/components/Languages.tsx

View File

@ -0,0 +1,38 @@
import type { Meta, Wrap } from "./base";
import type { UserProfile } from "./user";
import type { ProblemInfo } from "./problem";
import { api } from "./api";
export interface SubmissionInfo {
meta: Meta;
problem: ProblemInfo;
user: UserProfile;
language: string;
code: string;
}
export interface SubmitRequest {
pid: number;
language: string;
code: string;
}
export interface ReJudgeResponse {
sid: number;
}
export const submissionApi = api.injectEndpoints({
endpoints: (builder) => ({
submit: builder.mutation<Wrap<string>, SubmitRequest>({
query: (data: SubmitRequest) => ({
url: "/submission/create",
method: "POST",
body: data,
}),
invalidatesTags: [{ type: "Status", id: "Search" }],
}),
}),
// TODO: admin endpoints: rejudge
});
export const { useSubmitMutation } = submissionApi;

View File

@ -0,0 +1,10 @@
/* eslint-disable prettier/prettier */
export const LanguageMap: { [lang: string]: { label: string; mode: string; prism: string } } = {
c: { label: "C", mode: "c_cpp", prism: "cpp" },
cpp: { label: "C++", mode: "c_cpp", prism: "cpp" },
python3: { label: "Python3", mode: "python", prism: "python" },
pypy3: { label: "PyPy3", mode: "python", prism: "python" },
rust: { label: "Rust", mode: "rust", prism: "rust" },
go: { label: "Go", mode: "golang", prism: "go" },
};
/* eslint-enable prettier/prettier */

View File

@ -85,7 +85,7 @@ export default function LoginPage() {
try { try {
// authSlice will automatically handle the response // authSlice will automatically handle the response
await login(formState).unwrap(); await login(formState);
navigate("/"); navigate("/");
} catch (err) { } catch (err) {
const errTyped = err as { status: number | string; data: Wrap<void> }; const errTyped = err as { status: number | string; data: Wrap<void> };

65
src/pages/SubmitPage.tsx Normal file
View File

@ -0,0 +1,65 @@
import { lazy, useEffect, useState } from "react";
import { Box, Button, Stack, useToast } from "@chakra-ui/react";
import { useNavigate, useParams } from "react-router-dom";
import { MdPlayCircleOutline } from "react-icons/md";
import { LanguageMap } from "../components/Languages";
import { useDetailQuery } from "../app/services/problem";
import { useSubmitMutation } from "../app/services/submission";
const Editor = lazy(() => import("../components/Editor"));
const ProblemInfoMenu = lazy(() => import("../components/ProblemInfoMenu"));
export default function SubmitPage() {
const { id } = useParams();
const toast = useToast();
const navigate = useNavigate();
const { data: details } = useDetailQuery({ pid: Number(id) || 0 });
const [submit, result] = useSubmitMutation();
const [lang, setLang] = useState("c");
const [code, setCode] = useState("");
const submitCode = () => {
void submit({ pid: Number(id) || 0, language: lang, code: code });
};
useEffect(() => {
if (result.isSuccess) {
navigate(`/problem/${id}/status`);
} else if (result.isError) {
toast({
status: "error",
title: "Oops...",
description: "Submit Failed",
isClosable: true,
});
}
}, [id, navigate, result, toast]);
const actionBtn = (
<Button
variant="solid"
size="sm"
colorScheme="green"
leftIcon={<MdPlayCircleOutline />}
isLoading={result.isLoading}
onClick={submitCode}
>
Submit
</Button>
);
return (
<>
<Stack direction={{ base: "column", md: "row" }}>
<Box w="100%">
<Editor mode={LanguageMap[lang].mode} onChange={setCode} />
</Box>
<Box w="480px">
<ProblemInfoMenu data={details?.body} onLanguageSelect={setLang} action={actionBtn} />
</Box>
</Stack>
</>
);
}

View File

@ -3,13 +3,14 @@ import type { RouteObject } from "react-router-dom";
import { Root } from "./pages/Root"; import { Root } from "./pages/Root";
import { ErrorPage } from "./pages/ErrorPage"; import { ErrorPage } from "./pages/ErrorPage";
// import { RequireAuth } from "./components/RequireAuth"; import { RequireAuth } from "./components/RequireAuth";
const HomePage = lazy(() => import("./pages/HomePage")); const HomePage = lazy(() => import("./pages/HomePage"));
const LoginPage = lazy(() => import("./pages/LoginPage")); const LoginPage = lazy(() => import("./pages/LoginPage"));
const LogoutPage = lazy(() => import("./pages/LogoutPage")); const LogoutPage = lazy(() => import("./pages/LogoutPage"));
const ProblemListPage = lazy(() => import("./pages/ProblemListPage")); const ProblemListPage = lazy(() => import("./pages/ProblemListPage"));
const ProblemDetailPage = lazy(() => import("./pages/ProblemDetailPage")); const ProblemDetailPage = lazy(() => import("./pages/ProblemDetailPage"));
const SubmitPage = lazy(() => import("./pages/SubmitPage"));
export const router: RouteObject[] = [ export const router: RouteObject[] = [
{ {
@ -41,6 +42,14 @@ export const router: RouteObject[] = [
path: "problem/:id", path: "problem/:id",
element: <ProblemDetailPage />, element: <ProblemDetailPage />,
}, },
{
path: "problem/:id/submit",
element: (
<RequireAuth>
<SubmitPage />
</RequireAuth>
),
},
], ],
}, },
]; ];