Skip to content

Commit 29ffac1

Browse files
committed
Update question reducer to set error message
1 parent 650d7a0 commit 29ffac1

File tree

2 files changed

+59
-43
lines changed

2 files changed

+59
-43
lines changed

frontend/src/pages/QuestionDetail/index.tsx

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,54 +7,35 @@ import {
77
Typography,
88
useTheme,
99
} from "@mui/material";
10-
import { useEffect, useState } from "react";
10+
import { useEffect, useReducer } from "react";
1111
import { useParams } from "react-router-dom";
1212
import Markdown from "markdown-to-jsx";
1313
import AppMargin from "../../components/AppMargin";
1414
import { grey } from "@mui/material/colors";
1515
import classes from "./index.module.css";
1616
import NotFound from "../../components/NotFound";
17-
18-
type Question = {
19-
title: string;
20-
description: string;
21-
complexity: string;
22-
categories: Array<string>;
23-
};
17+
import reducer, {
18+
getQuestionById,
19+
initialState,
20+
setSelectedQuestionError,
21+
} from "../../reducers/questionReducer";
2422

2523
const QuestionDetail: React.FC = () => {
2624
const { questionId } = useParams<{ questionId: string }>();
27-
const [question, setQuestion] = useState<Question | null>(null);
28-
const [isLoading, setIsLoading] = useState(true);
25+
const [state, dispatch] = useReducer(reducer, initialState);
2926
const theme = useTheme();
3027

3128
useEffect(() => {
3229
if (!questionId) {
33-
setIsLoading(false);
30+
setSelectedQuestionError("Unable to fetch question.", dispatch);
3431
return;
3532
}
3633

37-
// TODO: fetch question
38-
const md =
39-
"# Sample header 1\n" +
40-
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.<br /><br />" +
41-
"**Example ordered list:**\n" +
42-
"1. Item 1\n" +
43-
"2. `Item 2`\n\n" +
44-
"*Example unordered list:*\n" +
45-
"- Item 1\n" +
46-
"- Item 2";
47-
setQuestion({
48-
title: "Test Question",
49-
description: md,
50-
complexity: "Medium",
51-
categories: ["Category 1", "Category 2"],
52-
});
53-
setIsLoading(false);
34+
getQuestionById(questionId, dispatch);
5435
}, []);
5536

56-
if (!question) {
57-
if (isLoading) {
37+
if (!state.selectedQuestion) {
38+
if (state.selectedQuestionError) {
5839
return (
5940
<AppMargin classname={`${classes.fullheight} ${classes.center}`}>
6041
<NotFound
@@ -83,22 +64,22 @@ const QuestionDetail: React.FC = () => {
8364
})}
8465
>
8566
<Typography component={"h1"} variant="h3">
86-
{question.title}
67+
{state.selectedQuestion.title}
8768
</Typography>
8869
<Stack
8970
direction={"row"}
9071
sx={(theme) => ({ marginTop: theme.spacing(2) })}
9172
>
9273
<Chip
93-
key={question.complexity}
94-
label={question.complexity}
74+
key={state.selectedQuestion.complexity}
75+
label={state.selectedQuestion.complexity}
9576
color="primary"
9677
sx={(theme) => ({
9778
marginLeft: theme.spacing(1),
9879
marginRight: theme.spacing(1),
9980
})}
10081
/>
101-
{question.categories.map((cat) => (
82+
{state.selectedQuestion.categories.map((cat) => (
10283
<Chip
10384
key={cat}
10485
label={cat}
@@ -164,7 +145,7 @@ const QuestionDetail: React.FC = () => {
164145
},
165146
}}
166147
>
167-
{question.description}
148+
{state.selectedQuestion.description}
168149
</Markdown>
169150
</Box>
170151
</AppMargin>

frontend/src/reducers/questionReducer.ts

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ type QuestionDetail = {
1010
};
1111

1212
enum QuestionActionTypes {
13+
ERROR_FETCHING_SELECTED_QN = "error_fetching_selected_qn",
1314
VIEW_QUESTION = "view_question",
1415
}
1516

1617
type QuestionActions = {
1718
type: QuestionActionTypes;
18-
payload: Array<QuestionDetail> | QuestionDetail;
19+
payload: Array<QuestionDetail> | QuestionDetail | string;
1920
};
2021

2122
type QuestionsState = {
@@ -24,10 +25,21 @@ type QuestionsState = {
2425
selectedQuestionError: string | null;
2526
};
2627

27-
const isQuestionList = (
28-
questionsList: Array<QuestionDetail> | QuestionDetail
29-
): questionsList is Array<QuestionDetail> => {
30-
return Array.isArray(questionsList);
28+
const isQuestion = (question: any): question is QuestionDetail => {
29+
if (!question || typeof question !== "object") {
30+
return false;
31+
}
32+
33+
return (
34+
typeof question.questionId === "string" &&
35+
typeof question.title === "string" &&
36+
typeof question.description === "string" &&
37+
typeof question.complexity === "string" &&
38+
Array.isArray(question.categories) &&
39+
(question.categories as Array<any>).every(
40+
(value) => typeof value === "string"
41+
)
42+
);
3143
};
3244

3345
export const initialState: QuestionsState = {
@@ -36,7 +48,10 @@ export const initialState: QuestionsState = {
3648
selectedQuestionError: null,
3749
};
3850

39-
export const getQuestionById = (questionId: string, dispatch: Dispatch<QuestionActions>) => {
51+
export const getQuestionById = (
52+
questionId: string,
53+
dispatch: Dispatch<QuestionActions>
54+
) => {
4055
// questionClient
4156
// .get(`/questions/${questionId}`)
4257
// .then((res) =>
@@ -63,13 +78,33 @@ export const getQuestionById = (questionId: string, dispatch: Dispatch<QuestionA
6378
});
6479
};
6580

66-
const reducer = (state: QuestionsState, action: QuestionActions): QuestionsState => {
81+
export const setSelectedQuestionError = (
82+
error: string,
83+
dispatch: React.Dispatch<QuestionActions>
84+
) => {
85+
dispatch({
86+
type: QuestionActionTypes.ERROR_FETCHING_SELECTED_QN,
87+
payload: error,
88+
});
89+
};
90+
91+
const reducer = (
92+
state: QuestionsState,
93+
action: QuestionActions
94+
): QuestionsState => {
6795
const { type } = action;
6896

6997
switch (type) {
98+
case QuestionActionTypes.ERROR_FETCHING_SELECTED_QN: {
99+
const { payload } = action;
100+
if (typeof payload !== "string") {
101+
return state;
102+
}
103+
return { ...state, selectedQuestionError: payload };
104+
}
70105
case QuestionActionTypes.VIEW_QUESTION: {
71106
const { payload } = action;
72-
if (isQuestionList(payload)) {
107+
if (!isQuestion(payload)) {
73108
return state;
74109
}
75110
return { ...state, selectedQuestion: payload };

0 commit comments

Comments
 (0)