diff --git a/__tests__/Layout.test.js b/__tests__/Layout.test.js
index 936fb35..4a4bf09 100644
--- a/__tests__/Layout.test.js
+++ b/__tests__/Layout.test.js
@@ -18,8 +18,14 @@ const patterns = [
codeES5: 'Code ES5 - Prototype',
codeES6: 'Code ES6 - Prototype',
answered: false,
- answerId: null,
- correct: null
+ correct: null,
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
},
{
@@ -29,8 +35,14 @@ const patterns = [
codeES5: 'Code ES5 - Singleton',
codeES6: 'Code ES6 - Singleton',
answered: false,
- answerId: null,
- correct: null
+ correct: null,
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
}
];
diff --git a/__tests__/middleware/submit.test.js b/__tests__/middleware/submit.test.js
index 101c630..812c8d1 100644
--- a/__tests__/middleware/submit.test.js
+++ b/__tests__/middleware/submit.test.js
@@ -12,8 +12,14 @@ const patterns = [
codeES5: 'Code ES5',
codeES6: 'Code ES6',
answered: false,
- answerId: null,
- correct: null
+ correct: null,
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
},
{
@@ -23,8 +29,14 @@ const patterns = [
codeES5: 'Code ES5',
codeES6: 'Code ES6',
answered: false,
- answerId: null,
- correct: null
+ correct: null,
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
}
];
@@ -45,23 +57,29 @@ describe('Submit middleware', () => {
payload: {
currentIndex: 0,
recentlyAnswered: {
- answerId: 'abc123',
answered: true,
correct: true,
name: 'Prototype',
type: 'creational',
- uuid: 'abc123'
+ uuid: 'abc123',
+ variantUuid: 'abc123'
},
remainingPatterns: [
{
- answerId: null,
answered: false,
codeES5: 'Code ES5',
codeES6: 'Code ES6',
correct: null,
name: 'Singleton',
type: 'creational',
- uuid: 'abc234'
+ uuid: 'abc234',
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
}
]
},
diff --git a/__tests__/pages/Game.test.js b/__tests__/pages/Game.test.js
index 9ae91c6..35ca10f 100644
--- a/__tests__/pages/Game.test.js
+++ b/__tests__/pages/Game.test.js
@@ -19,8 +19,14 @@ const patterns = [
codeES5: 'Code ES5 - Prototype',
codeES6: 'Code ES6 - Prototype',
answered: false,
- answerId: null,
- correct: null
+ correct: null,
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
},
{
@@ -30,8 +36,14 @@ const patterns = [
codeES5: 'Code ES5 - Singleton',
codeES6: 'Code ES6 - Singleton',
answered: false,
- answerId: null,
- correct: null
+ correct: null,
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
}
];
@@ -161,8 +173,15 @@ describe('Game page - RESULTS', () => {
codeES5: 'Code ES5 - Prototype',
codeES6: 'Code ES6 - Prototype',
answered: true,
- answerId: 'abc123',
- correct: true
+ correct: true,
+ variantUuid: 'abc123',
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
},
{
@@ -172,8 +191,15 @@ describe('Game page - RESULTS', () => {
codeES5: 'Code ES5 - Singleton',
codeES6: 'Code ES6 - Singleton',
answered: true,
- answerId: 'abc123',
- correct: false
+ correct: false,
+ variantUuid: 'abc123',
+ variants: [{
+ uuid: 'abc234',
+ name: 'SIngleton'
+ }, {
+ uuid: 'abc123',
+ name: 'Prototype'
+ }]
}
];
const store = mockStore({
@@ -215,7 +241,10 @@ describe('Game page - RESULTS', () => {
});
it('reacts to button click', () => {
- tree.find('button').simulate('click');
+ // button restart and 2 button with incorrect answers
+ expect(tree.find('button')).toHaveLength(3);
+ // button restart
+ tree.find('button#try_again').simulate('click');
const actions = store.getActions();
expect(actions).toMatchObject([{ type: RESTART }]);
});
diff --git a/__tests__/pages/__snapshots__/Game.test.js.snap b/__tests__/pages/__snapshots__/Game.test.js.snap
index bf29e24..1fd2330 100644
--- a/__tests__/pages/__snapshots__/Game.test.js.snap
+++ b/__tests__/pages/__snapshots__/Game.test.js.snap
@@ -4,7 +4,6 @@ exports[`Game page - GAME - DARK style renders a
component 1`] = `
component 1`] = `
"name": "Prototype",
"type": "creational",
"uuid": "abc123",
+ "variants": Array [
+ Object {
+ "name": "SIngleton",
+ "uuid": "abc234",
+ },
+ Object {
+ "name": "Prototype",
+ "uuid": "abc123",
+ },
+ ],
}
}
dispatch={[Function]}
@@ -364,7 +373,6 @@ exports[`Game page - GAME - DARK style renders a component 1`] =
remaining={
Array [
Object {
- "answerId": null,
"answered": false,
"codeES5": "Code ES5 - Singleton",
"codeES6": "Code ES6 - Singleton",
@@ -372,6 +380,16 @@ exports[`Game page - GAME - DARK style renders a component 1`] =
"name": "SIngleton",
"type": "creational",
"uuid": "abc234",
+ "variants": Array [
+ Object {
+ "name": "SIngleton",
+ "uuid": "abc234",
+ },
+ Object {
+ "name": "Prototype",
+ "uuid": "abc123",
+ },
+ ],
},
]
}
@@ -461,7 +479,6 @@ exports[`Game page - GAME - LIGHT style renders a
component 1`] = `
component 1`] = `
"name": "Prototype",
"type": "creational",
"uuid": "abc123",
+ "variants": Array [
+ Object {
+ "name": "SIngleton",
+ "uuid": "abc234",
+ },
+ Object {
+ "name": "Prototype",
+ "uuid": "abc123",
+ },
+ ],
}
}
dispatch={[Function]}
@@ -763,7 +790,6 @@ exports[`Game page - GAME - LIGHT style renders a component 1`]
remaining={
Array [
Object {
- "answerId": null,
"answered": false,
"codeES5": "Code ES5 - Singleton",
"codeES6": "Code ES6 - Singleton",
@@ -771,6 +797,16 @@ exports[`Game page - GAME - LIGHT style renders a component 1`]
"name": "SIngleton",
"type": "creational",
"uuid": "abc234",
+ "variants": Array [
+ Object {
+ "name": "SIngleton",
+ "uuid": "abc234",
+ },
+ Object {
+ "name": "Prototype",
+ "uuid": "abc123",
+ },
+ ],
},
]
}
@@ -987,7 +1023,6 @@ exports[`Game page - RESULTS renders a component 1`] = `
answers={
Array [
Object {
- "answerId": "abc123",
"answered": true,
"codeES5": "Code ES5 - Prototype",
"codeES6": "Code ES6 - Prototype",
@@ -995,9 +1030,19 @@ exports[`Game page - RESULTS renders a component 1`] = `
"name": "Prototype",
"type": "creational",
"uuid": "abc123",
+ "variantUuid": "abc123",
+ "variants": Array [
+ Object {
+ "name": "SIngleton",
+ "uuid": "abc234",
+ },
+ Object {
+ "name": "Prototype",
+ "uuid": "abc123",
+ },
+ ],
},
Object {
- "answerId": "abc123",
"answered": true,
"codeES5": "Code ES5 - Singleton",
"codeES6": "Code ES6 - Singleton",
@@ -1005,6 +1050,17 @@ exports[`Game page - RESULTS renders a component 1`] = `
"name": "SIngleton",
"type": "creational",
"uuid": "abc234",
+ "variantUuid": "abc123",
+ "variants": Array [
+ Object {
+ "name": "SIngleton",
+ "uuid": "abc234",
+ },
+ Object {
+ "name": "Prototype",
+ "uuid": "abc123",
+ },
+ ],
},
]
}
@@ -1078,7 +1134,6 @@ exports[`Game page - RESULTS renders a component 1`] = `
answers={
Array [
Object {
- "answerId": "abc123",
"answered": true,
"codeES5": "Code ES5 - Prototype",
"codeES6": "Code ES6 - Prototype",
@@ -1086,9 +1141,19 @@ exports[`Game page - RESULTS renders a component 1`] = `
"name": "Prototype",
"type": "creational",
"uuid": "abc123",
+ "variantUuid": "abc123",
+ "variants": Array [
+ Object {
+ "name": "SIngleton",
+ "uuid": "abc234",
+ },
+ Object {
+ "name": "Prototype",
+ "uuid": "abc123",
+ },
+ ],
},
Object {
- "answerId": "abc123",
"answered": true,
"codeES5": "Code ES5 - Singleton",
"codeES6": "Code ES6 - Singleton",
@@ -1096,6 +1161,17 @@ exports[`Game page - RESULTS renders a component 1`] = `
"name": "SIngleton",
"type": "creational",
"uuid": "abc234",
+ "variantUuid": "abc123",
+ "variants": Array [
+ Object {
+ "name": "SIngleton",
+ "uuid": "abc234",
+ },
+ Object {
+ "name": "Prototype",
+ "uuid": "abc123",
+ },
+ ],
},
]
}
diff --git a/__tests__/reducers/reducers.test.js b/__tests__/reducers/reducers.test.js
index 7e9a6f1..7a754c3 100644
--- a/__tests__/reducers/reducers.test.js
+++ b/__tests__/reducers/reducers.test.js
@@ -14,7 +14,6 @@ const answers = [
type: 'behavioral',
answered: true,
correct: true,
- answerId: 'ba2ca6b0-0c86-4573-baf0-60f33ce6e947',
uuid: 'ba2ca6b0-0c86-4573-baf0-60f33ce6e947'
},
{
@@ -22,7 +21,6 @@ const answers = [
type: 'behavioral',
answered: false,
correct: null,
- answerId: null,
uuid: 'eb9427c5-0167-4d65-a99b-a5ffadf5fd46'
},
{
@@ -30,7 +28,6 @@ const answers = [
type: 'creational',
answered: false,
correct: null,
- answerId: null,
uuid: 'slearknbqarlnbqasOLdnv'
}
];
diff --git a/src/components/Button.jsx b/src/components/Button.jsx
index 92e2ca9..b7038ef 100644
--- a/src/components/Button.jsx
+++ b/src/components/Button.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import styled from 'styled-components';
const StyledButton = styled.button`
- background-color: ${props => props.theme.buttonBackground};
+ background-color: ${props => props.buttonBackground || props.theme.buttonBackground};
border: 1px solid ${props => props.theme.buttonBorder};
border-radius: 4px;
cursor: pointer;
@@ -19,7 +19,7 @@ const StyledButton = styled.button`
}
&:hover {
- background-color: ${props => props.theme.buttonBackgroundHover};
+ background-color: ${props => props.buttonBackgroundHover || props.theme.buttonBackgroundHover};
border-color: ${props => props.theme.buttonBorderHover};
& span {
@@ -28,20 +28,23 @@ const StyledButton = styled.button`
}
`;
-export const Button = props => {
- const { id, label, onClick } = props;
-
- return (
-
- {label && {label}}
-
- );
-};
+export const Button = ({ id, label, onClick = () => {}, buttonBackground, buttonBackgroundHover }) => (
+
+ {label && {label}}
+
+);
Button.propTypes = {
- label: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
- onClick: PropTypes.func.isRequired
+ label: PropTypes.string.isRequired,
+ onClick: PropTypes.func,
+ buttonBackground: PropTypes.string,
+ buttonBackgroundHover: PropTypes.string
};
export default Button;
diff --git a/src/components/ButtonContainer.jsx b/src/components/ButtonContainer.jsx
index 06018a8..2e862d0 100644
--- a/src/components/ButtonContainer.jsx
+++ b/src/components/ButtonContainer.jsx
@@ -4,8 +4,7 @@ import styled from 'styled-components';
import { connect } from 'react-redux';
import Button from './Button';
import { submitAnswer } from '../actions/submitAnswer';
-import { getCurrent, getPatterns } from '../selectors';
-import { shuffle } from '../helpers/shuffleArray';
+import { getCurrent } from '../selectors';
const StyledButtonContainer = styled.div`
align-content: space-around;
@@ -16,34 +15,22 @@ const StyledButtonContainer = styled.div`
margin: 1rem 0 2rem;
`;
-export const ButtonContainer = props => {
- const { current, patterns, onSubmitAnswer } = props;
-
- // get 3 random patterns in addition to correct one
- const allOtherAnswers = patterns.filter(pattern => pattern.uuid !== current.uuid);
- const additional = shuffle(allOtherAnswers).slice(0, 3);
- // shuffle the 4 answers
- const variants = shuffle([current, ...additional]);
-
- return (
-
- {variants.map(({ uuid, name }) => (
-
- );
-};
+export const ButtonContainer = ({ current, onSubmitAnswer }) => (
+
+ {current.variants.map(({ uuid, name }) => (
+
+);
ButtonContainer.propTypes = {
- patterns: PropTypes.array.isRequired,
current: PropTypes.object.isRequired,
onSubmitAnswer: PropTypes.func.isRequired
};
export default connect(
state => ({
- current: getCurrent(state),
- patterns: getPatterns(state)
+ current: getCurrent(state)
}),
{
onSubmitAnswer: id => submitAnswer(id)
diff --git a/src/components/Code.jsx b/src/components/Code.jsx
index 558698c..89b4a01 100644
--- a/src/components/Code.jsx
+++ b/src/components/Code.jsx
@@ -7,25 +7,21 @@ import { getJS, getCurrent } from '../selectors';
SyntaxHighlighter.registerLanguage('javascript', js);
-const Code = props => {
- const { js, current, style } = props;
+export const Code = ({ js, current, style }) => (
+
+ {js === 'es5' && (
+
+ {current.codeES5}
+
+ )}
- return (
-
- {js === 'es5' && (
-
- {current.codeES5}
-
- )}
-
- {js === 'es6' && (
-
- {current.codeES6}
-
- )}
-
- );
-};
+ {js === 'es6' && (
+
+ {current.codeES6}
+
+ )}
+
+);
Code.propTypes = {
js: PropTypes.string.isRequired,
diff --git a/src/components/IncorrectAnswers.jsx b/src/components/IncorrectAnswers.jsx
new file mode 100644
index 0000000..b278d72
--- /dev/null
+++ b/src/components/IncorrectAnswers.jsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { getAnswers, getPatterns } from '../selectors';
+import IncorrectCode from './IncorrectCode';
+
+export const IncorrectAnswers = ({ answers, style }) => {
+ const incorrectAnswers = answers.filter(answer => !answer.correct);
+
+ return incorrectAnswers.map(({ uuid }) => (
+
+ ));
+};
+
+IncorrectAnswers.propTypes = {
+ answers: PropTypes.array.isRequired,
+ style: PropTypes.object.isRequired
+};
+
+export default connect(state => ({
+ answers: getAnswers(state),
+ patterns: getPatterns(state)
+}))(IncorrectAnswers);
diff --git a/src/components/IncorrectCode.jsx b/src/components/IncorrectCode.jsx
new file mode 100644
index 0000000..fcd7952
--- /dev/null
+++ b/src/components/IncorrectCode.jsx
@@ -0,0 +1,87 @@
+import React, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import styled from 'styled-components';
+import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
+import js from 'react-syntax-highlighter/dist/languages/hljs/javascript';
+import Button from './Button';
+import { getJS, getPatterns, getAnswers } from '../selectors';
+import { ATLANTIS, CRIMSON } from '../static/constants/colors';
+
+SyntaxHighlighter.registerLanguage('javascript', js);
+
+const StyledButtonContainer = styled.div`
+ align-content: space-around;
+ display: flex;
+ flex-wrap: wrap;
+ height: 9rem;
+ justify-content: space-around;
+ margin: 1rem 0 2rem;
+`;
+
+const Code = ({ answers, uuid, patterns, js, style }) => {
+ const currentAnswer = answers.find(pattern => pattern.uuid === uuid);
+ const currentPattern = patterns.find(pattern => pattern.uuid === uuid);
+
+ if (!currentAnswer) {
+ return null;
+ }
+
+ return (
+
+
+ {js === 'es5' ? currentPattern.codeES5 : currentPattern.codeES6}
+
+
+ {currentPattern.variants.map(({ uuid, name }) => {
+ // correct answer
+ if (uuid === currentAnswer.uuid) {
+ return (
+
+ );
+ }
+ // chosen but incorrect answer
+ if (uuid === currentAnswer.variantUuid) {
+ return (
+
+ );
+ }
+ // not chosen, incorrect answers
+ return (
+
+ );
+ })}
+
+
+ );
+};
+
+Code.propTypes = {
+ answers: PropTypes.array.isRequired,
+ js: PropTypes.string.isRequired,
+ patterns: PropTypes.array.isRequired,
+ style: PropTypes.object.isRequired,
+ uuid: PropTypes.string.isRequired
+};
+
+export default connect(state => ({
+ answers: getAnswers(state),
+ js: getJS(state),
+ patterns: getPatterns(state)
+}))(Code);
diff --git a/src/middleware/submit.js b/src/middleware/submit.js
index 9a7c5d5..e39e0a6 100644
--- a/src/middleware/submit.js
+++ b/src/middleware/submit.js
@@ -14,8 +14,8 @@ export const submitMiddleware = ({ getState }) => next => action => {
const recentlyAnswered = {
...filtered,
+ variantUuid: action.payload,
answered: true,
- answerId: action.payload,
correct: action.payload === progress.current.uuid
};
diff --git a/src/pages/Game.jsx b/src/pages/Game.jsx
index 062c063..5fe66be 100644
--- a/src/pages/Game.jsx
+++ b/src/pages/Game.jsx
@@ -10,6 +10,7 @@ import ProgressBar from '../components/ProgressBar';
import Code from '../components/Code';
import Result from '../components/Result';
import Percentage from '../components/Percentage';
+import IncorrectAnswers from '../components/IncorrectAnswers';
import Button from '../components/Button';
const Intro = styled.div`
@@ -87,6 +88,7 @@ const Game = ({ intro, current, answers, style, onStart, onRestart }) => {
+
({
- ...pattern,
- answered: false,
- correct: null,
- answerId: null,
- uuid: uuid()
-}));
+const patternsWithUuids = patterns.map(pattern => ({ ...pattern, uuid: uuid() }));
+export const answers = patternsWithUuids.map(current => {
+ // get 3 random patterns in addition to correct one
+ const allOtherAnswers = patternsWithUuids.filter(pattern => pattern.uuid !== current.uuid);
+ const additional = shuffle(allOtherAnswers).slice(0, 3);
+ // shuffle the 4 answers
+ const variants = shuffle([current, ...additional]);
+
+ return {
+ ...current,
+ // ButtonContainer needs only name and uuid
+ variants: variants.map(({ name, uuid }) => ({ name, uuid })),
+ answered: false,
+ correct: null
+ };
+});
export const initialProgress = {
answers: [],
diff --git a/stories/Percentage.stories.js b/stories/Percentage.stories.js
index a8c1be3..d634f21 100644
--- a/stories/Percentage.stories.js
+++ b/stories/Percentage.stories.js
@@ -8,7 +8,6 @@ const initialArray = (n, isAnswered, isCorrect) => {
return arr.map((x, i) => {
return {
patternId: null,
- answerId: null,
answered: isAnswered,
correct: isCorrect,
uuid: i
diff --git a/stories/ProgressBar.stories.js b/stories/ProgressBar.stories.js
index 7084cbf..9f2d6f8 100644
--- a/stories/ProgressBar.stories.js
+++ b/stories/ProgressBar.stories.js
@@ -8,7 +8,6 @@ const initialArray = (n, isAnswered, isCorrect) => {
return arr.map((x, i) => {
return {
patternId: null,
- answerId: null,
answered: isAnswered,
correct: isCorrect,
uuid: i