diff --git a/README.md b/README.md index 34ce288..c827dc9 100644 --- a/README.md +++ b/README.md @@ -1 +1,8 @@ Projet de quizz + +Il est plus simple de raisonner avec un state un peu centralisé et de le faire +passer dans les props. + +Une correction est présente dans le quiz-react.zip + +:) diff --git a/quiz-react.zip b/quiz-react.zip new file mode 100644 index 0000000..a2148e1 Binary files /dev/null and b/quiz-react.zip differ diff --git a/src/App.js b/src/App.js index 497bc0b..76d8f5c 100644 --- a/src/App.js +++ b/src/App.js @@ -1,77 +1,96 @@ -import React, { Component } from 'react'; -import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; +import React, { Component } from "react"; +import MuiThemeProvider from "material-ui/styles/MuiThemeProvider"; // import './App.css'; import quiz from "./exo_quiz_react.json"; -import Gabarit from './components/Layout'; +import Gabarit from "./components/Layout"; import Titre from "./components/titre"; import Navigation from "./components/navigation"; import Question from "./components/Question"; -import Valider from './components/Valider'; +import Valider from "./components/Valider"; class App extends Component { - constructor(props){ - super(props) - this.current = this.current.bind(this) - this.valider = this.valider.bind(this) + constructor(props) { + super(props); + // pour éviter les bind on peut utiliser les fonctions fléchée + this.valider = this.valider.bind(this); } + state = { current: 0, validate: false - } - - current(c) { + }; + + // current(c) { + // this.setState({ + // current: c, + // validate: false + // }); + // } + + current = c => this.setState({ current: c, validate: false - }) - } + }); - valider(){ - if (this.display_correction) this.setState({validate: true}) + valider() { + if (this.display_correction) this.setState({ validate: true }); } get question() { const question = quiz.questions[this.state.current]; return { - ...question, - params: {...quiz.default_params, ...question.params}, - } + ...question, + params: { ...quiz.default_params, ...question.params } + }; } get display_correction() { - return this.question.params.display_correction + return this.question.params.display_correction; } render() { - const title = ( - - ) + // pas vraiment nécessaire de stocker dans des variables. + // on peut les passer directement dans les props. + // ou en tant qu'enfant de Gabarit + const title = ; const navigation = ( - - ) + + ); const question = ( - - ) + + ); const valider = ( - - ) + ); return ( - } + navigation={navigation} + question={question} + valider={valider} /> + {/* + + + + + + + */} ); } diff --git a/src/components/Layout.js b/src/components/Layout.js index 6997c1c..dfc8640 100644 --- a/src/components/Layout.js +++ b/src/components/Layout.js @@ -1,26 +1,24 @@ -import React from 'react'; -import Paper from 'material-ui/Paper'; +import React from "react"; +import Paper from "material-ui/Paper"; const styleQuiz = { height: 550, width: 520, - margin: 'auto', + margin: "auto", padding: 20, - display: 'block', - textAlign: 'center', + display: "block", + textAlign: "center" }; -const Gabarit = (props) => { -return ( - +const Gabarit = props => { + return ( + {props.title} {props.navigation} - - {props.question} - - {props.valider} + {props.question} + {props.valider} - ) -} + ); +}; -export default Gabarit; \ No newline at end of file +export default Gabarit; diff --git a/src/components/Question/choix-check.js b/src/components/Question/choix-check.js index d5af7ad..431b478 100644 --- a/src/components/Question/choix-check.js +++ b/src/components/Question/choix-check.js @@ -1,73 +1,68 @@ -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; -import Checkbox from 'material-ui/Checkbox'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import Checkbox from "material-ui/Checkbox"; export default class ChoixCheck extends Component { - constructor(props){ - super(props) - this.onChange = this.onChange.bind(this) - } + constructor(props) { + super(props); + this.onChange = this.onChange.bind(this); + } - state = {} + state = {}; - componentWillMount() { - this.props.answers.forEach( answer => { - this.setState ({ - [answer.text]: {checked: false} - }) - }) - } + componentWillMount() { + this.props.answers.forEach(answer => { + this.setState({ + [answer.text]: { checked: false } + }); + }); + } - componentWillReceiveProps(nextProps) { - if (nextProps.uuid !== this.props.uuid) { - nextProps.answers.forEach( answer => { - this.setState ({ - [answer.text]: {checked: false} - }) - }) - } - } - - onChange(e) { - const val = e.target.id; + componentWillReceiveProps(nextProps) { + if (nextProps.uuid !== this.props.uuid) { + nextProps.answers.forEach(answer => { this.setState({ - [val]: {checked: !this.state[val].checked} - }) - } - - get answers(){ - const {validate} = this.props; - const answers = this.props.answers.map( answer => { - const {text, is_correct} = answer; - const style = validate - ? {color: is_correct ? 'green' : 'red'} - : {color: 'inherit'}; - const checked = this.state[text] && this.state[text].checked; - return ( - - )} - ); - return answers; - } - render(){ - return( -
- {this.answers} -
- - ) + [answer.text]: { checked: false } + }); + }); } -}; + } + + onChange(e) { + const val = e.target.id; + this.setState({ + [val]: { checked: !this.state[val].checked } + }); + } + + get answers() { + const { validate } = this.props; + const answers = this.props.answers.map(answer => { + const { text, is_correct } = answer; + const style = validate + ? { color: is_correct ? "green" : "red" } + : { color: "inherit" }; + const checked = this.state[text] && this.state[text].checked; + return ( + + ); + }); + return answers; + } + render() { + return
{this.answers}
; + } +} ChoixCheck.propTypes = { - uuid: PropTypes.string, - answers: PropTypes.array, - validate: PropTypes.bool, - }; \ No newline at end of file + uuid: PropTypes.string, + answers: PropTypes.array, + validate: PropTypes.bool +}; diff --git a/src/components/Question/choix-radio.js b/src/components/Question/choix-radio.js index 071d3fc..c681088 100644 --- a/src/components/Question/choix-radio.js +++ b/src/components/Question/choix-radio.js @@ -1,79 +1,76 @@ -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; -import {RadioButton, RadioButtonGroup} from 'material-ui/RadioButton'; -import CheckBoxOutlineBlank from 'material-ui/svg-icons/toggle/check-box-outline-blank'; -import CheckBox from 'material-ui/svg-icons/toggle/check-box'; +import { RadioButton, RadioButtonGroup } from "material-ui/RadioButton"; +import CheckBoxOutlineBlank from "material-ui/svg-icons/toggle/check-box-outline-blank"; +import CheckBox from "material-ui/svg-icons/toggle/check-box"; export default class ChoixRadio extends Component { - constructor(props){ - super(props) - this.onChange = this.onChange.bind(this) - } + constructor(props) { + super(props); + this.onChange = this.onChange.bind(this); + } - state = { - option: '' - } + state = { + option: "" + }; - componentWillMount() { - this.props.answers.forEach( answer => { - this.setState ({ - [answer.text]: {checked: false} - }) - }) - } + componentWillMount() { + this.props.answers.forEach(answer => { + this.setState({ + [answer.text]: { checked: false } + }); + }); + } - componentWillReceiveProps(nextProps) { - if (nextProps.uuid !== this.props.uuid) { - nextProps.answers.forEach( answer => { - this.setState ({ - [answer.text]: {checked: false} - }) - }) - } - } - - onChange(e, v) { - this.setState({option: v}) + componentWillReceiveProps(nextProps) { + if (nextProps.uuid !== this.props.uuid) { + nextProps.answers.forEach(answer => { + this.setState({ + [answer.text]: { checked: false } + }); + }); } + } - get answers() { - const {validate} = this.props; - const answers = this.props.answers.map( answer => { - const {text, is_correct} = answer; - const style = validate - ? {color: is_correct ? 'green' : 'red'} - : {color: 'inherit'}; + onChange(e, v) { + this.setState({ option: v }); + } - return( - } - uncheckedIcon={} - value={text} - label={text} - labelStyle={style} - /> - ); - }) - return answers; - } + get answers() { + const { validate } = this.props; + const answers = this.props.answers.map(answer => { + const { text, is_correct } = answer; + const style = validate + ? { color: is_correct ? "green" : "red" } + : { color: "inherit" }; - render() { - return( - - {this.answers} - - - ) - } -}; + return ( + } + uncheckedIcon={} + value={text} + label={text} + labelStyle={style} + /> + ); + }); + return answers; + } + + render() { + return ( + + {this.answers} + + ); + } +} ChoixRadio.propTypes = { - uuid: PropTypes.string, - answers: PropTypes.array, - validate: PropTypes.bool, - }; \ No newline at end of file + uuid: PropTypes.string, + answers: PropTypes.array, + validate: PropTypes.bool +}; diff --git a/src/components/Question/index.js b/src/components/Question/index.js index c17188a..54518e6 100644 --- a/src/components/Question/index.js +++ b/src/components/Question/index.js @@ -1,31 +1,26 @@ -import React from 'react'; -import Divider from 'material-ui/Divider'; -import {Card, CardTitle, CardActions} from 'material-ui/Card'; +import React from "react"; +import Divider from "material-ui/Divider"; +import { Card, CardTitle, CardActions } from "material-ui/Card"; import ChoixCheck from "./choix-check"; import ChoixRadio from "./choix-radio"; - -export default function Question(props) { - const {params, image, text, answers, uuid, validate} = props; - const {multiple_choices} = params; - - return ( - - - {image && } - - - {multiple_choices - ? - : - } - - - ) -}; + +export default function Question(props) { + const { params, image, text, answers, uuid, validate } = props; + const { multiple_choices } = params; + + return ( + + + {image && } + + + {multiple_choices ? ( + + ) : ( + + )} + + + ); +} diff --git a/src/components/Valider.js b/src/components/Valider.js index fbf1e75..c3713a9 100644 --- a/src/components/Valider.js +++ b/src/components/Valider.js @@ -1,16 +1,28 @@ -import React from 'react'; -import RaisedButton from 'material-ui/RaisedButton'; +import React from "react"; +import RaisedButton from "material-ui/RaisedButton"; export default function ValiderButton(props) { - const {valider, display_correction} = props; - return ( - - ) + const { valider, display_correction } = props; + return ( + + ); } + +// ce type de composant peut être simplifier au niveau de l'écriture: +const ValiderButtonRefacto = ({ valider, display_correction }) => ( + +); diff --git a/src/components/navigation.js b/src/components/navigation.js index 63212c7..4660ce7 100644 --- a/src/components/navigation.js +++ b/src/components/navigation.js @@ -1,73 +1,81 @@ -import React , {Component} from 'react'; -import PropTypes from 'prop-types'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; -import RaisedButton from 'material-ui/RaisedButton'; -import {GridList} from 'material-ui/GridList'; +import RaisedButton from "material-ui/RaisedButton"; +import { GridList } from "material-ui/GridList"; export default class Navigation extends Component { - constructor(props) { - super(props); - this.prec = this.prec.bind(this) - this.next = this.next.bind(this) - } + static propTypes = { + current: PropTypes.func, + qte: PropTypes.number + }; - state = { - index: 0, - prec: false, - next: 1, - } - - prec() { - const {index} = this.state; - const prec = (index > 1); - const nextIndex = (prec) ? index - 1 : 0; - this.setState({ - index: nextIndex, - prec, - next: true - }); - this.props.current(nextIndex) - } - next() { - const {index} = this.state; - const next = (index < this.len - 1); - const nextIndex = (next) ? index + 1 : this.len; - this.setState({ - index: nextIndex, - next, - prec: true - }); - this.props.current(nextIndex) - } + constructor(props) { + super(props); + this.prec = this.prec.bind(this); + this.next = this.next.bind(this); + } - get len() { - return this.props.qte - 1; - } + // Sur ce genre d'appli il est plus intéressant d'avoir le state dans le composant App et de faire tout passer en props + state = { + index: 0, + prec: false, + next: 1 + }; - render() { - const {prec, next} = this.state; - return ( - - - - - ) - } -}; + prec() { + const { index } = this.state; + const prec = index > 1; + const nextIndex = prec ? index - 1 : 0; + this.setState({ + index: nextIndex, + prec, + next: true + }); + this.props.current(nextIndex); + } + next() { + const { index } = this.state; + const next = index < this.len - 1; + const nextIndex = next ? index + 1 : this.len; + this.setState({ + index: nextIndex, + next, + prec: true + }); + this.props.current(nextIndex); + } -Navigation.propTypes = { - current: PropTypes.func, - qte: PropTypes.number, - }; \ No newline at end of file + get len() { + return this.props.qte - 1; + } + + render() { + const { prec, next } = this.state; + return ( + + + + + ); + } +} + +// peut être directement écrit dans la classe en static + +// Navigation.propTypes = { +// current: PropTypes.func, +// qte: PropTypes.number +// }; diff --git a/src/components/titre.js b/src/components/titre.js index 3bd13de..e6025b8 100644 --- a/src/components/titre.js +++ b/src/components/titre.js @@ -1,7 +1,8 @@ -import React from 'react'; +import React from "react"; export default function Titre(props) { - return ( -

{props.title}

- ) -} \ No newline at end of file + return

{props.title}

; +} + +// ce type de composant peut être simplifier au niveau de l'écriture: +const TitreRefacto = ({ title }) =>

{props.title}

; diff --git a/src/index.js b/src/index.js index 68a3401..89a839f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,9 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import registerServiceWorker from './registerServiceWorker'; +import React from "react"; +import ReactDOM from "react-dom"; +import registerServiceWorker from "./registerServiceWorker"; -import './index.css'; -import App from './App'; +import "./index.css"; +import App from "./App"; -ReactDOM.render( - , - document.getElementById('root') -); +ReactDOM.render(, document.getElementById("root")); registerServiceWorker();