├── src ├── assets │ └── bg.jpg ├── sounds │ ├── play.mp3 │ ├── wait.mp3 │ ├── wrong.mp3 │ └── correct.mp3 ├── index.js ├── components │ ├── Timer.jsx │ ├── Start.jsx │ └── Trivia.jsx ├── App.css └── App.jsx ├── .gitignore ├── package.json ├── README.md └── public └── index.html /src/assets/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/React-quiz/HEAD/src/assets/bg.jpg -------------------------------------------------------------------------------- /src/sounds/play.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/React-quiz/HEAD/src/sounds/play.mp3 -------------------------------------------------------------------------------- /src/sounds/wait.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/React-quiz/HEAD/src/sounds/wait.mp3 -------------------------------------------------------------------------------- /src/sounds/wrong.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/React-quiz/HEAD/src/sounds/wrong.mp3 -------------------------------------------------------------------------------- /src/sounds/correct.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlanBinu007/React-quiz/HEAD/src/sounds/correct.mp3 -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/components/Timer.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export default function Timer({ setTimeOut, questionNumber }) { 4 | const [timer, setTimer] = useState(30); 5 | 6 | useEffect(() => { 7 | if (timer === 0) return setTimeOut(true); 8 | const interval = setInterval(() => { 9 | setTimer((prev) => prev - 1); 10 | }, 1000); 11 | return () => clearInterval(interval); 12 | }, [timer, setTimeOut]); 13 | 14 | useEffect(() => { 15 | setTimer(30); 16 | }, [questionNumber]); 17 | return timer; 18 | } 19 | -------------------------------------------------------------------------------- /src/components/Start.jsx: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | 3 | export default function Start({ setUsername }) { 4 | const inputRef = useRef(); 5 | 6 | const handleClick = () => { 7 | inputRef.current.value && setUsername(inputRef.current.value); 8 | }; 9 | 10 | return ( 11 |
12 | 17 | 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "milionaire", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "react": "^17.0.2", 10 | "react-dom": "^17.0.2", 11 | "react-scripts": "4.0.3", 12 | "use-sound": "^3.0.0", 13 | "web-vitals": "^1.0.1" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Cone the repo 6 | 7 | `git clone https://github.com/AlanBinu007/React-quiz` 8 | 9 | In the project directory, you can run: 10 | 11 | ### `yarn start` 12 | 13 | Runs the app in the development mode.\ 14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 15 | 16 | The page will reload if you make edits.\ 17 | You will also see any lint errors in the console. 18 | 19 | ### `yarn test` 20 | 21 | Launches the test runner in the interactive watch mode.\ 22 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 23 | 24 | ### `yarn build` 25 | 26 | Builds the app for production to the `build` folder.\ 27 | It correctly bundles React in production mode and optimizes the build for the best performance. 28 | 29 | The build is minified and the filenames include the hashes.\ 30 | Your app is ready to be deployed! 31 | 32 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 33 | -------------------------------------------------------------------------------- /src/components/Trivia.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import useSound from "use-sound"; 3 | import play from "../sounds/play.mp3"; 4 | import correct from "../sounds/correct.mp3"; 5 | import wrong from "../sounds/wrong.mp3"; 6 | 7 | export default function Trivia({ 8 | data, 9 | questionNumber, 10 | setQuestionNumber, 11 | setTimeOut, 12 | }) { 13 | const [question, setQuestion] = useState(null); 14 | const [selectedAnswer, setSelectedAnswer] = useState(null); 15 | const [className, setClassName] = useState("answer"); 16 | const [letsPlay] = useSound(play); 17 | const [correctAnswer] = useSound(correct); 18 | const [wrongAnswer] = useSound(wrong); 19 | 20 | useEffect(() => { 21 | letsPlay(); 22 | }, [letsPlay]); 23 | 24 | useEffect(() => { 25 | setQuestion(data[questionNumber - 1]); 26 | }, [data, questionNumber]); 27 | 28 | const delay = (duration, callback) => { 29 | setTimeout(() => { 30 | callback(); 31 | }, duration); 32 | }; 33 | 34 | const handleClick = (a) => { 35 | setSelectedAnswer(a); 36 | setClassName("answer active"); 37 | delay(3000, () => { 38 | setClassName(a.correct ? "answer correct" : "answer wrong"); 39 | }); 40 | // setTimeout(() => { 41 | // setClassName(a.correct ? "answer correct" : "answer wrong"); 42 | // }, 3000); 43 | 44 | // setTimeout(() => { 45 | delay(5000, () => { 46 | if (a.correct) { 47 | correctAnswer(); 48 | delay(1000, () => { 49 | setQuestionNumber((prev) => prev + 1); 50 | setSelectedAnswer(null); 51 | }); 52 | // setTimeout(() => { 53 | // setQuestionNumber((prev) => prev + 1); 54 | // setSelectedAnswer(null); 55 | // }, 1000); 56 | } else { 57 | wrongAnswer(); 58 | delay(1000, () => { 59 | setTimeOut(true); 60 | }); 61 | // setTimeout(() => { 62 | // setTimeOut(true); 63 | // }, 1000); 64 | } 65 | // }, 5000); 66 | }) 67 | }; 68 | return ( 69 |
70 |
{question?.question}
71 |
72 | {question?.answers.map((a) => ( 73 |
!selectedAnswer && handleClick(a)} 76 | > 77 | {a.text} 78 |
79 | ))} 80 |
81 |
82 | ); 83 | } 84 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 14 | 20 | React Quiz 21 | 22 | 23 | 24 | 25 |
26 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .app { 2 | height: 100vh; 3 | display: flex; 4 | color: white; 5 | background-color: #020230; 6 | } 7 | 8 | .main { 9 | width: 75%; 10 | background: linear-gradient(to bottom, rgba(0, 0, 0, 0), #020230), 11 | url("https://i.ytimg.com/vi/yQbJRGs0fy8/maxresdefault.jpg") center; 12 | display: flex; 13 | flex-direction: column; 14 | } 15 | 16 | .pyramid { 17 | width: 25%; 18 | background-color: #020230; 19 | display: flex; 20 | align-items: center; 21 | justify-content: center; 22 | } 23 | 24 | .moneyList { 25 | padding: 20px; 26 | list-style: none; 27 | width: 100%; 28 | } 29 | 30 | .moneyListItem { 31 | display: flex; 32 | align-items: center; 33 | padding: 5px; 34 | border-radius: 5px; 35 | } 36 | 37 | .moneyListItem.active { 38 | background-color: teal; 39 | } 40 | 41 | .moneyListItemNumber { 42 | width: 30%; 43 | font-size: 18px; 44 | font-weight: 100; 45 | } 46 | 47 | .moneyListItemAmount { 48 | font-size: 20px; 49 | font-weight: 300; 50 | } 51 | 52 | .top { 53 | height: 50%; 54 | position: relative; 55 | } 56 | 57 | .timer { 58 | width: 70px; 59 | height: 70px; 60 | border-radius: 50%; 61 | border: 5px solid white; 62 | display: flex; 63 | align-items: center; 64 | justify-content: center; 65 | position: absolute; 66 | bottom: 10px; 67 | left: 80px; 68 | font-size: 30px; 69 | font-weight: 700; 70 | } 71 | 72 | .bottom { 73 | height: 50%; 74 | } 75 | 76 | .trivia { 77 | height: 100%; 78 | display: flex; 79 | flex-direction: column; 80 | align-items: center; 81 | justify-content: space-around; 82 | } 83 | 84 | .question { 85 | width: 80%; 86 | background: linear-gradient(#100241, black); 87 | text-align: center; 88 | padding: 20px; 89 | border-radius: 10px; 90 | border: 2px solid white; 91 | font-size: 20px; 92 | } 93 | 94 | .answers { 95 | width: 100%; 96 | display: flex; 97 | justify-content: center; 98 | flex-wrap: wrap; 99 | } 100 | 101 | .answer { 102 | width: 40%; 103 | padding: 10px; 104 | margin: 0 10px 20px 10px; 105 | text-align: center; 106 | background: linear-gradient(#0e0124, #22074d); 107 | border: 1px solid white; 108 | border-radius: 15px; 109 | font-weight: 300; 110 | font-size: 20px; 111 | cursor: pointer; 112 | } 113 | 114 | .answer:hover, 115 | .answer.active { 116 | background: mediumblue; 117 | } 118 | 119 | .answer.correct { 120 | animation: correct 3s ease forwards; 121 | } 122 | 123 | @keyframes correct { 124 | 0%, 125 | 22%, 126 | 42% { 127 | background: mediumblue; 128 | } 129 | 20%, 130 | 40%, 131 | 60% { 132 | background: linear-gradient(#0e0124, #22074d); 133 | } 134 | 62%, 135 | 100% { 136 | background: green; 137 | } 138 | } 139 | 140 | .answer.wrong { 141 | animation: wrong 3s ease forwards; 142 | } 143 | 144 | @keyframes wrong { 145 | 0%, 146 | 22%, 147 | 42% { 148 | background: mediumblue; 149 | } 150 | 20%, 151 | 40%, 152 | 60% { 153 | background: linear-gradient(#0e0124, #22074d); 154 | } 155 | 62%, 156 | 100% { 157 | background: crimson; 158 | } 159 | } 160 | 161 | .endText { 162 | position: relative; 163 | top: 0; 164 | bottom: 0; 165 | left: 0; 166 | right: 0; 167 | margin: auto; 168 | } 169 | 170 | .start { 171 | width: 250px; 172 | height: 100px; 173 | display: flex; 174 | flex-direction: column; 175 | align-items: center; 176 | justify-content: space-around; 177 | position: relative; 178 | top: 0; 179 | bottom: 0; 180 | left: 0; 181 | right: 0; 182 | margin: auto; 183 | } 184 | 185 | .startInput { 186 | width: 100%; 187 | height: 30px; 188 | border: none; 189 | border-radius: 5px; 190 | text-align: center; 191 | font-size: 18px; 192 | } 193 | 194 | .startInput:focus { 195 | outline: none; 196 | } 197 | 198 | .startButton { 199 | width: 100%; 200 | height: 30px; 201 | border: none; 202 | border-radius: 5px; 203 | cursor: pointer; 204 | font-size: 18px; 205 | font-weight: 500; 206 | } -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import "./App.css"; 2 | import { useEffect, useMemo, useState } from "react"; 3 | import Start from "./components/Start"; 4 | import Timer from "./components/Timer"; 5 | import Trivia from "./components/Trivia"; 6 | 7 | function App() { 8 | const [username, setUsername] = useState(null); 9 | const [timeOut, setTimeOut] = useState(false); 10 | const [questionNumber, setQuestionNumber] = useState(1); 11 | const [earned, setEarned] = useState("$ 0"); 12 | 13 | const data = [ 14 | { 15 | id: 1, 16 | question: "Rolex is a company that specializes in what type of product?", 17 | answers: [ 18 | { 19 | text: "Phone", 20 | correct: false, 21 | }, 22 | { 23 | text: "Watches", 24 | correct: true, 25 | }, 26 | { 27 | text: "Food", 28 | correct: false, 29 | }, 30 | { 31 | text: "Cosmetic", 32 | correct: false, 33 | }, 34 | ], 35 | }, 36 | { 37 | id: 2, 38 | question: "When did the website `Facebook` launch?", 39 | answers: [ 40 | { 41 | text: "2004", 42 | correct: true, 43 | }, 44 | { 45 | text: "2005", 46 | correct: false, 47 | }, 48 | { 49 | text: "2006", 50 | correct: false, 51 | }, 52 | { 53 | text: "2007", 54 | correct: false, 55 | }, 56 | ], 57 | }, 58 | { 59 | id: 3, 60 | question: "Who played the character of harry potter in movie?", 61 | answers: [ 62 | { 63 | text: "Johnny Deep", 64 | correct: false, 65 | }, 66 | { 67 | text: "Leonardo Di Caprio", 68 | correct: false, 69 | }, 70 | { 71 | text: "Denzel Washington", 72 | correct: false, 73 | }, 74 | { 75 | text: "Daniel Red Cliff", 76 | correct: true, 77 | }, 78 | ], 79 | }, 80 | ]; 81 | 82 | const moneyPyramid = useMemo( 83 | () => 84 | [ 85 | { id: 1, amount: "$ 100" }, 86 | { id: 2, amount: "$ 200" }, 87 | { id: 3, amount: "$ 300" }, 88 | { id: 4, amount: "$ 500" }, 89 | { id: 5, amount: "$ 1.000" }, 90 | { id: 6, amount: "$ 2.000" }, 91 | { id: 7, amount: "$ 4.000" }, 92 | { id: 8, amount: "$ 8.000" }, 93 | { id: 9, amount: "$ 16.000" }, 94 | { id: 10, amount: "$ 32.000" }, 95 | { id: 11, amount: "$ 64.000" }, 96 | { id: 12, amount: "$ 125.000" }, 97 | { id: 13, amount: "$ 250.000" }, 98 | { id: 14, amount: "$ 500.000" }, 99 | { id: 15, amount: "$ 1.000.000" }, 100 | ].reverse(), 101 | [] 102 | ); 103 | 104 | useEffect(() => { 105 | questionNumber > 1 && 106 | setEarned(moneyPyramid.find((m) => m.id === questionNumber - 1).amount); 107 | }, [questionNumber, moneyPyramid]); 108 | 109 | return ( 110 |
111 | {!username ? ( 112 | 113 | ) : ( 114 | <> 115 |
116 | {timeOut ? ( 117 |

You earned: {earned}

118 | ) : ( 119 | <> 120 |
121 |
122 | 126 |
127 |
128 |
129 | 135 |
136 | 137 | )} 138 |
139 |
140 |
    141 | {moneyPyramid.map((m) => ( 142 |
  • 149 | {m.id} 150 | {m.amount} 151 |
  • 152 | ))} 153 |
154 |
155 | 156 | )} 157 |
158 | ); 159 | } 160 | 161 | export default App; 162 | --------------------------------------------------------------------------------