feat: add SubmitPage
This commit is contained in:
parent
0be3286bb3
commit
9274b3314d
@ -2,3 +2,5 @@ node_modules/
|
|||||||
/dist/
|
/dist/
|
||||||
/pnpm-lock.yaml
|
/pnpm-lock.yaml
|
||||||
/postcss.config.cjs
|
/postcss.config.cjs
|
||||||
|
|
||||||
|
src/components/Languages.tsx
|
||||||
|
38
src/app/services/submission.ts
Normal file
38
src/app/services/submission.ts
Normal 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;
|
10
src/components/Languages.tsx
Normal file
10
src/components/Languages.tsx
Normal 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 */
|
@ -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
65
src/pages/SubmitPage.tsx
Normal 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>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -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>
|
||||||
|
),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user