diff --git a/site/source/components/conversation/QuestionEnCours.tsx b/site/source/components/conversation/QuestionEnCours.tsx index 54914ca4a..c0b2494e2 100644 --- a/site/source/components/conversation/QuestionEnCours.tsx +++ b/site/source/components/conversation/QuestionEnCours.tsx @@ -1,5 +1,6 @@ +import { isObject } from 'effect/Predicate' import { DottedName } from 'modele-social' -import Engine, { PublicodesExpression } from 'publicodes' +import { PublicodesExpression } from 'publicodes' import React, { useCallback } from 'react' import { Trans, useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' @@ -16,7 +17,10 @@ import { useEngine } from '@/components/utils/EngineContext' import { Button } from '@/design-system/buttons' import { Grid } from '@/design-system/layout' import { H3 } from '@/design-system/typography/heading' -import { enregistreLaRéponse } from '@/store/actions/actions' +import { + enregistreLaRéponse, + enregistreLesRéponses, +} from '@/store/actions/actions' import { estSurLaPremièreQuestionRépondueSelector } from '@/store/selectors/estSurLaPremièreQuestionRépondue.selector' import { situationSelector } from '@/store/selectors/simulationSelectors' import { evaluateQuestion } from '@/utils' @@ -72,7 +76,16 @@ export function QuestionEnCours({ value: PublicodesExpression | undefined, dottedName: DottedName ) => { - dispatch(enregistreLaRéponse(dottedName, value)) + if (value && isObject(value) && 'batchUpdate' in value) { + dispatch( + enregistreLesRéponses( + dottedName, + value.batchUpdate as Record + ) + ) + } else { + dispatch(enregistreLaRéponse(dottedName, value)) + } } const isDateQuestion = diff --git a/site/source/components/conversation/RuleInput.tsx b/site/source/components/conversation/RuleInput.tsx index aa028efa5..cf860566b 100644 --- a/site/source/components/conversation/RuleInput.tsx +++ b/site/source/components/conversation/RuleInput.tsx @@ -151,7 +151,7 @@ export default function RuleInput({ <> commonProps.onChange(c)} + onChange={(c) => commonProps.onChange({ batchUpdate: c })} // 😭 value={value as Evaluation} /> diff --git a/site/source/domaine/updateSituation.ts b/site/source/domaine/updateSituation.ts index 4495a35eb..068b58d3e 100644 --- a/site/source/domaine/updateSituation.ts +++ b/site/source/domaine/updateSituation.ts @@ -1,6 +1,3 @@ -import { pipe } from 'effect' -import { isNumber, isString } from 'effect/Predicate' -import * as R from 'effect/Record' import { DottedName } from 'modele-social' import { PublicodesExpression } from 'publicodes' @@ -22,17 +19,8 @@ export function updateSituation( const objectifsExclusifs = config['objectifs exclusifs'] ?? [] - const nouvellesValeurs = - isString(value) || isNumber(value) - ? { [dottedName]: value } - : pipe( - value, - R.mapKeys((suffixe) => `${dottedName} . ${suffixe}`), - R.map((valeur) => (isString(valeur) ? `'${valeur}'` : valeur)) // 😭 - ) - if (!objectifsExclusifs.includes(dottedName)) { - return { ...currentSituation, ...nouvellesValeurs } + return { ...currentSituation, [dottedName]: value } } const objectifsToReset = objectifsExclusifs.filter( diff --git a/site/source/domaine/updateSituationMultiple.ts b/site/source/domaine/updateSituationMultiple.ts new file mode 100644 index 000000000..902bfc106 --- /dev/null +++ b/site/source/domaine/updateSituationMultiple.ts @@ -0,0 +1,24 @@ +import { pipe } from 'effect' +import { isString } from 'effect/Predicate' +import * as R from 'effect/Record' +import { DottedName } from 'modele-social' +import { PublicodesExpression } from 'publicodes' + +import { SimulationConfig } from '@/domaine/SimulationConfig' +import { Situation } from '@/domaine/Situation' +import { ImmutableType } from '@/types/utils' + +export function updateSituationMultiple( + config: ImmutableType, + currentSituation: Situation, + préfixe: DottedName, + valeurs: Record +): Situation { + const nouvellesValeurs = pipe( + valeurs, + R.mapKeys((suffixe) => `${préfixe} . ${suffixe}`), + R.map((valeur) => (isString(valeur) ? `'${valeur}'` : valeur)) // 😭 + ) + + return { ...currentSituation, ...nouvellesValeurs } +} diff --git a/site/source/store/actions/actions.ts b/site/source/store/actions/actions.ts index 66faa2c6c..1cdeebbf0 100644 --- a/site/source/store/actions/actions.ts +++ b/site/source/store/actions/actions.ts @@ -21,6 +21,7 @@ export type Action = | typeof vaÀLaQuestionSuivante | typeof ajusteLaSituation | typeof enregistreLaRéponse + | typeof enregistreLesRéponses | typeof deleteFromSituation | typeof updateUnit | typeof batchUpdateSituation @@ -79,6 +80,16 @@ export const enregistreLaRéponse = ( value, } as const) +export const enregistreLesRéponses = ( + règle: DottedName, + valeurs: Record +) => + ({ + type: 'ENREGISTRE_LES_RÉPONSES', + règle, + valeurs, + }) as const + export const deleteFromSituation = (fieldName: DottedName) => ({ type: 'DELETE_FROM_SITUATION', diff --git a/site/source/store/reducers/simulation.reducer.ts b/site/source/store/reducers/simulation.reducer.ts index 58e9abaf3..b31acdeaf 100644 --- a/site/source/store/reducers/simulation.reducer.ts +++ b/site/source/store/reducers/simulation.reducer.ts @@ -4,6 +4,7 @@ import { SimulationConfig } from '@/domaine/SimulationConfig' import { Situation } from '@/domaine/Situation' import { updateSituation } from '@/domaine/updateSituation' import { updateSituationMulti } from '@/domaine/updateSituationMulti' +import { updateSituationMultiple } from '@/domaine/updateSituationMultiple' import { Action } from '@/store/actions/actions' import { omit, reject } from '@/utils' @@ -87,6 +88,27 @@ export function simulationReducer( } } + case 'ENREGISTRE_LES_RÉPONSES': { + const déjàDansLesQuestionsRépondues = state.answeredQuestions.includes( + action.règle + ) + + const answeredQuestions = déjàDansLesQuestionsRépondues + ? state.answeredQuestions + : [...state.answeredQuestions, action.règle] + + return { + ...state, + answeredQuestions, + situation: updateSituationMultiple( + state.config, + state.situation, + action.règle, + action.valeurs + ), + } + } + case 'DELETE_FROM_SITUATION': { const newState = { ...state,