Skip to content
This repository has been archived by the owner on Feb 12, 2025. It is now read-only.

Commit

Permalink
refactor: use SelectAble component
Browse files Browse the repository at this point in the history
  • Loading branch information
משה וילנר authored and shootermv committed Jan 31, 2025
1 parent 32d9e25 commit 8235140
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 76 deletions.
11 changes: 5 additions & 6 deletions e2e/can-run-quiz.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,18 @@ test("question page should contain 4 options and `submit` button", async ({
await page.getByRole("button", { name: "Submit", exact: true }).click();
});

test("selected option must have 'answers-btns--selected' class", async ({
page
}) => {
test("selected first option must be checked", async ({ page }) => {
await page.getByRole("button", { name: "HTML" }).click();

await page.getByRole("button", { name: "10", exact: true }).click();

const firstOptionText = await page.getByRole("button").first().textContent();
// Select the first option (no matter if it's right or wrong)
await page.getByRole("button").first().click();

await expect(page.getByRole("button").first()).toHaveClass(
/answers-btns--selected/
);
// Check if the first radio is checked
const hiddenRadioButton = page.locator(`input[id='${firstOptionText}']`);
await expect(hiddenRadioButton).toBeChecked();
});

test("should show a modal after selecting one option and click the `submit` button", async ({
Expand Down
2 changes: 1 addition & 1 deletion e2e/score-and-results.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ test("should show 'success' modal after selecting the correct option", async ({
const questionData = await getQuestionData(question || "");

const answer = questionData.Answer;
await page.getByRole("button", { name: answer }).click();
await page.getByRole("button", { name: answer, exact: true }).click();
await page.getByRole("button", { name: "Submit", exact: true }).click();

await verifyModalResponse(page, correctModalResponses, "1");
Expand Down
32 changes: 32 additions & 0 deletions src/components/Selectable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";

const Selectable = ({
options,
groupName,
onChange
}: {
options: string[];
groupName: string;
onChange: (val: string) => void;
}) => {
return (
<ul className="select-btn-div">
{options.map((itm: string) => (
<li key={itm}>
<label className={"select-btns"} htmlFor={itm} role="button">
<input
type="radio"
id={itm}
name={groupName}
value={itm}
onChange={e => onChange(e.target.value)}
/>

{itm}
</label>
</li>
))}
</ul>
);
};
export default Selectable;
3 changes: 2 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export const CATEGORIES = [
"IT",
"Linux",
"Python",
"SQL"
"SQL",
"Random"
];

export const ALL_CATEGORIES = [
Expand Down
65 changes: 32 additions & 33 deletions src/pages/Questions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import QuizModal from "../components/QuizModal";
import React, { useEffect } from "react";

import { QuizProps } from "../types";
import Selectable from "../components/Selectable";

const Questions: React.FC<QuizProps> = QuizProps => {
const navigate = useNavigate();
Expand All @@ -20,43 +21,41 @@ const Questions: React.FC<QuizProps> = QuizProps => {
<p>Points: {QuizProps.points}</p>
</div>
<h1 className="quiz-heading">Question {QuizProps.questionNumber}</h1>
<div className="quiz-div">
<form className="select-quiz-styles">
{QuizProps.chooseAnswer ? (
<QuizModal {...QuizProps.modalProps} />
) : (
<fieldset className="quiz-answers-div">
<legend>
<span className="sr-only">
Question {QuizProps.questionNumber}
</span>
{QuizProps.currQuestion.Question}
</legend>
<ul>
{QuizProps.choicesArr.length > 0 &&
QuizProps.choicesArr[QuizProps.questionNumber - 1].map(
(choice: string, index: number) => (
<li key={index}>
<button
className={`answers-btns ${choice === QuizProps.selectedOption ? `answers-btns--selected` : ``}`}
onClick={() => QuizProps.selectOption(choice)}
>
{choice}
</button>
</li>
)
)}
</ul>
<hr />
<button
className="select-btns submit-btn"
style={{ opacity: QuizProps.selectedOption ? 1 : 0.5 }}
onClick={() => QuizProps.checkAnswer()}
>
Submit
</button>
</fieldset>
<>
<fieldset className="quiz-answers-div">
<legend>
<span className="sr-only">
Question {QuizProps.questionNumber}
</span>
{QuizProps.currQuestion.Question}
</legend>
</fieldset>

<Selectable
options={QuizProps.choicesArr[QuizProps.questionNumber - 1]}
groupName="answers"
onChange={(choice: string) => {
QuizProps.selectOption(choice);
}}
/>

<fieldset className="quiz-answers-div">
<hr />
<button
className="select-btns submit-btn"
style={{ opacity: QuizProps.selectedOption ? 1 : 0.5 }}
onClick={() => QuizProps.checkAnswer()}
>
Submit
</button>
</fieldset>
</>
)}
</div>
</form>
</>
);
};
Expand Down
27 changes: 10 additions & 17 deletions src/pages/SelectCategory.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
import React from "react";
import { CATEGORIES } from "../constants";
import { SelectCategoryProps } from "../types";
import Selectable from "../components/Selectable";

const SelectCategory: React.FC<SelectCategoryProps> = SelectCategoryProps => {
return (
<div className="select-quiz-styles">
<h2 className="quiz-heading">Choose a Category</h2>
<div className="select-btn-div">
{CATEGORIES.map((category: string, index: number) => (
<button
className="select-btns"
onClick={() => SelectCategoryProps.selectQuiz(category, index)}
key={index}
>
{category}
</button>
))}
<button
className="select-btns"
onClick={SelectCategoryProps.startRandomQuiz}
>
Random
</button>
</div>
<Selectable
options={CATEGORIES}
groupName="categories"
onChange={category =>
category === "Random"
? SelectCategoryProps.startRandomQuiz()
: SelectCategoryProps.selectQuiz(category, 0)
}
/>
</div>
);
};
Expand Down
29 changes: 12 additions & 17 deletions src/pages/SelectQuestionsTotal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { QUESTION_NUMS } from "../constants";
import { SelectQuestionsTotalProps } from "../types";
import Selectable from "../components/Selectable";

const SelectQuestionsTotal: React.FC<SelectQuestionsTotalProps> = ({
totalQuestions,
Expand All @@ -13,24 +14,18 @@ const SelectQuestionsTotal: React.FC<SelectQuestionsTotalProps> = ({
return (
<div className="select-quiz-styles">
<h2 className="quiz-heading">Choose a length for the Quiz</h2>
<div className="select-btn-div">
{availableQuizLengths.map((choice: number, index: number) => (
<button
className="select-btns"
onClick={() => startQuiz(choice)}
key={index}
>
{choice}
</button>
))}

<button
className="select-btns"
onClick={() => startQuiz(totalQuestions)}
>
All ({totalQuestions})
</button>
</div>
<Selectable
options={[
...availableQuizLengths.map(n => `${n}`),
`All (${totalQuestions})`
]}
groupName="QuizLengths"
onChange={(choice: string) => {
const num_choice = Number(choice.replace(/\D/g, ""));
startQuiz(num_choice);
}}
/>
</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/stylesheets/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ hr {

@media screen and (min-width: 768px) {
.select-btn-div {
width: 25%;
width: 50%;
padding: 0;
}
}
16 changes: 16 additions & 0 deletions src/stylesheets/Button.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,26 @@
font-size: 25px;
}

label:has(input[type="radio"]:checked) {
background-color: var(--bg-answer-selected);
}

@media screen and (max-width: 480px) {
.large-btn {
width: 200px;
height: 75px;
font-size: 22px;
}
}

ul,
li {
list-style-type: none;
input[type="radio"] {
display: none;
}
label {
color: #0a0a23;
text-align: center;
}
}

0 comments on commit 8235140

Please sign in to comment.