Skip to content

Commit 69df845

Browse files
feat: curriculum progress local storage
1 parent 6fb8d2c commit 69df845

File tree

10 files changed

+91
-33
lines changed

10 files changed

+91
-33
lines changed

data/javascript/minus-operator-coercion/index.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"title": "Minus Operator Coercion",
3+
"key": "minus-operator-coercion",
34
"description": "Understand the - operator implicit type coercion",
4-
"questionFile": "question.js",
55
"difficulty": 3,
66
"explanation": "The - here is the arithmetic substraction operator. If the operands (the left and right of the -) are booleans or numbers or strings, it will coerce to numbers (true becomes 1, false becomes 0). If the operands are not valid numbers or cannot be coerce to numbers, it will result in NaN",
77
"correctAnswer": "1 NaN 2",

data/javascript/plus-operator-coercion/index.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"title": "Plus Operator Coercion",
3+
"key": "plus-operator-coercion",
34
"description": "Understand the + operator implicit type coercion",
4-
"questionFile": "question.js",
55
"difficulty": 3,
66
"explanation": "Since JavaScript is a weakly-typed language, values can also be converted between different types automatically, and it is called implicit type coercion. The + here is the arithmetic addition operator. If the operands (the left and right of the +) are booleans or numbers, it will coerce to numbers (true becomes 1, false becomes 0). If any of the operands is a string, it will do string concatenation.",
77
"correctAnswer": "1 'truefoo' 'bar5'",

data/javascript/simple-add/index.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"title": "Simple Add",
3+
"key": "simple-add",
34
"description": "Solve a simple addition",
4-
"questionFile": "question.js",
55
"difficulty": 1,
66
"correctAnswer": "5",
77
"explanation": "Arrow function is an other way to write a function, simpleAdd(2,3) returns the sum of 2 and 3",

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
"precommit": "yarn run lint"
1515
},
1616
"dependencies": {
17+
"@fortawesome/fontawesome-svg-core": "^1.2.25",
18+
"@fortawesome/free-solid-svg-icons": "^5.11.2",
19+
"@fortawesome/react-fontawesome": "^0.1.5",
1720
"bootstrap": "^4.3.1",
1821
"css-loader": "^3.2.0",
1922
"express": "^4.17.1",

src/js/views/Javascript.jsx

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/js/views/Javascript/index.jsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from 'react';
2+
import { Link } from 'react-router-dom';
3+
import { Container } from 'react-bootstrap';
4+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
5+
import { faCheck } from '@fortawesome/free-solid-svg-icons/faCheck';
6+
import { faTimes } from '@fortawesome/free-solid-svg-icons/faTimes';
7+
8+
import data from '../../../../data/javascript/index.json';
9+
import './javascript.css';
10+
11+
const Javascript = () => {
12+
const curriculumProgress = JSON.parse(
13+
localStorage.getItem('curriculumProgress'),
14+
);
15+
const showCurriculumProgress = key => {
16+
if (curriculumProgress[key] === 'success') {
17+
return <FontAwesomeIcon icon={faCheck} color="green" />;
18+
}
19+
if (curriculumProgress[key] === 'fail') {
20+
return <FontAwesomeIcon icon={faTimes} color="red" />;
21+
}
22+
return '';
23+
};
24+
return (
25+
<Container className="mt-5 mb-3">
26+
<h2>This is Javascript</h2>
27+
<div>
28+
{data.quizzes.map(quizz => (
29+
<div key={quizz.key}>
30+
<Link to={`javascript/${quizz.key}`} className="link-question">
31+
{quizz.title}
32+
</Link>
33+
{showCurriculumProgress(quizz.key)}
34+
</div>
35+
))}
36+
</div>
37+
</Container>
38+
);
39+
};
40+
41+
export default Javascript;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.link-question {
2+
color: #333;
3+
margin-right: 5px;
4+
}

src/js/views/JsExercise.jsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,27 @@ import JsList from '../../../data/javascript/index.json';
99
const JsExercise = ({ match }) => {
1010
const [data, setData] = useState({});
1111
const [userAnswer, setUserAnswer] = useState('');
12-
const [question, setQuestion] = useState('const a = "loading";');
12+
const [question, setQuestion] = useState('');
1313
const [result, setResult] = useState('');
1414
const [nextQuestion, setNextQuestion] = useState({});
1515

16-
console.log('match', match);
17-
1816
const onSubmit = e => {
1917
e.preventDefault();
20-
18+
let curriculumProgress = JSON.parse(
19+
localStorage.getItem('curriculumProgress'),
20+
);
2121
if (userAnswer === data.correctAnswer) {
2222
setResult('success');
23+
curriculumProgress = { ...curriculumProgress, [data.key]: 'success' };
2324
} else {
2425
setResult('fail');
26+
curriculumProgress = { ...curriculumProgress, [data.key]: 'fail' };
2527
}
28+
localStorage.setItem(
29+
'curriculumProgress',
30+
JSON.stringify(curriculumProgress),
31+
);
32+
console.log(curriculumProgress);
2633
};
2734

2835
const handleOnChange = e => {
@@ -33,37 +40,34 @@ const JsExercise = ({ match }) => {
3340
/* if we have move to a new exercise, match object from react router will be different,
3441
so we can trigger a clean up of the state */
3542
setResult('');
43+
setUserAnswer('');
3644
}, [match]);
3745

3846
useEffect(() => {
3947
// Find the index of the current question in the list
4048
const indexCurrent = JsList.quizzes.findIndex(q => {
4149
return q.title === data.title;
4250
});
43-
console.log('JsList', JsList);
4451
// check if there is a next question, and update state
4552
if (indexCurrent >= 0 && JsList.quizzes.length > indexCurrent + 1) {
4653
setNextQuestion(JsList.quizzes[indexCurrent + 1]);
4754
} else if (indexCurrent >= 0 && JsList.quizzes.length <= indexCurrent + 1) {
4855
setNextQuestion({});
4956
}
50-
console.log('nextQuestion', nextQuestion);
5157
}, [data, match]);
5258

5359
Prism.highlightAll();
5460
useEffect(() => {
5561
import(`../../../data/javascript/${match.params.exercise}/index.json`).then(
5662
json => {
5763
setData(json);
58-
console.log(json);
5964
},
6065
);
6166
import(
6267
`!raw-loader! ../../../data/javascript/${match.params.exercise}/question.js`
6368
).then(js => {
6469
setQuestion(js.default);
6570
Prism.highlightAll();
66-
console.log('line 20', js.default, typeof js.default);
6771
});
6872
}, [match]);
6973

@@ -86,6 +90,7 @@ const JsExercise = ({ match }) => {
8690
type="radio"
8791
name="answer"
8892
value={a.answer}
93+
checked={a.answer === userAnswer}
8994
disabled={result !== ''}
9095
/>
9196
<br />

webpack.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = {
1111
devServer: {
1212
contentBase: './',
1313
port: 8080,
14+
historyApiFallback: true,
1415
},
1516
resolve: {
1617
extensions: ['.js', '.jsx', '.json'],

yarn.lock

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,32 @@
702702
lodash "^4.17.13"
703703
to-fast-properties "^2.0.0"
704704

705+
"@fortawesome/fontawesome-common-types@^0.2.25":
706+
version "0.2.25"
707+
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.25.tgz#6df015905081f2762e5cfddeb7a20d2e9b16c786"
708+
integrity sha512-3RuZPDuuPELd7RXtUqTCfed14fcny9UiPOkdr2i+cYxBoTOfQgxcDoq77fHiiHcgWuo1LoBUpvGxFF1H/y7s3Q==
709+
710+
"@fortawesome/fontawesome-svg-core@^1.2.25":
711+
version "1.2.25"
712+
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.25.tgz#24b03391d14f0c6171e8cad7057c687b74049790"
713+
integrity sha512-MotKnn53JKqbkLQiwcZSBJVYtTgIKFbh7B8+kd05TSnfKYPFmjKKI59o2fpz5t0Hzl35vVGU6+N4twoOpZUrqA==
714+
dependencies:
715+
"@fortawesome/fontawesome-common-types" "^0.2.25"
716+
717+
"@fortawesome/free-solid-svg-icons@^5.11.2":
718+
version "5.11.2"
719+
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.11.2.tgz#2f2f1459743a27902b76655a0d0bc5ec4d945631"
720+
integrity sha512-zBue4i0PAZJUXOmLBBvM7L0O7wmsDC8dFv9IhpW5QL4kT9xhhVUsYg/LX1+5KaukWq4/cbDcKT+RT1aRe543sg==
721+
dependencies:
722+
"@fortawesome/fontawesome-common-types" "^0.2.25"
723+
724+
"@fortawesome/react-fontawesome@^0.1.5":
725+
version "0.1.5"
726+
resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.5.tgz#8bc3cd5c617749534787a35e29caa7a6cff705c9"
727+
integrity sha512-WYDKTgyAWOncujWhhzhW7k8sgO5Eo2pZTUL51yNzSQNBUwwr6rNKg/JUSE3iebaU1XShHw74aKc1kJ+jvtRNew==
728+
dependencies:
729+
prop-types "^15.5.10"
730+
705731
"@restart/context@^2.1.4":
706732
version "2.1.4"
707733
resolved "https://registry.yarnpkg.com/@restart/context/-/context-2.1.4.tgz#a99d87c299a34c28bd85bb489cb07bfd23149c02"

0 commit comments

Comments
 (0)