diff --git a/src/App.style.ts b/src/App.style.ts index e200584..a61a184 100644 --- a/src/App.style.ts +++ b/src/App.style.ts @@ -41,7 +41,8 @@ export const Wrapper = styled.div` text-align: center; margin-bottom: 2rem; @media (max-width: 768px) { - font-size: 2rem; + font-size: 1.4rem; + margin-bottom: .5rem; } } @@ -50,13 +51,14 @@ export const Wrapper = styled.div` } .details { - margin: 2rem 0; + margin: .3rem 0; font-size: 1.4rem; display: flex; justify-content: space-between; flex-wrap: wrap; @media (max-width: 768px) { flex-direction: column; + font-size: 1.2rem; } } @@ -109,7 +111,7 @@ export const ButtonWrapper = styled.div` export const SelectWrapper = styled.select` width: 100%; max-width: 70rem; - font-size: 1.6rem; + font-size: 1.4rem; background-color: #22363c; color: white; padding: 0.24rem; diff --git a/src/App.tsx b/src/App.tsx index 023f4d0..18f3a71 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,25 +5,26 @@ import { GlobalStyle, Wrapper } from './App.style'; import SelectDifficulty, { Difficulty } from './components/SelectDifficulty'; import SelectQuestions, { TotalQuestions } from './components/SelectQuestions'; import SelectCategory from './components/SelectCategory'; +import DetailsCard from './components/DetailsCard'; import { Category, QuestionState, AnswerObject } from './Types'; const App = () => { const [loading, setLoading] = useState(false); const [questions, setQuestions] = useState([]); - const [number, setNumber] = useState(0); + const [questionNumber, setQuestionNumber] = useState(0); const [userAnswers, setUserAnswers] = useState([]); const [score, setScore] = useState(0); - const [gameOver, setGameOver] = useState(true); + const [gameOver, setGameOver] = useState(true); const [difficulty, setDifficulty] = useState(Difficulty.EASY); const [totalQuestionNumber, setTotalQuestionNumber] = useState( TotalQuestions.TEN ); - const [category, setCategory] = useState(1); + const [categoryID, setCategoryID] = useState(1); const [categoryList, setCategoryList] = useState>([]); useEffect(() => { - fetchCategories().then((data) => setCategoryList(data)); + fetchCategories().then((categories) => setCategoryList(categories)); }, []); const startTrivia = async () => { @@ -32,14 +33,14 @@ const App = () => { const newQuestions = await fetchQuizQuestions( totalQuestionNumber, - category, + categoryID, difficulty ); - setQuestions(newQuestions); setScore(0); setUserAnswers([]); - setNumber(0); + setQuestionNumber(0); + setQuestions(newQuestions); setLoading(false); }; @@ -47,17 +48,16 @@ const App = () => { if (!gameOver) { const answer = e.currentTarget.value; - const correct = questions[number].correct_answer === answer; - + const correct = questions[questionNumber].correct_answer === answer; if (correct) { setScore((prev) => prev + 1); } const answerObject = { - question: questions[number].question, + question: questions[questionNumber].question, answer, correct, - correctAnswer: questions[number].correct_answer + correctAnswer: questions[questionNumber].correct_answer }; setUserAnswers((prev) => [...prev, answerObject]); @@ -65,11 +65,10 @@ const App = () => { }; const nextQuestion = () => { - const nextNumber = number + 1; - if (nextNumber === totalQuestionNumber) { + if (questionNumber + 1 >= totalQuestionNumber) { setGameOver(true); } else { - setNumber(nextNumber); + setQuestionNumber(questionNumber + 1); } }; @@ -79,7 +78,7 @@ const App = () => {

Quiz

- {gameOver || number + 1 === totalQuestionNumber ? ( + {gameOver || questionNumber === totalQuestionNumber ? (
{ setTotalQuestionNumber={setTotalQuestionNumber} />
) : null} - {loading ??

Load Questions...

} + {loading ??

Loading Questions...

} + { + + } {!loading && !gameOver && ( )} {!gameOver && !loading && - userAnswers.length === number + 1 && - number + 1 !== totalQuestionNumber ? ( + userAnswers.length === questionNumber + 1 && + questionNumber !== totalQuestionNumber ? ( diff --git a/src/Utils.ts b/src/Utils.ts index 325dee5..4dab2c9 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -9,3 +9,18 @@ export const Capitalize = (text: string) => { (_, m1, m2) => m1.toUpperCase() + m2.toLowerCase() ); }; + +export const unEscape = (text: string) => { + text = text.replace(/'/g, "'"); + text = text.replace(/á/g, 'á'); + text = text.replace(/&/g, '&'); + text = text.replace(/å/g, 'å'); + text = text.replace(/ä/g, 'ä'); + text = text.replace(/>/g, '>'); + text = text.replace(/</g, '<'); + text = text.replace(/ñ/g, 'ñ'); + text = text.replace(/ö/g, 'ö'); + text = text.replace(/"/g, '"'); + text = text.replace(/ü/g, 'ü'); + return text; +}; diff --git a/src/components/DetailsCard.tsx b/src/components/DetailsCard.tsx new file mode 100644 index 0000000..ff2904e --- /dev/null +++ b/src/components/DetailsCard.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { Capitalize } from '../Utils'; + +type Props = { + difficulty: string; + category: string | undefined; + questionNumber: number; + totalQuestions: number; + score: number; + gameOver:boolean; +}; + +const DetailsCard: React.FC = ({ + difficulty, + category, + questionNumber, + totalQuestions, + score, + gameOver +}) => { + return ( +
+
+
Difficulty: {Capitalize(difficulty)}
+
+ Question: {!gameOver && questionNumber + 1+'\/'}{totalQuestions} +
+
Score: {score}
+ {category && ( +
+ Category: {category.replace(/Entertainment: |Science: /g, '')} +
+ )} +
+
+ ); +}; + +export default DetailsCard; diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..6037985 --- /dev/null +++ b/src/components/ErrorBoundary.tsx @@ -0,0 +1,34 @@ +import React, { Component, ErrorInfo, ReactNode } from "react"; + +interface Props { + children?: ReactNode; +} + +interface State { + hasError: boolean; +} + +class ErrorBoundary extends Component { + public state: State = { + hasError: false + }; + + public static getDerivedStateFromError(_: Error): State { + // Update state so the next render will show the fallback UI. + return { hasError: true }; + } + + public componentDidCatch(error: Error, errorInfo: ErrorInfo) { + console.error("Uncaught error:", error, errorInfo); + } + + public render() { + if (this.state.hasError) { + return

Sorry.. there was an error

; + } + + return this.props.children; + } +} + +export default ErrorBoundary; \ No newline at end of file diff --git a/src/components/QuestionCard.tsx b/src/components/QuestionCard.tsx index 56d2108..0477358 100644 --- a/src/components/QuestionCard.tsx +++ b/src/components/QuestionCard.tsx @@ -1,64 +1,36 @@ import React from 'react'; import { ButtonWrapper } from '../App.style'; import { AnswerObject } from '../Types'; -import { Capitalize } from '../Utils'; +import { unEscape } from '../Utils'; type Props = { answers: string[]; callback: (e: React.MouseEvent) => void; - difficulty: string; question: string; - category: string; - questionNr: number; - score: number; - totalQuestions: number; - userAnswer: AnswerObject | undefined; + userAnswers: AnswerObject | undefined; }; const QuestionCard: React.FC = ({ answers, callback, - difficulty, question, - category, - questionNr, - score, - totalQuestions, - userAnswer + userAnswers }) => (
-
-
Difficulty: {Capitalize(difficulty)}
-
{category}
+

{unEscape(question)}

+
+ {answers.map((answer) => ( + + + + ))}
-
-
- Question: {questionNr}/{totalQuestions} -
-
Score: {score}
-
- - {!(questionNr === totalQuestions) && ( - <> -

-

- {answers.map((answer) => ( - - - - ))} -
- - )}
); diff --git a/src/components/SelectCategory.tsx b/src/components/SelectCategory.tsx index d445135..ed00b7c 100644 --- a/src/components/SelectCategory.tsx +++ b/src/components/SelectCategory.tsx @@ -4,24 +4,24 @@ import { SelectWrapper } from '../App.style'; import { Category } from '../Types'; type Props = { - category: number; + categoryID: number; categoryList: Array; - setCategory: (category: number) => void; + setCategoryID: (categoryID: number) => void; }; -const SelectCategory = ({ category, categoryList, setCategory }: Props) => { +const SelectCategory = ({ categoryID, categoryList, setCategoryID }: Props) => { return ( ) => { e.preventDefault(); - setCategory(e.target.value as number); + setCategoryID(e.target.value as number); }} > - - {categoryList.map((cat) => ( - + {categoryList.map((category) => ( + ))} diff --git a/src/index.tsx b/src/index.tsx index 7baec16..174a164 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,12 +2,15 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; +import ErrorBoundary from './components/ErrorBoundary'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( - + + + );