refactor(salarié): Réorganise les composants de fiche de paie

pull/3156/head
Alice Dahan 2024-09-20 16:25:27 +02:00 committed by liliced
parent bdd85ca297
commit 4c716132b4
10 changed files with 287 additions and 252 deletions

View File

@ -687,6 +687,51 @@ protection sociale . maladie . maternité paternité adoption:
références:
'Congé maternité : les indemnités journalières pour les salariées ': https://www.ameli.fr/assure/remboursements/indemnites-journalieres/conge-maternite-salariee
protection sociale . maladie . accidents du travail et maladies professionnelles:
icônes: ☣️
résumé: Offre une couverture complète des maladies ou accidents du travail.
description: |
Vous avez subi un accident du travail ou êtes atteint dune maladie professionnelle ?
Vos frais médicaux sont pris en charge à 100 %.
Pour compenser votre perte de salaire, vous pouvez percevoir des indemnités journalières.
Si vous êtes déclaré inapte suite à votre accident / maladie, vous pouvez recevoir une indemnité temporaire d'inaptitude.
unité: €/jour
applicable si: salarié
références:
"Comprendre l'assurance AT/MP": https://www.ameli.fr/entreprise/votre-entreprise/cotisation-atmp
'Maladie professionnelle : prise en charge et indemnités journalières': https://www.ameli.fr/assure/remboursements/indemnites-journalieres/maladie-professionnelle
'Accident du travail : prise en charge et indemnités journalières': https://www.ameli.fr/assure/remboursements/indemnites-journalieres/accident-travail
"Qu'est-ce qu'un accident de trajet ?": https://www.service-public.fr/particuliers/vosdroits/F31881
"Qu'est-ce qu'une maladie professionnelle ?": https://www.service-public.fr/particuliers/vosdroits/F31880
"Accident du travail : indemnités journalières pendant l'arrêt de travail": https://www.service-public.fr/particuliers/vosdroits/F175
"Maladie professionnelle : indemnités journalières pendant l'arrêt de travail": https://www.service-public.fr/particuliers/vosdroits/F32148
Articles R433-1 à R433-17 du Code de la Sécurité Sociale: https://www.legifrance.gouv.fr/codes/id/LEGISCTA000006156659/2020-12-10/
avec:
indemmnités:
produit:
- salaire journalier de référence
- 60%
avec:
à partir du 29ème jour:
produit:
- salaire journalier de référence
- 80%
indemmnités . salaire journalier de référence:
privé: oui
valeur: salarié . cotisations . assiette
unité: €/jour
plafond:
arrondi: 2 décimales
unité: €/jour
le minimum de:
- 0.834% * (plafond sécurité sociale * 1 an) / 1 jour
- salarié . cotisations . assiette - abattement forfaitaire salarié
protection sociale . invalidité et décès:
icônes: 🦽
type: branche
@ -929,51 +974,6 @@ protection sociale . famille:
Allocations destinées aux familles: https://www.service-public.fr/particuliers/vosdroits/N156
Tout savoir sur les Allocations familiales: https://www.caf.fr/nous-connaitre/qui-sommes-nous
protection sociale . maladie . accidents du travail et maladies professionnelles:
icônes: ☣️
résumé: Offre une couverture complète des maladies ou accidents du travail.
description: |
Vous avez subi un accident du travail ou êtes atteint dune maladie professionnelle ?
Vos frais médicaux sont pris en charge à 100 %.
Pour compenser votre perte de salaire, vous pouvez percevoir des indemnités journalières.
Si vous êtes déclaré inapte suite à votre accident / maladie, vous pouvez recevoir une indemnité temporaire d'inaptitude.
unité: €/jour
applicable si: salarié
références:
"Comprendre l'assurance AT/MP": https://www.ameli.fr/entreprise/votre-entreprise/cotisation-atmp
'Maladie professionnelle : prise en charge et indemnités journalières': https://www.ameli.fr/assure/remboursements/indemnites-journalieres/maladie-professionnelle
'Accident du travail : prise en charge et indemnités journalières': https://www.ameli.fr/assure/remboursements/indemnites-journalieres/accident-travail
"Qu'est-ce qu'un accident de trajet ?": https://www.service-public.fr/particuliers/vosdroits/F31881
"Qu'est-ce qu'une maladie professionnelle ?": https://www.service-public.fr/particuliers/vosdroits/F31880
"Accident du travail : indemnités journalières pendant l'arrêt de travail": https://www.service-public.fr/particuliers/vosdroits/F175
"Maladie professionnelle : indemnités journalières pendant l'arrêt de travail": https://www.service-public.fr/particuliers/vosdroits/F32148
Articles R433-1 à R433-17 du Code de la Sécurité Sociale: https://www.legifrance.gouv.fr/codes/id/LEGISCTA000006156659/2020-12-10/
avec:
indemmnités:
produit:
- salaire journalier de référence
- 60%
avec:
à partir du 29ème jour:
produit:
- salaire journalier de référence
- 80%
indemmnités . salaire journalier de référence:
privé: oui
valeur: salarié . cotisations . assiette
unité: €/jour
plafond:
arrondi: 2 décimales
unité: €/jour
le minimum de:
- 0.834% * (plafond sécurité sociale * 1 an) / 1 jour
- salarié . cotisations . assiette - abattement forfaitaire salarié
protection sociale . formation:
icônes: 👩‍🎓
résumé: Finance la possibilité de suivre des formations professionnelles.
@ -982,14 +982,6 @@ protection sociale . formation:
Pour avoir un compte-rendu personnalisé de vos droits à la formation, rendez-vous sur [www.moncompteactivite.gouv.fr](https://www.moncompteactivite.gouv.fr).
protection sociale . autres:
icônes: 🔧
résumé: Autres contributions au système social.
description: |
Toutes les contributions transverses au système social.
On y retrouve par exemple la CRDS (contribution pour le remboursement de la dette sociale) qui est un impôt destiné à résorber l'endettement de la Sécurité sociale, et ainsi assurer la viabilité de la protection sociale pour vos enfants et petits enfants.
protection sociale . transport:
icônes: 🚌
résumé: Permet de maintenir le prix d'un billet de transport en commun à un bas prix
@ -1001,3 +993,11 @@ protection sociale . transport:
- **263 € / an / habitant** de gain de pouvoir d'achat pour les habitants d'Île-de-France
références:
wikipedia: https://fr.wikipedia.org/wiki/Versement_transport
protection sociale . autres:
icônes: 🔧
résumé: Autres contributions au système social.
description: |
Toutes les contributions transverses au système social.
On y retrouve par exemple la CRDS (contribution pour le remboursement de la dette sociale) qui est un impôt destiné à résorber l'endettement de la Sécurité sociale, et ainsi assurer la viabilité de la protection sociale pour vos enfants et petits enfants.

View File

@ -6,7 +6,11 @@ import { useTranslation } from 'react-i18next'
import RuleLink from '@/components/RuleLink'
import { EngineContext } from '@/components/utils/EngineContext'
export default function Cotisation({ dottedName }: { dottedName: DottedName }) {
export default function CotisationLine({
dottedName,
}: {
dottedName: DottedName
}) {
const language = useTranslation().i18n.language
const engine = useContext(EngineContext)
const partSalariale = engine.evaluate(

View File

@ -3,20 +3,78 @@ import { ASTNode, ParsedRules, reduceAST, Rule, RuleNode } from 'publicodes'
import { Fragment } from 'react'
import { Trans } from 'react-i18next'
import { useEngine } from '@/components/utils/EngineContext'
import './PaySlip.css'
import { Strong } from '@/design-system/typography'
import { H4, H5 } from '@/design-system/typography/heading'
import { Body } from '@/design-system/typography/paragraphs'
import { ExplicableRule } from './conversation/Explicable'
import Value from './EngineValue/Value'
import { ExplicableRule } from '../conversation/Explicable'
import Value from '../EngineValue/Value'
import { useEngine } from '../utils/EngineContext'
import CotisationLine from './CotisationLine'
import Line from './Line'
import './PaySlip.css'
export function Cotisations() {
const parsedRules = useEngine().getParsedRules()
const cotisationsBySection = getCotisationsBySection(parsedRules)
import { styled } from 'styled-components'
return (
<>
<div className="payslip__cotisationsSection">
<H4>
<Trans>Cotisations sociales</Trans>
</H4>
<H4>
<Trans>employeur</Trans>
</H4>
<H4>
<Trans>salarié</Trans>
</H4>
{cotisationsBySection.map(([sectionDottedName, cotisations]) => {
const section = parsedRules[sectionDottedName]
import Cotisation from './PaySlipCotisation'
import { Line, SalaireBrutSection, SalaireNetSection } from './PaySlipSections'
return (
<Fragment key={section.dottedName}>
<H5 className="payslip__cotisationTitle">
{section.title}
<ExplicableRule light dottedName={section.dottedName} />
</H5>
{cotisations.map((cotisation) => (
<CotisationLine key={cotisation} dottedName={cotisation} />
))}
</Fragment>
)
})}
{/* Total cotisation */}
<Body className="payslip__total">
<Strong>
<Trans>Total des retenues</Trans>
</Strong>
</Body>
<div>
<Value
expression="salarié . cotisations . employeur"
displayedUnit="€"
className="payslip__total"
/>
</div>
<div>
<Value
expression="salarié . cotisations . salarié"
displayedUnit="€"
className="payslip__total"
/>
</div>
{/* Salaire chargé */}
<Line rule="salarié . coût total employeur" />
<span />
</div>
</>
)
}
export const SECTION_ORDER = [
'protection sociale . maladie',
@ -97,88 +155,3 @@ export function getCotisationsBySection(
SECTION_ORDER.indexOf(b as Section)
) as Array<[Section, DottedName[]]>
}
export default function PaySlip() {
const parsedRules = useEngine().getParsedRules()
const cotisationsBySection = getCotisationsBySection(parsedRules)
return (
<StyledContainer className="payslip__container">
<div className="payslip__salarySection">
<Line
rule="salarié . temps de travail"
displayedUnit="heures/mois"
precision={1}
/>
<Line
rule="salarié . temps de travail . heures supplémentaires"
displayedUnit="heures/mois"
precision={1}
/>
</div>
<SalaireBrutSection />
{/* Section cotisations */}
<div className="payslip__cotisationsSection">
<H4>
<Trans>Cotisations sociales</Trans>
</H4>
<H4>
<Trans>employeur</Trans>
</H4>
<H4>
<Trans>salarié</Trans>
</H4>
{cotisationsBySection.map(([sectionDottedName, cotisations]) => {
const section = parsedRules[sectionDottedName]
return (
<Fragment key={section.dottedName}>
<H5 className="payslip__cotisationTitle">
{section.title}
<ExplicableRule light dottedName={section.dottedName} />
</H5>
{cotisations.map((cotisation) => (
<Cotisation key={cotisation} dottedName={cotisation} />
))}
</Fragment>
)
})}
{/* Total cotisation */}
<Body className="payslip__total">
<Strong>
<Trans>Total des retenues</Trans>
</Strong>
</Body>
<div>
<Value
expression="salarié . cotisations . employeur"
displayedUnit="€"
className="payslip__total"
/>
</div>
<div>
<Value
expression="salarié . cotisations . salarié"
displayedUnit="€"
className="payslip__total"
/>
</div>
{/* Salaire chargé */}
<Line rule="salarié . coût total employeur" />
<span />
</div>
{/* Section salaire net */}
<SalaireNetSection />
</StyledContainer>
)
}
const StyledContainer = styled.div`
.value {
display: flex;
align-items: flex-end;
justify-content: flex-end;
padding-right: 0.2em;
}
`

View File

@ -0,0 +1,40 @@
import { DottedName } from 'modele-social'
import { ValueProps } from '@/components/EngineValue/types'
import RuleLink from '@/components/RuleLink'
import { Condition } from '../EngineValue/Condition'
import Value from '../EngineValue/Value'
import { WhenAlreadyDefined } from '../EngineValue/WhenAlreadyDefined'
import { WhenApplicable } from '../EngineValue/WhenApplicable'
type LineProps = {
rule: DottedName
title?: string
negative?: boolean
} & Omit<ValueProps<DottedName>, 'expression'>
export default function Line({
rule,
displayedUnit = '€',
negative = false,
title,
...props
}: LineProps) {
return (
<WhenApplicable dottedName={rule}>
<WhenAlreadyDefined dottedName={rule}>
<Condition expression={`${rule} > 0`}>
<RuleLink dottedName={rule}>{title}</RuleLink>
<Value
linkToRule={false}
expression={(negative ? '- ' : '') + rule}
unit={displayedUnit === '€' ? '€/mois' : displayedUnit}
displayedUnit={displayedUnit}
{...props}
/>
</Condition>
</WhenAlreadyDefined>
</WhenApplicable>
)
}

View File

@ -0,0 +1,42 @@
import './PaySlip.css'
import { styled } from 'styled-components'
import { Cotisations } from './Cotisations'
import Line from './Line'
import SalaireBrut from './SalaireBrut'
import SalaireNet from './SalaireNet'
export default function PaySlip() {
return (
<StyledContainer className="payslip__container">
<div className="payslip__salarySection">
<Line
rule="salarié . temps de travail"
displayedUnit="heures/mois"
precision={1}
/>
<Line
rule="salarié . temps de travail . heures supplémentaires"
displayedUnit="heures/mois"
precision={1}
/>
</div>
<SalaireBrut />
<Cotisations />
<SalaireNet />
</StyledContainer>
)
}
const StyledContainer = styled.div`
line-height: 1.5rem;
.value {
display: flex;
align-items: flex-end;
justify-content: flex-end;
padding-right: 0.2em;
}
`

View File

@ -0,0 +1,30 @@
import { Trans } from 'react-i18next'
import { H4 } from '@/design-system/typography/heading'
import { Condition } from '../EngineValue/Condition'
import Line from './Line'
import './PaySlip.css'
export default function SalaireBrut() {
return (
<div className="payslip__salarySection">
<H4 className="payslip__salaryTitle" as="h3">
<Trans>Salaire</Trans>
</H4>
<Line rule="salarié . contrat . salaire brut" />
<Line rule="salarié . rémunération . avantages en nature . montant" />
<Line rule="salarié . activité partielle . retrait absence" />
<Line rule="salarié . activité partielle . indemnités" />
<Line rule="salarié . rémunération . heures supplémentaires" />
<Line rule="salarié . rémunération . heures complémentaires" />
<Line rule="salarié . rémunération . primes" />
<Line rule="salarié . rémunération . frais professionnels" />
<Line rule="salarié . rémunération . indemnités CDD" />
<Condition expression="salarié . contrat . salaire brut != salarié . rémunération . brut">
<Line rule="salarié . rémunération . brut" />
</Condition>
</div>
)
}

View File

@ -0,0 +1,49 @@
import { Trans, useTranslation } from 'react-i18next'
import './PaySlip.css'
import { H4 } from '@/design-system/typography/heading'
import { Condition } from '../EngineValue/Condition'
import Line from './Line'
export default function SalaireNet() {
const { t } = useTranslation()
return (
<div className="payslip__salarySection">
<H4 className="payslip__salaryTitle" as="h3">
<Trans>Salaire net</Trans>
</H4>
<Line rule="salarié . rémunération . net . imposable" />
<Condition
expression={{
'toutes ces conditions': [
'salarié . rémunération . avantages en nature', // bool
'salarié . rémunération . frais professionnels . titres-restaurant', // bool
],
}}
>
<Line rule="salarié . rémunération . net . à payer avant impôt" />
</Condition>
<Line
negative
rule="salarié . rémunération . avantages en nature . montant"
/>
<Line
negative
rule="salarié . rémunération . frais professionnels . titres-restaurant . montant"
/>
<Line rule="salarié . rémunération . net . à payer avant impôt" />
<Condition expression="impôt . montant > 0">
<Line
negative
rule="impôt . montant"
title={t('impôt sur le revenu')}
unit="€/mois"
/>
<Line rule="salarié . rémunération . net . payé après impôt" />
</Condition>
</div>
)
}

View File

@ -1,105 +0,0 @@
import { DottedName } from 'modele-social'
import { Trans, useTranslation } from 'react-i18next'
import { ValueProps } from '@/components/EngineValue/types'
import RuleLink from '@/components/RuleLink'
import { H4 } from '@/design-system/typography/heading'
import { Condition } from './EngineValue/Condition'
import Value from './EngineValue/Value'
import { WhenAlreadyDefined } from './EngineValue/WhenAlreadyDefined'
import { WhenApplicable } from './EngineValue/WhenApplicable'
export const SalaireBrutSection = () => {
return (
<div className="payslip__salarySection">
<H4 className="payslip__salaryTitle" as="h3">
<Trans>Salaire</Trans>
</H4>
<Line rule="salarié . contrat . salaire brut" />
<Line rule="salarié . rémunération . avantages en nature . montant" />
<Line rule="salarié . activité partielle . retrait absence" />
<Line rule="salarié . activité partielle . indemnités" />
<Line rule="salarié . rémunération . heures supplémentaires" />
<Line rule="salarié . rémunération . heures complémentaires" />
<Line rule="salarié . rémunération . primes" />
<Line rule="salarié . rémunération . frais professionnels" />
<Line rule="salarié . rémunération . indemnités CDD" />
<Condition expression="salarié . contrat . salaire brut != salarié . rémunération . brut">
<Line rule="salarié . rémunération . brut" />
</Condition>
</div>
)
}
export const SalaireNetSection = () => {
const { t } = useTranslation()
return (
<div className="payslip__salarySection">
<H4 className="payslip__salaryTitle" as="h3">
<Trans>Salaire net</Trans>
</H4>
<Line rule="salarié . rémunération . net . imposable" />
<Condition
expression={{
'toutes ces conditions': [
'salarié . rémunération . avantages en nature', // bool
'salarié . rémunération . frais professionnels . titres-restaurant', // bool
],
}}
>
<Line rule="salarié . rémunération . net . à payer avant impôt" />
</Condition>
<Line
negative
rule="salarié . rémunération . avantages en nature . montant"
/>
<Line
negative
rule="salarié . rémunération . frais professionnels . titres-restaurant . montant"
/>
<Line rule="salarié . rémunération . net . à payer avant impôt" />
<Condition expression="impôt . montant > 0">
<Line
negative
rule="impôt . montant"
title={t('impôt sur le revenu')}
unit="€/mois"
/>
<Line rule="salarié . rémunération . net . payé après impôt" />
</Condition>
</div>
)
}
type LineProps = {
rule: DottedName
title?: string
negative?: boolean
} & Omit<ValueProps<DottedName>, 'expression'>
export function Line({
rule,
displayedUnit = '€',
negative = false,
title,
...props
}: LineProps) {
return (
<WhenApplicable dottedName={rule}>
<WhenAlreadyDefined dottedName={rule}>
<Condition expression={`${rule} > 0`}>
<RuleLink dottedName={rule}>{title}</RuleLink>
<Value
linkToRule={false}
expression={(negative ? '- ' : '') + rule}
unit={displayedUnit === '€' ? '€/mois' : displayedUnit}
displayedUnit={displayedUnit}
{...props}
/>
</Condition>
</WhenAlreadyDefined>
</WhenApplicable>
)
}

View File

@ -2,7 +2,6 @@ import { useRef } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useTheme } from 'styled-components'
import PaySlip, { getCotisationsBySection } from '@/components/PaySlip'
import { ÀQuoiServentMesCotisationsSection } from '@/components/simulationExplanation/ÀQuoiServentMesCotisationsSection'
import StackedBarChart from '@/components/StackedBarChart'
import { FromTop } from '@/components/ui/animate'
@ -14,6 +13,9 @@ import { Link } from '@/design-system/typography/link'
import { SmallBody } from '@/design-system/typography/paragraphs'
import { useCurrentSimulatorData } from '@/hooks/useCurrentSimulatorData'
import { getCotisationsBySection } from '../FicheDePaie/Cotisations'
import PaySlip from '../FicheDePaie/PaySlip'
export default function SalaryExplanation() {
const payslipRef = useRef<HTMLDivElement>(null)