diff --git a/mon-entreprise/source/components/PeriodSwitch.tsx b/mon-entreprise/source/components/PeriodSwitch.tsx index d19771a92..acb0c6ed1 100644 --- a/mon-entreprise/source/components/PeriodSwitch.tsx +++ b/mon-entreprise/source/components/PeriodSwitch.tsx @@ -10,7 +10,7 @@ export default function PeriodSwitch() { const units = ['€/mois', '€/an'] return ( - +
{units.map((unit) => ( ))} - +
) } diff --git a/mon-entreprise/source/components/SimulationGoals.tsx b/mon-entreprise/source/components/SimulationGoals.tsx index 830392bdd..9c96bcf24 100644 --- a/mon-entreprise/source/components/SimulationGoals.tsx +++ b/mon-entreprise/source/components/SimulationGoals.tsx @@ -5,7 +5,10 @@ import { DottedName } from 'modele-social' import { formatValue, UNSAFE_isNotApplicable } from 'publicodes' import { createContext, useContext, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { situationSelector } from 'Selectors/simulationSelectors' +import { + situationSelector, + targetUnitSelector, +} from 'Selectors/simulationSelectors' import RuleInput from './conversation/RuleInput' import RuleLink from './RuleLink' import AnimatedTargetValue from './ui/AnimatedTargetValue' @@ -26,7 +29,10 @@ export function SimulationGoals({ return ( -
+
    {children}
@@ -45,7 +51,7 @@ function useInitialRender() { type SimulationGoalProps = { dottedName: DottedName - labelWithTitle?: boolean + labelWithQuestion?: boolean small?: boolean appear?: boolean editable?: boolean @@ -53,16 +59,21 @@ type SimulationGoalProps = { export function SimulationGoal({ dottedName, - labelWithTitle = false, + labelWithQuestion = false, small = false, appear = true, editable = true, }: SimulationGoalProps) { const dispatch = useDispatch() const engine = useEngine() + const currentUnit = useSelector(targetUnitSelector) const situation = useSelector(situationSelector) const isNotApplicable = UNSAFE_isNotApplicable(engine, dottedName) - const evaluation = engine.evaluate(dottedName) + const evaluation = engine.evaluate({ + valeur: dottedName, + unité: currentUnit, + arrondi: 'oui', + }) const rule = engine.getRule(dottedName) const initialRender = useContext(InitialRenderContext) const [isFocused, setFocused] = useState(false) @@ -79,6 +90,12 @@ export function SimulationGoal({ isFocused || initialRender || Object.keys(situation).length === 0 + if ( + !editable && + (evaluation.nodeValue === false || evaluation.nodeValue === null) + ) { + return null + } return (
  • @@ -86,7 +103,9 @@ export function SimulationGoal({
    @@ -101,6 +120,10 @@ export function SimulationGoal({ { focused: isFocused } )} isTarget + modifiers={{ + unité: currentUnit, + arrondi: 'oui', + }} dottedName={dottedName} onFocus={() => setFocused(true)} onBlur={() => setFocused(false)} diff --git a/mon-entreprise/source/components/conversation/RuleInput.tsx b/mon-entreprise/source/components/conversation/RuleInput.tsx index c59d6ec7f..454f1713f 100644 --- a/mon-entreprise/source/components/conversation/RuleInput.tsx +++ b/mon-entreprise/source/components/conversation/RuleInput.tsx @@ -27,6 +27,7 @@ export type Props = Omit< useSwitch?: boolean isTarget?: boolean onSubmit?: (source: string) => void + modifiers?: Record } export type InputProps = Props & @@ -51,11 +52,12 @@ export default function RuleInput({ useSwitch = false, isTarget = false, onSubmit = () => null, + modifiers = {}, ...props }: Props) { const engine = useContext(EngineContext) const rule = engine.getRule(dottedName) - const evaluation = engine.evaluate(dottedName) + const evaluation = engine.evaluate({ valeur: dottedName, ...modifiers }) const language = useTranslation().i18n.language const value = evaluation.nodeValue const commonProps: InputProps = { diff --git a/mon-entreprise/source/pages/Simulateurs/ArtisteAuteur.tsx b/mon-entreprise/source/pages/Simulateurs/ArtisteAuteur.tsx index d4d3c909d..f91ab1f40 100644 --- a/mon-entreprise/source/pages/Simulateurs/ArtisteAuteur.tsx +++ b/mon-entreprise/source/pages/Simulateurs/ArtisteAuteur.tsx @@ -22,14 +22,29 @@ export default function ArtisteAuteur() { <> - - - + + + - + - + diff --git a/mon-entreprise/source/pages/Simulateurs/AutoEntrepreneur.tsx b/mon-entreprise/source/pages/Simulateurs/AutoEntrepreneur.tsx index 13f384d7a..df9aefa6a 100644 --- a/mon-entreprise/source/pages/Simulateurs/AutoEntrepreneur.tsx +++ b/mon-entreprise/source/pages/Simulateurs/AutoEntrepreneur.tsx @@ -1,6 +1,7 @@ import { updateSituation } from 'Actions/actions' import Conversation from 'Components/conversation/Conversation' import { Condition } from 'Components/EngineValue' +import PeriodSwitch from 'Components/PeriodSwitch' import SearchButton from 'Components/SearchButton' import SimulateurWarning from 'Components/SimulateurWarning' import { SimulationGoal, SimulationGoals } from 'Components/SimulationGoals' @@ -18,14 +19,14 @@ export default function AutoEntrepreneur() { <> - + +
    @@ -34,31 +35,29 @@ export default function AutoEntrepreneur() {
  • - - + + + + + diff --git a/publicodes/core/source/format.ts b/publicodes/core/source/format.ts index 53646c6dd..950f67998 100644 --- a/publicodes/core/source/format.ts +++ b/publicodes/core/source/format.ts @@ -1,4 +1,5 @@ import { Evaluation, Unit } from './AST/types' +import { simplifyNodeUnit } from './nodeUnits' import { formatUnit, serializeUnit } from './units' export const numberFormatter = ({ @@ -29,27 +30,27 @@ export const numberFormatter = ({ }).format(value) } -export const formatCurrency = (value: number | undefined, language: string) => { - return value == null +export const formatCurrency = (nodeValue: number | undefined, language: string) => { + return nodeValue == null ? '' - : (formatNumber({ unit: '€', language, value }) ?? '').replace( + : (formatNumber({ unit: '€', language, nodeValue }) ?? '').replace( /^(-)?€/, '$1€\u00A0' ) } -export const formatPercentage = (value: number | undefined) => - value == null +export const formatPercentage = (nodeValue: number | undefined) => + nodeValue == null ? '' - : formatNumber({ unit: '%', value, maximumFractionDigits: 2 }) + : formatNumber({ unit: '%', nodeValue, maximumFractionDigits: 2 }) -export type formatValueOptions = { +type formatValueOptions = { maximumFractionDigits?: number minimumFractionDigits?: number language?: string unit?: Unit | string formatUnit?: formatUnit - value: number + nodeValue: number } function formatNumber({ @@ -58,13 +59,13 @@ function formatNumber({ language, formatUnit, unit, - value, + nodeValue, }: formatValueOptions) { - if (typeof value !== 'number') { - return value + if (typeof nodeValue !== 'number') { + return nodeValue } const serializedUnit = unit - ? serializeUnit(unit, value, formatUnit) + ? serializeUnit(unit, nodeValue, formatUnit) : undefined switch (serializedUnit) { case '€': @@ -73,13 +74,13 @@ function formatNumber({ maximumFractionDigits, minimumFractionDigits, language, - })(value) + })(nodeValue) case '%': return numberFormatter({ style: 'percent', maximumFractionDigits, language, - })(value / 100) + })(nodeValue / 100) default: return ( numberFormatter({ @@ -87,7 +88,7 @@ function formatNumber({ minimumFractionDigits, maximumFractionDigits, language, - })(value) + + })(nodeValue) + (typeof serializedUnit === 'string' ? `\u00A0${serializedUnit}` : '') ) } @@ -116,18 +117,11 @@ export function formatValue( { language = 'fr', displayedUnit, formatUnit, precision = 2 }: Options = {} ) { - const nodeValue = + let nodeValue = typeof value === 'number' || typeof value === 'undefined' ? value : value.nodeValue - const unit = - displayedUnit ?? - (typeof value === 'number' || - typeof value === 'undefined' || - !('unit' in value) - ? undefined - : value.unit) if ( (typeof nodeValue === 'number' && Number.isNaN(nodeValue)) || @@ -135,22 +129,38 @@ export function formatValue( ) { return '-' } - return typeof nodeValue === 'string' - ? capitalise0(nodeValue.replace('\\n', '\n')) - : typeof nodeValue === 'object' - ? (nodeValue as any).nom - : typeof nodeValue === 'boolean' - ? booleanTranslations[language][nodeValue] - : typeof nodeValue === 'number' - ? formatNumber({ + if (typeof nodeValue === 'string'){ + return capitalise0(nodeValue.replace('\\n', '\n')) + } + if (typeof nodeValue === 'object') + return (nodeValue as any).nom + if (typeof nodeValue === 'boolean') + return booleanTranslations[language][nodeValue] + if (typeof nodeValue === 'number'){ + let unit = + (typeof value === 'number' || + typeof value === 'undefined' || + !('unit' in value) + ? undefined + : value.unit) + if (unit) { + const simplifiedNode = simplifyNodeUnit({ + unit, + nodeValue + }) + unit = simplifiedNode.unit + nodeValue = simplifiedNode.nodeValue as number + } + return formatNumber({ minimumFractionDigits: 0, maximumFractionDigits: precision, language, formatUnit, - unit, - value: nodeValue, + nodeValue, + unit: displayedUnit ?? unit }) - : null + } + return null } export function serializeValue( diff --git a/publicodes/core/source/nodeUnits.ts b/publicodes/core/source/nodeUnits.ts index e4c118aa9..7fc16640e 100644 --- a/publicodes/core/source/nodeUnits.ts +++ b/publicodes/core/source/nodeUnits.ts @@ -1,8 +1,9 @@ +import { EvaluatedNode, Unit } from './AST/types' import { mapTemporal } from './temporal' import { convertUnit, simplifyUnit } from './units' -import { EvaluatedNode, Unit } from './AST/types' export function simplifyNodeUnit(node) { + console.log('jhjoiijoijo', node) if (!node.unit) { return node }