Skip to content

Commit cbb3fc2

Browse files
committed
Added timers
1 parent e460684 commit cbb3fc2

2 files changed

Lines changed: 99 additions & 24 deletions

File tree

src/pages/games/Gk_quiz.js

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from "react";
1+
import React, { useEffect, useState, useRef } from "react";
22
import "../../styles/pages/games/Gk_quiz.css";
33

44
const ALL_QUESTIONS = [
@@ -24,6 +24,8 @@ const ALL_QUESTIONS = [
2424
{ q: "Which is the hardest natural substance?", options: ["Gold", "Iron", "Diamond", "Silver"], ans: 2 }
2525
];
2626

27+
const QUESTION_TIME = 15; // seconds
28+
2729
function shuffleArray(arr) {
2830
const copy = [...arr];
2931
for (let i = copy.length - 1; i > 0; i--) {
@@ -41,11 +43,48 @@ export default function GKQuiz() {
4143
const [answered, setAnswered] = useState(false);
4244
const [chosenIndex, setChosenIndex] = useState(null);
4345
const [showResult, setShowResult] = useState(false);
46+
const [timeLeft, setTimeLeft] = useState(QUESTION_TIME);
47+
48+
// to clear interval when question changes or component unmounts
49+
const timerRef = useRef(null);
4450

4551
useEffect(() => {
4652
startQuiz();
4753
}, []);
4854

55+
// start timer whenever question changes
56+
useEffect(() => {
57+
if (questions.length === 0) return;
58+
startTimer();
59+
return () => {
60+
clearInterval(timerRef.current);
61+
};
62+
}, [current, questions]);
63+
64+
function startTimer() {
65+
clearInterval(timerRef.current);
66+
setTimeLeft(QUESTION_TIME);
67+
timerRef.current = setInterval(() => {
68+
setTimeLeft((prev) => {
69+
if (prev <= 1) {
70+
clearInterval(timerRef.current);
71+
if (!answered) {
72+
handleTimeUp();
73+
}
74+
return 0;
75+
}
76+
return prev - 1;
77+
});
78+
}, 1000);
79+
}
80+
81+
function handleTimeUp() {
82+
const qObj = questions[current];
83+
setAnswered(true);
84+
setChosenIndex(null);
85+
setWrong((w) => w + 1);
86+
}
87+
4988
function startQuiz() {
5089
const shuffled = shuffleArray(ALL_QUESTIONS).slice(0, 5);
5190
setQuestions(shuffled);
@@ -55,20 +94,23 @@ export default function GKQuiz() {
5594
setAnswered(false);
5695
setChosenIndex(null);
5796
setShowResult(false);
97+
setTimeLeft(QUESTION_TIME);
5898
}
5999

60100
function handleOptionClick(index) {
61101
if (answered) return;
62102
const qObj = questions[current];
63103
setChosenIndex(index);
64104
setAnswered(true);
105+
clearInterval(timerRef.current);
65106
if (index === qObj.ans) setCorrect((c) => c + 1);
66107
else setWrong((w) => w + 1);
67108
}
68109

69110
function handleNext() {
70111
if (current === questions.length - 1) {
71112
setShowResult(true);
113+
clearInterval(timerRef.current);
72114
return;
73115
}
74116
setCurrent((c) => c + 1);
@@ -101,6 +143,7 @@ export default function GKQuiz() {
101143
}
102144

103145
const qObj = questions[current];
146+
const pct = Math.round((timeLeft / QUESTION_TIME) * 100);
104147

105148
return (
106149
<div className="gk-quiz-wrapper">
@@ -110,7 +153,13 @@ export default function GKQuiz() {
110153
<p className="gk-quiz-subtitle">Answer the questions and check instantly</p>
111154
</div>
112155
<div className="gk-quiz-body">
113-
<p className="gk-quiz-progress">Question {current + 1} of {questions.length}</p>
156+
<div className="gk-top-row">
157+
<p className="gk-quiz-progress">Question {current + 1} of {questions.length}</p>
158+
<div className={`gk-timer ${timeLeft <= 5 ? "low" : ""}`}>
159+
<div className="gk-timer-bar" style={{ width: pct + "%" }}></div>
160+
<span className="gk-timer-text">{timeLeft}s</span>
161+
</div>
162+
</div>
114163
<h3 className="gk-quiz-question">{qObj.q}</h3>
115164
<div className="gk-quiz-options">
116165
{qObj.options.map((opt, idx) => {
@@ -137,7 +186,7 @@ export default function GKQuiz() {
137186
<div className="gk-quiz-feedback">
138187
{chosenIndex === qObj.ans
139188
? <>✅ Correct! The right answer is: {qObj.options[qObj.ans]}</>
140-
: <>Wrong! The correct answer is: {qObj.options[qObj.ans]}</>}
189+
: <>Time up / wrong! The correct answer is: {qObj.options[qObj.ans]}</>}
141190
</div>
142191
)}
143192
{answered && (

src/styles/pages/games/Gk_quiz.css

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,53 @@
3737
padding: 20px;
3838
}
3939

40+
.gk-top-row {
41+
display: flex;
42+
justify-content: space-between;
43+
align-items: center;
44+
gap: 14px;
45+
margin-bottom: 14px;
46+
}
47+
4048
.gk-quiz-progress {
4149
color: #64748b;
42-
margin-bottom: 12px;
4350
font-size: 0.82rem;
4451
}
4552

53+
.gk-timer {
54+
position: relative;
55+
width: 120px;
56+
height: 26px;
57+
background: #e2e8f0;
58+
border-radius: 9999px;
59+
overflow: hidden;
60+
border: 1px solid rgba(15, 23, 42, 0.08);
61+
}
62+
63+
.gk-timer-bar {
64+
position: absolute;
65+
top: 0;
66+
left: 0;
67+
height: 100%;
68+
background: #22c55e;
69+
transition: width 0.25s linear;
70+
}
71+
72+
.gk-timer-text {
73+
position: absolute;
74+
inset: 0;
75+
display: flex;
76+
align-items: center;
77+
justify-content: center;
78+
font-size: 0.75rem;
79+
font-weight: 600;
80+
color: #0f172a;
81+
}
82+
83+
.gk-timer.low .gk-timer-bar {
84+
background: #ef4444;
85+
}
86+
4687
.gk-quiz-question {
4788
font-size: 1.05rem;
4889
font-weight: 600;
@@ -71,14 +112,6 @@
71112
gap: 10px;
72113
}
73114

74-
.gk-quiz-option::before {
75-
content: "";
76-
width: 8px;
77-
height: 8px;
78-
border-radius: 9999px;
79-
background: rgba(37, 99, 235, 0.12);
80-
}
81-
82115
.gk-quiz-option:hover:not(:disabled) {
83116
background: #ecf2ff;
84117
border-color: rgba(37, 99, 235, 0.28);
@@ -94,19 +127,11 @@
94127
border-color: rgba(34, 197, 94, 0.4);
95128
}
96129

97-
.gk-quiz-option.gk-correct::before {
98-
background: #22c55e;
99-
}
100-
101130
.gk-quiz-option.gk-wrong {
102131
background: #fee2e2;
103132
border-color: rgba(239, 68, 68, 0.4);
104133
}
105134

106-
.gk-quiz-option.gk-wrong::before {
107-
background: #ef4444;
108-
}
109-
110135
.gk-quiz-feedback {
111136
margin-top: 14px;
112137
font-weight: 600;
@@ -159,10 +184,11 @@
159184
.gk-quiz-body {
160185
padding: 18px 14px 24px;
161186
}
162-
.gk-quiz-question {
163-
font-size: 1rem;
187+
.gk-top-row {
188+
flex-direction: column;
189+
align-items: flex-start;
164190
}
165-
.gk-quiz-option {
166-
font-size: 0.9rem;
191+
.gk-timer {
192+
width: 100%;
167193
}
168194
}

0 commit comments

Comments
 (0)