mirror of
https://github.com/betagouv/mon-entreprise
synced 2025-02-13 06:05:02 +00:00
feat(lodeom): stylise les switchs
This commit is contained in:
parent
b67d0dec5f
commit
617d0ee6df
8 changed files with 239 additions and 83 deletions
|
@ -2,9 +2,12 @@ import { DottedName } from 'modele-social'
|
|||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import { styled } from 'styled-components'
|
||||
|
||||
import { useEngine } from '@/components/utils/EngineContext'
|
||||
import { Radio, ToggleGroup } from '@/design-system'
|
||||
import { Strong } from '@/design-system/typography'
|
||||
import { Body } from '@/design-system/typography/paragraphs'
|
||||
import { enregistreLaRéponse } from '@/store/actions/actions'
|
||||
|
||||
export default function EffectifSwitch() {
|
||||
|
@ -21,16 +24,46 @@ export default function EffectifSwitch() {
|
|||
}, [currentEffectif, engineEffectif])
|
||||
|
||||
return (
|
||||
<ToggleGroup
|
||||
value={currentEffectif}
|
||||
onChange={(value) => {
|
||||
setCurrentEffectif(value)
|
||||
dispatch(enregistreLaRéponse(dottedName, `'${value}'`))
|
||||
}}
|
||||
aria-label={t("Effectif de l'entreprise")}
|
||||
>
|
||||
<Radio value="10">{t('Moins de 50 salariés')}</Radio>
|
||||
<Radio value="100">{t('Plus de 50 salariés')}</Radio>
|
||||
</ToggleGroup>
|
||||
<Container>
|
||||
<StyledBody id="effectif-switch-label">
|
||||
<Strong>{t("Effectif de l'entreprise")} :</Strong>
|
||||
</StyledBody>
|
||||
<StyledToggleGroup
|
||||
value={currentEffectif}
|
||||
onChange={(value) => {
|
||||
setCurrentEffectif(value)
|
||||
dispatch(enregistreLaRéponse(dottedName, `'${value}'`))
|
||||
}}
|
||||
aria-labelledby="effectif-switch-label"
|
||||
>
|
||||
<StyledRadio value="10">{t('Moins de 50 salariés')}</StyledRadio>
|
||||
<StyledRadio value="100">{t('Plus de 50 salariés')}</StyledRadio>
|
||||
</StyledToggleGroup>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
column-gap: ${({ theme }) => theme.spacings.sm};
|
||||
width: 100%;
|
||||
`
|
||||
const StyledBody = styled(Body)`
|
||||
margin: ${({ theme }) => theme.spacings.xxs} 0;
|
||||
`
|
||||
const StyledToggleGroup = styled(ToggleGroup)`
|
||||
display: flex;
|
||||
> * {
|
||||
display: flex;
|
||||
/* flex-direction: column; */
|
||||
}
|
||||
`
|
||||
const StyledRadio = styled(Radio)`
|
||||
white-space: nowrap;
|
||||
> span {
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import { styled } from 'styled-components'
|
||||
|
||||
import { Radio, ToggleGroup } from '@/design-system'
|
||||
import { Strong } from '@/design-system/typography'
|
||||
import { Body } from '@/design-system/typography/paragraphs'
|
||||
import { RégularisationMethod } from '@/utils/réductionDeCotisations'
|
||||
|
||||
type Props = {
|
||||
|
@ -15,28 +18,62 @@ export default function RégularisationSwitch({
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<ToggleGroup
|
||||
value={régularisationMethod}
|
||||
onChange={(value) => {
|
||||
setRégularisationMethod(value as RégularisationMethod)
|
||||
}}
|
||||
aria-label={t(
|
||||
'pages.simulateurs.réduction-générale.régularisation.type',
|
||||
'Type de régularisation'
|
||||
)}
|
||||
>
|
||||
<Radio value="annuelle">
|
||||
{t(
|
||||
'pages.simulateurs.réduction-générale.régularisation.annuelle',
|
||||
'Régularisation annuelle'
|
||||
)}
|
||||
</Radio>
|
||||
<Radio value="progressive">
|
||||
{t(
|
||||
'pages.simulateurs.réduction-générale.régularisation.progressive',
|
||||
'Régularisation progressive'
|
||||
)}
|
||||
</Radio>
|
||||
</ToggleGroup>
|
||||
<Container>
|
||||
<StyledBody id="régularisation-switch-label">
|
||||
<Strong>
|
||||
{t(
|
||||
'pages.simulateurs.réduction-générale.régularisation.type',
|
||||
'Type de régularisation'
|
||||
)}{' '}
|
||||
:
|
||||
</Strong>
|
||||
</StyledBody>
|
||||
|
||||
<StyledToggleGroup
|
||||
value={régularisationMethod}
|
||||
onChange={(value) => {
|
||||
setRégularisationMethod(value as RégularisationMethod)
|
||||
}}
|
||||
aria-labelledby="régularisation-switch-label"
|
||||
>
|
||||
<StyledRadio value="annuelle">
|
||||
{t(
|
||||
'pages.simulateurs.réduction-générale.régularisation.annuelle',
|
||||
'Régularisation annuelle'
|
||||
)}
|
||||
</StyledRadio>
|
||||
<StyledRadio value="progressive">
|
||||
{t(
|
||||
'pages.simulateurs.réduction-générale.régularisation.progressive',
|
||||
'Régularisation progressive'
|
||||
)}
|
||||
</StyledRadio>
|
||||
</StyledToggleGroup>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
column-gap: ${({ theme }) => theme.spacings.sm};
|
||||
width: 100%;
|
||||
`
|
||||
const StyledBody = styled(Body)`
|
||||
margin: ${({ theme }) => theme.spacings.xxs} 0;
|
||||
`
|
||||
const StyledToggleGroup = styled(ToggleGroup)`
|
||||
display: flex;
|
||||
> * {
|
||||
display: flex;
|
||||
/* flex-direction: column; */
|
||||
}
|
||||
`
|
||||
const StyledRadio = styled(Radio)`
|
||||
white-space: nowrap;
|
||||
> span {
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
|
|
|
@ -379,7 +379,6 @@ Vous êtes dirigeant d'une SAS(U) ? <2>Accéder au simulateur de revenu dédié<
|
|||
with a company director, there are <1>3 possible statuses</1> for
|
||||
you<3>(collaborating spouse</3>, <6>associate spouse</6> or <9>salaried
|
||||
spouse</9>).
|
||||
Zone de l'entreprise: Company zone
|
||||
accessibility:
|
||||
description: Référentiel Général d'Amélioration de l'Accessibilité (General
|
||||
Accessibility Improvement Reference System)
|
||||
|
@ -1451,6 +1450,7 @@ pages:
|
|||
included in the simulator.</5>
|
||||
title: Corporate tax simulator
|
||||
lodeom:
|
||||
barème-switch-label: "Scale to be applied :"
|
||||
legend: Employee's gross salary and applicable Lodeom exemption
|
||||
meta:
|
||||
description: Estimated amount of Lodeom exemption. This exemption applies, under
|
||||
|
@ -1490,6 +1490,7 @@ pages:
|
|||
salaries below 3.5 SMIC. This means, for 2024, a total
|
||||
remuneration not exceeding <2>€6,306.30</2> gross per month.
|
||||
stage: The Lodeom exemption does not apply to internship bonuses.
|
||||
zone-switch-label: Company location
|
||||
médecin:
|
||||
meta:
|
||||
description: Calculation of net income after deduction of contributions, based
|
||||
|
|
|
@ -402,7 +402,6 @@ Vous êtes dirigeant d'une SAS(U) ? <2>Accéder au simulateur de revenu dédié<
|
|||
"Vous êtes marié(e), pacsé(e) ou en union libre avec un chef d’entreprise : il
|
||||
existe <1>3 statuts possibles</1> pour vous (<3>conjoint collaborateur</3>,
|
||||
<6>conjoint associé</6> ou <9>conjoint salarié</9>)."
|
||||
Zone de l'entreprise: Zone de l'entreprise
|
||||
accessibility:
|
||||
description: Référentiel Général d’Amélioration de l’Accessibilité
|
||||
title: Accessibilité
|
||||
|
@ -1544,6 +1543,7 @@ pages:
|
|||
pas intégrés dans le simulateur.</5>
|
||||
title: Simulateur d'impôt sur les sociétés
|
||||
lodeom:
|
||||
barème-switch-label: "Barème à appliquer :"
|
||||
legend: Rémunération brute du salarié et exonération Lodeom applicable
|
||||
meta:
|
||||
description: Estimation du montant de l'exonération Lodeom. Cette exonération
|
||||
|
@ -1587,6 +1587,7 @@ pages:
|
|||
2024, une rémunération totale qui ne dépasse pas <2>6 306,30 €</2>
|
||||
bruts par mois.
|
||||
stage: L'exonération Lodeom ne s'applique pas sur les gratifications de stage.
|
||||
zone-switch-label: Localisation de l'entreprise
|
||||
médecin:
|
||||
meta:
|
||||
description: Calcul du revenu net après déduction des cotisations à partir du
|
||||
|
|
|
@ -3,7 +3,7 @@ import { DottedName } from 'modele-social'
|
|||
import { PublicodesExpression, RuleNode } from 'publicodes'
|
||||
import { useCallback, useContext } from 'react'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { styled } from 'styled-components'
|
||||
import { IStyledComponent, styled } from 'styled-components'
|
||||
|
||||
import { ExplicableRule } from '@/components/conversation/Explicable'
|
||||
import RuleInput from '@/components/conversation/RuleInput'
|
||||
|
@ -73,6 +73,7 @@ type SimpleFieldProps = {
|
|||
showSuggestions?: boolean
|
||||
label?: string
|
||||
['aria-label']?: string
|
||||
labelStyle?: IStyledComponent<'web', object>
|
||||
}
|
||||
|
||||
export function SimpleField(props: SimpleFieldProps) {
|
||||
|
@ -82,6 +83,7 @@ export function SimpleField(props: SimpleFieldProps) {
|
|||
summary,
|
||||
showSuggestions = false,
|
||||
label,
|
||||
labelStyle,
|
||||
} = props
|
||||
const dispatch = useDispatch()
|
||||
const engine = useContext(EngineContext)
|
||||
|
@ -95,39 +97,38 @@ export function SimpleField(props: SimpleFieldProps) {
|
|||
[dispatch]
|
||||
)
|
||||
|
||||
let displayedQuestion =
|
||||
question ?? evaluateQuestion(engine, engine.getRule(dottedName))
|
||||
|
||||
const labelId = useSSRSafeId()
|
||||
const targetUnit = useSelector(targetUnitSelector)
|
||||
|
||||
if (evaluation.nodeValue === null) {
|
||||
return null
|
||||
}
|
||||
let displayedLabel =
|
||||
label ??
|
||||
(!displayedQuestion
|
||||
? rule.title + (rule.rawNode.résumé ? ` – ${rule.rawNode.résumé}` : '')
|
||||
: undefined)
|
||||
let displayedLabel = label
|
||||
if (!displayedLabel) {
|
||||
displayedLabel =
|
||||
question ?? evaluateQuestion(engine, engine.getRule(dottedName))
|
||||
}
|
||||
if (!displayedLabel) {
|
||||
displayedLabel =
|
||||
rule.title + (rule.rawNode.résumé ? ` – ${rule.rawNode.résumé}` : '')
|
||||
}
|
||||
|
||||
if (meta.requis === 'oui') {
|
||||
if (displayedLabel) {
|
||||
displayedLabel += ' *'
|
||||
}
|
||||
if (displayedQuestion) {
|
||||
displayedQuestion += ' *'
|
||||
}
|
||||
}
|
||||
|
||||
const markdownComponents = {
|
||||
p: labelStyle ?? Intro,
|
||||
}
|
||||
|
||||
return (
|
||||
<FadeIn>
|
||||
{displayedQuestion ? (
|
||||
<StyledQuestion id={labelId}>
|
||||
<Markdown components={{ p: Intro }}>{displayedQuestion}</Markdown>
|
||||
<ExplicableRule dottedName={dottedName} />
|
||||
</StyledQuestion>
|
||||
) : (
|
||||
<Spacing sm />
|
||||
)}
|
||||
<StyledQuestion id={labelId}>
|
||||
<Markdown components={markdownComponents}>{displayedLabel}</Markdown>
|
||||
<ExplicableRule dottedName={dottedName} />
|
||||
</StyledQuestion>
|
||||
{summary && <SmallBody>{summary ?? rule.rawNode.résumé}</SmallBody>}
|
||||
<RuleInput
|
||||
dottedName={dottedName}
|
||||
|
@ -136,8 +137,7 @@ export function SimpleField(props: SimpleFieldProps) {
|
|||
? targetUnit
|
||||
: undefined
|
||||
}
|
||||
aria-labelledby={displayedQuestion ? labelId : undefined}
|
||||
label={displayedLabel}
|
||||
aria-labelledby={labelId}
|
||||
required={meta.requis === 'oui'}
|
||||
missing={
|
||||
evaluation.nodeValue === undefined ||
|
||||
|
|
|
@ -1,18 +1,49 @@
|
|||
import { DottedName } from 'modele-social'
|
||||
import { renderToString } from 'react-dom/server'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { styled } from 'styled-components'
|
||||
|
||||
import { Body } from '@/design-system/typography/paragraphs'
|
||||
import { useZoneLodeom } from '@/hooks/useZoneLodeom'
|
||||
import { SimpleField } from '@/pages/assistants/components/Fields'
|
||||
|
||||
export default function BarèmeSwitch() {
|
||||
const { currentZone } = useZoneLodeom()
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
currentZone && (
|
||||
<SimpleField
|
||||
dottedName={
|
||||
`salarié . cotisations . exonérations . lodeom . ${currentZone} . barèmes` as DottedName
|
||||
}
|
||||
/>
|
||||
<Container>
|
||||
<SimpleField
|
||||
dottedName={
|
||||
`salarié . cotisations . exonérations . lodeom . ${currentZone} . barèmes` as DottedName
|
||||
}
|
||||
label={renderToString(
|
||||
<p>
|
||||
<strong>
|
||||
{t(
|
||||
'pages.simulateurs.lodeom.barème-switch-label',
|
||||
'Barème à appliquer :'
|
||||
)}
|
||||
</strong>
|
||||
</p>
|
||||
)}
|
||||
labelStyle={StyledBody}
|
||||
/>
|
||||
</Container>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
column-gap: ${({ theme }) => theme.spacings.sm};
|
||||
width: 100%;
|
||||
margin-bottom: -${({ theme }) => theme.spacings.xl};
|
||||
`
|
||||
const StyledBody = styled(Body)`
|
||||
margin: ${({ theme }) => theme.spacings.xxs} 0;
|
||||
`
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import { styled } from 'styled-components'
|
||||
|
||||
import { Radio, ToggleGroup } from '@/design-system'
|
||||
import { Strong } from '@/design-system/typography'
|
||||
import { Body } from '@/design-system/typography/paragraphs'
|
||||
import { useZoneLodeom } from '@/hooks/useZoneLodeom'
|
||||
|
||||
export default function ZoneSwitch() {
|
||||
|
@ -8,17 +11,53 @@ export default function ZoneSwitch() {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<ToggleGroup
|
||||
value={currentZone}
|
||||
onChange={(value) => {
|
||||
updateZone(value)
|
||||
}}
|
||||
aria-label={t("Zone de l'entreprise")}
|
||||
>
|
||||
<Radio value="zone un">
|
||||
{t('Guadeloupe, Guyane, Martinique, La Réunion')}
|
||||
</Radio>
|
||||
<Radio value="zone deux">{t('Saint-Barthélémy, Saint-Martin')}</Radio>
|
||||
</ToggleGroup>
|
||||
<Container>
|
||||
<StyledBody id="zone-switch-label">
|
||||
<Strong>
|
||||
{t(
|
||||
'pages.simulateurs.lodeom.zone-switch-label',
|
||||
"Localisation de l'entreprise"
|
||||
)}{' '}
|
||||
:
|
||||
</Strong>
|
||||
</StyledBody>
|
||||
<StyledToggleGroup
|
||||
value={currentZone}
|
||||
onChange={updateZone}
|
||||
aria-labelledby="zone-switch-label"
|
||||
>
|
||||
<StyledRadio value="zone un">
|
||||
{t('Guadeloupe, Guyane, Martinique, La Réunion')}
|
||||
</StyledRadio>
|
||||
<StyledRadio value="zone deux">
|
||||
{t('Saint-Barthélémy, Saint-Martin')}
|
||||
</StyledRadio>
|
||||
</StyledToggleGroup>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
column-gap: ${({ theme }) => theme.spacings.sm};
|
||||
width: 100%;
|
||||
`
|
||||
const StyledBody = styled(Body)`
|
||||
margin: ${({ theme }) => theme.spacings.xxs} 0;
|
||||
`
|
||||
const StyledToggleGroup = styled(ToggleGroup)`
|
||||
display: flex;
|
||||
> * {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
`
|
||||
const StyledRadio = styled(Radio)`
|
||||
white-space: nowrap;
|
||||
> span {
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
|
|
|
@ -6,7 +6,7 @@ import { styled } from 'styled-components'
|
|||
|
||||
import { useEngine } from '@/components/utils/EngineContext'
|
||||
import { Radio, ToggleGroup } from '@/design-system'
|
||||
import { FlexCenter } from '@/design-system/global-style'
|
||||
import { Strong } from '@/design-system/typography'
|
||||
import { Body } from '@/design-system/typography/paragraphs'
|
||||
import { enregistreLaRéponse } from '@/store/actions/actions'
|
||||
import { réductionGénéraleDottedName } from '@/utils/réductionDeCotisations'
|
||||
|
@ -30,9 +30,9 @@ export default function CongésPayésSwitch() {
|
|||
return (
|
||||
<Container>
|
||||
<StyledBody id="caisse-congés-payés-label">
|
||||
{engine.getRule(dottedName).title}
|
||||
<Strong>{engine.getRule(dottedName).title} :</Strong>
|
||||
</StyledBody>
|
||||
<ToggleGroup
|
||||
<StyledToggleGroup
|
||||
value={currentCongésPayés}
|
||||
onChange={(value) => {
|
||||
setCurrentCongésPayés(value)
|
||||
|
@ -40,19 +40,33 @@ export default function CongésPayésSwitch() {
|
|||
}}
|
||||
aria-labelledby="caisse-congés-payés-label"
|
||||
>
|
||||
<Radio value="oui">{t('Oui')}</Radio>
|
||||
<Radio value="non">{t('Non')}</Radio>
|
||||
</ToggleGroup>
|
||||
<StyledRadio value="oui">{t('Oui')}</StyledRadio>
|
||||
<StyledRadio value="non">{t('Non')}</StyledRadio>
|
||||
</StyledToggleGroup>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
${FlexCenter}
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
column-gap: ${({ theme }) => theme.spacings.sm};
|
||||
width: 100%;
|
||||
`
|
||||
const StyledBody = styled(Body)`
|
||||
margin: ${({ theme }) => theme.spacings.xxs} 0;
|
||||
`
|
||||
const StyledToggleGroup = styled(ToggleGroup)`
|
||||
display: flex;
|
||||
> * {
|
||||
display: flex;
|
||||
}
|
||||
`
|
||||
const StyledRadio = styled(Radio)`
|
||||
white-space: nowrap;
|
||||
> span {
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
|
|
Loading…
Add table
Reference in a new issue