parent
e02964330b
commit
4eff86a18a
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue