Skip to content
This repository was archived by the owner on Dec 25, 2022. It is now read-only.

Commit cae4942

Browse files
committed
Update time and custom quantity in exam
1 parent 9c1830d commit cae4942

File tree

4 files changed

+202
-70
lines changed

4 files changed

+202
-70
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "quizlet-learn",
3-
"version": "1.0.8",
3+
"version": "1.0.9",
44
"private": true,
55
"dependencies": {
66
"@nextui-org/react": "^1.0.0-beta.9",

src/components/DetailCourse/DetailCourse.js

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Fragment, useEffect, useState } from 'react';
1+
import { Fragment, useEffect, useRef, useState } from 'react';
22
import { useParams, useNavigate } from 'react-router-dom';
33
import {
44
Text,
@@ -51,9 +51,12 @@ const DetailCourse = () => {
5151
const [contentExport, setContentExport] = useState('');
5252
const [isConnecting, setIsConnecting] = useState(true);
5353
const [isFailedConnect, setIsFailedConnect] = useState(false);
54+
const [showEnterQuantityQuestion, setShowEnterQuantityQuestion] =
55+
useState(false);
5456

5557
const { id } = useParams();
5658
const navigate = useNavigate();
59+
const quantityRef = useRef();
5760

5861
const handleSearchChange = (e) => {
5962
setSearch(e.target.value);
@@ -134,6 +137,32 @@ const DetailCourse = () => {
134137
setShowModalExport(true);
135138
};
136139

140+
const handleSubmitExam = () => {
141+
const quantity = quantityRef.current.value;
142+
143+
// check valid quantity string from user input by regex
144+
const regex = /^[0-9]*$/;
145+
if (regex.test(quantity)) {
146+
const number = Number.parseInt(quantity);
147+
if (number > 0 && number <= 100) {
148+
const temp1 = JSON.parse(localStorage.getItem(id));
149+
if (temp1.name.includes('multiple')) {
150+
navigate('/course/pmg/' + id + '/exam', {
151+
state: {
152+
quantity: number,
153+
},
154+
});
155+
} else {
156+
navigate('/course/' + id + '/exam', {
157+
state: {
158+
quantity: number,
159+
},
160+
});
161+
}
162+
}
163+
}
164+
};
165+
137166
return (
138167
<div>
139168
<Card
@@ -155,6 +184,54 @@ const DetailCourse = () => {
155184
{!isConnecting && isFailedConnect && <FcCancel size="2rem" />}
156185
{!isConnecting && !isFailedConnect && <FcApproval size="2rem" />}
157186
</Card>
187+
<Modal
188+
closeButton
189+
blur
190+
aria-labelledby="modal-titlea"
191+
open={showEnterQuantityQuestion}
192+
onClose={() => {
193+
setShowEnterQuantityQuestion(false);
194+
}}
195+
width={'300px'}
196+
>
197+
<Modal.Header>
198+
<Text p b size={14}>
199+
Enter quantity question
200+
</Text>
201+
</Modal.Header>
202+
<Modal.Body>
203+
<Text
204+
p
205+
i
206+
size={12}
207+
color={'red'}
208+
css={{
209+
margin: '0 auto',
210+
}}
211+
>
212+
Only accept number from 1 to 100
213+
</Text>
214+
<Input
215+
width={'auto'}
216+
labelLeft={'Quantity'}
217+
clearable
218+
ref={quantityRef}
219+
/>
220+
<Button
221+
onPress={() => {
222+
handleSubmitExam();
223+
}}
224+
auto="true"
225+
css={{
226+
width: '100px',
227+
margin: '0 auto',
228+
}}
229+
color="success"
230+
>
231+
Start exam
232+
</Button>
233+
</Modal.Body>
234+
</Modal>
158235
<Modal
159236
closeButton
160237
blur
@@ -218,12 +295,7 @@ const DetailCourse = () => {
218295
handleButtonLearnPress();
219296
break;
220297
case 'Exam':
221-
const u = JSON.parse(localStorage.getItem(id));
222-
if (u.name.includes('multiple')) {
223-
navigate('/course/pmg/' + id + '/exam');
224-
} else {
225-
navigate('/course/' + id + '/exam');
226-
}
298+
setShowEnterQuantityQuestion(true);
227299
break;
228300
case 'Delete':
229301
handleDelete();

src/components/Exam/Exam.js

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Fragment, useEffect, useState } from 'react';
22
import classes from './Exam.module.css';
33
import flagExam from '../../images/flag-exam.png';
4-
import { useNavigate, useParams } from 'react-router-dom';
4+
import { useNavigate, useParams, useLocation } from 'react-router-dom';
55
import {
66
Modal,
77
Button,
@@ -28,29 +28,46 @@ const generateAnswer = (answer) => {
2828
return ['A', 'B', 'C', 'D', 'E', 'F'];
2929
};
3030

31-
const getRamdom30 = (id) => {
31+
const getRamdom = (id, quantity) => {
3232
const arrayQuestion = JSON.parse(localStorage.getItem(id))
3333
.data.map((item) => {
3434
item.answer = item.answer.trim().toUpperCase();
3535
item.choose = undefined;
3636
return item;
3737
})
3838
.filter((item) => item.answer.length === 1);
39-
return arrayQuestion.sort(() => Math.random() - 0.5).slice(0, 30);
39+
return arrayQuestion
40+
.sort(() => Math.random() - 0.5)
41+
.slice(0, quantity ? quantity : 30);
4042
};
4143

4244
const Exam = () => {
4345
const { id } = useParams();
4446
const navigate = useNavigate();
47+
const location = useLocation();
4548

46-
const [listQuestion, setListQuestion] = useState(getRamdom30(id));
49+
const [listQuestion, setListQuestion] = useState(
50+
getRamdom(id, location.state.quantity)
51+
);
4752
const [indexQuestion, setIndexQuestion] = useState(0);
4853
const [enableSubmit, setEnableSubmit] = useState(false);
4954
const [showWarning, setShowWarning] = useState(true);
5055
const [countDown, setCountDown] = useState(60);
56+
const [time, setTime] = useState(60 * location.state.quantity);
5157

5258
const [showModal, setShowModal] = useState(false);
5359

60+
useEffect(() => {
61+
const a = setTimeout(() => {
62+
if (time > 0) {
63+
setTime(time - 1);
64+
} else {
65+
setShowModal(true);
66+
}
67+
}, 1000);
68+
return () => clearTimeout(a);
69+
}, [time]);
70+
5471
useEffect(() => {
5572
const elem = document.documentElement;
5673
if (elem.requestFullscreen) {
@@ -122,33 +139,44 @@ const Exam = () => {
122139
}, 250);
123140
};
124141

142+
let munites = Math.floor(time / 60);
143+
if (munites < 10) {
144+
munites = '0' + munites;
145+
}
146+
let seconds = time % 60;
147+
if (seconds < 10) {
148+
seconds = '0' + seconds;
149+
}
150+
125151
return (
126152
<Fragment>
127-
{showWarning && <div className={classes.popup}>
128-
<Text p b css={{ color: '#ff5100' }}>
129-
<TiWarning color="ff5100" />
130-
Cảnh báo:
131-
</Text>
132-
<Spacer y={0.3} />
133-
<Text p size={12}>
134-
Đây là một trang web được thiết kế để tập trung vào việc học tập và
135-
làm quen với giao diện phần mềm EOS của trường <b>"Đại học FPT"</b>.
136-
</Text>
137-
<Spacer y={0.3} />
138-
<Text p size={12}>
139-
Nếu sử dụng trang web sai mục đích, vi phạm quy định của nhà trường, tôi
140-
sẽ không chịu trách nhiệm về bất kỳ hành vi nào của bạn.
141-
</Text>
142-
<Spacer y={0.3} />
143-
<Text p size={12}>
144-
Nếu bạn không đồng ý với điều khoản trên, vui lòng thoát khỏi trang web
145-
ngay lập tức.
146-
</Text>
147-
<Spacer y={0.6} />
148-
<Text p i size={12}>
149-
Cảnh báo sẽ tự đóng sau <b>{countDown} giây</b>.
150-
</Text>
151-
</div>}
153+
{showWarning && (
154+
<div className={classes.popup}>
155+
<Text p b css={{ color: '#ff5100' }}>
156+
<TiWarning color="ff5100" />
157+
Cảnh báo:
158+
</Text>
159+
<Spacer y={0.3} />
160+
<Text p size={12}>
161+
Đây là một trang web được thiết kế để tập trung vào việc học tập và
162+
làm quen với giao diện phần mềm EOS của trường <b>"Đại học FPT"</b>.
163+
</Text>
164+
<Spacer y={0.3} />
165+
<Text p size={12}>
166+
Nếu sử dụng trang web sai mục đích, vi phạm quy định của nhà trường,
167+
tôi sẽ không chịu trách nhiệm về bất kỳ hành vi nào của bạn.
168+
</Text>
169+
<Spacer y={0.3} />
170+
<Text p size={12}>
171+
Nếu bạn không đồng ý với điều khoản trên, vui lòng thoát khỏi trang
172+
web ngay lập tức.
173+
</Text>
174+
<Spacer y={0.6} />
175+
<Text p i size={12}>
176+
Cảnh báo sẽ tự đóng sau <b>{countDown} giây</b>.
177+
</Text>
178+
</div>
179+
)}
152180
<Modal
153181
closeButton
154182
aria-labelledby="modal-title"
@@ -287,7 +315,7 @@ const Exam = () => {
287315
</div>
288316
<div className={classes.headerTimeFlag}>
289317
<img width={160} src={flagExam} />
290-
<div>30:00</div>
318+
<div>{munites}:{seconds}</div>
291319
</div>
292320
</div>
293321
<div className={classes.tempBody}>

0 commit comments

Comments
 (0)