Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Commit

Permalink
feat : blank problem submit
Browse files Browse the repository at this point in the history
  • Loading branch information
kasterra committed May 12, 2024
1 parent aaab4c8 commit baa880f
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 71 deletions.
2 changes: 1 addition & 1 deletion app/API/lecture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ export async function getLectureWithLectureId(
}

export async function getProblemWithProblemId(
problemId: number,
problemId: number | string,
token: string
): Promise<ProblemDetailResponse> {
const response = await fetch(`${API_SERVER_URL}/problem/${problemId}`, {
Expand Down
26 changes: 16 additions & 10 deletions app/components/CodeBlank/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@ const CodeBlank = ({ parsedCode, language }: Props) => {
<code className={`language-${language}`}>
{parsedCode.map((line, idx) => (
<span key={idx}>
{line.map((element, idx) =>
element.type === "span" ? (
<span className={element.className}>{element.content}</span>
) : (
<input
className="blank"
style={{ width: element.content.length * 15 }}
/>
)
)}
{line.map((element, idx) => {
let holeIdx = 0;
if (element.type === "span") {
return (
<span className={element.className}>{element.content}</span>
);
} else {
return (
<input
className="blank"
style={{ width: element.content.length * 15 }}
name="blank[]"
/>
);
}
})}
<br />
</span>
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import Modal from "~/components/Modal";
import styles from "./index.module.css";
import formStyles from "~/components/common/form.module.css";
Expand All @@ -10,6 +10,9 @@ import { lanugage } from "~/types";
import { submit } from "~/API/submission";
import { useAuth } from "~/contexts/AuthContext";
import { useNavigate, useParams } from "@remix-run/react";
import CodeBlank from "~/components/CodeBlank";
import { getProblemWithProblemId } from "~/API/lecture";
import { generateFullCode } from "~/util/codeHole";

interface Props {
isOpen: boolean;
Expand All @@ -18,78 +21,129 @@ interface Props {

const SubmitModal = ({ isOpen, onClose }: Props) => {
const auth = useAuth();
const { labId, lectureId } = useParams();
const { labId, lectureId, practiceId } = useParams();
const navigate = useNavigate();
const [code, setCode] = useState("");
const [fileList, setFileList] = useState<FileList | null>(null);
const [language, setLanguage] = useState<lanugage>("c");
const [entryPoint, setEntryPoint] = useState("");
return (
const [isLoading, setIsLoading] = useState(true);
const [problemDetail, setProblemDetail] = useState<any>();

useEffect(() => {
async function getData() {
const response = await getProblemWithProblemId(labId!, auth.token);
if (response.status / 100 === 2) {
setProblemDetail((response as any).data);
setIsLoading(false);
}
}

getData();
}, []);

return isLoading ? null : (
<Modal
title="정답 제출"
subtitle="파일 업로드, 코드 직접 제출 모두 가능합니다"
subtitle={
problemDetail!.type === "blank"
? "빈칸 채우기"
: "파일 업로드, 코드 직접 제출 모두 가능합니다"
}
isOpen={isOpen}
onClose={onClose}
>
<form
className={styles["modal-body"]}
onSubmit={async (e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
formData.append("language", language);
if (fileList) {
[...fileList].forEach((file) => formData.append("codes", file));
}
formData.append("code", code);
if (entryPoint) {
formData.append("entrypoint", entryPoint);
}
await submit(auth.token, labId!, formData);
navigate(`/students/${lectureId}/history`);
}}
>
<RadioGroup
title="프로그래밍 언어"
name="language"
valueList={["c", "java", "python", "plaintext"]}
textList={["C", "Java", "Python", "Text"]}
onChange={setLanguage as (value: string) => void}
/>

<div className={styles.flex}>
{fileList && fileList.length > 1 ? (
<RadioGroup
title="엔트리 포인트 설정"
name="entry"
valueList={[...fileList].map((file) => file.name)}
textList={[...fileList].map((file) => file.name)}
onChange={setEntryPoint as (value: string) => void}
/>
) : null}
<MultipleFileInput
title="파일로 제출"
name="files"
onFileUpload={async (files) => {
setFileList(files);
}}
{problemDetail!.type === "blank" ? (
<form
className={styles["modal-body"]}
style={{ minWidth: "500px" }}
onSubmit={async (e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
formData.append(
"language",
problemDetail!.parsed_code_elements.language
);
formData.append(
"code",
generateFullCode(
problemDetail!.parsed_code_elements.data,
formData.getAll("blank[]") as string[]
)
);
await submit(auth.token, labId!, formData);
navigate(`/students/${lectureId}/history`);
}}
>
<CodeBlank
parsedCode={problemDetail!.parsed_code_elements.data}
language={problemDetail!.parsed_code_elements.language}
/>
<button className={formStyles["primary-button"]} type="submit">
제출
</button>
</form>
) : (
<form
className={styles["modal-body"]}
onSubmit={async (e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
formData.append("language", language);
if (fileList) {
[...fileList].forEach((file) => formData.append("codes", file));
}
formData.append("code", code);
if (entryPoint) {
formData.append("entrypoint", entryPoint);
}
await submit(auth.token, labId!, formData);
navigate(`/students/${lectureId}/history`);
}}
>
<RadioGroup
title="프로그래밍 언어"
name="language"
valueList={["c", "java", "python", "plaintext"]}
textList={["C", "Java", "Python", "Text"]}
onChange={setLanguage as (value: string) => void}
/>
{!fileList || fileList.length === 0 ? (
<div>
<span className={inputStyle.title}>코드로 작성하여 제출</span>
<CodeBlock
height={500}
language={language}
value={code}
onChange={setCode}

<div className={styles.flex}>
{fileList && fileList.length > 1 ? (
<RadioGroup
title="엔트리 포인트 설정"
name="entry"
valueList={[...fileList].map((file) => file.name)}
textList={[...fileList].map((file) => file.name)}
onChange={setEntryPoint as (value: string) => void}
/>
</div>
) : null}
</div>
) : null}
<MultipleFileInput
title="파일로 제출"
name="files"
onFileUpload={async (files) => {
setFileList(files);
}}
/>
{!fileList || fileList.length === 0 ? (
<div>
<span className={inputStyle.title}>코드로 작성하여 제출</span>
<CodeBlock
height={500}
language={language}
value={code}
onChange={setCode}
/>
</div>
) : null}
</div>

<button className={formStyles["primary-button"]} type="submit">
제출
</button>
</form>
<button className={formStyles["primary-button"]} type="submit">
제출
</button>
</form>
)}
</Modal>
);
};
Expand Down
19 changes: 19 additions & 0 deletions app/util/codeHole.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,22 @@ export function parsedCodesToString(parsedCodes: parsedCodeElement[][]) {
)
.join("\r\n");
}

export function generateFullCode(
parsedCodes: parsedCodeElement[][],
blanks: string[]
) {
console.log(blanks);
let blankIdx = 0;
return parsedCodes
.map((parsedCode) =>
parsedCode
.map((parsedCodeElement) =>
parsedCodeElement.type === "span"
? parsedCodeElement.content
: blanks[blankIdx++]
)
.join("")
)
.join("\r\n");
}

0 comments on commit baa880f

Please sign in to comment.