From 4eff86a18a9f0c1a72664bd9543f4adb76c86a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Rialland?= Date: Mon, 7 Mar 2022 18:24:47 +0100 Subject: [PATCH] =?UTF-8?q?WIP=20exon=C3=A9ration-covid=20fix=20#2045=20Co?= =?UTF-8?q?-authored-by:=20Johan=20Girod=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- exoneration-covid/index.d.ts | 2 +- .../règles/exonération-covid.yaml | 6 +-- site/package.json | 3 +- .../components/conversation/ChoicesInput.tsx | 18 ++++--- .../components/conversation/RuleInput.tsx | 15 +++--- .../Simulateurs/ExonerationCovid/index.tsx | 50 +++++++++++++++++++ site/source/pages/Simulateurs/Home.tsx | 9 +++- site/source/pages/Simulateurs/metadata-src.ts | 26 ++++++++++ site/source/pages/Simulateurs/metadata.tsx | 6 +++ site/source/sitePaths.ts | 2 + yarn.lock | 7 +-- 11 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 site/source/pages/Simulateurs/ExonerationCovid/index.tsx diff --git a/exoneration-covid/index.d.ts b/exoneration-covid/index.d.ts index 5520252a5..910d25c17 100644 --- a/exoneration-covid/index.d.ts +++ b/exoneration-covid/index.d.ts @@ -4,7 +4,7 @@ import { Rule } from 'publicodes' import { Names } from './dist/names' -export type DottedName = Names +export type DottedNames = Names declare let rules: Record export default rules diff --git a/exoneration-covid/règles/exonération-covid.yaml b/exoneration-covid/règles/exonération-covid.yaml index 8017df8ff..f8d2a0096 100644 --- a/exoneration-covid/règles/exonération-covid.yaml +++ b/exoneration-covid/règles/exonération-covid.yaml @@ -7,17 +7,17 @@ secteur: secteur . S1: valeur: secteur = 'S1' titre: Secteur dit S1 - Description: Activités du tourisme, de l’hôtellerie, de la restauration, du sport, de la culture, du transport aérien et de l’événementiel + description: Activités du tourisme, de l’hôtellerie, de la restauration, du sport, de la culture, du transport aérien et de l’événementiel secteur . S1bis: valeur: secteur = 'S1bis' titre: Secteur dit S1bis - Description: Activités dépendantes du secteur 1 + description: Activités dépendantes du secteur 1 secteur . S2: valeur: secteur = 'S2' titre: Secteur dit S2 - Description: Autres activités ayant fait l'objet d'une interdiction (par exemple, commerces) + description: Autres activités ayant fait l'objet d'une interdiction (par exemple, commerces) secteur . S1 ou S1bis: une de ces conditions: diff --git a/site/package.json b/site/package.json index a89b87d88..b03f735e4 100644 --- a/site/package.json +++ b/site/package.json @@ -74,10 +74,11 @@ "@sentry/react": "^6.19.2", "@sentry/tracing": "^6.19.2", "algoliasearch": "^4.10.2", + "exoneration-covid": "workspace:^", "fuse.js": "^6.4.6", "iframe-resizer": "^4.3.2", "markdown-to-jsx": "^7.1.5", - "modele-social": "^0.6.0", + "modele-social": "workspace:^", "publicodes": "^1.0.0-beta.32", "publicodes-react": "^1.0.0-beta.32", "ramda": "^0.27.0", diff --git a/site/source/components/conversation/ChoicesInput.tsx b/site/source/components/conversation/ChoicesInput.tsx index c13c1e06e..1ab8b0469 100644 --- a/site/source/components/conversation/ChoicesInput.tsx +++ b/site/source/components/conversation/ChoicesInput.tsx @@ -46,10 +46,10 @@ export type Choice = RuleNode & { // this undesirable option. export const HiddenOptionContext = createContext>([]) -export function MultipleAnswerInput({ +export function MultipleAnswerInput({ choice, ...props -}: { choice: Choice } & InputProps) { +}: { choice: Choice } & InputProps) { // seront stockées ainsi dans le state : // [parent object path]: dotted fieldName relative to parent const { handleChange, defaultValue, currentSelection } = useSelection(props) @@ -65,14 +65,14 @@ export function MultipleAnswerInput({ ) } -function RadioChoice({ +function RadioChoice({ choice, autoFocus, rootDottedName, }: { choice: Choice autoFocus?: string - rootDottedName: DottedName + rootDottedName: Names }) { const relativeDottedName = (radioDottedName: string) => radioDottedName.split(rootDottedName + ' . ')[1] @@ -144,7 +144,9 @@ const StyledSubRadioGroup = styled.div` margin-top: calc(${({ theme }) => theme.spacings.md} * -1); ` -export function OuiNonInput(props: InputProps) { +export function OuiNonInput( + props: InputProps +) { // seront stockées ainsi dans le state : // [parent object path]: dotted fieldName relative to parent const { handleChange, defaultValue, currentSelection } = useSelection(props) @@ -161,7 +163,11 @@ export function OuiNonInput(props: InputProps) { ) } -function useSelection({ value, onChange, missing }: InputProps) { +function useSelection({ + value, + onChange, + missing, +}: InputProps) { const defaultValue = serializeEvaluation({ nodeValue: value, } as EvaluatedNode) diff --git a/site/source/components/conversation/RuleInput.tsx b/site/source/components/conversation/RuleInput.tsx index 468101f0d..c1ea8bbd9 100644 --- a/site/source/components/conversation/RuleInput.tsx +++ b/site/source/components/conversation/RuleInput.tsx @@ -18,18 +18,15 @@ import ParagrapheInput from './ParagrapheInput' import SelectPaysDétachement from './select/SelectPaysDétachement' import TextInput from './TextInput' -type Props = Omit< +type Props = Omit< React.HTMLAttributes, 'onChange' | 'defaultValue' | 'onSubmit' > & { required?: boolean autoFocus?: boolean small?: boolean - dottedName: Name - onChange: ( - value: PublicodesExpression | undefined, - dottedName: DottedName - ) => void + dottedName: Names + onChange: (value: PublicodesExpression | undefined, dottedName: Names) => void // TODO: It would be preferable to replace this "showSuggestions" parameter by // a build-in logic in the engine, by setting the "applicability" of // suggestions. @@ -66,7 +63,7 @@ export const binaryQuestion = [ // be displayed to get a user input through successive if statements // That's not great, but we won't invest more time until we have more diverse // input components and a better type system. -export default function RuleInput({ +export default function RuleInput({ dottedName, onChange, showSuggestions = true, @@ -74,12 +71,12 @@ export default function RuleInput({ showDefaultDateValue = false, modifiers = {}, ...props -}: Props) { +}: Props) { const engine = useContext(EngineContext) const rule = engine.getRule(dottedName) const evaluation = engine.evaluate({ valeur: dottedName, ...modifiers }) const value = evaluation.nodeValue - const commonProps: InputProps = { + const commonProps: InputProps = { dottedName, value, missing: !showDefaultDateValue && !!evaluation.missingVariables[dottedName], diff --git a/site/source/pages/Simulateurs/ExonerationCovid/index.tsx b/site/source/pages/Simulateurs/ExonerationCovid/index.tsx new file mode 100644 index 000000000..60f1f21c7 --- /dev/null +++ b/site/source/pages/Simulateurs/ExonerationCovid/index.tsx @@ -0,0 +1,50 @@ +import exonerationCovid, { DottedNames } from 'exoneration-covid' +import Engine, { PublicodesExpression } from 'publicodes' +import { EngineProvider } from '@/components/utils/EngineContext' +import RuleInput from '@/components/conversation/RuleInput' +import { useState, useCallback } from 'react' +import Value from '@/components/EngineValue' +import { H3 } from '@/design-system/typography/heading' + +const covidEngine = new Engine(exonerationCovid) + +export default function ExonérationCovid() { + const [situation, setSituation] = useState< + Partial> + >({}) + const updateSituation = useCallback( + (name: DottedNames, value: PublicodesExpression | undefined) => { + const newSituation = { ...situation, [name]: value } + setSituation(newSituation) + covidEngine.setSituation(newSituation) + }, + [situation] + ) + + return ( + <> + + updateSituation('secteur', value)} + /> + +

{covidEngine.getRule("début d'activité").rawNode.question}

+ updateSituation("début d'activité", value)} + /> + +

{covidEngine.getRule("lieu d'exercice").rawNode.question}

+ updateSituation("début d'activité", value)} + /> + +
+ + +
+ + ) +} diff --git a/site/source/pages/Simulateurs/Home.tsx b/site/source/pages/Simulateurs/Home.tsx index 71d0c5598..7cfddcaed 100644 --- a/site/source/pages/Simulateurs/Home.tsx +++ b/site/source/pages/Simulateurs/Home.tsx @@ -92,6 +92,14 @@ export default function Simulateurs() { +

+ Outils pour les indépendants +

+ + + + +

Autres outils

@@ -99,7 +107,6 @@ export default function Simulateurs() { - diff --git a/site/source/pages/Simulateurs/metadata-src.ts b/site/source/pages/Simulateurs/metadata-src.ts index daf360972..f7a0e0ee2 100644 --- a/site/source/pages/Simulateurs/metadata-src.ts +++ b/site/source/pages/Simulateurs/metadata-src.ts @@ -698,6 +698,32 @@ const metadataSrc = (t: TFunction<'translation', string>) => { nextSteps: ['salarié', 'is', 'comparaison-statuts'], }, + 'exonération-covid': { + icône: '😷', + tracking: 'exoneration_covid', + iframePath: 'exoneration-covid', + pathId: 'simulateurs.exonération-covid', + meta: { + title: t( + 'pages.simulateurs.dividendes.meta.title', + 'Exonération de cotisations covid' + ), + description: t( + 'pages.simulateurs.dividendes.meta.description', + "Indépendants : calculez le montant de l'exonération de cotisations covid sur vos cotisations de 2021." + ), + }, + shortName: t( + 'pages.simulateurs.dividendes.meta.title', + 'Exonération Covid' + ), + title: t( + 'pages.simulateurs.dividendes.title', + "Simulateur d'exonération de cotisations Covid pour indépendant" + ), + + nextSteps: ['aide-déclaration-indépendant'], + }, } as const return data diff --git a/site/source/pages/Simulateurs/metadata.tsx b/site/source/pages/Simulateurs/metadata.tsx index 366532ddd..55561c1b7 100644 --- a/site/source/pages/Simulateurs/metadata.tsx +++ b/site/source/pages/Simulateurs/metadata.tsx @@ -24,6 +24,7 @@ import professionLibéraleConfig from './configs/profession-libérale.yaml' import salariéConfig from './configs/salarié.yaml' import DividendesSimulation from './Dividendes' import ÉconomieCollaborative from './EconomieCollaborative' +import ExonérationCovid from './ExonerationCovid' import AutoEntrepreneurPreview from './images/AutoEntrepreneurPreview.png' import ChômagePartielPreview from './images/ChômagePartielPreview.png' import urlIllustrationNetBrutEn from './images/illustration-net-brut-en.png' @@ -685,6 +686,11 @@ function getSimulatorsData({ ), }, + 'exonération-covid': { + ...pureSimulatorsData['exonération-covid'], + path: sitePaths.simulateurs['exonération-covid'], + component: ExonérationCovid, + }, } as const } diff --git a/site/source/sitePaths.ts b/site/source/sitePaths.ts index 205572a81..cb53e28df 100644 --- a/site/source/sitePaths.ts +++ b/site/source/sitePaths.ts @@ -76,6 +76,7 @@ const rawSitePathsFr = { is: '/impot-societe', 'aides-embauche': '/aides-embauche', dividendes: '/dividendes', + 'exonération-covid': '/exonération-covid', }, nouveautés: '/nouveautés', stats: '/stats', @@ -144,6 +145,7 @@ const rawSitePathsEn = { is: '/corporate-tax', 'aides-embauche': '/hiring-incentives', dividendes: '/dividends', + 'exonération-covid': '/exoneration-covid', }, nouveautés: '/news', accessibilité: '/accessibility', diff --git a/yarn.lock b/yarn.lock index 67c0af638..e7dd4fc2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10603,7 +10603,7 @@ __metadata: languageName: node linkType: hard -"exoneration-covid@workspace:exoneration-covid": +"exoneration-covid@workspace:^, exoneration-covid@workspace:exoneration-covid": version: 0.0.0-use.local resolution: "exoneration-covid@workspace:exoneration-covid" dependencies: @@ -14382,7 +14382,7 @@ __metadata: languageName: node linkType: hard -"modele-social@^0.6.0, modele-social@workspace:modele-social": +"modele-social@workspace:^, modele-social@workspace:modele-social": version: 0.0.0-use.local resolution: "modele-social@workspace:modele-social" dependencies: @@ -17690,12 +17690,13 @@ __metadata: cypress-plugin-tab: ^1.0.5 cypress-wait-until: ^1.7.2 dotenv: =8.1.0 + exoneration-covid: "workspace:^" fuse.js: ^6.4.6 i18next-parser: ^6.0.0 iframe-resizer: ^4.3.2 isomorphic-fetch: ^2.2.1 markdown-to-jsx: ^7.1.5 - modele-social: ^0.6.0 + modele-social: "workspace:^" publicodes: ^1.0.0-beta.32 publicodes-react: ^1.0.0-beta.32 ramda: ^0.27.0