Skip to content

Commit 73dc942

Browse files
committed
Few issues/enhancement
1 parent 73804c7 commit 73dc942

File tree

3 files changed

+109
-58
lines changed

3 files changed

+109
-58
lines changed

app/practice/page.tsx

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use client";
22

3-
import { useState } from "react";
3+
import { useState, useEffect, useCallback } from "react";
4+
import { useRouter, useSearchParams } from "next/navigation";
45
import { gql, useQuery } from "@apollo/client";
56
import type { NextPage } from "next";
67
import QuizForm from "@azure-fundamentals/components/QuizForm";
@@ -29,11 +30,15 @@ const questionsQuery = gql`
2930
}
3031
`;
3132

32-
const Practice: NextPage<{ searchParams: { url: string; name: string } }> = ({
33-
searchParams,
34-
}) => {
35-
const { url } = searchParams;
36-
const [currentQuestionIndex, setCurrentQuestionIndex] = useState<number>(1);
33+
const Practice: NextPage = () => {
34+
const router = useRouter();
35+
const searchParams = useSearchParams();
36+
37+
const url = searchParams.get("url") || "";
38+
const seqParam = searchParams.get("seq");
39+
const seq = seqParam ? parseInt(seqParam) : 1;
40+
41+
const [currentQuestionIndex, setCurrentQuestionIndex] = useState<number>(seq);
3742
const editedUrl = url.substring(0, url.lastIndexOf("/") + 1);
3843

3944
const { loading, error, data } = useQuery(questionQuery, {
@@ -48,9 +53,26 @@ const Practice: NextPage<{ searchParams: { url: string; name: string } }> = ({
4853
variables: { link: url },
4954
});
5055

56+
const setThisSeqIntoURL = useCallback(
57+
(seq: number) => {
58+
const newSearchParams = new URLSearchParams(searchParams.toString());
59+
newSearchParams.set("seq", seq.toString());
60+
const newUrl = `${
61+
window.location.pathname
62+
}?${newSearchParams.toString()}`;
63+
router.push(newUrl, { shallow: true });
64+
},
65+
[router, searchParams],
66+
);
67+
68+
useEffect(() => {
69+
setCurrentQuestionIndex(seq);
70+
}, [seq]);
71+
5172
const handleNextQuestion = (questionNo: number) => {
5273
if (questionNo > 0 && questionNo - 1 < questionsData?.questions?.count) {
5374
setCurrentQuestionIndex(questionNo);
75+
setThisSeqIntoURL(questionNo);
5476
}
5577
};
5678

components/QuizForm.tsx

Lines changed: 77 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,20 @@ const QuizForm: FC<Props> = ({
2323
link,
2424
}) => {
2525
const { register, handleSubmit, reset, watch } = useForm();
26-
const [showCorrectAnswer, setShowCorrectAnswer] = useState<boolean>(false);
26+
const [showCorrectAnswer, setShowCorrectAnswer] = useState<{
27+
[key: number]: boolean;
28+
}>({});
2729
const [isThinking, setIsThinking] = useState<boolean>(false);
2830
const [ollamaAvailable, setOllamaAvailable] = useState<boolean>(false);
2931
const [explanation, setExplanation] = useState<string | null>(null);
30-
const [lastIndex, setLastIndex] = useState<number>(1);
31-
const [canGoBack, setCanGoBack] = useState<boolean>(false);
3232
const [savedAnswers, setSavedAnswers] = useState<{
3333
[key: number]: string | string[];
3434
}>({});
35+
36+
const [checkedAnswers, setCheckedAnswers] = useState<{
37+
[key: number]: string[];
38+
}>({});
39+
3540
const [selectedImage, setSelectedImage] = useState<{
3641
url: string;
3742
alt: string;
@@ -52,14 +57,20 @@ const QuizForm: FC<Props> = ({
5257
checkOllamaStatus();
5358
}, []);
5459

60+
const recordShowCorrectAnswer = () => {
61+
setShowCorrectAnswer((prev) => ({
62+
...prev,
63+
[currentQuestionIndex]: true,
64+
}));
65+
};
66+
5567
const onSubmit = (data: FieldValues) => {
5668
setSavedAnswers((prev) => ({
5769
...prev,
5870
[currentQuestionIndex]: data.options[currentQuestionIndex],
5971
}));
60-
setShowCorrectAnswer(true);
61-
setCanGoBack(true);
62-
reset();
72+
73+
recordShowCorrectAnswer();
6374
};
6475

6576
const isOptionChecked = (optionText: string): boolean | undefined => {
@@ -109,28 +120,63 @@ const QuizForm: FC<Props> = ({
109120

110121
if (isLoading) return <p>Loading...</p>;
111122
//Error Handling for loading issues
112-
if (!questionSet) return <p>Loading questions failed</p>;
123+
if (!questionSet) {
124+
handleNextQuestion(1);
125+
return <p>Loading questions failed</p>;
126+
}
113127

114128
const { question, options, images } = questionSet!;
115129
const watchInput = watch(`options.${currentQuestionIndex}`);
116130

117131
const noOfAnswers = options.filter((el) => el.isAnswer === true).length;
132+
133+
const handleNextQueClick = () => {
134+
setExplanation(null);
135+
setSavedAnswers((prev) => ({
136+
...prev,
137+
[currentQuestionIndex]: watchInput,
138+
}));
139+
if (currentQuestionIndex === totalQuestions) {
140+
handleNextQuestion(1);
141+
} else {
142+
handleNextQuestion(currentQuestionIndex + 1);
143+
}
144+
reset();
145+
};
146+
147+
const isOptionCheckedWithoutReveal = (
148+
optionText: string,
149+
): boolean | undefined => {
150+
const savedAnswer = checkedAnswers[currentQuestionIndex];
151+
if (savedAnswer?.length) {
152+
return savedAnswer.includes(optionText);
153+
} else {
154+
return;
155+
}
156+
};
157+
158+
const handleRadioCheckboxClick = (event: any, isItMulti: boolean = false) => {
159+
let finalData = [event.target.value];
160+
if (isItMulti) {
161+
const savedData = checkedAnswers[currentQuestionIndex] || [];
162+
finalData = [...savedData, event.target.value];
163+
}
164+
setCheckedAnswers((prev) => ({
165+
...prev,
166+
[currentQuestionIndex]: finalData,
167+
}));
168+
};
169+
118170
return (
119171
<form onSubmit={handleSubmit(onSubmit)}>
120172
<div className="relative min-h-40">
121173
<div className="flex justify-center ">
122174
<button
123175
type="button"
124176
onClick={() => {
125-
if (currentQuestionIndex < lastIndex + 2) {
126-
setShowCorrectAnswer(true);
127-
} else {
128-
setShowCorrectAnswer(false);
129-
}
130-
reset();
131177
handleNextQuestion(currentQuestionIndex - 1);
132178
}}
133-
disabled={!(currentQuestionIndex > 1) || !canGoBack}
179+
disabled={currentQuestionIndex == 1}
134180
className="group"
135181
>
136182
<svg
@@ -159,11 +205,6 @@ const QuizForm: FC<Props> = ({
159205
max={totalQuestions}
160206
value={currentQuestionIndex}
161207
onChange={(e) => {
162-
if (Number(e.target.value) < lastIndex + 1) {
163-
setShowCorrectAnswer(true);
164-
} else {
165-
setShowCorrectAnswer(false);
166-
}
167208
handleNextQuestion(Number(e.target.value));
168209
reset();
169210
}}
@@ -174,16 +215,8 @@ const QuizForm: FC<Props> = ({
174215
</div>
175216
<button
176217
type="button"
177-
onClick={() => {
178-
if (currentQuestionIndex < lastIndex) {
179-
setShowCorrectAnswer(true);
180-
} else {
181-
setShowCorrectAnswer(false);
182-
}
183-
reset();
184-
handleNextQuestion(currentQuestionIndex + 1);
185-
}}
186-
disabled={!(currentQuestionIndex < lastIndex)}
218+
onClick={handleNextQueClick}
219+
disabled={currentQuestionIndex == totalQuestions}
187220
className="group"
188221
>
189222
<svg
@@ -248,9 +281,17 @@ const QuizForm: FC<Props> = ({
248281
type={noOfAnswers > 1 ? "checkbox" : "radio"}
249282
label={option.text}
250283
isAnswer={option.isAnswer}
251-
showCorrectAnswer={showCorrectAnswer}
252-
disabled={showCorrectAnswer}
253-
defaultChecked={isOptionChecked(option.text)}
284+
showCorrectAnswer={
285+
showCorrectAnswer[currentQuestionIndex] || false
286+
}
287+
disabled={showCorrectAnswer[currentQuestionIndex] || false}
288+
defaultChecked={
289+
isOptionChecked(option.text) ||
290+
isOptionCheckedWithoutReveal(option.text)
291+
}
292+
handleChange={(e) => {
293+
handleRadioCheckboxClick(e, noOfAnswers > 1 ? true : false);
294+
}}
254295
/>
255296
</li>
256297
))}
@@ -263,7 +304,7 @@ const QuizForm: FC<Props> = ({
263304
type="submit"
264305
intent="secondary"
265306
size="medium"
266-
disabled={showCorrectAnswer}
307+
disabled={showCorrectAnswer[currentQuestionIndex] || false}
267308
>
268309
Reveal Answer
269310
</Button>
@@ -274,7 +315,7 @@ const QuizForm: FC<Props> = ({
274315
size="medium"
275316
disabled={isThinking}
276317
onClick={() => {
277-
setShowCorrectAnswer(true);
318+
recordShowCorrectAnswer();
278319
setIsThinking(true);
279320
explainCorrectAnswer();
280321
reset();
@@ -287,24 +328,8 @@ const QuizForm: FC<Props> = ({
287328
type="button"
288329
intent="primary"
289330
size="medium"
290-
disabled={currentQuestionIndex < lastIndex}
291-
onClick={() => {
292-
setShowCorrectAnswer(false);
293-
setExplanation(null);
294-
setSavedAnswers((prev) => ({
295-
...prev,
296-
[currentQuestionIndex]: watchInput,
297-
}));
298-
if (currentQuestionIndex === totalQuestions) {
299-
handleNextQuestion(1);
300-
setLastIndex(1);
301-
} else {
302-
handleNextQuestion(currentQuestionIndex + 1);
303-
setLastIndex(currentQuestionIndex + 1);
304-
}
305-
setCanGoBack(false);
306-
reset();
307-
}}
331+
// disabled={currentQuestionIndex < lastIndex}
332+
onClick={handleNextQueClick}
308333
>
309334
Next Question
310335
</Button>

components/SelectionInput.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type Props = {
88
showCorrectAnswer?: boolean;
99
disabled?: boolean;
1010
checked?: boolean;
11+
handleChange?: Function;
1112
} & InputHTMLAttributes<HTMLInputElement>;
1213

1314
const SelectionInput = forwardRef<HTMLInputElement, Props>(
@@ -22,6 +23,7 @@ const SelectionInput = forwardRef<HTMLInputElement, Props>(
2223
showCorrectAnswer,
2324
disabled = false,
2425
defaultChecked,
26+
handleChange = () => {},
2527
...rest
2628
},
2729
ref,
@@ -36,6 +38,7 @@ const SelectionInput = forwardRef<HTMLInputElement, Props>(
3638
id={id}
3739
className={`peer hidden [&:checked_+_label_svg_path]:block `}
3840
defaultChecked={defaultChecked}
41+
onClick={handleChange}
3942
{...rest}
4043
/>
4144
<label
@@ -71,6 +74,7 @@ const SelectionInput = forwardRef<HTMLInputElement, Props>(
7174
clipRule="evenodd"
7275
/>
7376
</svg>
77+
7478
<span className="text-gray-200 pl-7 break-words inline-block w-full">
7579
{label}
7680
</span>

0 commit comments

Comments
 (0)