WIP exonération-covid

fix #2045
Co-authored-by: Johan Girod <dev@johangirod.com>
pull/2077/head
Jérémy Rialland 2022-03-07 18:24:47 +01:00 committed by Johan Girod
parent e02964330b
commit 4eff86a18a
11 changed files with 120 additions and 24 deletions

View File

@ -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<Names, Rule>
export default rules

View File

@ -7,17 +7,17 @@ secteur:
secteur . S1:
valeur: secteur = 'S1'
titre: Secteur dit S1
Description: Activités du tourisme, de lhôtellerie, de la restauration, du sport, de la culture, du transport aérien et de lévénementiel
description: Activités du tourisme, de lhô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:

View File

@ -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",

View File

@ -46,10 +46,10 @@ export type Choice = RuleNode & {
// this undesirable option.
export const HiddenOptionContext = createContext<Array<DottedName>>([])
export function MultipleAnswerInput({
export function MultipleAnswerInput<Names extends string = DottedName>({
choice,
...props
}: { choice: Choice } & InputProps<DottedName>) {
}: { choice: Choice } & InputProps<Names>) {
// 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<Names extends string = DottedName>({
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<DottedName>) {
export function OuiNonInput<Names extends string = DottedName>(
props: InputProps<Names>
) {
// 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<DottedName>) {
)
}
function useSelection({ value, onChange, missing }: InputProps<DottedName>) {
function useSelection<Names extends string = DottedName>({
value,
onChange,
missing,
}: InputProps<Names>) {
const defaultValue = serializeEvaluation({
nodeValue: value,
} as EvaluatedNode)

View File

@ -18,18 +18,15 @@ import ParagrapheInput from './ParagrapheInput'
import SelectPaysDétachement from './select/SelectPaysDétachement'
import TextInput from './TextInput'
type Props<Name extends string = DottedName> = Omit<
type Props<Names extends string = DottedName> = Omit<
React.HTMLAttributes<HTMLInputElement>,
'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<Names extends string = DottedName>({
dottedName,
onChange,
showSuggestions = true,
@ -74,12 +71,12 @@ export default function RuleInput({
showDefaultDateValue = false,
modifiers = {},
...props
}: Props<DottedName>) {
}: Props<Names>) {
const engine = useContext(EngineContext)
const rule = engine.getRule(dottedName)
const evaluation = engine.evaluate({ valeur: dottedName, ...modifiers })
const value = evaluation.nodeValue
const commonProps: InputProps<DottedName> = {
const commonProps: InputProps<Names> = {
dottedName,
value,
missing: !showDefaultDateValue && !!evaluation.missingVariables[dottedName],

View File

@ -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<Record<DottedNames, PublicodesExpression | undefined>>
>({})
const updateSituation = useCallback(
(name: DottedNames, value: PublicodesExpression | undefined) => {
const newSituation = { ...situation, [name]: value }
setSituation(newSituation)
covidEngine.setSituation(newSituation)
},
[situation]
)
return (
<>
<EngineProvider value={covidEngine}>
<RuleInput
dottedName={'secteur'}
onChange={(value) => updateSituation('secteur', value)}
/>
<H3>{covidEngine.getRule("début d'activité").rawNode.question}</H3>
<RuleInput
dottedName="début d'activité"
onChange={(value) => updateSituation("début d'activité", value)}
/>
<H3>{covidEngine.getRule("lieu d'exercice").rawNode.question}</H3>
<RuleInput
dottedName="lieu d'exercice"
onChange={(value) => updateSituation("début d'activité", value)}
/>
<hr />
<Value expression={'secteur'} />
</EngineProvider>
</>
)
}

View File

@ -92,6 +92,14 @@ export default function Simulateurs() {
</Grid>
</>
<H3>
<Trans>Outils pour les indépendants</Trans>
</H3>
<Grid container spacing={3}>
<SimulateurCard {...simulators['exonération-covid']} />
<SimulateurCard {...simulators['aide-déclaration-indépendant']} />
</Grid>
<H2>
<Trans>Autres outils</Trans>
</H2>
@ -99,7 +107,6 @@ export default function Simulateurs() {
<SimulateurCard {...simulators['is']} />
<SimulateurCard {...simulators['dividendes']} />
<SimulateurCard {...simulators['économie-collaborative']} />
<SimulateurCard {...simulators['aide-déclaration-indépendant']} />
<SimulateurCard {...simulators['demande-mobilité']} />
</Grid>
</section>

View File

@ -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

View File

@ -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({
</Trans>
),
},
'exonération-covid': {
...pureSimulatorsData['exonération-covid'],
path: sitePaths.simulateurs['exonération-covid'],
component: ExonérationCovid,
},
} as const
}

View File

@ -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',

View File

@ -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