🎨 Fusionne les boutons "Passer →" et "Suivant →"

pull/1022/head
Maxime Quandalle 2020-05-06 05:40:51 +02:00
parent 38c2051232
commit 9ab3641dfa
7 changed files with 120 additions and 129 deletions

View File

@ -1,22 +1,20 @@
import { goToQuestion, validateStepWithValue } from 'Actions/actions'
import QuickLinks from 'Components/QuickLinks'
import RuleInput from 'Components/conversation/RuleInput'
import React, { useContext, useEffect } from 'react'
import QuickLinks from 'Components/QuickLinks'
import * as Animate from 'Components/ui/animate'
import { EngineContext } from 'Components/utils/EngineContext'
import { useNextQuestions } from 'Components/utils/useNextQuestion'
import { default as React, useContext, useEffect } from 'react'
import emoji from 'react-easy-emoji'
import { Trans } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { RootState } from 'Reducers/rootReducer'
import * as Animate from 'Components/ui/animate'
import {
answeredQuestionsSelector,
situationSelector
} from 'Selectors/simulationSelectors'
import Aide from './Aide'
import './conversation.css'
import FormDecorator from './FormDecorator'
import { useNextQuestions } from 'Components/utils/useNextQuestion'
import { EngineContext } from 'Components/utils/EngineContext'
import PreviousAnswers from 'sites/mon-entreprise.fr/pages/Créer/GuideStatut/PreviousAnswers'
import {
answeredQuestionsSelector,
currentQuestionSelector
} from 'Selectors/simulationSelectors'
export type ConversationProps = {
customEndMessages?: React.ReactNode
@ -26,6 +24,8 @@ export default function Conversation({ customEndMessages }: ConversationProps) {
const dispatch = useDispatch()
const rules = useContext(EngineContext).getParsedRules()
const currentQuestion = useNextQuestions()[0]
const situation = useSelector(situationSelector)
const currentQuestionIsAnswered = !!situation[currentQuestion]
const previousAnswers = useSelector(answeredQuestionsSelector)
const setDefault = () =>
@ -42,6 +42,13 @@ export default function Conversation({ customEndMessages }: ConversationProps) {
setDefault()
}
}
const submit = source =>
dispatch({
type: 'STEP_ACTION',
name: 'fold',
step: currentQuestion,
source
})
const DecoratedInputComponent = FormDecorator(RuleInput)
return currentQuestion ? (
@ -62,12 +69,16 @@ export default function Conversation({ customEndMessages }: ConversationProps) {
</button>
</>
)}
<button
onClick={setDefault}
className="ui__ simple small push-right button"
>
<Trans>Passer</Trans>
</button>
{currentQuestionIsAnswered ? (
<SendButton onSubmit={submit} />
) : (
<button
onClick={setDefault}
className="ui__ simple small push-right button"
>
<Trans>Passer</Trans>
</button>
)}
</div>
</div>
<QuickLinks />
@ -92,3 +103,33 @@ export default function Conversation({ customEndMessages }: ConversationProps) {
</div>
)
}
type SendButtonProps = {
onSubmit: (cause: string) => void
}
function SendButton({ onSubmit }: SendButtonProps) {
useEffect(() => {
const handleKeyDown = ({ key }: KeyboardEvent) => {
if (key !== 'Enter') return
onSubmit('enter')
}
window.addEventListener('keydown', handleKeyDown)
return () => {
window.removeEventListener('keydown', handleKeyDown)
}
}, [onSubmit])
return (
<button
className="ui__ plain button "
css="margin-left: 1.2rem"
onClick={() => onSubmit('accept')}
>
<span className="text">
<Trans>Suivant</Trans>
</span>
</button>
)
}

View File

@ -3,7 +3,6 @@ import { Rule } from 'publicodes'
import React, { useCallback, useMemo } from 'react'
import styled from 'styled-components'
import InputSuggestions from './InputSuggestions'
import SendButton from './SendButton'
type DateInputProps = {
onChange: RuleInputProps['onChange']
@ -57,7 +56,6 @@ export default function DateInput({
onChange={handleDateChange}
/>
</div>
{onSubmit && <SendButton disabled={!dateValue} onSubmit={onSubmit} />}
</div>
)
}

View File

@ -1,64 +0,0 @@
import { ThemeColorsContext } from 'Components/utils/colors'
import React, { useCallback, useContext } from 'react'
import { useTranslation } from 'react-i18next'
import NumberFormat from 'react-number-format'
import { debounce, currencyFormat } from '../../utils'
import InputSuggestions from './InputSuggestions'
import SendButton from './SendButton'
import { formatValue } from 'publicodes'
// TODO: fusionner Input.js et CurrencyInput.js
export default function Input({
suggestions,
onChange,
onSubmit,
dottedName,
value,
defaultValue,
autoFocus,
unit
}) {
const colors = useContext(ThemeColorsContext)
const debouncedOnChange = useCallback(debounce(750, onChange), [])
const { language } = useTranslation().i18n
const { thousandSeparator, decimalSeparator } = currencyFormat(language)
return (
<div className="step input">
<div>
<InputSuggestions
suggestions={suggestions}
onFirstClick={value => {
onChange(value)
}}
onSecondClick={() => onSubmit && onSubmit('suggestion')}
unit={unit}
/>
<NumberFormat
autoFocus={autoFocus}
className="suffixed"
id={'step-' + dottedName}
placeholder={defaultValue?.nodeValue ?? defaultValue}
thousandSeparator={thousandSeparator}
decimalSeparator={decimalSeparator}
allowEmptyFormatting={true}
style={{ border: `1px solid ${colors.textColorOnWhite}` }}
onValueChange={({ floatValue }) => {
debouncedOnChange(floatValue)
}}
value={value}
autoComplete="off"
/>
<span className="suffix">
{formatValue({ nodeValue: value ?? 0, unit }, { language }).replace(
/[\d,.]*/g,
''
)}
</span>
</div>
{onSubmit && (
<SendButton disabled={value === undefined} onSubmit={onSubmit} />
)}
</div>
)
}

View File

@ -0,0 +1,58 @@
import { ThemeColorsContext } from 'Components/utils/colors'
import React, { useCallback, useContext } from 'react'
import { useTranslation } from 'react-i18next'
import NumberFormat from 'react-number-format'
import { debounce, currencyFormat } from '../../utils'
import InputSuggestions from './InputSuggestions'
import { formatValue } from 'publicodes'
// TODO: fusionner Input.js et CurrencyInput.js
export default function Input({
suggestions,
onChange,
onSubmit,
dottedName,
value,
defaultValue,
autoFocus,
unit
}) {
const colors = useContext(ThemeColorsContext)
const debouncedOnChange = useCallback(debounce(750, onChange), [])
const { language } = useTranslation().i18n
const { thousandSeparator, decimalSeparator } = currencyFormat(language)
return (
<div className="step input">
<InputSuggestions
suggestions={suggestions}
onFirstClick={value => {
onChange(value)
}}
onSecondClick={() => onSubmit?.('suggestion')}
unit={unit}
/>
<NumberFormat
autoFocus={autoFocus}
className="suffixed"
id={'step-' + dottedName}
placeholder={defaultValue?.nodeValue ?? defaultValue}
thousandSeparator={thousandSeparator}
decimalSeparator={decimalSeparator}
allowEmptyFormatting={true}
style={{ border: `1px solid ${colors.textColorOnWhite}` }}
onValueChange={({ floatValue }) => {
debouncedOnChange(floatValue)
}}
value={value}
autoComplete="off"
/>
<span className="suffix">
{formatValue({ nodeValue: value ?? 0, unit }, { language }).replace(
/[\d,.]*/g,
''
)}
</span>
</div>
)
}

View File

@ -5,7 +5,6 @@ import React, { useCallback, useContext } from 'react'
import emoji from 'react-easy-emoji'
import { Trans } from 'react-i18next'
import { ExplicableRule } from './Explicable'
import SendButton from './SendButton'
/* Ceci est une saisie de type "radio" : l'utilisateur choisit une réponse dans
une liste, ou une liste de listes. Les données @choices sont un arbre de type:
@ -115,7 +114,6 @@ export default function Question({
css="margin-top: 0.6rem; display: flex; align-items: center; flex-wrap: wrap;"
>
{choiceElements}
{onSubmit && <SendButton disabled={!currentValue} onSubmit={onSubmit} />}
</div>
)
}

View File

@ -1,3 +1,7 @@
import Input from 'Components/conversation/Input'
import Question from 'Components/conversation/Question'
import SelectGéo from 'Components/conversation/select/SelectGeo'
import SelectAtmp from 'Components/conversation/select/SelectTauxRisque'
import CurrencyInput from 'Components/CurrencyInput/CurrencyInput'
import PercentageField from 'Components/PercentageField'
import ToggleSwitch from 'Components/ui/ToggleSwitch'
@ -7,11 +11,6 @@ import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { DottedName } from 'Rules'
import DateInput from './DateInput'
import Input from './Input'
import Question from './Question'
import SelectGéo from './select/SelectGeo'
import SelectAtmp from './select/SelectTauxRisque'
import SendButton from './SendButton'
export const binaryOptionChoices = [
{ value: 'non', label: 'Non' },
@ -119,7 +118,6 @@ export default function RuleInput({
className="targetInput"
onChange={evt => onChange(evt.target.value)}
/>
{onSubmit && <SendButton disabled={!value} onSubmit={onSubmit} />}
</>
)
}

View File

@ -1,38 +0,0 @@
import React, { useCallback, useEffect } from 'react'
import { Trans } from 'react-i18next'
type SendButtonProps = {
disabled: boolean
onSubmit: (cause: string) => void
}
export default function SendButton({ disabled, onSubmit }: SendButtonProps) {
const getAction = useCallback(cause => (!disabled ? onSubmit(cause) : null), [
disabled,
onSubmit
])
useEffect(() => {
const handleKeyDown = ({ key }: KeyboardEvent) => {
if (key !== 'Enter') return
getAction('enter')
}
window.addEventListener('keydown', handleKeyDown)
return () => {
window.removeEventListener('keydown', handleKeyDown)
}
}, [getAction])
return (
<button
className="ui__ plain button "
css="margin-left: 1.2rem"
disabled={disabled}
onClick={() => getAction('accept')}
>
<span className="text">
<Trans>Suivant</Trans>
</span>
</button>
)
}