Première version du comparateur à la suite de l'assistant (WIP)

pull/2782/head
Johan Girod 2023-06-21 11:34:32 +02:00
parent 30332ac478
commit 0cc4038665
14 changed files with 254 additions and 448 deletions

View File

@ -1,5 +1,4 @@
entreprise . associés:
possiblement non applicable: non
une possibilité:
choix obligatoire: oui
possibilités:
@ -48,26 +47,26 @@ entreprise . catégorie juridique . EI:
valeur: catégorie juridique = 'EI'
avec:
auto-entrepreneur:
applicable si: associés . unique
acronyme: AE
non applicable si:
une de ces conditions:
- entreprise . imposition . IR . type de bénéfices = 'BA'
- toutes ces conditions:
- activité . nature . libérale . réglementée
- dirigeant . indépendant . PL . métier . rattaché CIPAV = non
question: Êtes-vous auto-entrepreneur ?
acronyme: AE
par défaut:
applicable si: associés . unique
non applicable si:
une de ces conditions:
- entreprise . imposition . IR . type de bénéfices = 'BA'
- toutes ces conditions:
- activité . nature . libérale . réglementée
- dirigeant . indépendant . PL . métier . rattaché CIPAV = non
nom: par défaut
experimental: oui
valeur: oui
EI:
applicable si: associés . unique
titre: entreprise individuelle
acronyme: EI
valeur: auto-entrepreneur = non
par défaut:
applicable si: associés . unique
### (niveau 1 code 5) Société commerciale ###
@ -76,12 +75,13 @@ entreprise . catégorie juridique . SARL:
code insee: 5499
titre: SARL ou EURL
valeur: catégorie juridique = 'SARL'
non applicable si: activité . nature . libérale . réglementée
par défaut:
non applicable si: activité . nature . libérale . réglementée
avec:
SARL:
titre: Société à responsabilité limitée
acronyme: SARL
applicable si: associés . multiples
valeur: associés . multiples
description: |
La société à responsabilité limitée (SARL) comprend au minimum deux associés. Cette forme juridique est la plus répandue pour les sociétés. En revanche, elle ne peut être choisie pour les professions juridiques, judiciaires ou de santé (hors pharmaciens).
@ -104,7 +104,7 @@ entreprise . catégorie juridique . SARL:
EURL:
titre: Entreprise unipersonnelle à responsabilité limitée
acronyme: EURL
applicable si: associés . unique
valeur: associés . unique
description: |
L'entreprise unipersonnelle à responsabilité limitée (EURL) est une société à responsabilité limitée (SARL) constituée d'un seul associé. Elle est également appelée SARL unipersonnelle.
@ -127,31 +127,24 @@ entreprise . catégorie juridique . SARL:
déprécié: oui
valeur: EURL
entreprise . catégorie juridique . SNC:
titre: Société en nom collectif
acronyme: SNC
valeur: catégorie juridique = 'SNC'
applicable si: associés . multiples
meta:
code insee: 5202
entreprise . catégorie juridique . SAS:
non applicable si: activité . nature . libérale . réglementée
titre: SAS ou SASU
acronyme: SAS(U)
valeur: catégorie juridique = 'SAS'
par défaut:
non applicable si: activité . nature . libérale . réglementée
meta:
code insee: 5710
avec:
SASU:
titre: Société par actions simplifiée unipersonnelle
acronyme: SASU
applicable si: associés . unique
valeur: associés . unique
SAS:
titre: Société par actions simplifiée
acronyme: SAS
applicable si: associés . multiples
valeur: associés . multiples
unipersonnelle:
déprécié: oui
@ -160,40 +153,42 @@ entreprise . catégorie juridique . SAS:
### (niveau 1 code 6) Autre personne morale immatriculée au RCS ###
entreprise . catégorie juridique . SELARL:
applicable si: activité . nature . libérale . réglementée
acronyme: SELARL(U)
titre: SELARL ou SELARLU
description: Société d'exercice libéral à responsabilité limitée
valeur: catégorie juridique = 'SELARL'
par défaut:
applicable si: activité . nature . libérale . réglementée
meta:
code insee: 5485
avec:
SELARLU:
acronyme: SELARLU
titre: Société d'exercice libéral à responsabilité limitée unipersonnelle
applicable si: associés . unique
valeur: associés . unique
SELARL:
acronyme: SELARL
titre: Société d'exercice libéral à responsabilité limitée
applicable si: associés . multiples
valeur: associés . multiples
entreprise . catégorie juridique . SELAS:
applicable si: activité . nature . libérale . réglementée
acronyme: SELAS(U)
titre: SELAS ou SELASU
description: Société d'exercice libéral par actions simplifiées
valeur: catégorie juridique = 'SELAS'
par défaut:
applicable si: activité . nature . libérale . réglementée
meta:
code insee: 5785
avec:
SELASU:
acronyme: SELASU
titre: Société d'exercice libéral par action simplifiée unipersonnelle
applicable si: associés . unique
valeur: associés . unique
SELAS:
acronyme: SELAS
titre: Société d'exercice libéral par action simplifiée
applicable si: associés . multiples
valeur: associés . multiples
entreprise . catégorie juridique . association:
valeur: catégorie juridique = 'association'
@ -206,20 +201,14 @@ entreprise . catégorie juridique . autre:
Ce simulateur ne gère pas encore tout les types d'entreprises, le montant affiché pourrait être incorrect.
entreprise . catégorie juridique . remplacements:
# On extrait tous les remplacements dans un espace de nom que l'on peut désactiver pour l'aide au choix du statut par exemple
# Cela permet d'éviter des boucles de dans les missingVariables
# Ces remplacements mette à jour les régimes d'imposition et la nature d'activité en fonctions de ceux compatibles avec le statut juridique connu.
experimental: oui
valeur: non
valeur: oui
avec:
régime micro-entreprise:
privé: oui
applicable si:
toutes ces conditions:
- remplacements
- EI . auto-entrepreneur
valeur: oui
applicable si: EI . auto-entrepreneur
remplace:
- règle: imposition . régime
par: "'micro-entreprise'"
@ -232,45 +221,20 @@ entreprise . catégorie juridique . remplacements:
associé unique:
privé: oui
applicable si:
toutes ces conditions:
- remplacements
- une de ces conditions:
- EI
- SARL . EURL
- SAS . SASU
- SELAS . SELASU
- SELARL . SELARLU
toutes ces conditions:
- remplacements
- EI
remplace:
- règle: associés
par: "'unique'"
associé multiples:
privé: oui
applicable si:
toutes ces conditions:
- remplacements
- une de ces conditions:
- SNC
- SARL . SARL
- SAS . SAS
- SELAS . SELAS
- SELARL . SELARL
remplace:
- règle: associés
par: "'multiples'"
profession libérale reglementée:
privé: oui
# privé: oui
valeur: oui
applicable si:
toutes ces conditions:
- remplacements
- une de ces conditions:
- SELARL
- SELAS
une de ces conditions:
- SELARL
- SELAS
remplace:
- règle: activités . libérale
par: oui
@ -288,9 +252,9 @@ entreprise . catégorie juridique . remplacements:
pas profession libérale reglementée:
privé: oui
valeur: oui
non applicable si:
une de ces conditions:
- remplacements = non
- SELARL
- SELAS
rend non applicable: activités . libérale . réglementée

View File

@ -0,0 +1,44 @@
import { Route, Routes, useNavigate } from 'react-router-dom'
import Popover from '@/design-system/popover/Popover'
import Documentation from '@/pages/Documentation'
import { EngineComparison } from '@/pages/simulateurs/comparaison-statuts/components/Comparateur'
import { useSitePaths } from '@/sitePaths'
export function EngineDocumentationRoutes({
namedEngines,
}: {
namedEngines: EngineComparison
}) {
const navigate = useNavigate()
const { absoluteSitePaths } = useSitePaths()
return (
<Routes>
{namedEngines.map(({ engine, name }) => (
<Route
key={name}
path={`${name}/*`}
element={
<div>
<Popover
isOpen
isDismissable
onClose={() => {
navigate(absoluteSitePaths.simulateurs.comparaison, {
replace: true,
})
}}
>
<Documentation
engine={engine}
documentationPath={`/simulateurs/comparaison-régimes-sociaux/${name}`}
/>
</Popover>
</div>
}
/>
))}
</Routes>
)
}

View File

@ -27,7 +27,6 @@ const TAG_DATA = {
SASU: {
color: 'secondary',
longName: 'Société par actions simplifiée unipersonnelle',
acronym: 'SASU',
icon: HexagonIcon,
},

View File

@ -186,8 +186,16 @@ function useUpdateSituationWithGuichet(guichetEntries: GuichetEntry[] | null) {
batchUpdateSituation({
'entreprise . activités . principale . code guichet': `'${guichet.code}'`,
'entreprise . imposition . IR . type de bénéfices': `'${guichet.typeBénéfice}'`,
'entreprise . activité . nature': PLRMétier
'entreprise . activité . nature': guichet.catégorieActivité.includes(
'LIBERALE'
)
? "'libérale'"
: guichet.catégorieActivité.includes('ARTISANALE')
? "'artisanale'"
: guichet.catégorieActivité.includes('COMMERCIALE')
? "'commerciale'"
: guichet.catégorieActivité.includes('AGRICOLE')
? "'agricole'"
: undefined,
'entreprise . activité . nature . libérale . réglementée': PLRMétier
? 'oui'

View File

@ -109,11 +109,15 @@ function useRémunérationState(): [
setState(newState)
dispatch(
batchUpdateSituation({
"entreprise . chiffre d'affaires": {
valeur: newState.CA,
unité: '€/an',
},
'entreprise . charges': { valeur: newState.charges, unité: '€/an' },
"entreprise . chiffre d'affaires": newState.CA
? {
valeur: newState.CA,
unité: '€/an',
}
: undefined,
'entreprise . charges': newState.charges
? { valeur: newState.charges, unité: '€/an' }
: undefined,
})
)
}

View File

@ -1,31 +1,34 @@
import Engine from 'publicodes'
import { useTranslation } from 'react-i18next'
import { Route, Routes, useNavigate } from 'react-router-dom'
import { DottedName } from '@/../../modele-social'
import { EngineDocumentationRoutes } from '@/components/EngineDocumentationRoutes'
import PeriodSwitch from '@/components/PeriodSwitch'
import Simulation, {
SimulationGoal,
SimulationGoals,
} from '@/components/Simulation'
import { Statut } from '@/components/StatutTag'
import { Spacing } from '@/design-system/layout'
import Popover from '@/design-system/popover/Popover'
import Documentation from '@/pages/Documentation'
import { useSitePaths } from '@/sitePaths'
import Détails from './Détails'
import Résultats from './Résultats'
type ComparateurProps = {
engines: [Engine<DottedName>, Engine<DottedName>, Engine<DottedName>]
type NamedEngine = {
engine: Engine<DottedName>
name: Statut
}
function Comparateur({ engines }: ComparateurProps) {
const { t } = useTranslation()
const navigate = useNavigate()
const [assimiléEngine, autoEntrepreneurEngine, indépendantEngine] = engines
export type EngineComparison = [NamedEngine, NamedEngine, NamedEngine]
const { absoluteSitePaths } = useSitePaths()
function Comparateur({ namedEngines }: { namedEngines: EngineComparison }) {
const { t } = useTranslation()
const engines = namedEngines.map(({ engine }) => engine) as [
Engine<DottedName>,
Engine<DottedName>,
Engine<DottedName>
]
return (
<>
@ -49,73 +52,9 @@ function Comparateur({ engines }: ComparateurProps) {
</SimulationGoals>
</Simulation>
<Spacing md />
<Résultats engines={engines} />
<Détails engines={engines} />
<Routes>
<Route
path="SASU/*"
element={
<div>
<Popover
isOpen
isDismissable
onClose={() => {
navigate(absoluteSitePaths.simulateurs.comparaison, {
replace: true,
})
}}
>
<Documentation
engine={assimiléEngine}
documentationPath="/simulateurs/comparaison-régimes-sociaux/SASU"
/>
</Popover>
</div>
}
/>
<Route
path="EI/*"
element={
<div>
<Popover
isOpen
isDismissable
onClose={() => {
navigate(absoluteSitePaths.simulateurs.comparaison, {
replace: true,
})
}}
>
<Documentation
engine={indépendantEngine}
documentationPath="/simulateurs/comparaison-régimes-sociaux/EI"
/>
</Popover>
</div>
}
/>
<Route
path="auto-entrepreneur/*"
element={
<div>
<Popover
isOpen
isDismissable
onClose={() => {
navigate(absoluteSitePaths.simulateurs.comparaison, {
replace: true,
})
}}
>
<Documentation
engine={autoEntrepreneurEngine}
documentationPath="/simulateurs/comparaison-régimes-sociaux/auto-entrepreneur"
/>
</Popover>
</div>
}
/>
</Routes>
<Résultats namedEngines={namedEngines} />
<Détails namedEngines={namedEngines} />
<EngineDocumentationRoutes namedEngines={namedEngines} />
</>
)
}

View File

@ -12,80 +12,49 @@ import { HelpIcon } from '@/design-system/icons'
import { Grid } from '@/design-system/layout'
import { getBestOption, OptionType } from '../utils'
import { EngineComparison } from './Comparateur'
import StatusCard from './StatusCard'
const getStatusLabelsArray = (statusArray: OptionType[]) =>
statusArray.map(
(statusOption) => statusOption.type.toUpperCase() as 'SASU' | 'EI' | 'AE'
)
const getGridSizes = (statusArray: OptionType[]) => {
return { sizeXs: 12, sizeLg: 4 * statusArray.length }
}
const DetailsRowCards = ({
engines: [assimiléEngine, autoEntrepreneurEngine, indépendantEngine],
namedEngines,
dottedName,
unit,
bestOption,
evolutionDottedName,
evolutionLabel,
footers,
label,
warnings,
footer,
warning,
}: {
engines: [Engine<DottedName>, Engine<DottedName>, Engine<DottedName>]
namedEngines: EngineComparison
dottedName: DottedName
unit?: string
bestOption?: 'sasu' | 'ei' | 'ae'
bestOption?: 1 | 2 | 3
evolutionDottedName?: DottedName
evolutionLabel?: ReactNode | string
footers?: { sasu: ReactNode; ei: ReactNode; ae: ReactNode }
label?: ReactNode | string
warnings?: { sasu?: ReactNode; ei?: ReactNode; ae?: ReactNode }
warning?: (engine: Engine<DottedName>) => ReactNode
footer?: (engine: Engine<DottedName>) => ReactNode
}) => {
const assimiléEvaluation = assimiléEngine.evaluate({
valeur: dottedName,
...(unit && { unité: unit }),
})
const indépendantEvaluation = indépendantEngine.evaluate({
valeur: dottedName,
...(unit && { unité: unit }),
})
const autoEntrepreneurEvaluation = autoEntrepreneurEngine.evaluate({
valeur: dottedName,
...(unit && { unité: unit }),
})
const options: OptionType[] = [
{
type: 'sasu',
value: Math.round(assimiléEvaluation.nodeValue as number),
engine: assimiléEngine,
documentationPath: '/simulateurs/comparaison-régimes-sociaux/SASU',
},
{
type: 'ei',
value: Math.round(indépendantEvaluation.nodeValue as number),
engine: indépendantEngine,
documentationPath: '/simulateurs/comparaison-régimes-sociaux/EI',
},
{
type: 'ae',
value: Math.round(autoEntrepreneurEvaluation.nodeValue as number),
engine: autoEntrepreneurEngine,
documentationPath:
'/simulateurs/comparaison-régimes-sociaux/auto-entrepreneur',
},
]
console.log(namedEngines)
const options = namedEngines.map(({ engine, name }) => ({
engine,
name,
value: engine.evaluate({
valeur: dottedName,
...(unit && { unité: unit }),
}).nodeValue,
})) as [OptionType, OptionType, OptionType]
const bestOptionValue = bestOption ?? getBestOption(options)
const sortedStatus = [...options]
.reduce((acc: OptionType[][], option: OptionType) => {
const groupedOptions = options
.reduce((acc, option) => {
const newAcc = [...acc]
const sameValues = options.filter(
(optionFiltered) => optionFiltered.value === option.value
@ -94,7 +63,7 @@ const DetailsRowCards = ({
if (
!newAcc.find((arrayOfStatus) =>
arrayOfStatus.some(
(statusObject: OptionType) => statusObject.value === option.value
(statusObject) => statusObject.value === option.value
)
)
) {
@ -102,30 +71,31 @@ const DetailsRowCards = ({
}
return newAcc
}, [] as OptionType[][])
.filter((arrayOfStatus: OptionType[]) => arrayOfStatus.length > 0)
}, [] as (typeof options)[0][][])
.filter((arrayOfStatus) => arrayOfStatus.length > 0)
return (
<Grid container spacing={4}>
{sortedStatus.map((statusArray: OptionType[]) => {
const statusObject: OptionType = statusArray[0]
{groupedOptions.map((sameValueOptions) => {
const statusObject = sameValueOptions[0]
const { sizeXs, sizeLg } = getGridSizes(statusArray)
const { sizeXs, sizeLg } = getGridSizes(sameValueOptions)
return (
<Grid
key={`${dottedName}-${statusObject.type}`}
key={`${dottedName}-${statusObject.name}`}
item
xs={sizeXs}
lg={sizeLg}
as="ul"
>
<StatusCard
statut={getStatusLabelsArray(statusArray)}
footerContent={footers?.[statusObject.type]}
statut={sameValueOptions.map(({ name }) => name)}
footerContent={footer?.(statusObject.engine)}
isBestOption={
statusArray.length !== 3 &&
bestOptionValue === statusObject.type
sameValueOptions.length !== 3 &&
bestOptionValue === statusObject.name
}
>
<WhenNotApplicable
@ -133,6 +103,13 @@ const DetailsRowCards = ({
engine={statusObject.engine}
>
<DisabledLabel>Ne s'applique pas</DisabledLabel>
<StyledRuleLink
documentationPath={`/simulateurs/comparaison-régimes-sociaux/${statusObject.name}`}
dottedName={dottedName}
engine={statusObject.engine}
>
<HelpIcon />
</StyledRuleLink>
</WhenNotApplicable>
<WhenApplicable
dottedName={dottedName}
@ -151,14 +128,13 @@ const DetailsRowCards = ({
{label && label}
</span>
<StyledRuleLink
documentationPath={statusObject.documentationPath}
documentationPath={`/simulateurs/comparaison-régimes-sociaux/${statusObject.name}`}
dottedName={dottedName}
engine={statusObject.engine}
>
<HelpIcon />
</StyledRuleLink>
{warnings?.[statusObject.type] &&
warnings?.[statusObject.type]}
{warning?.(statusObject.engine)}
</StyledDiv>
{evolutionDottedName && (
<Precisions>

View File

@ -1,32 +1,23 @@
import Engine from 'publicodes'
import { Trans } from 'react-i18next'
import styled from 'styled-components'
import { DottedName } from '@/../../modele-social'
import { ExplicableRule } from '@/components/conversation/Explicable'
import Value, {
WhenAlreadyDefined,
WhenValueEquals,
} from '@/components/EngineValue'
import Value, { Condition } from '@/components/EngineValue'
import { Accordion, Item } from '@/design-system'
import { Emoji } from '@/design-system/emoji'
import { ExternalLinkIcon, PlusCircleIcon } from '@/design-system/icons'
import { Container, Grid, Spacing } from '@/design-system/layout'
import { Container, Spacing } from '@/design-system/layout'
import { Strong } from '@/design-system/typography'
import { H2, H4 } from '@/design-system/typography/heading'
import { StyledLink } from '@/design-system/typography/link'
import { Body } from '@/design-system/typography/paragraphs'
import { EngineComparison } from './Comparateur'
import DetailsRowCards from './DetailsRowCards'
import ItemTitle from './ItemTitle'
import StatusCard from './StatusCard'
import WarningTooltip from './WarningTooltip'
const Détails = ({
engines: [assimiléEngine, autoEntrepreneurEngine, indépendantEngine],
}: {
engines: [Engine<DottedName>, Engine<DottedName>, Engine<DottedName>]
}) => {
const Détails = ({ namedEngines }: { namedEngines: EngineComparison }) => {
return (
<StyledContainer
backgroundColor={(theme) =>
@ -78,11 +69,7 @@ const Détails = ({
<DetailsRowCards
dottedName="protection sociale . retraite . base"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/mois"
/>
@ -108,11 +95,7 @@ const Détails = ({
<DetailsRowCards
dottedName="protection sociale . retraite . complémentaire"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/mois"
evolutionLabel={<Trans>au bout de 10 ans</Trans>}
/>
@ -157,40 +140,36 @@ const Détails = ({
</Body>
<DetailsRowCards
dottedName="protection sociale . maladie . arrêt maladie"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/jour"
warnings={{
sasu: (
<WhenValueEquals
engine={assimiléEngine}
expression="protection sociale . maladie . arrêt maladie"
value={0}
>
<WarningTooltip
tooltip={
<span
css={`
font-weight: normal;
`}
>
<Trans>
Votre <Strong>rémunération</Strong> est{' '}
<Strong>trop faible</Strong> pour bénéficier darrêt
maladie en SASU.
</Trans>
</span>
}
id="tooltip-sasu-arrêt-maladie"
/>
</WhenValueEquals>
),
}}
footers={{
sasu: (
warning={(engine) => (
<Condition
engine={engine}
expression="protection sociale . maladie . arrêt maladie = 0"
>
<WarningTooltip
tooltip={
<span
css={`
font-weight: normal;
`}
>
<Trans>
Votre <Strong>rémunération</Strong> est{' '}
<Strong>trop faible</Strong> pour bénéficier darrêt
maladie.
</Trans>
</span>
}
id="tooltip-sasu-arrêt-maladie"
/>
</Condition>
)}
footer={(engine) => (
<Condition
engine={engine}
expression="protection sociale . maladie . arrêt maladie != 0"
>
<StyledDiv>
<PlusCircleIcon
css={`
@ -204,50 +183,17 @@ const Détails = ({
>
<Trans>
Pour y prétendre, vous devez voir cotisé au moins{' '}
<Strong>3 mois</Strong>
<Strong>
<Value
engine={engine}
expression="protection sociale . maladie . arrêt maladie . délai d'attente"
/>
</Strong>
</Trans>
</Body>
</StyledDiv>
),
ei: (
<StyledDiv>
<PlusCircleIcon
css={`
margin-top: 0 !important;
`}
/>
<Body
css={`
margin: 0;
`}
>
<Trans>
Pour y prétendre, vous devez voir cotisé au moins{' '}
<Strong>12 mois</Strong>
</Trans>
</Body>
</StyledDiv>
),
ae: (
<StyledDiv>
<PlusCircleIcon
css={`
margin-top: 0 !important;
`}
/>
<Body
css={`
margin: 0;
`}
>
<Trans>
Pour y prétendre, vous devez voir cotisé au moins{' '}
<Strong>12 mois</Strong>
</Trans>
</Body>
</StyledDiv>
),
}}
</Condition>
)}
/>
<StyledH4>
@ -264,11 +210,7 @@ const Détails = ({
</Body>
<DetailsRowCards
dottedName="protection sociale . maladie . accidents du travail et maladies professionnelles . indemmnités"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/mois"
evolutionDottedName="protection sociale . maladie . accidents du travail et maladies professionnelles . indemmnités . à partir du 29ème jour"
evolutionLabel={<Trans>à partir du 29ème jour</Trans>}
@ -308,11 +250,7 @@ const Détails = ({
<DetailsRowCards
dottedName="protection sociale . maladie . maternité paternité adoption"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/jour"
/>
@ -332,11 +270,7 @@ const Détails = ({
</Body>
<DetailsRowCards
dottedName="protection sociale . maladie . maternité paternité adoption . allocation forfaitaire de repos maternel"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
label={<Trans>versés en deux fois</Trans>}
/>
@ -356,11 +290,7 @@ const Détails = ({
</Body>
<DetailsRowCards
dottedName="protection sociale . maladie . maternité paternité adoption . allocation forfaitaire de repos adoption"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
label={<Trans>versés en une fois</Trans>}
/>
</Item>
@ -417,11 +347,7 @@ const Détails = ({
<DetailsRowCards
dottedName="protection sociale . invalidité et décès . pension invalidité . invalidité partielle"
evolutionDottedName="protection sociale . invalidité et décès . pension invalidité . invalidité totale"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/mois"
label={
<span style={{ fontSize: '1rem' }}>
@ -448,11 +374,7 @@ const Détails = ({
</Body>
<DetailsRowCards
dottedName="protection sociale . invalidité et décès . accidents du travail et maladies professionnelles . rente incapacité"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/mois"
/>
@ -469,11 +391,7 @@ const Détails = ({
</Body>
<DetailsRowCards
dottedName="protection sociale . invalidité et décès . capital décès"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
/>
<Body
@ -489,7 +407,7 @@ const Détails = ({
sa vie professionnelle.
</Trans>
</Body>
<StatusCard statut={['SASU', 'EI', 'AE']}>
{/* <StatusCard statut={['SASU', 'EI', 'AE']}>
<span>
<Value
linkToRule={false}
@ -505,7 +423,7 @@ const Détails = ({
<Trans>maximum</Trans>
</WhenAlreadyDefined>
</span>
</StatusCard>
</StatusCard> */}
<Body
css={`
@ -520,11 +438,7 @@ const Détails = ({
<DetailsRowCards
dottedName="protection sociale . invalidité et décès . accidents du travail et maladies professionnelles . rente décès"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/mois"
/>
@ -541,11 +455,7 @@ const Détails = ({
<DetailsRowCards
dottedName="protection sociale . invalidité et décès . capital décès . orphelin"
engines={[
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
]}
namedEngines={namedEngines}
unit="€/enfant"
/>
</Item>
@ -623,7 +533,7 @@ const Détails = ({
*/
}
<StyledH4>
{/* <StyledH4>
<Trans>Dépôt de capital</Trans>
<ExplicableRule dottedName="entreprise . capital social" />
</StyledH4>
@ -648,9 +558,9 @@ const Détails = ({
</DisabledLabel>
</StatusCard>
</Grid>
</Grid>
</Grid> */}
<StyledH4>
{/* <StyledH4>
<Trans>Statut du conjoint</Trans>
</StyledH4>
<Body>
@ -678,7 +588,7 @@ const Détails = ({
<Trans>Conjoint collaborateur</Trans>
</StatusCard>
</Grid>
</Grid>
</Grid> */}
</Item>
</Accordion>
</StyledContainer>

View File

@ -1,59 +1,31 @@
import Engine from 'publicodes'
import { Trans, useTranslation } from 'react-i18next'
import styled from 'styled-components'
import { DottedName } from '@/../../modele-social'
import Value, { Condition, WhenAlreadyDefined } from '@/components/EngineValue'
import RuleLink from '@/components/RuleLink'
import { CheckList } from '@/design-system'
import { ExternalLinkIcon, HelpIcon } from '@/design-system/icons'
import { Grid } from '@/design-system/layout'
import { ExternalLinkIcon } from '@/design-system/icons'
import { H2 } from '@/design-system/typography/heading'
import { StyledLink } from '@/design-system/typography/link'
import { Body } from '@/design-system/typography/paragraphs'
import { getBestOption, OptionType } from '../utils'
import AllerPlusLoinRevenus from './AllerPlusLoinRevenus'
import StatusCard from './StatusCard'
import WarningTooltip from './WarningTooltip'
import { EngineComparison } from './Comparateur'
const RevenuAprèsImpot = ({
engines,
namedEngines,
}: {
engines: [Engine<DottedName>, Engine<DottedName>, Engine<DottedName>]
namedEngines: EngineComparison
}) => {
const [assimiléEngine, autoEntrepreneurEngine, indépendantEngine] = engines
const [assimiléEngine, autoEntrepreneurEngine, indépendantEngine] =
namedEngines
const { t } = useTranslation()
const assimiléValue = assimiléEngine.evaluate({
valeur: 'dirigeant . rémunération . net . après impôt',
unité: '€/mois',
}).nodeValue
const indépendantValue = indépendantEngine.evaluate({
valeur: 'dirigeant . rémunération . net . après impôt',
unité: '€/mois',
}).nodeValue
const autoEntrepreneurValue = autoEntrepreneurEngine.evaluate({
valeur: 'dirigeant . rémunération . net . après impôt',
unité: '€/mois',
}).nodeValue
const options: OptionType[] = [
{
type: 'sasu',
value: assimiléValue,
},
{
type: 'ei',
value: indépendantValue,
},
{
type: 'ae',
value: autoEntrepreneurValue,
},
]
const options = namedEngines.map(({ engine, name }) => ({
engine,
name,
value: engine.evaluate({
valeur: 'dirigeant . rémunération . net . après impôt',
unité: '€/mois',
}).nodeValue,
})) as [OptionType, OptionType, OptionType]
const bestOption = getBestOption(options)
@ -62,12 +34,12 @@ const RevenuAprèsImpot = ({
<H2>
<Trans>Revenu après impôt</Trans>
</H2>
{/*
<Grid container spacing={4}>
<Grid item xs={12} lg={4}>
<StatusCard
statut={['SASU']}
isBestOption={bestOption === 'sasu'}
isBestOption={bestOption === 'SASU'}
footerContent={
<CheckList
items={[
@ -281,7 +253,7 @@ const RevenuAprèsImpot = ({
</Grid>
<DivAlignRight>
<AllerPlusLoinRevenus engines={engines} />
</DivAlignRight>
</DivAlignRight> */}
</>
)
}

View File

@ -1,17 +1,12 @@
import Engine from 'publicodes'
import styled from 'styled-components'
import { DottedName } from '@/../../modele-social'
import { Container } from '@/design-system/layout'
import { EngineComparison } from './Comparateur'
import RevenuAprèsImpot from './RevenuAprèsImpot'
import RevenuEstimé from './RevenuEstimé'
const Résultats = ({
engines,
}: {
engines: [Engine<DottedName>, Engine<DottedName>, Engine<DottedName>]
}) => {
const Résultats = ({ namedEngines }: { namedEngines: EngineComparison }) => {
return (
<StyledContainer
backgroundColor={(theme) =>
@ -21,7 +16,7 @@ const Résultats = ({
}
>
<RevenuEstimé />
<RevenuAprèsImpot engines={engines} />
<RevenuAprèsImpot namedEngines={namedEngines} />
</StyledContainer>
)
}

View File

@ -2,7 +2,7 @@ import { ReactNode, useRef } from 'react'
import { Trans } from 'react-i18next'
import styled from 'styled-components'
import { StatutTag } from '@/components/StatutTag'
import { Statut, StatutTag } from '@/components/StatutTag'
import { CardContainer } from '@/design-system/card/Card'
import { Emoji } from '@/design-system/emoji'
import { Grid } from '@/design-system/layout'
@ -11,7 +11,7 @@ import { Body } from '@/design-system/typography/paragraphs'
import { generateUuid } from '@/utils'
type StatutCardType = {
statut: ('SASU' | 'EI' | 'AE')[]
statut: Statut[]
footerContent?: ReactNode
isBestOption?: boolean
children: ReactNode
@ -31,7 +31,7 @@ const StatusCard = ({
<Grid container spacing={1}>
{status.map((statusString) => (
<Grid item key={statusString}>
<StatutTag statut={statusString} text="longName" showIcon />
<StatutTag statut={statusString} text="acronym" showIcon />
</Grid>
))}
</Grid>

View File

@ -1,5 +1,3 @@
import { DottedName } from 'modele-social'
import Engine from 'publicodes'
import { useMemo } from 'react'
import { Trans } from 'react-i18next'
@ -7,7 +5,7 @@ import { useEngine, useRawSituation } from '@/components/utils/EngineContext'
import { Strong } from '@/design-system/typography'
import { Intro } from '@/design-system/typography/paragraphs'
import Comparateur from './components/Comparateur'
import Comparateur, { EngineComparison } from './components/Comparateur'
import {
CasParticuliersProvider,
useCasParticuliers,
@ -58,10 +56,10 @@ function ComparateurStatutsUI() {
)
const engines = [
assimiléEngine,
autoEntrepreneurEngine,
indépendantEngine,
] as [Engine<DottedName>, Engine<DottedName>, Engine<DottedName>]
{ engine: assimiléEngine, name: 'SASU' },
{ engine: indépendantEngine, name: 'EI' },
{ engine: autoEntrepreneurEngine, name: 'AE' },
] as EngineComparison
return (
<>
@ -76,7 +74,7 @@ function ComparateurStatutsUI() {
correspond le mieux.
</Trans>
</Intro>
<Comparateur engines={engines} />
<Comparateur namedEngines={engines} />
</>
)
}

View File

@ -1,18 +1,12 @@
import Engine from 'publicodes'
import Engine, { Evaluation } from 'publicodes'
import { DottedName } from '@/../../modele-social'
import { Statut } from '@/components/StatutTag'
export type ValueType =
| string
| number
| boolean
| null
| Record<string, unknown>
export type OptionType = {
type: 'sasu' | 'ei' | 'ae'
value?: ValueType
engine?: Engine<DottedName>
documentationPath?: string
engine: Engine<DottedName>
name: Statut
value: Evaluation
}
export const getBestOption = (options: OptionType[]) => {
const sortedOptions = [...options].sort(
@ -30,5 +24,5 @@ export const getBestOption = (options: OptionType[]) => {
}
)
return sortedOptions?.[0]?.type
return sortedOptions?.[0]?.name
}

View File

@ -46,6 +46,9 @@ export function coûtCréationEntrepriseConfig({
'oui',
'dirigeant . indépendant . PL . métier . santé . vétérinaire . par défaut':
'oui',
'entreprise . catégorie juridique . association': {
'applicable si': 'non',
},
},
},
component: CoutCreationEntreprise,