From 6a465a508eaedf464967a1fe9a1153a674e092fa Mon Sep 17 00:00:00 2001 From: Kate Date: Fri, 2 Nov 2018 13:07:53 +0000 Subject: [PATCH 1/5] render initial question and update the score --- src/actions/index.js | 55 +++++++++++++++++++++++++++++ src/components/App.js | 3 +- src/components/Question.js | 36 +++++++++++++++++++ src/containers/QuestionContainer.js | 27 ++++++++++++++ src/reducers/index.js | 6 ++-- src/reducers/placeholder.js | 8 ----- src/reducers/question.js | 12 +++++++ src/reducers/score.js | 19 ++++++++++ 8 files changed, 155 insertions(+), 11 deletions(-) create mode 100644 src/components/Question.js create mode 100644 src/containers/QuestionContainer.js delete mode 100644 src/reducers/placeholder.js create mode 100644 src/reducers/question.js create mode 100644 src/reducers/score.js diff --git a/src/actions/index.js b/src/actions/index.js index a1d9430..416841c 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,5 +1,60 @@ +export function receiveQuestion(currentQuestion){ + console.log('Step 5. creating RECEIVE_QUESTION obj') + return{ + type:'RECEIVE_QUESTION', + currentQuestion + } +}; + + + export function fetchQuestion(){ + console.log('Step 4. calling fetch') return function(dispatch){ + fetch(`https://opentdb.com/api.php?amount=1&type=multiple`) + .then(response => response.json()) + .then(body => { + const question=body.results[0]; + const currentQuestion=Object.assign({},question, {options:question.incorrect_answers.concat(question.correct_answer).sort()}) + dispatch(receiveQuestion(currentQuestion)) + }) + } +}; + +export function correctAnswer(pointsAwarded){ + return { + type: 'CORRECT_ANSWER', + points: pointsAwarded + } + +}; + +export function incorrectAnswer(pointsAwarded){ + return { + type: 'INCORRECT_ANSWER', + points: pointsAwarded + } + + +} + +export function selectOption(selected){ + return function( dispatch, getState){ + const currentQuestion=getState().question; + console.log(currentQuestion) + const pointsSchedule = { + easy: 1, + medium:2, + hard:3 + } + const currentDifficulty = currentQuestion.difficulty; + const pointsAwarded = pointsSchedule[currentDifficulty]; + if(selected === currentQuestion.correct_answer){ + dispatch(correctAnswer(pointsAwarded)) + } else { + dispatch(incorrectAnswer(pointsAwarded)) + alert(`Sorry! Try again next time. You scored ${getState().score}.`) + } } } diff --git a/src/components/App.js b/src/components/App.js index ef2abb3..a853435 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,10 +1,11 @@ import React from 'react'; +import QuestionContainer from '../containers/QuestionContainer'; class App extends React.Component { render(){ return (
- App contents go here +
) } diff --git a/src/components/Question.js b/src/components/Question.js new file mode 100644 index 0000000..bb5f0c7 --- /dev/null +++ b/src/components/Question.js @@ -0,0 +1,36 @@ +import React from "react"; +// const { fetchQuestion, currentQuestion } = this.props; + +class Question extends React.Component { + constructor() { + super(); + } + + componentDidMount() { + console.log("Step 2. calling fetchQuestion"); + this.props.fetchQuestion(); + } + + render() { + console.log(this.props.currentScore) + return ( +
+ {Object.values(this.props.currentQuestion).length !== 0 && ( + + )} +
+ ); + } +} + +export default Question; diff --git a/src/containers/QuestionContainer.js b/src/containers/QuestionContainer.js new file mode 100644 index 0000000..8db562b --- /dev/null +++ b/src/containers/QuestionContainer.js @@ -0,0 +1,27 @@ +import {connect} from 'react-redux'; +import Question from '../components/Question'; +import {fetchQuestion, selectOption} from '../actions'; + +function mapStateToProps (state) { + console.log('Step 1. calling mapStateToProps in QuestionContainer') + + return { + currentQuestion:state.question, + currentScore: state.score + } +} + +function mapDispatchToProps (dispatch) { + return { + fetchQuestion: () => { + console.log('Step 3. getting action creator') + dispatch(fetchQuestion()) + }, + selectOption: (selected) => { + dispatch(selectOption(selected)) + } + } +} + + +export default connect(mapStateToProps,mapDispatchToProps)(Question); diff --git a/src/reducers/index.js b/src/reducers/index.js index 8e738e8..9ca4720 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,6 +1,8 @@ import { combineReducers } from 'redux'; -import placeholder from './placeholder'; +import question from './question'; +import score from './score'; export default combineReducers({ - placeholder + question, + score }); diff --git a/src/reducers/placeholder.js b/src/reducers/placeholder.js deleted file mode 100644 index 25755c5..0000000 --- a/src/reducers/placeholder.js +++ /dev/null @@ -1,8 +0,0 @@ -function placeholder(state = '', action){ - switch (action.type) { - default: - return state - } -} - -export default placeholder; diff --git a/src/reducers/question.js b/src/reducers/question.js new file mode 100644 index 0000000..8df4eac --- /dev/null +++ b/src/reducers/question.js @@ -0,0 +1,12 @@ +function question(state = {}, action){ + switch (action.type) { + case 'RECEIVE_QUESTION': + + console.log('Step 6. setting question in state') + return Object.assign({}, state, action.currentQuestion); + default: + return state + } +} + +export default question; diff --git a/src/reducers/score.js b/src/reducers/score.js new file mode 100644 index 0000000..25819a9 --- /dev/null +++ b/src/reducers/score.js @@ -0,0 +1,19 @@ +function score(state = 0, action){ + switch (action.type) { + case 'CORRECT_ANSWER': + state += action.points + return state; + case 'INCORRECT_ANSWER': + if(state - action.points >=0){ + state -= action.points + return state; + } else { + state = 0 + return state; + } + default: + return state; + } +} + +export default score; From f98355ec89bdd678a3c39d8f4b98188905586d9e Mon Sep 17 00:00:00 2001 From: Kate Date: Fri, 2 Nov 2018 16:19:23 +0000 Subject: [PATCH 2/5] score table added --- src/actions/index.js | 24 +++++++++++++++---- src/components/App.js | 4 +++- src/components/Question.js | 6 +++-- src/components/ScoreTable.js | 14 +++++++++++ src/containers/AppContainer.js | 4 ++++ src/containers/QuestionContainer.js | 11 +++++---- src/containers/ScoreTableContainer.js | 18 ++++++++++++++ src/index.js | 4 ++-- src/reducers/index.js | 4 ++-- src/reducers/score.js | 19 --------------- src/reducers/scores.js | 34 +++++++++++++++++++++++++++ 11 files changed, 107 insertions(+), 35 deletions(-) create mode 100644 src/components/ScoreTable.js create mode 100644 src/containers/AppContainer.js create mode 100644 src/containers/ScoreTableContainer.js delete mode 100644 src/reducers/score.js create mode 100644 src/reducers/scores.js diff --git a/src/actions/index.js b/src/actions/index.js index 416841c..9563d22 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -29,10 +29,11 @@ export function correctAnswer(pointsAwarded){ }; -export function incorrectAnswer(pointsAwarded){ +export function incorrectAnswer(pointsAwarded, name){ return { type: 'INCORRECT_ANSWER', - points: pointsAwarded + points: pointsAwarded, + name } @@ -51,10 +52,23 @@ export function selectOption(selected){ const pointsAwarded = pointsSchedule[currentDifficulty]; if(selected === currentQuestion.correct_answer){ dispatch(correctAnswer(pointsAwarded)) - + dispatch(fetchQuestion()) } else { - dispatch(incorrectAnswer(pointsAwarded)) - alert(`Sorry! Try again next time. You scored ${getState().score}.`) + + const name=window.prompt(`Game Over! Please enter your name to see the ranking table:`) + + dispatch(incorrectAnswer(pointsAwarded, name)) } + } } + +// export function displayScores(){ +// return function (dispatch, getState) { +// const allScores = getState().scores.allScores +// dispatch({ +// type:"DISPLAY_SCORES", +// allScores +// }) +// } +// } diff --git a/src/components/App.js b/src/components/App.js index a853435..e82f424 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,11 +1,13 @@ import React from 'react'; -import QuestionContainer from '../containers/QuestionContainer'; +import {QuestionContainer} from '../containers/QuestionContainer'; +import ScoreTableContainer from '../containers/ScoreTableContainer'; class App extends React.Component { render(){ return (
+ {this.props.scores.gameOver && }
) } diff --git a/src/components/Question.js b/src/components/Question.js index bb5f0c7..8b8ffc8 100644 --- a/src/components/Question.js +++ b/src/components/Question.js @@ -12,7 +12,7 @@ class Question extends React.Component { } render() { - console.log(this.props.currentScore) + return (
{Object.values(this.props.currentQuestion).length !== 0 && ( @@ -20,7 +20,9 @@ class Question extends React.Component {

{this.props.currentQuestion.question}

{this.props.currentQuestion.options.map(option => (
  • this.props.selectOption(event.target.textContent)} + onClick={event => { + this.props.selectOption(event.target.textContent) + }} key={option} > {option} diff --git a/src/components/ScoreTable.js b/src/components/ScoreTable.js new file mode 100644 index 0000000..42f8b7e --- /dev/null +++ b/src/components/ScoreTable.js @@ -0,0 +1,14 @@ +import React from 'react'; + +function ScoreTable({currentScore, allScores}){ + + return( +
      + {allScores.map(player => { + return
    • {player.name} {player.score}
    • + })} +
    + ) +} + +export default ScoreTable; diff --git a/src/containers/AppContainer.js b/src/containers/AppContainer.js new file mode 100644 index 0000000..ac95705 --- /dev/null +++ b/src/containers/AppContainer.js @@ -0,0 +1,4 @@ +import { connect } from "react-redux"; +import App from '../components/App'; + +export default connect(state => state)(App); diff --git a/src/containers/QuestionContainer.js b/src/containers/QuestionContainer.js index 8db562b..4553fe4 100644 --- a/src/containers/QuestionContainer.js +++ b/src/containers/QuestionContainer.js @@ -1,13 +1,13 @@ import {connect} from 'react-redux'; import Question from '../components/Question'; +// import Score from '../components/Score'; import {fetchQuestion, selectOption} from '../actions'; function mapStateToProps (state) { console.log('Step 1. calling mapStateToProps in QuestionContainer') - + return { - currentQuestion:state.question, - currentScore: state.score + currentQuestion:state.question } } @@ -24,4 +24,7 @@ function mapDispatchToProps (dispatch) { } -export default connect(mapStateToProps,mapDispatchToProps)(Question); +export const connector = connect(mapStateToProps,mapDispatchToProps); + +export const QuestionContainer = connector(Question); +// export const ScoreContainer = connector(Score); diff --git a/src/containers/ScoreTableContainer.js b/src/containers/ScoreTableContainer.js new file mode 100644 index 0000000..cdb1c6f --- /dev/null +++ b/src/containers/ScoreTableContainer.js @@ -0,0 +1,18 @@ +import ScoreTable from '../components/ScoreTable'; +import {connect} from 'react-redux'; +// import {displayScores} from '../actions'; + +const mapStateToProps = (state) => { + return { + currentScore:state.scores.currentScore, + allScores: state.scores.allScores + } +} + +// const mapDispatchToProps = (dispatch) => { +// return { +// displayScores: ()=> dispatch(displayScores()) +// } +// } + +export default connect(mapStateToProps)(ScoreTable); diff --git a/src/index.js b/src/index.js index 846662e..dc7ff56 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; - +import AppContainer from './containers/AppContainer'; import thunkMiddleware from 'redux-thunk'; import { createStore, applyMiddleware } from 'redux'; import { Provider } from 'react-redux'; @@ -13,7 +13,7 @@ const store = createStore(rootReducer, applyMiddleware( ReactDOM.render( - + , document.getElementById('root') ); diff --git a/src/reducers/index.js b/src/reducers/index.js index 9ca4720..37fa133 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,8 +1,8 @@ import { combineReducers } from 'redux'; import question from './question'; -import score from './score'; +import scores from './scores'; export default combineReducers({ question, - score + scores }); diff --git a/src/reducers/score.js b/src/reducers/score.js deleted file mode 100644 index 25819a9..0000000 --- a/src/reducers/score.js +++ /dev/null @@ -1,19 +0,0 @@ -function score(state = 0, action){ - switch (action.type) { - case 'CORRECT_ANSWER': - state += action.points - return state; - case 'INCORRECT_ANSWER': - if(state - action.points >=0){ - state -= action.points - return state; - } else { - state = 0 - return state; - } - default: - return state; - } -} - -export default score; diff --git a/src/reducers/scores.js b/src/reducers/scores.js new file mode 100644 index 0000000..2681d4a --- /dev/null +++ b/src/reducers/scores.js @@ -0,0 +1,34 @@ +const initialState = { currentScore: 0, allScores: [], gameOver: false }; + +function scores(state = initialState, action) { + switch (action.type) { + case "CORRECT_ANSWER": + state.currentScore += action.points; + return state; + case "INCORRECT_ANSWER": + function compare(a, b) { + return b.score - a.score; + } + if (state - action.points >= 0) { + state.currentScore -= action.points; + const allScores = state.allScores.concat([ + { name: action.name, score: state.currentScore } + ]); + const sortedAllScores = allScores.sort(compare); + state = Object.assign({}, state, { allScores: sortedAllScores }, {gameOver: true}); + return state; + } else { + state.currentScore = 0; + const allScores = state.allScores.concat([ + { name: action.name, score: state.currentScore } + ]); + const sortedAllScores = allScores; + state = Object.assign({}, state, { allScores: sortedAllScores }, {gameOver: true}); + return state; + } + default: + return state; + } +} + +export default scores; From f120b79f8c9f1cead6a6c826916a22941be5b4c2 Mon Sep 17 00:00:00 2001 From: Kate Date: Sun, 4 Nov 2018 02:01:48 +0000 Subject: [PATCH 3/5] add check-box --- package-lock.json | 900 +++++++++++++++++++++++++- package.json | 5 + src/actions/index.js | 128 ++-- src/components/App.js | 9 +- src/components/Category.js | 24 + src/components/Question.js | 26 +- src/components/ScoreTable.js | 7 +- src/containers/CategoryContainer.js | 18 + src/containers/QuestionContainer.js | 10 +- src/containers/ScoreTableContainer.js | 14 +- src/reducers/category.js | 23 + src/reducers/index.js | 4 +- src/reducers/question.js | 4 +- src/reducers/scores.js | 42 +- src/style/App.scss | 10 + src/style/Category.scss | 17 + src/style/Question.scss | 15 + src/style/_parameters.scss | 28 + webpack.config.js | 14 + 19 files changed, 1197 insertions(+), 101 deletions(-) create mode 100644 src/components/Category.js create mode 100644 src/containers/CategoryContainer.js create mode 100644 src/reducers/category.js create mode 100644 src/style/App.scss create mode 100644 src/style/Category.scss create mode 100644 src/style/Question.scss create mode 100644 src/style/_parameters.scss diff --git a/package-lock.json b/package-lock.json index 90154a0..ceb4ddd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -362,6 +362,12 @@ "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "acorn": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", @@ -398,6 +404,12 @@ "json-schema-traverse": "^0.3.0" } }, + "ajv-errors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", + "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", + "dev": true + }, "ajv-keywords": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", @@ -481,6 +493,16 @@ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -520,6 +542,12 @@ "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -634,6 +662,12 @@ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true + }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -1750,6 +1784,15 @@ "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==", "dev": true }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "~2.0.0" + } + }, "bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", @@ -2040,6 +2083,24 @@ "dev": true, "optional": true }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, "caniuse-lite": { "version": "1.0.30000865", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", @@ -2325,6 +2386,29 @@ "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", "dev": true }, + "clone-deep": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", + "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.0", + "shallow-clone": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -2453,6 +2537,12 @@ "date-now": "^0.1.4" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -2562,6 +2652,34 @@ "randomfill": "^1.0.3" } }, + "css-loader": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz", + "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "css-selector-tokenizer": "^0.7.0", + "icss-utils": "^2.1.0", + "loader-utils": "^1.0.2", + "lodash": "^4.17.11", + "postcss": "^6.0.23", + "postcss-modules-extract-imports": "^1.2.0", + "postcss-modules-local-by-default": "^1.2.0", + "postcss-modules-scope": "^1.1.0", + "postcss-modules-values": "^1.3.0", + "postcss-value-parser": "^3.3.0", + "source-list-map": "^2.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } + } + }, "css-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", @@ -2573,11 +2691,41 @@ "nth-check": "~1.0.1" } }, + "css-selector-tokenizer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", + "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", + "dev": true, + "requires": { + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" + }, + "dependencies": { + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + } + } + }, "css-what": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=" }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, "cssom": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", @@ -2593,6 +2741,15 @@ "cssom": "0.3.x" } }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, "cyclist": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", @@ -2758,6 +2915,12 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -3521,6 +3684,12 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, "fb-watchman": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", @@ -4240,6 +4409,18 @@ } } }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -4255,12 +4436,65 @@ "is-callable": "^1.1.3" } }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -4474,6 +4708,17 @@ } } }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", @@ -4622,6 +4867,12 @@ "has-symbol-support-x": "^1.4.1" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -4674,6 +4925,11 @@ "minimalistic-assert": "^1.0.1" } }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -4768,6 +5024,21 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + } + }, "ieee754": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", @@ -4802,6 +5073,12 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "dev": true + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", @@ -6430,6 +6707,12 @@ "merge-stream": "^1.0.1" } }, + "js-base64": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", + "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6979,6 +7262,18 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.10.tgz", "integrity": "sha512-iesFYPmxYYGTcmQK0sL8bX3TGHyM6b2qREaB4kamHfQyfPJP0xgoGxp19nsH16nsfquLdiyKyX3mQkfiSGV8Rg==" }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -6990,12 +7285,24 @@ "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" }, + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "dev": true + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.tail": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", + "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", + "dev": true + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -7099,6 +7406,16 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -7153,6 +7470,12 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -7281,6 +7604,32 @@ "readable-stream": "^2.0.1" } }, + "meow": { + "version": "3.7.0", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "merge": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", @@ -7426,6 +7775,24 @@ } } }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "dev": true, + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -7477,8 +7844,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, - "optional": true + "dev": true }, "nanomatch": { "version": "1.2.13", @@ -7543,6 +7909,34 @@ "is-stream": "^1.0.1" } }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7600,6 +7994,116 @@ "which": "^1.3.0" } }, + "node-sass": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.4.tgz", + "integrity": "sha512-MXyurANsUoE4/6KmfMkwGcBzAnJQ5xJBGW7Ei6ea8KnUKuzHr/SguVBIi3uaUAHtZCPUYkvlJ3Ef5T5VAwVpaA==", + "dev": true, + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash.assign": "^4.2.0", + "lodash.clonedeep": "^4.3.2", + "lodash.mergewith": "^4.6.0", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.10.0", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "^2.2.4", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "dev": true, + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + } + } + }, "nomnom": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", @@ -7609,6 +8113,15 @@ "underscore": "~1.4.4" } }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -7650,6 +8163,18 @@ "path-key": "^2.0.0" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, "nth-check": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", @@ -7916,6 +8441,16 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, "p-cancelable": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", @@ -8172,6 +8707,99 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", + "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", + "dev": true, + "requires": { + "postcss": "^6.0.1" + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true, + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^6.0.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -8602,6 +9230,16 @@ "resolve": "^1.1.6" } }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, "redux": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.0.tgz", @@ -8986,6 +9624,124 @@ } } }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "dev": true, + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, + "sass-loader": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", + "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", + "dev": true, + "requires": { + "clone-deep": "^2.0.1", + "loader-utils": "^1.0.1", + "lodash.tail": "^4.1.1", + "neo-async": "^2.5.0", + "pify": "^3.0.0", + "semver": "^5.5.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", @@ -9034,6 +9790,27 @@ "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=", "dev": true }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", @@ -9095,6 +9872,25 @@ "safe-buffer": "^5.0.1" } }, + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "dev": true, + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -9416,6 +10212,15 @@ } } }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", @@ -9569,6 +10374,62 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "style-loader": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", + "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -9592,6 +10453,17 @@ "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", "dev": true }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, "temp": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", @@ -9768,12 +10640,27 @@ "punycode": "^2.1.0" } }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "requires": { + "glob": "^7.1.2" + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -10669,6 +11556,15 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", diff --git a/package.json b/package.json index 7102a0e..6572820 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "classnames": "^2.2.6", "enzyme": "^3.3.0", "enzyme-adapter-react-16": "^1.1.1", + "he": "^1.2.0", "prop-types": "^15.6.2", "react": "^16.2.0", "react-dom": "^16.2.0", @@ -32,8 +33,12 @@ "babel-loader": "^7.1.3", "babel-preset-env": "^1.6.1", "babel-preset-react": "^6.24.1", + "css-loader": "^1.0.1", "jest": "^22.4.2", + "node-sass": "^4.9.4", "react-test-renderer": "^16.4.1", + "sass-loader": "^7.1.0", + "style-loader": "^0.23.1", "webpack": "^4.0.1", "webpack-cli": "^2.0.9" } diff --git a/src/actions/index.js b/src/actions/index.js index 9563d22..a5ed09e 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,74 +1,94 @@ -export function receiveQuestion(currentQuestion){ - console.log('Step 5. creating RECEIVE_QUESTION obj') - return{ - type:'RECEIVE_QUESTION', - currentQuestion - } -}; - +export function receiveQuestion(question) { + console.log("Step 5. creating RECEIVE_QUESTION obj"); + return { + type: "RECEIVE_QUESTION", + currentQuestion: question + }; +} +export function fetchQuestion(key) { + console.log("Step 4. calling fetch"); -export function fetchQuestion(){ - console.log('Step 4. calling fetch') - return function(dispatch){ - fetch(`https://opentdb.com/api.php?amount=1&type=multiple`) - .then(response => response.json()) - .then(body => { - const question=body.results[0]; - const currentQuestion=Object.assign({},question, {options:question.incorrect_answers.concat(question.correct_answer).sort()}) - dispatch(receiveQuestion(currentQuestion)) - }) - } -}; + return function(dispatch) { + fetch(`https://opentdb.com/api.php?amount=1&category=${key}&type=multiple`) + .then(response => response.json()) + .then(body => { + const question = body.results[0]; + const currentQuestion = Object.assign({}, question, { + options: question.incorrect_answers + .concat(question.correct_answer) + .sort() + }); + console.log(question.correct_answer) + dispatch(receiveQuestion(currentQuestion)); + }) + .catch(error => error.message) + }; +} -export function correctAnswer(pointsAwarded){ +export function correctAnswer(pointsAwarded) { return { - type: 'CORRECT_ANSWER', + type: "CORRECT_ANSWER", points: pointsAwarded - } - -}; + }; +} -export function incorrectAnswer(pointsAwarded, name){ +export function incorrectAnswer(pointsAwarded, name) { return { - type: 'INCORRECT_ANSWER', + type: "INCORRECT_ANSWER", points: pointsAwarded, name - } - - + }; } -export function selectOption(selected){ - return function( dispatch, getState){ - const currentQuestion=getState().question; - console.log(currentQuestion) +export function selectOption(selected) { + return function(dispatch, getState) { + const currentQuestion = getState().question; + const categoryKey = Object.keys(getState().category.category)[0]; + const pointsSchedule = { easy: 1, - medium:2, - hard:3 - } + medium: 2, + hard: 3 + }; const currentDifficulty = currentQuestion.difficulty; const pointsAwarded = pointsSchedule[currentDifficulty]; - if(selected === currentQuestion.correct_answer){ - dispatch(correctAnswer(pointsAwarded)) - dispatch(fetchQuestion()) - } else { - const name=window.prompt(`Game Over! Please enter your name to see the ranking table:`) + if (selected === currentQuestion.correct_answer) { + dispatch(correctAnswer(pointsAwarded)); + dispatch(fetchQuestion(categoryKey)); + } else { + const name = window.prompt( + `Sorry! The correct answer is: ${currentQuestion.correct_answer}. +Please enter your name to see your ranking:` + ); - dispatch(incorrectAnswer(pointsAwarded, name)) - } + dispatch(incorrectAnswer(pointsAwarded, name)); + } + }; +} - } +export function restart() { + return function(dispatch) { + dispatch(receiveQuestion({})); + dispatch({ + type: "RESTART" + }); + }; } -// export function displayScores(){ -// return function (dispatch, getState) { -// const allScores = getState().scores.allScores -// dispatch({ -// type:"DISPLAY_SCORES", -// allScores -// }) -// } -// } +export function selectCategory(category){ + + return function(dispatch, getState){ + const options = getState().category.options + const selectedKey = Object.keys(options).find( + key => options[key] === category + ); + + dispatch({ + type:'SELECT_CATEGORY', + category:{[selectedKey]:category} + }); + dispatch(fetchQuestion(selectedKey)); + + }} diff --git a/src/components/App.js b/src/components/App.js index e82f424..795fd5a 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,13 +1,16 @@ import React from 'react'; import {QuestionContainer} from '../containers/QuestionContainer'; import ScoreTableContainer from '../containers/ScoreTableContainer'; +import CategoryContainer from '../containers/CategoryContainer'; +import '../style/App.scss'; class App extends React.Component { render(){ return ( -
    - - {this.props.scores.gameOver && } +
    + + {!this.props.scores.gameOver ? + :}
    ) } diff --git a/src/components/Category.js b/src/components/Category.js new file mode 100644 index 0000000..fb02272 --- /dev/null +++ b/src/components/Category.js @@ -0,0 +1,24 @@ +import React from "react"; +import '../style/Category.scss'; + +function Category({ selectCategory, options, category }) { + return ( +
    + {Object.values(options).map(category => { + return ( + + ); + })} +
    + ); +} + +export default Category; diff --git a/src/components/Question.js b/src/components/Question.js index 8b8ffc8..356d97a 100644 --- a/src/components/Question.js +++ b/src/components/Question.js @@ -1,4 +1,6 @@ import React from "react"; +import {decode} from 'he'; +import '../style/Question.scss'; // const { fetchQuestion, currentQuestion } = this.props; class Question extends React.Component { @@ -8,28 +10,32 @@ class Question extends React.Component { componentDidMount() { console.log("Step 2. calling fetchQuestion"); - this.props.fetchQuestion(); + this.props.fetchQuestion(Object.keys(this.props.category)[0]); } render() { return ( -
    +
    {Object.values(this.props.currentQuestion).length !== 0 && ( -
      -

      {this.props.currentQuestion.question}

      +
      +

      {decode(this.props.currentQuestion.question)}

      {this.props.currentQuestion.options.map(option => ( -
    • + { - this.props.selectOption(event.target.textContent) + this.props.selectOption(option) }} key={option} - > - {option} -
    • + /> + +
      ))} -
    +
    )} +

    Difficulty: {this.props.question.difficulty}

    +

    Points: {this.props.currentScore}

    ); } diff --git a/src/components/ScoreTable.js b/src/components/ScoreTable.js index 42f8b7e..46347aa 100644 --- a/src/components/ScoreTable.js +++ b/src/components/ScoreTable.js @@ -1,13 +1,16 @@ import React from 'react'; -function ScoreTable({currentScore, allScores}){ +function ScoreTable({currentScore, allScores, restart}){ return( +
      {allScores.map(player => { - return
    • {player.name} {player.score}
    • + return
    • {player.name}: {player.score} points
    • })}
    + +
    ) } diff --git a/src/containers/CategoryContainer.js b/src/containers/CategoryContainer.js new file mode 100644 index 0000000..111332b --- /dev/null +++ b/src/containers/CategoryContainer.js @@ -0,0 +1,18 @@ +import Category from '../components/Category'; +import {connect} from 'react-redux'; +import {selectCategory} from '../actions'; + +function mapStateToProps (state) { + return { + options: state.category.options, + category: state.category.category + } +} + +const mapDispatchToProps = (dispatch) => { + return { + selectCategory: (category) => dispatch(selectCategory(category)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(Category); diff --git a/src/containers/QuestionContainer.js b/src/containers/QuestionContainer.js index 4553fe4..2fa366b 100644 --- a/src/containers/QuestionContainer.js +++ b/src/containers/QuestionContainer.js @@ -7,15 +7,19 @@ function mapStateToProps (state) { console.log('Step 1. calling mapStateToProps in QuestionContainer') return { - currentQuestion:state.question + currentQuestion:state.question, + category: state.category.category, + currentScore: state.scores.currentScore, + question: state.question } } function mapDispatchToProps (dispatch) { return { - fetchQuestion: () => { + fetchQuestion: (categoryKey) => { + console.log('Step 3. getting action creator') - dispatch(fetchQuestion()) + dispatch(fetchQuestion(categoryKey)) }, selectOption: (selected) => { dispatch(selectOption(selected)) diff --git a/src/containers/ScoreTableContainer.js b/src/containers/ScoreTableContainer.js index cdb1c6f..586da63 100644 --- a/src/containers/ScoreTableContainer.js +++ b/src/containers/ScoreTableContainer.js @@ -1,6 +1,6 @@ import ScoreTable from '../components/ScoreTable'; import {connect} from 'react-redux'; -// import {displayScores} from '../actions'; +import {restart} from '../actions'; const mapStateToProps = (state) => { return { @@ -9,10 +9,10 @@ const mapStateToProps = (state) => { } } -// const mapDispatchToProps = (dispatch) => { -// return { -// displayScores: ()=> dispatch(displayScores()) -// } -// } +const mapDispatchToProps = (dispatch) => { + return { + restart: () => dispatch(restart()) + } +} -export default connect(mapStateToProps)(ScoreTable); +export default connect(mapStateToProps,mapDispatchToProps)(ScoreTable); diff --git a/src/reducers/category.js b/src/reducers/category.js new file mode 100644 index 0000000..05c3796 --- /dev/null +++ b/src/reducers/category.js @@ -0,0 +1,23 @@ +const initialState ={ + category: {9:'General Knowledge'}, + options: {9:'General Knowledge', + 11:'Entertainment: Film', + 18: 'Science: Computers', + + 23: 'History', + 22: 'Geography', + 25: 'Art' + } +} + +function category(state=initialState , action){ + switch (action.type) { + case 'SELECT_CATEGORY': + // const selectedKey = Object.keys(state.options).find(key => state.options[key] === action.category) + return Object.assign({}, state, {category: action.category}) + default: + return state + } +} + +export default category; diff --git a/src/reducers/index.js b/src/reducers/index.js index 37fa133..8dc5100 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,8 +1,10 @@ import { combineReducers } from 'redux'; import question from './question'; import scores from './scores'; +import category from './category'; export default combineReducers({ question, - scores + scores, + category }); diff --git a/src/reducers/question.js b/src/reducers/question.js index 8df4eac..a150b67 100644 --- a/src/reducers/question.js +++ b/src/reducers/question.js @@ -3,7 +3,9 @@ function question(state = {}, action){ case 'RECEIVE_QUESTION': console.log('Step 6. setting question in state') - return Object.assign({}, state, action.currentQuestion); + + return action.currentQuestion; + default: return state } diff --git a/src/reducers/scores.js b/src/reducers/scores.js index 2681d4a..899d778 100644 --- a/src/reducers/scores.js +++ b/src/reducers/scores.js @@ -1,4 +1,8 @@ -const initialState = { currentScore: 0, allScores: [], gameOver: false }; +const initialState = { + currentScore: 0, + allScores: [], + gameOver: false +}; function scores(state = initialState, action) { switch (action.type) { @@ -9,23 +13,25 @@ function scores(state = initialState, action) { function compare(a, b) { return b.score - a.score; } - if (state - action.points >= 0) { - state.currentScore -= action.points; - const allScores = state.allScores.concat([ - { name: action.name, score: state.currentScore } - ]); - const sortedAllScores = allScores.sort(compare); - state = Object.assign({}, state, { allScores: sortedAllScores }, {gameOver: true}); - return state; - } else { - state.currentScore = 0; - const allScores = state.allScores.concat([ - { name: action.name, score: state.currentScore } - ]); - const sortedAllScores = allScores; - state = Object.assign({}, state, { allScores: sortedAllScores }, {gameOver: true}); - return state; - } + + const allScores = state.allScores.concat([ + { name: action.name, score: state.currentScore } + ]); + const sortedAllScores = allScores.sort(compare); + state = Object.assign({}, state, { + allScores: sortedAllScores, + + gameOver: true + }); + return state; + case "RESTART": + state = Object.assign( + {}, + state, + { currentScore: 0 }, + { gameOver: false } + ); + return state; default: return state; } diff --git a/src/style/App.scss b/src/style/App.scss new file mode 100644 index 0000000..3586475 --- /dev/null +++ b/src/style/App.scss @@ -0,0 +1,10 @@ +@import "parameters"; + +body{ + margin:0; +} +.wrapper{ + font-family: $font-family; + background-color: $background-color; + +} diff --git a/src/style/Category.scss b/src/style/Category.scss new file mode 100644 index 0000000..b366837 --- /dev/null +++ b/src/style/Category.scss @@ -0,0 +1,17 @@ +@import "parameters"; + +button{ + @extend %button; + padding: $content-padding; + margin: 2px; + + border-radius: 10%; + cursor: pointer; +} + +.category{ + display: grid; + grid-template-columns: 1fr 1fr 1fr ; + font-size: $normal-font-size; + +} diff --git a/src/style/Question.scss b/src/style/Question.scss new file mode 100644 index 0000000..1b68ff9 --- /dev/null +++ b/src/style/Question.scss @@ -0,0 +1,15 @@ +@import "parameters"; + + +input[type=checkbox] { + + /* For mobile, it's typically better to position checkbox on top of clickable + area and turn opacity to 0 instead. */ +} + +/* Default State */ + +/* Toggled State */ +input[type=checkbox]:checked + label { + border: red; +} diff --git a/src/style/_parameters.scss b/src/style/_parameters.scss new file mode 100644 index 0000000..3be1df5 --- /dev/null +++ b/src/style/_parameters.scss @@ -0,0 +1,28 @@ +$primary-color: #252525; +$background-color: #ffffff; +$font-family: "Open Sans", sans-serif; +//color scheme +$border-color: #878e88; +$font-color: #252726; + +$normal-font-size: 16px; +$medium-font-size: 13px; +$small-font-size: 10px; + +$background-color: #f5f5f5; + +$content-padding: 1px 7px 2px 7px; +$card-gap: 10px; + +$margin: 7px; +$margin-double: 14px; + +%button { + background-color: #63B1C2; + color: white; + + &:hover { + background-color: #16BAC5; + transition: 0.3s; + } +} diff --git a/webpack.config.js b/webpack.config.js index 9355dc3..61db905 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -13,6 +13,20 @@ module.exports = { test: /\.js$/, exclude: /(node_modules)/, loader: require.resolve('babel-loader') + }, + { + test: /\.scss$/, + use: [ + { + loader: "style-loader" + }, + { + loader: "css-loader" + }, + { + loader: "sass-loader" + } + ] } ] } From c830251157ced234b57e34124cda00c88b62e0a9 Mon Sep 17 00:00:00 2001 From: Kate Date: Sun, 4 Nov 2018 16:13:13 +0000 Subject: [PATCH 4/5] styling --- src/actions/index.js | 40 +++++++++++++++++++++---------- src/components/App.js | 18 ++++++++++++-- src/components/ScoreTable.js | 6 +++-- src/reducers/image.js | 46 ++++++++++++++++++++++++++++++++++++ src/reducers/index.js | 4 +++- src/style/App.scss | 6 ++--- src/style/Category.scss | 7 +++--- src/style/ScoreTable.scss | 16 +++++++++++++ src/style/_parameters.scss | 16 +++++++++---- 9 files changed, 131 insertions(+), 28 deletions(-) create mode 100644 src/reducers/image.js create mode 100644 src/style/ScoreTable.scss diff --git a/src/actions/index.js b/src/actions/index.js index a5ed09e..106dfe8 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -19,10 +19,10 @@ export function fetchQuestion(key) { .concat(question.correct_answer) .sort() }); - console.log(question.correct_answer) + console.log(question.correct_answer); dispatch(receiveQuestion(currentQuestion)); }) - .catch(error => error.message) + .catch(error => error.message); }; } @@ -57,12 +57,14 @@ export function selectOption(selected) { if (selected === currentQuestion.correct_answer) { dispatch(correctAnswer(pointsAwarded)); dispatch(fetchQuestion(categoryKey)); + dispatch(loadImage()) } else { - const name = window.prompt( + let name = window.prompt( `Sorry! The correct answer is: ${currentQuestion.correct_answer}. Please enter your name to see your ranking:` ); - + name==''? name='Superhero': name + dispatch(loadSorryImage()) dispatch(incorrectAnswer(pointsAwarded, name)); } }; @@ -73,22 +75,34 @@ export function restart() { dispatch(receiveQuestion({})); dispatch({ type: "RESTART" - }); + }) + dispatch(loadImage()) }; } -export function selectCategory(category){ - - return function(dispatch, getState){ - const options = getState().category.options - const selectedKey = Object.keys(options).find( +export function selectCategory(category) { + return function(dispatch, getState) { + const options = getState().category.options; + const selectedKey = Object.keys(options).find( key => options[key] === category ); dispatch({ - type:'SELECT_CATEGORY', - category:{[selectedKey]:category} + type: "SELECT_CATEGORY", + category: { [selectedKey]: category } }); dispatch(fetchQuestion(selectedKey)); + }; +} - }} +export function loadImage() { + return { + type:'LOAD_IMAGE' + } +} + +export function loadSorryImage() { + return { + type:'LOAD_SORRY_IMAGE' + } +} diff --git a/src/components/App.js b/src/components/App.js index 795fd5a..3ac05f8 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -5,12 +5,26 @@ import CategoryContainer from '../containers/CategoryContainer'; import '../style/App.scss'; class App extends React.Component { + render(){ + return (
    + + {!this.props.scores.gameOver ? +
    - {!this.props.scores.gameOver ? - :} + + +
    + + : +
    + + + +
    + }
    ) } diff --git a/src/components/ScoreTable.js b/src/components/ScoreTable.js index 46347aa..5d86f8e 100644 --- a/src/components/ScoreTable.js +++ b/src/components/ScoreTable.js @@ -1,14 +1,16 @@ import React from 'react'; +import '../style/ScoreTable.scss'; function ScoreTable({currentScore, allScores, restart}){ return(
    -
      +

      Quiz Citizens Premier League Table

      +
        {allScores.map(player => { return
      1. {player.name}: {player.score} points
      2. })} -
    +
    ) diff --git a/src/reducers/image.js b/src/reducers/image.js new file mode 100644 index 0000000..4794bc6 --- /dev/null +++ b/src/reducers/image.js @@ -0,0 +1,46 @@ +const startImages=[ + 'https://media.giphy.com/media/uFmMNcXaDNrMCzjCMq/giphy.gif', + 'https://media.giphy.com/media/KBx7fQoLxuV7G/giphy.gif', + 'https://media.giphy.com/media/5th0Kv3uoZkDC/giphy.gif', + 'https://media.giphy.com/media/3o6ZtePsqpjpew9Kzm/giphy.gif' +]; +const index = Math.floor(Math.random()*startImages.length); + +function image(state=startImages[index], action){ + + switch (action.type) { + case 'LOAD_IMAGE': + const images=[ + 'https://media.giphy.com/media/uFmMNcXaDNrMCzjCMq/giphy.gif', + 'https://media.giphy.com/media/KBx7fQoLxuV7G/giphy.gif', + 'https://media.giphy.com/media/5th0Kv3uoZkDC/giphy.gif', + 'https://media.giphy.com/media/3o6ZtePsqpjpew9Kzm/giphy.gif', + 'https://media.giphy.com/media/9B18cSkNiBW9i/giphy.gif', + 'https://media.giphy.com/media/GCvktC0KFy9l6/giphy.gif', + 'https://media.giphy.com/media/1zSiX3p2XEZpe/giphy.gif', + 'https://media.giphy.com/media/Dg0hzaN9wiEjS/giphy.gif', + 'https://media.giphy.com/media/xTiTnzEhdR9y9PNyc8/giphy.gif', + 'https://media.giphy.com/media/5oGIdt1xapQ76/giphy.gif' + ]; + const image = images[Math.floor(Math.random()*images.length)]; + + return state = image; + case 'LOAD_SORRY_IMAGE': + const sorryImages=[ + 'https://media.giphy.com/media/3o7aD4XavHnL5UsWEE/giphy.gif', + 'https://media.giphy.com/media/3ohs7Ys9J8XyFVheg0/giphy.gif', + 'https://media.giphy.com/media/kAC4na628Wljy/giphy.gif', + 'https://media.giphy.com/media/O6Hw3wYDqzUis/giphy.gif', + 'https://media.giphy.com/media/26BRzJmX5rH5Jbzuo/giphy.gif', + 'https://media.giphy.com/media/26xBziMPJcCmBbpVm/giphy.gif', + 'https://media.giphy.com/media/3oriOfZaIiMIf9pA6k/giphy.gif' + ] + const sorryImage = sorryImages[Math.floor(Math.random()*sorryImages.length)]; + return state = sorryImage; + default: + return state + } + +} + +export default image; diff --git a/src/reducers/index.js b/src/reducers/index.js index 8dc5100..f543ea6 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -2,9 +2,11 @@ import { combineReducers } from 'redux'; import question from './question'; import scores from './scores'; import category from './category'; +import image from './image'; export default combineReducers({ question, scores, - category + category, + image }); diff --git a/src/style/App.scss b/src/style/App.scss index 3586475..0ebf6dd 100644 --- a/src/style/App.scss +++ b/src/style/App.scss @@ -1,10 +1,10 @@ @import "parameters"; body{ - margin:0; + margin:$margin; } .wrapper{ font-family: $font-family; - background-color: $background-color; - + + } diff --git a/src/style/Category.scss b/src/style/Category.scss index b366837..0bb9b69 100644 --- a/src/style/Category.scss +++ b/src/style/Category.scss @@ -2,16 +2,17 @@ button{ @extend %button; - padding: $content-padding; + margin: 2px; - border-radius: 10%; + font-family: $font-family; + cursor: pointer; } .category{ display: grid; - grid-template-columns: 1fr 1fr 1fr ; + grid-template-columns: 50% 50%; font-size: $normal-font-size; } diff --git a/src/style/ScoreTable.scss b/src/style/ScoreTable.scss new file mode 100644 index 0000000..6f012b0 --- /dev/null +++ b/src/style/ScoreTable.scss @@ -0,0 +1,16 @@ +@import url('https://fonts.googleapis.com/css?family=Abril+Fatface'); + +ol { + list-style: none; + counter-reset: my-awesome-counter; +} +ol li { + counter-increment: my-awesome-counter; +} +ol li::before { + content: "0" counter(my-awesome-counter); + font-size: 2em; + margin-right: 0.5em; + font-family: 'Abril Fatface', serif; + font-weight: bold; +} diff --git a/src/style/_parameters.scss b/src/style/_parameters.scss index 3be1df5..e9101c5 100644 --- a/src/style/_parameters.scss +++ b/src/style/_parameters.scss @@ -1,6 +1,7 @@ $primary-color: #252525; $background-color: #ffffff; -$font-family: "Open Sans", sans-serif; +$font-family: 'Titillium Web',sans-serif; + //color scheme $border-color: #878e88; $font-color: #252726; @@ -18,11 +19,18 @@ $margin: 7px; $margin-double: 14px; %button { - background-color: #63B1C2; - color: white; + background-color: #0C0F0A; + color:#FFFFFF; + padding: 0.2em; + border:none; + font-family: $font-family; &:hover { - background-color: #16BAC5; + background-color: #FBFF12; transition: 0.3s; + color:#0C0F0A; } + font-weight: bold; + font-size: 1em; + } From fae36599352c0d5aa5af6df9dcff444b4c5238d9 Mon Sep 17 00:00:00 2001 From: Kate Date: Mon, 5 Nov 2018 00:02:59 +0000 Subject: [PATCH 5/5] heroku --- Procfile.js | 1 + package.json | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Procfile.js diff --git a/Procfile.js b/Procfile.js new file mode 100644 index 0000000..5b50a56 --- /dev/null +++ b/Procfile.js @@ -0,0 +1 @@ +// web: node server.js diff --git a/package.json b/package.json index 6572820..017f640 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "test": "jest", "dev": "webpack --mode development", - "build": "webpack --mode production" + "build": "webpack --mode production", + "heroku-postbuild":"npm run build" }, "author": "", "license": "ISC", @@ -41,5 +42,8 @@ "style-loader": "^0.23.1", "webpack": "^4.0.1", "webpack-cli": "^2.0.9" + }, + "engines": { + "node": "10.9.0" } }