import classNames from 'classnames'
import { T } from 'Components'
import InputSuggestions from 'Components/conversation/InputSuggestions'
import PercentageField from 'Components/PercentageField'
import PeriodSwitch from 'Components/PeriodSwitch'
import RuleLink from 'Components/RuleLink'
import withColours from 'Components/utils/withColours'
import withSitePaths from 'Components/utils/withSitePaths'
import { encodeRuleName } from 'Engine/rules'
import { serialiseUnit } from 'Engine/units'
import { compose, isEmpty, isNil, propEq } from 'ramda'
import React, { memo, useEffect, useState } from 'react'
import emoji from 'react-easy-emoji'
import { useTranslation } from 'react-i18next'
import { connect, useDispatch, useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import { change, Field, formValueSelector, reduxForm } from 'redux-form'
import {
analysisWithDefaultsSelector,
flatRulesSelector
} from 'Selectors/analyseSelectors'
import Animate from 'Ui/animate'
import AnimatedTargetValue from 'Ui/AnimatedTargetValue'
import CurrencyInput from './CurrencyInput/CurrencyInput'
import './TargetSelection.css'
export default compose(
withColours,
reduxForm({
form: 'conversation',
destroyOnUnmount: false
}),
connect(
state => ({
getTargetValue: dottedName =>
formValueSelector('conversation')(state, dottedName),
analysis: analysisWithDefaultsSelector(state),
flatRules: flatRulesSelector(state),
activeInput: state.activeTargetInput,
objectifs: state.simulation?.config.objectifs || [],
secondaryObjectives:
state.simulation?.config['objectifs secondaires'] || []
}),
dispatch => ({
setFormValue: (fieldName, value) => {
dispatch({ type: 'UPDATE_SITUATION', fieldName, value })
dispatch(change('conversation', fieldName, value))
},
setActiveInput: name =>
dispatch({ type: 'SET_ACTIVE_TARGET_INPUT', name })
})
),
memo
)(function TargetSelection({
secondaryObjectives,
analysis,
getTargetValue,
setFormValue,
colours,
activeInput,
setActiveInput,
objectifs
}) {
const [initialRender, setInitialRender] = useState(true)
useEffect(() => {
let targets = getTargets()
// Initialize defaultValue for target that can't be computed
targets
.filter(
target =>
(!target.formule || isEmpty(target.formule)) &&
(!isNil(target.defaultValue) ||
!isNil(target.explanation?.defaultValue)) &&
!getTargetValue(target.dottedName)
)
.forEach(target => {
setFormValue(
target.dottedName,
!isNil(target.defaultValue)
? target.defaultValue
: target.explanation?.defaultValue
)
})
if (initialRender) {
setInitialRender(false)
}
}, [])
const getTargets = () => {
if (!analysis) return []
return analysis.targets.filter(
t =>
!secondaryObjectives.includes(t.dottedName) &&
t.dottedName !== 'contrat salarié . aides employeur'
)
}
let targets = getTargets()
return (
{(typeof objectifs[0] === 'string' ? [{ objectifs }] : objectifs).map(
({ icône, objectifs: groupTargets, nom }, index) => (
{nom && (
{emoji(icône)} {nom}
)}
{index === 0 &&
}
groupTargets.includes(dottedName)
),
initialRender
}}
/>
)
)}
)
})
let Targets = ({
activeInput,
setActiveInput,
setFormValue,
targets,
initialRender
}) => (
{targets
.map(target => target.explanation || target)
.filter(target => {
return (
target.isApplicable !== false &&
(target.question || target.nodeValue)
)
})
.map(target => (
))}
)
const Target = ({
target,
activeInput,
targets,
setActiveInput,
setFormValue,
initialRender
}) => {
const isSmallTarget =
!target.question || !target.formule || isEmpty(target.formule)
return (
{isSmallTarget && (
)}
{activeInput === target.dottedName && (
{
setFormValue(target.dottedName, '' + value)
}}
rulePeriod={target.période}
colouredBackground={true}
/>
)}
)
}
let Header = withSitePaths(({ target, sitePaths }) => {
const ruleLink =
sitePaths.documentation.index + '/' + encodeRuleName(target.dottedName)
return (
{target.title || target.name}
{target.summary}
)
})
let CurrencyField = withColours(props => {
return (
)
})
let DebouncedPercentageField = props => (
)
let TargetInputOrValue = ({
target,
targets,
activeInput,
setActiveInput,
firstStepCompleted
}) => {
const { i18n } = useTranslation()
const dispatch = useDispatch()
let inputIsActive = activeInput === target.dottedName
const Component = { '€': CurrencyField, '%': DebouncedPercentageField }[
serialiseUnit(target.unit)
]
return (
{inputIsActive || !target.formule || isEmpty(target.formule) ? (
dispatch({
type: 'UPDATE_SITUATION',
fieldName: target.dottedName,
value: evt.target.value
})
}
onBlur={event => event.preventDefault()}
component={
{ '€': CurrencyField, '%': DebouncedPercentageField }[
serialiseUnit(target.unit)
]
}
{...(inputIsActive ? { autoFocus: true } : {})}
language={i18n.language}
/>
) : (
)}
{target.dottedName.includes('rémunération . total') && }
)
}
function TargetValue({ targets, target, activeInput, setActiveInput }) {
const blurValue = useSelector(
state => analysisWithDefaultsSelector(state)?.cache.inversionFail
)
const dispatch = useDispatch()
const setFormValue = (field, name) => {
dispatch({ type: 'REFACTO_UPDATE_ACTIVE_FIELD', field, name })
dispatch(change('conversation', field, name))
}
let targetWithValue = targets?.find(propEq('dottedName', target.dottedName)),
value = targetWithValue && targetWithValue.nodeValue
const showField = value => () => {
if (!target.question) return
if (value != null && !Number.isNaN(value))
setFormValue(target.dottedName, Math.round(value) + '')
if (activeInput) setFormValue(activeInput, '')
setActiveInput(target.dottedName)
}
return (
)
}
function AidesGlimpse() {
const targets = useSelector(
state => analysisWithDefaultsSelector(state).targets
)
const aides = targets?.find(
t => t.dottedName === 'contrat salarié . aides employeur'
)
if (!aides || !aides.nodeValue) return null
return (
-{' '}
{' '}
d'aides {emoji(aides.icons)}
)
}