Skip to content

Commit

Permalink
feat: 문제 페이지 Git 그래프 관련 API 연결
Browse files Browse the repository at this point in the history
  • Loading branch information
YuHyun-P committed Dec 7, 2023
1 parent c4e7b6d commit 97c63fc
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 38 deletions.
11 changes: 11 additions & 0 deletions packages/frontend/src/apis/quiz.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Categories,
Command,
Quiz,
QuizGitGraph,
QuizSolve,
SharedQuiz,
} from "../types/quiz";
Expand Down Expand Up @@ -41,6 +42,12 @@ export const quizAPI = {
);
return data;
},
getGraph: async (id: number) => {
const { data } = await instance.get<GetQuizGraphResponse>(
`${API_PATH.QUIZZES}/${id}/graph`,
);
return data;
},
};

type PostCommandRequest = {
Expand All @@ -53,3 +60,7 @@ export type GetSharedAnswerResponse = {
answer: string[];
quiz: SharedQuiz;
};

type GetQuizGraphResponse = {
graph: QuizGitGraph;
};
26 changes: 8 additions & 18 deletions packages/frontend/src/components/graph/Graph.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as d3 from "d3";
import React, { RefObject, useEffect, useRef, useState } from "react";
import React, { RefObject, useEffect, useRef } from "react";

import color from "../../design-system/tokens/color";
import { QuizGitGraphCommit } from "../../types/quiz";

import { deletedData, initialData, newMockData } from "./data";
import fillColor from "./fillColor";
import { InitialDataProps, parsingMultipleParents } from "./parsing";

Expand All @@ -15,6 +15,10 @@ type AddedLineType = {
};

function renderD3(svgRef: RefObject<SVGGElement>, data: InitialDataProps[]) {
if (!data.length) {
return;
}

const { parsedData, additionalLinks } = parsingMultipleParents(data);
const addedLine: AddedLineType[] = [];

Expand Down Expand Up @@ -108,25 +112,17 @@ function renderD3(svgRef: RefObject<SVGGElement>, data: InitialDataProps[]) {
}

interface GraphProps {
data: QuizGitGraphCommit[];
className?: string;
}

export function Graph({ className }: GraphProps) {
const [data, setData] = useState(initialData);
export function Graph({ data, className = "" }: GraphProps) {
const gRef = useRef<SVGGElement>(null);

useEffect(() => {
renderD3(gRef, data);
}, [data]);

const handleNewData = () => {
setData(newMockData);
};

const handleDelete = () => {
setData(deletedData);
};

return (
<div className={className}>
<svg width="100%">
Expand All @@ -136,12 +132,6 @@ export function Graph({ className }: GraphProps) {
<g id="text" />
</g>
</svg>
<button type="button" onClick={handleNewData}>
click
</button>
<button type="button" onClick={handleDelete}>
delete
</button>
</div>
); // Replace with your actual JSX
}
70 changes: 51 additions & 19 deletions packages/frontend/src/pages/quizzes/[id].page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import axios, { isAxiosError } from "axios";
import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from "next";
import { useRouter } from "next/router";
import { RefObject, useEffect, useReducer, useRef } from "react";
import {
RefObject,
useCallback,
useEffect,
useReducer,
useRef,
useState,
} from "react";

import { quizAPI } from "../../apis/quiz";
import { Editor } from "../../components/editor";
Expand All @@ -19,7 +26,7 @@ import {
terminalActionTypeMap,
terminalReducer,
} from "../../reducers/terminalReducer";
import { Categories, Quiz } from "../../types/quiz";
import { Categories, Quiz, QuizGitGraphCommit } from "../../types/quiz";
import { scrollIntoView } from "../../utils/scroll";
import { isString } from "../../utils/typeGuard";

Expand All @@ -31,30 +38,46 @@ export default function QuizPage({ quiz }: { quiz: Quiz }) {
query: { id },
} = router;

const [gitGraphData, setGitGraphData] = useState<QuizGitGraphCommit[]>([]);

const solvedModal = useSolvedModal(isString(id) ? +id : -1);
const [{ terminalMode, editorFile, contentArray }, terminalDispatch] =
useReducer(terminalReducer, initialTerminalState);

const terminalInputRef = useRef<HTMLSpanElement>(null);

const fetchGitGraphData = useCallback(async (curId: number) => {
try {
const { graph: nextGraph } = await quizAPI.getGraph(curId);
setGitGraphData(nextGraph);
} catch (error) {
handleResponseError(error);
}
}, []);

const fetchGitGraphDataRef = useRef(fetchGitGraphData);

const handleTerminal = async (input: string) => {
if (!isString(id)) {
return;
}

try {
const { result, message } = await quizAPI.postCommand({
const { result, message, graph } = await quizAPI.postCommand({
id: +id,
mode: terminalMode,
message: input,
});
if (graph) {
setGitGraphData(graph);
}
terminalDispatch({
type: terminalActionTypeMap[terminalMode][result],
input,
message,
});
} catch (error) {
handleResponseError(error);
handleResponseError(error, terminalMode);
}
};

Expand Down Expand Up @@ -85,26 +108,16 @@ export default function QuizPage({ quiz }: { quiz: Quiz }) {
router.push(`${BROWSWER_PATH.QUIZZES}/${+id + 1}`);
};

const handleResponseError = (error: unknown) => {
if (
isAxiosError(error) &&
error.response?.status === 403 &&
terminalMode === "command"
) {
toast.error("지원하지 않는 명령어입니다.");
return;
}

toast.error("일시적인 오류가 발생했습니다. 잠시 후 다시 시도해주세요");
};

const handleReset = async () => {
if (!isString(id)) {
return;
}

const numId = +id;

try {
await quizAPI.resetQuizById(+id);
await quizAPI.resetQuizById(numId);
fetchGitGraphDataRef?.current(numId);
terminalDispatch({ type: TerminalActionTypes.reset });
clearTextContent(terminalInputRef);
terminalInputRef.current?.focus();
Expand All @@ -117,6 +130,9 @@ export default function QuizPage({ quiz }: { quiz: Quiz }) {
};

useEffect(() => {
if (isString(id)) {
fetchGitGraphDataRef?.current(+id);
}
terminalDispatch({ type: TerminalActionTypes.reset });
clearTextContent(terminalInputRef);
}, [id]);
Expand All @@ -133,7 +149,7 @@ export default function QuizPage({ quiz }: { quiz: Quiz }) {
<main className={styles.mainContainer}>
<div className={styles.mainInnerContainer}>
<div className={styles.topContainer} ref={topRef}>
<Graph className={styles.graph} />
<Graph className={styles.graph} data={gitGraphData} />
<QuizGuide quiz={quiz} />
</div>
<div
Expand Down Expand Up @@ -214,3 +230,19 @@ function clearTextContent<T extends Element>(ref: RefObject<T>) {
function isEditorMode(terminalMode: "editor" | "command") {
return terminalMode === "editor";
}

function handleResponseError(
error: unknown,
curTerminalMode?: "command" | "editor",
) {
if (
isAxiosError(error) &&
error.response?.status === 403 &&
curTerminalMode === "command"
) {
toast.error("지원하지 않는 명령어입니다.");
return;
}

toast.error("일시적인 오류가 발생했습니다. 잠시 후 다시 시도해주세요");
}
11 changes: 10 additions & 1 deletion packages/frontend/src/types/quiz.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type CommandEditor = "editor";
export type Command = {
message: string;
result: CommandSuccess | CommandFail | CommandEditor;
graph?: string;
graph?: QuizGitGraph;
};

export type Quiz = {
Expand Down Expand Up @@ -42,3 +42,12 @@ export type QuizSolveCorrect = {
export type QuizSolveWrong = {
solved: false;
};

export type QuizGitGraphCommit = {
id: string;
parentId: string;
message: string;
refs: string;
};

export type QuizGitGraph = QuizGitGraphCommit[];

0 comments on commit 97c63fc

Please sign in to comment.