added error boundary, fixed selection and layout
This commit is contained in:
@@ -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<Props> = ({
|
||||
difficulty,
|
||||
category,
|
||||
questionNumber,
|
||||
totalQuestions,
|
||||
score,
|
||||
gameOver
|
||||
}) => {
|
||||
return (
|
||||
<div className="question-card-wrapper">
|
||||
<div className="details">
|
||||
<div>Difficulty: {Capitalize(difficulty)}</div>
|
||||
<div>
|
||||
Question: {!gameOver && questionNumber + 1+'\/'}{totalQuestions}
|
||||
</div>
|
||||
<div>Score: {score}</div>
|
||||
{category && (
|
||||
<div>
|
||||
Category: {category.replace(/Entertainment: |Science: /g, '')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailsCard;
|
||||
@@ -0,0 +1,34 @@
|
||||
import React, { Component, ErrorInfo, ReactNode } from "react";
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
}
|
||||
|
||||
class ErrorBoundary extends Component<Props, State> {
|
||||
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 <h1>Sorry.. there was an error</h1>;
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorBoundary;
|
||||
@@ -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<HTMLButtonElement>) => void;
|
||||
difficulty: string;
|
||||
question: string;
|
||||
category: string;
|
||||
questionNr: number;
|
||||
score: number;
|
||||
totalQuestions: number;
|
||||
userAnswer: AnswerObject | undefined;
|
||||
userAnswers: AnswerObject | undefined;
|
||||
};
|
||||
|
||||
const QuestionCard: React.FC<Props> = ({
|
||||
answers,
|
||||
callback,
|
||||
difficulty,
|
||||
question,
|
||||
category,
|
||||
questionNr,
|
||||
score,
|
||||
totalQuestions,
|
||||
userAnswer
|
||||
userAnswers
|
||||
}) => (
|
||||
<div className="question-card-wrapper">
|
||||
<div className="details">
|
||||
<div>Difficulty: {Capitalize(difficulty)}</div>
|
||||
<div>{category}</div>
|
||||
<p className="question">{unEscape(question)}</p>
|
||||
<div>
|
||||
{answers.map((answer) => (
|
||||
<ButtonWrapper
|
||||
correct={userAnswers?.correctAnswer === answer}
|
||||
userClicked={userAnswers?.answer === answer}
|
||||
key={answer}
|
||||
>
|
||||
<button disabled={!!userAnswers} onClick={callback} value={answer}>
|
||||
<span>{unEscape(answer)}</span>
|
||||
</button>
|
||||
</ButtonWrapper>
|
||||
))}
|
||||
</div>
|
||||
<div className="details">
|
||||
<div>
|
||||
Question: {questionNr}/{totalQuestions}
|
||||
</div>
|
||||
<div>Score: {score}</div>
|
||||
</div>
|
||||
|
||||
{!(questionNr === totalQuestions) && (
|
||||
<>
|
||||
<p
|
||||
className="question"
|
||||
dangerouslySetInnerHTML={{ __html: question }}
|
||||
/>
|
||||
<div>
|
||||
{answers.map((answer) => (
|
||||
<ButtonWrapper
|
||||
correct={userAnswer?.correctAnswer === answer}
|
||||
userClicked={userAnswer?.answer === answer}
|
||||
key={answer}
|
||||
>
|
||||
<button disabled={!!userAnswer} onClick={callback} value={answer}>
|
||||
<span dangerouslySetInnerHTML={{ __html: answer }} />
|
||||
</button>
|
||||
</ButtonWrapper>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -4,24 +4,24 @@ import { SelectWrapper } from '../App.style';
|
||||
import { Category } from '../Types';
|
||||
|
||||
type Props = {
|
||||
category: number;
|
||||
categoryID: number;
|
||||
categoryList: Array<Category>;
|
||||
setCategory: (category: number) => void;
|
||||
setCategoryID: (categoryID: number) => void;
|
||||
};
|
||||
|
||||
const SelectCategory = ({ category, categoryList, setCategory }: Props) => {
|
||||
const SelectCategory = ({ categoryID, categoryList, setCategoryID }: Props) => {
|
||||
return (
|
||||
<SelectWrapper
|
||||
value={category}
|
||||
value={categoryID}
|
||||
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
|
||||
e.preventDefault();
|
||||
setCategory(e.target.value as number);
|
||||
setCategoryID(e.target.value as number);
|
||||
}}
|
||||
>
|
||||
<option value={1}>Any Category</option>
|
||||
{categoryList.map((cat) => (
|
||||
<option value={cat.id} key={cat.id}>
|
||||
{cat.name}
|
||||
<option value={1}>Random Category</option>
|
||||
{categoryList.map((category) => (
|
||||
<option value={category.id} key={category.id}>
|
||||
{category.name.replace(/Entertainment: |Science: /g, '')}
|
||||
</option>
|
||||
))}
|
||||
</SelectWrapper>
|
||||
|
||||
Reference in New Issue
Block a user