From 7876bfed9f89ebe8420bda9b54def656f8880681 Mon Sep 17 00:00:00 2001 From: Johan Girod Date: Thu, 6 Jun 2019 16:33:06 +0200 Subject: [PATCH] =?UTF-8?q?:art:=20am=C3=A9liore=20l'UI=20/=20UX=20sur=20l?= =?UTF-8?q?es=20questions=20pos=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/components/PaySlip.js | 23 --- source/components/QuickLinks.js | 7 +- .../components/SalaryCompactExplanation.css | 31 ---- source/components/SalaryCompactExplanation.js | 59 ------- source/components/SalaryExplanation.js | 109 +++++++----- source/components/SalaryFirstExplanation.js | 40 ----- source/components/SchemeComparaison.js | 2 + source/components/Simulation.js | 39 ++++- source/components/{ => conversation}/Aide.css | 0 source/components/{ => conversation}/Aide.js | 2 +- .../{ => conversation}/AnswerList.css | 0 .../{ => conversation}/AnswerList.js | 2 +- .../components/conversation/Conversation.js | 159 +++++++----------- .../conversation/ResultReliability.js | 31 ++++ .../conversation/SeeAnswersButton.js | 23 +++ source/components/ui/Button/button.css | 1 + source/components/ui/Checklist/index.css | 4 +- source/components/ui/Progress.css | 3 +- source/components/ui/Progress.js | 4 +- source/components/ui/animate.js | 7 +- source/components/ui/index.css | 2 +- source/règles/base.yaml | 4 +- source/selectors/analyseSelectors.js | 3 +- 23 files changed, 231 insertions(+), 324 deletions(-) delete mode 100644 source/components/SalaryCompactExplanation.css delete mode 100644 source/components/SalaryCompactExplanation.js delete mode 100644 source/components/SalaryFirstExplanation.js rename source/components/{ => conversation}/Aide.css (100%) rename source/components/{ => conversation}/Aide.js (97%) rename source/components/{ => conversation}/AnswerList.css (100%) rename source/components/{ => conversation}/AnswerList.js (98%) create mode 100644 source/components/conversation/ResultReliability.js create mode 100644 source/components/conversation/SeeAnswersButton.js diff --git a/source/components/PaySlip.js b/source/components/PaySlip.js index 7fc8ebb7d..d2b935228 100644 --- a/source/components/PaySlip.js +++ b/source/components/PaySlip.js @@ -151,29 +151,6 @@ const PaySlip = ({ {salaireNetAprèsImpôt.montant} -
-

- - Le simulateur vous aide à comprendre votre bulletin de paie, sans lui - être opposable. Pour plus d'informations, rendez vous sur  - - service-public.fr - - . - -

-

- - Il ne prend pour l'instant pas en compte les accords et conventions - collectives, ni la myriade d'aides aux entreprises. Trouvez votre - convention collective{' '} - ici - , et explorez les aides sur  - aides-entreprises.fr. - -

) } diff --git a/source/components/QuickLinks.js b/source/components/QuickLinks.js index 2b28855f8..5fb0df7c8 100644 --- a/source/components/QuickLinks.js +++ b/source/components/QuickLinks.js @@ -28,9 +28,8 @@ const QuickLinks = ({ goToQuestion, quickLinks, quickLinksToHide }: Props) => { reject(dottedName => contains(dottedName, quickLinksToHide)) )(quickLinks) return ( -

- Répondre à une question précise : -
+ + Autres questions : {links.map(([label, dottedName]) => ( <> */} -

+ ) } diff --git a/source/components/SalaryCompactExplanation.css b/source/components/SalaryCompactExplanation.css deleted file mode 100644 index e7d89de65..000000000 --- a/source/components/SalaryCompactExplanation.css +++ /dev/null @@ -1,31 +0,0 @@ -.result-view__tabs { - display: flex; - align-items: center; - box-shadow: 0 -1px 0 0 #d4d4d5, 1px 0 0 0 #d4d4d5, -1px 0 0 0 #d4d4d5; - border-top-right-radius: 0.6em; - border: none; - border-top-left-radius: 0.6em; - margin-bottom: -1px; - border-bottom: 1px solid transparent; -} -.result-view__tabs button { - padding: 1em !important; - border-right: 1px solid #d4d4d5 !important; - text-decoration: none !important; -} -.result-view__tabs button.selected { - border-bottom: 1px solid white; -} -.result-view__tabs button:last-of-type { - border-right: none !important; -} -.result-view__header { - margin-top: 2em; - display: flex; - justify-content: space-between; -} - -.result-view__body { - border-top-left-radius: 0 !important; - margin-bottom: 2em; -} diff --git a/source/components/SalaryCompactExplanation.js b/source/components/SalaryCompactExplanation.js deleted file mode 100644 index 7b5fff224..000000000 --- a/source/components/SalaryCompactExplanation.js +++ /dev/null @@ -1,59 +0,0 @@ -/* @flow */ - -import Distribution from 'Components/Distribution' -import PaySlip from 'Components/PaySlip' -import SearchButton from 'Components/SearchButton' -import React, { Component } from 'react' -import { Trans } from 'react-i18next' -import './SalaryCompactExplanation.css' - -import type { Tracker } from 'Components/utils/withTracker' - -type ResultView = 'distribution' | 'payslip' -type State = { - resultView: ResultView -} -type Props = { - tracker: Tracker, - displayResults: boolean -} - -const resultViewTitle = { - distribution: 'Cotisations', - payslip: 'Fiche de paie' -} - -export default class SalaryCompactExplanation extends Component { - state = { - resultView: 'payslip' - } - handleClickOnTab = (resultView: ResultView) => () => { - this.setState({ resultView }) - this.props.tracker.push(['trackEvent', 'results', 'selectView', resultView]) - } - render() { - return ( - <> -
-
- {['payslip', 'distribution'].map(resultView => ( - - ))} -
- -
-
- {this.state.resultView === 'payslip' ? : } -
- - ) - } -} diff --git a/source/components/SalaryExplanation.js b/source/components/SalaryExplanation.js index 1dbc8baa1..c9a80c947 100644 --- a/source/components/SalaryExplanation.js +++ b/source/components/SalaryExplanation.js @@ -1,51 +1,78 @@ -import { React, T } from 'Components' -import PageFeedback from 'Components/Feedback/PageFeedback' +import Distribution from 'Components/Distribution' +import PaySlip from 'Components/PaySlip' import withTracker from 'Components/utils/withTracker' import { compose } from 'ramda' +import React from 'react' +import { Trans } from 'react-i18next' import { connect } from 'react-redux' +import { formValueSelector } from 'redux-form' import * as Animate from 'Ui/animate' -import SalaryCompactExplanation from './SalaryCompactExplanation' -import SalaryFirstExplanation from './SalaryFirstExplanation' export default compose( withTracker, connect(state => ({ - showCompactView: !!state.conversationSteps.foldedSteps.length + showDistributionFirst: !state.conversationSteps.foldedSteps.length })) -)( - class SalaryExplanation extends React.Component { - render() { - return ( - - {!this.props.showCompactView ? ( - <> - {/* - Êtes-vous satisfait de ce simulateur ? - - } - customEventName="rate simulator" - /> */} - - {this.props.protectionText} - - ) : ( - <> - - - Êtes-vous satisfait de ce simulateur ? - - } - customEventName="rate simulator" - /> - - )} -
- - ) - } - } +)(function SalaryExplanation({ showDistributionFirst }) { + return ( + + {showDistributionFirst ? ( + <> + + + + ) : ( + <> + + + + )} +

+ + Le simulateur vous aide à comprendre votre bulletin de paie, sans lui + être opposable. Pour plus d'informations, rendez vous sur  + + service-public.fr + + . + +

+

+ + Il ne prend pour l'instant pas en compte les accords et conventions + collectives, ni la myriade d'aides aux entreprises. Trouvez votre + convention collective{' '} + ici + , et explorez les aides sur  + aides-entreprises.fr. + +

+
+ ) +}) + +const PaySlipSection = connect(state => ({ + period: formValueSelector('conversation')(state, 'période') +}))(({ period }) => ( +
+

+ + {period === 'mois' + ? 'Fiche de paie mensuelle' + : 'Détail annuel des cotisations'} + +

+ +
+)) + +const DistributionSection = () => ( +
+

+ À quoi servent mes cotisations ? +

+ +
) diff --git a/source/components/SalaryFirstExplanation.js b/source/components/SalaryFirstExplanation.js deleted file mode 100644 index f2eb97e40..000000000 --- a/source/components/SalaryFirstExplanation.js +++ /dev/null @@ -1,40 +0,0 @@ -/* @flow */ - -import Distribution from 'Components/Distribution' -import PaySlip from 'Components/PaySlip' -import React, { Component } from 'react' -import { Trans } from 'react-i18next' -import { connect } from 'react-redux' -// $FlowFixMe -import { formValueSelector } from 'redux-form' - -type OwnProps = {} -type Props = OwnProps & { - period: 'mois' | 'année' -} - -export default (connect(state => ({ - period: formValueSelector('conversation')(state, 'période') -}))( - class SalaryFirstExplanation extends Component { - render() { - return ( - <> -

- À quoi servent mes cotisations ? -

- - -

- - {this.props.period === 'mois' - ? 'Fiche de paie mensuelle' - : 'Détail annuel des cotisations'} - -

- - - ) - } - } -): React$ComponentType) diff --git a/source/components/SchemeComparaison.js b/source/components/SchemeComparaison.js index f43614968..637fa1070 100644 --- a/source/components/SchemeComparaison.js +++ b/source/components/SchemeComparaison.js @@ -7,6 +7,7 @@ import { import classnames from 'classnames' import { T } from 'Components' import Conversation from 'Components/conversation/Conversation' +import SeeAnswersButton from 'Components/conversation/SeeAnswersButton' import PeriodSwitch from 'Components/PeriodSwitch' // $FlowFixMe import ComparaisonConfig from 'Components/simulationConfigs/rémunération-dirigeant.yaml' @@ -206,6 +207,7 @@ const SchemeComparaison = ({ ) : (
+
)} diff --git a/source/components/Simulation.js b/source/components/Simulation.js index db1780286..ae70224b7 100644 --- a/source/components/Simulation.js +++ b/source/components/Simulation.js @@ -1,29 +1,52 @@ import Controls from 'Components/Controls' import Conversation from 'Components/conversation/Conversation' +import ResultReliability from 'Components/conversation/ResultReliability' +import SeeAnswersButton from 'Components/conversation/SeeAnswersButton' import TargetSelection from 'Components/TargetSelection' import React from 'react' -import emoji from 'react-easy-emoji' import { connect } from 'react-redux' import { firstStepCompletedSelector } from 'Selectors/analyseSelectors' +import { simulationProgressSelector } from 'Selectors/progressSelectors' +import * as Animate from 'Ui/animate' +import Progress from 'Ui/Progress' export default connect(state => ({ - firstStepCompleted: firstStepCompletedSelector(state) + firstStepCompleted: firstStepCompletedSelector(state), + progress: simulationProgressSelector(state) }))(function Simulation({ firstStepCompleted, explanations, - customEndMessages + customEndMessages, + progress }) { return ( <> {firstStepCompleted && ( <> - -

{emoji('📝 ')}Votre simulation

- <> - + +
+ + +
+
+
+ + +
+
+ {progress < 1 && ( + + )} {explanations} - +
)} diff --git a/source/components/Aide.css b/source/components/conversation/Aide.css similarity index 100% rename from source/components/Aide.css rename to source/components/conversation/Aide.css diff --git a/source/components/Aide.js b/source/components/conversation/Aide.js similarity index 97% rename from source/components/Aide.js rename to source/components/conversation/Aide.js index 4a1a40547..82fe4716a 100644 --- a/source/components/Aide.js +++ b/source/components/conversation/Aide.js @@ -6,8 +6,8 @@ import { compose } from 'ramda' import React, { Component } from 'react' import { connect } from 'react-redux' import { flatRulesSelector } from 'Selectors/analyseSelectors' +import References from '../rule/References' import './Aide.css' -import References from './rule/References' export default compose( connect( diff --git a/source/components/AnswerList.css b/source/components/conversation/AnswerList.css similarity index 100% rename from source/components/AnswerList.css rename to source/components/conversation/AnswerList.css diff --git a/source/components/AnswerList.js b/source/components/conversation/AnswerList.js similarity index 98% rename from source/components/AnswerList.js rename to source/components/conversation/AnswerList.js index 538f891b5..438325c97 100644 --- a/source/components/AnswerList.js +++ b/source/components/conversation/AnswerList.js @@ -11,7 +11,7 @@ import { connect } from 'react-redux' import { createSelector } from 'reselect' import { règleAvecValeurSelector } from 'Selectors/regleSelectors' import Montant from 'Ui/Montant' -import { softCatch } from '../utils' +import { softCatch } from '../../utils' import './AnswerList.css' const formatAnswer = (answer, language) => { diff --git a/source/components/conversation/Conversation.js b/source/components/conversation/Conversation.js index 5f712ac1c..038f51e85 100644 --- a/source/components/conversation/Conversation.js +++ b/source/components/conversation/Conversation.js @@ -1,15 +1,11 @@ import { goToQuestion, resetSimulation, skipQuestion } from 'Actions/actions' import { T } from 'Components' -import Aide from 'Components/Aide' -import Answers from 'Components/AnswerList' import QuickLinks from 'Components/QuickLinks' import Scroll from 'Components/utils/Scroll' -import withColours from 'Components/utils/withColours' import { getInputComponent } from 'Engine/generateQuestions' import { compose } from 'ramda' -import React, { useState } from 'react' +import React from 'react' import emoji from 'react-easy-emoji' -import { withTranslation } from 'react-i18next' import { connect } from 'react-redux' import { reduxForm } from 'redux-form' import { @@ -17,31 +13,27 @@ import { flatRulesSelector, nextStepsSelector } from 'Selectors/analyseSelectors' -import { simulationProgressSelector } from 'Selectors/progressSelectors' import * as Animate from 'Ui/animate' -import Progress from 'Ui/Progress' +import Aide from './Aide' import './conversation.css' export default compose( - withColours, reduxForm({ form: 'conversation', destroyOnUnmount: false }), - withTranslation(), - connect( state => ({ flatRules: flatRulesSelector(state), currentQuestion: currentQuestionSelector(state), previousAnswers: state.conversationSteps.foldedSteps, - nextSteps: nextStepsSelector(state), - progress: simulationProgressSelector(state) + nextSteps: nextStepsSelector(state) }), { resetSimulation, skipQuestion, goToQuestion } ) )(function Conversation({ nextSteps, + previousAnswers, currentQuestion, customEndMessages, @@ -51,98 +43,63 @@ export default compose( skipQuestion, goToQuestion }) { - const arePreviousAnswers = previousAnswers.length > 0 - const [showAnswerModal, setShowAnswerModal] = useState(false) - return ( - -
-

- Précision du résultat : - -

-
- - {arePreviousAnswers ? ( + + {nextSteps.length ? ( + <> + +
+ {currentQuestion && ( + + + {getInputComponent(flatRules)(currentQuestion)} + +
+ {previousAnswers.length > 0 && ( + <> + + + )} + +
+
+ )} + +
+ + ) : ( +
+

+ {emoji('🌟')}{' '} + Vous avez completé cette simulation{' '} +

+

+ {customEndMessages ? ( + customEndMessages + ) : ( + + Vous avez maintenant accès à l'estimation la plus précise + possible. + + )} +

- ) : ( - - )} - -
- - {showAnswerModal && setShowAnswerModal(false)} />} - -
-
- {nextSteps.length ? ( - - -
- {currentQuestion && ( - - - {getInputComponent(flatRules)(currentQuestion)} - -
- {previousAnswers.length > 0 && ( - - )} - {nextSteps.length > 0 && ( - - )} -
-
- )} -
- -
- ) : ( - <> -

- {emoji('🌟')}{' '} - Simulation complétée à 100%{' '} -

-

- - Nous n'avons plus de questions à poser, vous avez atteint - l'estimation la plus précise. - - {customEndMessages} -

- - )}
-
- + )} +
) }) diff --git a/source/components/conversation/ResultReliability.js b/source/components/conversation/ResultReliability.js new file mode 100644 index 000000000..7d1175bea --- /dev/null +++ b/source/components/conversation/ResultReliability.js @@ -0,0 +1,31 @@ +import React from 'react' +import InfoBulle from 'Ui/InfoBulle' + +export default function ResultReliability({ progress }) { + return ( + + + Fiabilité du résultat :{' '} + + {progress === 0 + ? 'Mauvaise' + : progress < 0.2 + ? 'Faible' + : progress < 0.5 + ? 'Moyenne' + : progress < 0.7 + ? 'Bonne' + : progress < 0.8 + ? 'Très bonne' + : progress < 1 + ? 'Excellente' + : 'Optimale'} + + {' '} + + Le résultat peut varier énormément en fonction de votre situation. + Répondez aux questions pour en améliorer la précision. + {' '} + + ) +} diff --git a/source/components/conversation/SeeAnswersButton.js b/source/components/conversation/SeeAnswersButton.js new file mode 100644 index 000000000..66624febb --- /dev/null +++ b/source/components/conversation/SeeAnswersButton.js @@ -0,0 +1,23 @@ +import { T } from 'Components' +import React, { useState } from 'react' +import { connect } from 'react-redux' +import Answers from './AnswerList' +import './conversation.css' + +export default connect(state => ({ + arePreviousAnswers: !!state.conversationSteps.foldedSteps.length +}))(function SeeAnswersButton({ arePreviousAnswers }) { + const [showAnswerModal, setShowAnswerModal] = useState(false) + return ( + <> + {arePreviousAnswers && ( + + )} + {showAnswerModal && setShowAnswerModal(false)} />} + + ) +}) diff --git a/source/components/ui/Button/button.css b/source/components/ui/Button/button.css index 2a19632f7..80182ae22 100644 --- a/source/components/ui/Button/button.css +++ b/source/components/ui/Button/button.css @@ -76,6 +76,7 @@ .ui__.button.simple, .ui__.button.simple.small { border: none; + background: transparent; padding-left: 0; padding-right: 0; } diff --git a/source/components/ui/Checklist/index.css b/source/components/ui/Checklist/index.css index 453a5a38c..9e5acd60f 100644 --- a/source/components/ui/Checklist/index.css +++ b/source/components/ui/Checklist/index.css @@ -95,7 +95,7 @@ ul.ui__.checklist { } .ui__.checklist-explanation { - padding-left: calc(0.6rem + 8px); - border-left: 2px dashed var(--colour); + padding-left: calc(0.6rem + 10px); + border-left: 1px solid var(--lighterColour); margin: 0 0 -1rem 8px; } diff --git a/source/components/ui/Progress.css b/source/components/ui/Progress.css index 2804d95a0..5ab4e179f 100644 --- a/source/components/ui/Progress.css +++ b/source/components/ui/Progress.css @@ -1,6 +1,5 @@ .progress__container { - border-radius: 0.2rem; - height: 0.4rem; + height: 0.2rem; background-color: var(--lighterColour); overflow: hidden; } diff --git a/source/components/ui/Progress.js b/source/components/ui/Progress.js index 0641759b4..ba6ea7890 100644 --- a/source/components/ui/Progress.js +++ b/source/components/ui/Progress.js @@ -1,9 +1,9 @@ import React from 'react' import './Progress.css' -export default function Progress({ progress }) { +export default function Progress({ progress, style, className }) { return ( -
+
) diff --git a/source/components/ui/animate.js b/source/components/ui/animate.js index 392e00b0b..3fa542395 100644 --- a/source/components/ui/animate.js +++ b/source/components/ui/animate.js @@ -37,10 +37,9 @@ export const fromBottom = ({ {React.Children.map(children, (item, i) => ({ y, ...style }) => ( `translate3d(0, ${y}px,0)`), - ...(item && item.props.style), + ...style, ...inheritedStyle }}> @@ -68,7 +67,9 @@ export const fromTop = ({ `translate3d(0, ${y}px,0)`), + transform: y.interpolate(y => + y ? `translate3d(0, ${y}px,0)` : 'none' + ), ...style, ...inheritedStyle }}> diff --git a/source/components/ui/index.css b/source/components/ui/index.css index 289c05081..ae4589e24 100644 --- a/source/components/ui/index.css +++ b/source/components/ui/index.css @@ -61,7 +61,7 @@ section.ui__:not(:first-of-type) { padding-left: 0.6rem; } .ui__.container .ui__.full-width { - --margin: calc((850px - 100vw) / 2); + --margin: calc((850px - 100vw - 0.6rem) / 2); margin-right: var(--margin); margin-left: var(--margin); } diff --git a/source/règles/base.yaml b/source/règles/base.yaml index 25775f7e3..efd7443e9 100644 --- a/source/règles/base.yaml +++ b/source/règles/base.yaml @@ -739,9 +739,7 @@ niveau: avertissement message: | Le salaire saisi est inférieur au SMIC. - solution: - cible: contrat salarié . temps partiel - texte: Est-ce un temps partiel ? + - si: toutes ces conditions: - brut de base [mensuel] > 10000 diff --git a/source/selectors/analyseSelectors.js b/source/selectors/analyseSelectors.js index add85e26f..d9f8d917f 100644 --- a/source/selectors/analyseSelectors.js +++ b/source/selectors/analyseSelectors.js @@ -265,8 +265,7 @@ export let nextStepsSelector = createSelector( state => state.conversationSteps.foldedSteps ], (mv, questions, foldedSteps) => { - let nextSteps = getNextSteps(mv) - questions = difference(nextSteps, foldedSteps) + let nextSteps = difference(getNextSteps(mv), foldedSteps) if (questions && questions.blacklist) { return difference(nextSteps, questions.blacklist) }