├── .babelrc
├── .eslintrc
├── .gitignore
├── README.md
├── components
├── Question.jsx
└── Quiz.jsx
├── data
└── quiz.json
├── index.html
├── index.js
├── package.json
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets" : ["es2015", "react"],
3 | "plugins": ["transform-object-rest-spread"]
4 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "ecmaFeatures": {
3 | "jsx": true,
4 | "modules": true
5 | },
6 | "env": {
7 | "browser": true,
8 | "node": true,
9 | "es6": true
10 | },
11 | "parser": "babel-eslint",
12 | "rules": {
13 | "strict": 0,
14 | "semi": [2, "never"],
15 | "no-underscore-dangle": 0,
16 | "quotes": [
17 | 2,
18 | "single"
19 | ],
20 | "react/jsx-uses-react": 2,
21 | "react/jsx-uses-vars": 2,
22 | "react/react-in-jsx-scope": 2
23 | },
24 | "plugins": [
25 | "react"
26 | ]
27 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Quiz React
2 |
3 | ## Installation
4 |
5 | ```
6 | In an empty folder:
7 | $ git clone git@github.com:gchandrasa/quiz-react.git
8 | $ cd quiz-react
9 | $ npm install
10 | $ npm run build
11 | $ npm start
12 | ```
13 |
--------------------------------------------------------------------------------
/components/Question.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const Question = ({
4 | question,
5 | index,
6 | onAnswerSelected,
7 | onSubmit
8 | }) => {
9 | return (
10 |
11 |
{question.question}
12 |
13 | {question.answers.map((answer, i) =>
14 | -
15 |
16 | {' '}
17 |
18 |
19 | )}
20 |
21 |
22 |
23 | )
24 | }
25 |
26 | export default Question
27 |
--------------------------------------------------------------------------------
/components/Quiz.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import $ from 'jquery'
3 |
4 | import Question from './Question'
5 |
6 |
7 | export default class Quiz extends React.Component {
8 |
9 | constructor(props) {
10 | super(props)
11 | this.state = {
12 | quiz: {},
13 | index: 0,
14 | answers: []
15 | }
16 | }
17 |
18 | componentDidMount() {
19 | $.getJSON('./data/quiz.json', function(result) {
20 | this.setState({quiz: result})
21 | }.bind(this))
22 | }
23 |
24 | handleSubmit() {
25 | if (this.state.index < this.state.quiz.questions.length) {
26 | this.setState({'index': this.state.index + 1})
27 | } else {
28 | let score = this.state.score || 0
29 | this.state.answers.map((answer, i) => (
30 | score = score + this.state.quiz.questions[i].answers[answer].point
31 | ))
32 | this.setState({'score': score})
33 | }
34 | }
35 |
36 | handleAnswerSelected(event) {
37 | let list = [...this.state.answers.slice(0, this.state.index),
38 | parseInt(event.target.value),
39 | ...this.state.answers.slice(this.state.index + 1)]
40 | this.setState({'answers': list})
41 | }
42 |
43 | render() {
44 | const {
45 | quiz, index, answers
46 | } = this.state
47 |
48 | let completed = (quiz.questions && (index === quiz.questions.length)) ? true : false
49 | let numberOfQuestions = quiz.questions ? quiz.questions.length : 0
50 | let score = 0
51 | if (completed) {
52 | this.state.answers.map((answer, i) => (
53 | score = score + this.state.quiz.questions[i].answers[answer].point
54 | ))
55 | }
56 |
57 | return (
58 |
59 |
{quiz.title}
60 | {completed ?
61 |
62 |
Congratulation, you finished the quiz
63 | Your score is {score}
64 |
65 | :
66 |
67 |
Question {index + 1} of {numberOfQuestions}
68 | {quiz.questions && index < numberOfQuestions ?
69 | this.handleAnswerSelected(event)}
73 | onSubmit={() => this.handleSubmit()}
74 | />
75 | : ''}
76 |
77 | }
78 |
79 | )
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/data/quiz.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Elementary Math Quiz",
3 | "questions": [
4 | {
5 | "question": "5 x 4 =",
6 | "answers": [
7 | {
8 | "point": 1,
9 | "label": "20"
10 | },
11 | {
12 | "point": 0,
13 | "label": "10"
14 | },
15 | {
16 | "point": 0,
17 | "label": "30"
18 | },
19 | {
20 | "point": 0,
21 | "label": "25"
22 | }
23 | ]
24 | },
25 | {
26 | "question": "2 + 4 x 10 =",
27 | "answers": [
28 | {
29 | "point": 0,
30 | "label": "60"
31 | },
32 | {
33 | "point": 1,
34 | "label": "42"
35 | },
36 | {
37 | "point": 0,
38 | "label": "40"
39 | },
40 | {
41 | "point": 0,
42 | "label": "20"
43 | }
44 | ]
45 | }
46 | ]
47 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Build Quiz with React.js, Webpack + Redux
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import React from 'react'
3 | import { render } from 'react-dom'
4 | import Quiz from './components/Quiz'
5 |
6 | render(
7 | ,
8 | document.getElementById('root')
9 | )
10 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "QuizReact",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "watch": "webpack --progress --colors --watch",
8 | "start": "httpster",
9 | "build": "webpack -p"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "BSD",
14 | "dependencies": {
15 | "babel": "6.1.18",
16 | "babel-core": "6.2.1",
17 | "babel-loader": "6.2.0",
18 | "babel-plugin-transform-object-rest-spread": "6.1.18",
19 | "babel-polyfill": "6.3.14",
20 | "babel-preset-es2015": "6.1.18",
21 | "babel-preset-react": "6.1.18",
22 | "isomorphic-fetch": "2.2.0",
23 | "jquery": "2.1.4",
24 | "react": "0.14.3",
25 | "react-dom": "0.14.3",
26 | "react-redux": "4.0.0",
27 | "redux": "3.0.4",
28 | "redux-logger": "2.0.4",
29 | "redux-thunk": "1.0.0",
30 | "webpack": "1.12.9"
31 | },
32 | "devDependencies": {
33 | "httpster": "1.0.1"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var path = require('path');
3 |
4 | var config = {
5 | entry: ['./index'],
6 | output: {
7 | path: path.join(__dirname, 'dist'),
8 | filename: 'bundle.js'
9 | },
10 | module: {
11 | loaders: [
12 | {
13 | test: /\.jsx?/,
14 | exclude: /(node_modules)/,
15 | loader: 'babel'
16 | }
17 | ]
18 | },
19 | resolve: {
20 | modulesDirectories: ['node_modules'],
21 | extensions: ['', '.js', '.jsx']
22 | }
23 | };
24 |
25 | module.exports = config;
26 |
--------------------------------------------------------------------------------