🎨 Fusionne les boutons "Passer →" et "Suivant →"
parent
38c2051232
commit
9ab3641dfa
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
}
|
|
@ -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>
|
||||
)
|
||||
}
|
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue