feat(rgcp): ajout de champs pour gérer les mois incomplets
parent
b52009bd6f
commit
08b90703a2
|
@ -208,8 +208,9 @@ describe(
|
|||
.should('have.length', 12)
|
||||
.first()
|
||||
.click()
|
||||
cy.get('div[id="options-janvier"]').should('be.visible')
|
||||
cy.get('div[id="options-janvier"] input').type('{selectall}28,15')
|
||||
cy.get('input[id="option-heures-sup-janvier"]')
|
||||
.should('be.visible')
|
||||
.type('{selectall}28,15')
|
||||
|
||||
cy.get(
|
||||
'#salarié___cotisations___exonérations___réduction_générale-janvier'
|
||||
|
|
|
@ -1490,14 +1490,30 @@ pages:
|
|||
caption: "General discount month by month :"
|
||||
options:
|
||||
description: Adds fields to modulate employee activity
|
||||
heures-sup:
|
||||
popover: "<0>The number of hours of overtime and complementary work is used to
|
||||
calculate the general reduction: gross remuneration is compared with
|
||||
the SMIC increased by this number of hours.</0>"
|
||||
label:
|
||||
heures-complémentaires: Overtime
|
||||
heures-supplémentaires: Overtime
|
||||
popover: "<0>The number of hours of overtime or complementary work is used to
|
||||
calculate the general reduction: gross remuneration is compared with
|
||||
the SMIC increased by this number of hours.</0><1>If you have answered
|
||||
the question on overtime or complementary hours, the value will be
|
||||
overwritten by the value you enter month by month.</1>"
|
||||
heures-complémentaires: Number of overtime hours
|
||||
heures-supplémentaires: Number of overtime hours
|
||||
rémunération-etp: Basic remuneration for a full month
|
||||
rémunération-heures-complémentaires: Overtime pay
|
||||
rémunération-heures-supplémentaires: Overtime pay
|
||||
rémunération-primes: Remuneration not affected by the incomplete month
|
||||
mois-incomplet:
|
||||
description: Adds fields to handle incomplete months
|
||||
rémunération-etp:
|
||||
popover: <0>Indicate here the remuneration that would have been paid for a full
|
||||
month, <2>excluding</2>:<4><0>bonuses and other remuneration not
|
||||
affected by the absence ;</0><1>remuneration for overtime or
|
||||
additional hours worked.</1></4></0>
|
||||
rémunération-heures-sup:
|
||||
popover: <0>Indicate here the remuneration relating to the payment of overtime
|
||||
or complementary hours.</0>
|
||||
rémunération-primes:
|
||||
popover: <0>Indicate here any elements of remuneration not affected by the
|
||||
absence, such as bonuses.</0>
|
||||
régularisation:
|
||||
annuelle: Annual adjustment
|
||||
progressive: Progressive regularization
|
||||
|
|
|
@ -1584,15 +1584,30 @@ pages:
|
|||
caption: "Réduction générale mois par mois :"
|
||||
options:
|
||||
description: Ajoute des champs pour moduler l'activité du salarié
|
||||
heures-sup:
|
||||
popover: "<0>Le nombre d'heures supplémentaires et complémentaires est utilisé
|
||||
dans le calcul de la réduction générale : la rémunération brute est
|
||||
comparée au montant du SMIC majoré de ce nombre d'heures.</0>"
|
||||
label:
|
||||
heures-complémentaires: Heures complémentaires
|
||||
heures-supplémentaires: Heures supplémentaires
|
||||
popover: "<0>Le nombre d'heures supplémentaires et complémentaires est utilisé
|
||||
dans le calcul de la réduction générale : la rémunération brute est
|
||||
comparée au montant du SMIC majoré de ce nombre d'heures.</0><1>Si
|
||||
vous avez répondu à la question sur les heures supplémentaires ou
|
||||
complémentaires, la valeur sera écrasée par celle que vous saisissez
|
||||
mois par mois.</1>"
|
||||
heures-complémentaires: Nombre d'heures complémentaires
|
||||
heures-supplémentaires: Nombre d'heures supplémentaires
|
||||
rémunération-etp: Rémunération de base mois complet
|
||||
rémunération-heures-complémentaires: Rémunération des heures complémentaires
|
||||
rémunération-heures-supplémentaires: Rémunération des heures supplémentaires
|
||||
rémunération-primes: Rémunération non affectée par le mois incomplet
|
||||
mois-incomplet:
|
||||
description: Ajoute des champs pour gérer le cas d'un mois incomplet
|
||||
rémunération-etp:
|
||||
popover: <0>Indiquez ici la rémunération qui aurait été versée pour un mois
|
||||
complet, <2>en excluant</2> :<4><0>les primes et autres éléments de
|
||||
rémunération non affectés par l'absence ;</0><1>la rémunération des
|
||||
heures supplémentaires ou complémentaires.</1></4></0>
|
||||
rémunération-heures-sup:
|
||||
popover: <0>Indiquez ici la rémunération afférente au paiement des heures
|
||||
supplémentaires ou complémentaires.</0>
|
||||
rémunération-primes:
|
||||
popover: <0>Indiquez ici les éléments de rémunération non affectés par
|
||||
l'absence, comme les primes.</0>
|
||||
régularisation:
|
||||
annuelle: Régularisation annuelle
|
||||
progressive: Régularisation progressive
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { useState } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { styled } from 'styled-components'
|
||||
|
||||
import { Appear } from '@/components/ui/animate'
|
||||
import { useEngine } from '@/components/utils/EngineContext'
|
||||
import { Message, NumberField } from '@/design-system'
|
||||
import { NumberField } from '@/design-system'
|
||||
import { HelpButtonWithPopover } from '@/design-system/buttons'
|
||||
import {
|
||||
StyledInput,
|
||||
|
@ -11,7 +12,13 @@ import {
|
|||
StyledSuffix,
|
||||
} from '@/design-system/field/TextField'
|
||||
import { FlexCenter } from '@/design-system/global-style'
|
||||
import { RotatingChevronIcon } from '@/design-system/icons'
|
||||
import { Grid } from '@/design-system/layout'
|
||||
import { baseTheme } from '@/design-system/theme'
|
||||
import { Strong } from '@/design-system/typography'
|
||||
import { Li, Ul } from '@/design-system/typography/list'
|
||||
import { Body, SmallBody } from '@/design-system/typography/paragraphs'
|
||||
import { useMediaQuery } from '@/hooks/useMediaQuery'
|
||||
|
||||
import { Options } from '../utils'
|
||||
|
||||
|
@ -30,91 +37,275 @@ export default function MonthOptions({
|
|||
}: Props) {
|
||||
const { t } = useTranslation()
|
||||
const engine = useEngine()
|
||||
const [isMoisIncompletVisible, setMoisIncompletVisible] = useState(false)
|
||||
const isDesktop = useMediaQuery(
|
||||
`(min-width: ${baseTheme.breakpointsWidth.md})`
|
||||
)
|
||||
|
||||
const isTempsPartiel = engine.evaluate(
|
||||
'salarié . contrat . temps de travail . temps partiel'
|
||||
).nodeValue as boolean
|
||||
const additionalHours = isTempsPartiel ? 'complémentaires' : 'supplémentaires'
|
||||
const additionalHours = isTempsPartiel
|
||||
? 'heuresComplémentaires'
|
||||
: 'heuresSupplémentaires'
|
||||
const additionalHoursLabels = {
|
||||
supplémentaires: t(
|
||||
heuresSupplémentaires: t(
|
||||
'pages.simulateurs.réduction-générale.options.label.heures-supplémentaires',
|
||||
'Heures supplémentaires'
|
||||
"Nombre d'heures supplémentaires"
|
||||
),
|
||||
complémentaires: t(
|
||||
heuresComplémentaires: t(
|
||||
'pages.simulateurs.réduction-générale.options.label.heures-complémentaires',
|
||||
'Heures complémentaires'
|
||||
"Nombre d'heures complémentaires"
|
||||
),
|
||||
}
|
||||
const additionalHoursRémunérationLabels = {
|
||||
heuresSupplémentaires: t(
|
||||
'pages.simulateurs.réduction-générale.options.label.rémunération-heures-supplémentaires',
|
||||
'Rémunération des heures supplémentaires'
|
||||
),
|
||||
heuresComplémentaires: t(
|
||||
'pages.simulateurs.réduction-générale.options.label.rémunération-heures-complémentaires',
|
||||
'Rémunération des heures complémentaires'
|
||||
),
|
||||
}
|
||||
|
||||
const onChange = (value?: number) => {
|
||||
const options = {
|
||||
const onHeuresSupChange = (value?: number) => {
|
||||
const newOptions = {
|
||||
...options,
|
||||
heuresSupplémentaires: 0,
|
||||
heuresComplémentaires: 0,
|
||||
}
|
||||
if (isTempsPartiel) {
|
||||
options.heuresComplémentaires = value ?? 0
|
||||
newOptions.heuresComplémentaires = value ?? 0
|
||||
} else {
|
||||
options.heuresSupplémentaires = value ?? 0
|
||||
newOptions.heuresSupplémentaires = value ?? 0
|
||||
}
|
||||
onOptionsChange(index, options)
|
||||
onOptionsChange(index, newOptions)
|
||||
}
|
||||
|
||||
const onRémunérationETPChange = (value?: number) => {
|
||||
const newOptions = {
|
||||
...options,
|
||||
rémunérationETP: value ?? 0,
|
||||
}
|
||||
onOptionsChange(index, newOptions)
|
||||
}
|
||||
|
||||
const onRémunérationPrimesChange = (value?: number) => {
|
||||
const newOptions = {
|
||||
...options,
|
||||
rémunérationPrimes: value ?? 0,
|
||||
}
|
||||
onOptionsChange(index, newOptions)
|
||||
}
|
||||
|
||||
const onRémunérationHeuresSupChange = (value?: number) => {
|
||||
const newOptions = {
|
||||
...options,
|
||||
rémunérationHeuresSup: value ?? 0,
|
||||
}
|
||||
onOptionsChange(index, newOptions)
|
||||
}
|
||||
|
||||
return (
|
||||
<Appear>
|
||||
<InputContainer id={`options-${month}`}>
|
||||
<FlexDiv>
|
||||
<StyledSmallBody id={`heures-${additionalHours}-label`}>
|
||||
{additionalHoursLabels[additionalHours]}
|
||||
</StyledSmallBody>
|
||||
<HelpButtonWithPopover
|
||||
type="info"
|
||||
title={additionalHoursLabels[additionalHours]}
|
||||
>
|
||||
<HeuresSupplémentairesPopoverContent />
|
||||
</HelpButtonWithPopover>
|
||||
</FlexDiv>
|
||||
<Grid container columnSpacing={4} style={{ alignItems: 'center' }}>
|
||||
<Grid item>
|
||||
<FlexDiv>
|
||||
<StyledLabel id={`heures-sup-label`}>
|
||||
{additionalHoursLabels[additionalHours]}
|
||||
</StyledLabel>
|
||||
<HelpButtonWithPopover
|
||||
type="info"
|
||||
title={additionalHoursLabels[additionalHours]}
|
||||
>
|
||||
<HeuresSupplémentairesPopoverContent />
|
||||
</HelpButtonWithPopover>
|
||||
</FlexDiv>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<NumberFieldContainer>
|
||||
<NumberField
|
||||
id={`option-heures-sup-${month}`}
|
||||
small={true}
|
||||
value={options[additionalHours]}
|
||||
onChange={onHeuresSupChange}
|
||||
aria-labelledby={`heures-sup-label`}
|
||||
displayedUnit="heures"
|
||||
/>
|
||||
</NumberFieldContainer>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<NumberFieldContainer>
|
||||
<NumberField
|
||||
small={true}
|
||||
value={
|
||||
isTempsPartiel
|
||||
? options.heuresComplémentaires
|
||||
: options.heuresSupplémentaires
|
||||
}
|
||||
onChange={onChange}
|
||||
aria-labelledby={`heures-${additionalHours}-label`}
|
||||
displayedUnit="heures"
|
||||
/>
|
||||
</NumberFieldContainer>
|
||||
</InputContainer>
|
||||
<StyledButton
|
||||
role="button"
|
||||
onClick={() => setMoisIncompletVisible(!isMoisIncompletVisible)}
|
||||
aria-describedby="options-mois-incomplet-description"
|
||||
aria-expanded={isMoisIncompletVisible}
|
||||
aria-controls={`options-mois-incomplet-${month}`}
|
||||
aria-label={!isMoisIncompletVisible ? t('Déplier') : t('Replier')}
|
||||
>
|
||||
Mois incomplet {isDesktop && '(embauche, absences, départ...)'}{' '}
|
||||
<RotatingChevronIcon aria-hidden $isOpen={isMoisIncompletVisible} />
|
||||
</StyledButton>
|
||||
<span id="options-mois-incomplet-description" className="sr-only">
|
||||
{t(
|
||||
'pages.simulateurs.réduction-générale.options.mois-incomplet.description',
|
||||
"Ajoute des champs pour gérer le cas d'un mois incomplet"
|
||||
)}
|
||||
</span>
|
||||
|
||||
{isMoisIncompletVisible && (
|
||||
<Grid
|
||||
container
|
||||
columnSpacing={4}
|
||||
style={{ alignItems: 'center' }}
|
||||
id={`options-mois-incomplet-${month}`}
|
||||
>
|
||||
<Grid item>
|
||||
<FlexDiv>
|
||||
<StyledLabel id={`rémunération-etp-label`}>
|
||||
{t(
|
||||
'pages.simulateurs.réduction-générale.options.label.rémunération-etp',
|
||||
'Rémunération de base mois complet'
|
||||
)}
|
||||
</StyledLabel>
|
||||
<HelpButtonWithPopover
|
||||
type="info"
|
||||
title={t(
|
||||
'pages.simulateurs.réduction-générale.options.label.rémunération-etp',
|
||||
'Rémunération de base mois complet'
|
||||
)}
|
||||
>
|
||||
<RémunérationETPPopoverContent />
|
||||
</HelpButtonWithPopover>
|
||||
</FlexDiv>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<NumberFieldContainer>
|
||||
<NumberField
|
||||
id={`option-rémunération-etp-${month}`}
|
||||
small={true}
|
||||
value={options.rémunérationETP}
|
||||
onChange={onRémunérationETPChange}
|
||||
aria-labelledby={`rémunération-etp-label`}
|
||||
displayedUnit="€"
|
||||
/>
|
||||
</NumberFieldContainer>
|
||||
</Grid>
|
||||
|
||||
<Grid item>
|
||||
<FlexDiv>
|
||||
<StyledLabel id={`rémunération-primes-label`}>
|
||||
{t(
|
||||
'pages.simulateurs.réduction-générale.options.label.rémunération-primes',
|
||||
'Rémunération non affectée par le mois incomplet'
|
||||
)}
|
||||
</StyledLabel>
|
||||
<HelpButtonWithPopover
|
||||
type="info"
|
||||
title={t(
|
||||
'pages.simulateurs.réduction-générale.options.label.rémunération-primes',
|
||||
'Rémunération non affectée par le mois incomplet'
|
||||
)}
|
||||
>
|
||||
<RémunérationPrimesPopoverContent />
|
||||
</HelpButtonWithPopover>
|
||||
</FlexDiv>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<NumberFieldContainer>
|
||||
<NumberField
|
||||
id={`option-rémunération-primes-${month}`}
|
||||
small={true}
|
||||
value={options.rémunérationPrimes}
|
||||
onChange={onRémunérationPrimesChange}
|
||||
aria-labelledby={`rémunération-primes-label`}
|
||||
displayedUnit="€"
|
||||
/>
|
||||
</NumberFieldContainer>
|
||||
</Grid>
|
||||
|
||||
<Grid item>
|
||||
<FlexDiv>
|
||||
<StyledLabel id={`rémunération-heures-sup-label`}>
|
||||
{additionalHoursRémunérationLabels[additionalHours]}
|
||||
</StyledLabel>
|
||||
<HelpButtonWithPopover
|
||||
type="info"
|
||||
title={additionalHoursRémunérationLabels[additionalHours]}
|
||||
>
|
||||
<RémunérationHeuresSupPopoverContent />
|
||||
</HelpButtonWithPopover>
|
||||
</FlexDiv>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<NumberFieldContainer>
|
||||
<NumberField
|
||||
id={`option-rémunération-heures-sup-${month}`}
|
||||
small={true}
|
||||
value={options.rémunérationHeuresSup}
|
||||
onChange={onRémunérationHeuresSupChange}
|
||||
aria-labelledby={`rémunération-heures-sup-label`}
|
||||
displayedUnit="€"
|
||||
/>
|
||||
</NumberFieldContainer>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</Appear>
|
||||
)
|
||||
}
|
||||
|
||||
const HeuresSupplémentairesPopoverContent = () => (
|
||||
<Trans i18nKey="pages.simulateurs.réduction-générale.options.popover">
|
||||
<Trans i18nKey="pages.simulateurs.réduction-générale.options.heures-sup.popover">
|
||||
<Body>
|
||||
Le nombre d'heures supplémentaires et complémentaires est utilisé dans le
|
||||
calcul de la réduction générale : la rémunération brute est comparée au
|
||||
montant du SMIC majoré de ce nombre d'heures.
|
||||
</Body>
|
||||
<Message type="info">
|
||||
Si vous avez répondu à la question sur les heures supplémentaires ou
|
||||
complémentaires, la valeur sera écrasée par celle que vous saisissez mois
|
||||
par mois.
|
||||
</Message>
|
||||
</Trans>
|
||||
)
|
||||
|
||||
const InputContainer = styled.div`
|
||||
${FlexCenter}
|
||||
gap: ${({ theme }) => theme.spacings.md};
|
||||
`
|
||||
const RémunérationETPPopoverContent = () => (
|
||||
<Trans i18nKey="pages.simulateurs.réduction-générale.options.rémunération-etp.popover">
|
||||
<Body>
|
||||
Indiquez ici la rémunération qui aurait été versée pour un mois complet,{' '}
|
||||
<Strong>en excluant</Strong> :
|
||||
<Ul>
|
||||
<Li>
|
||||
les primes et autres éléments de rémunération non affectés par
|
||||
l'absence ;
|
||||
</Li>
|
||||
<Li>la rémunération des heures supplémentaires ou complémentaires.</Li>
|
||||
</Ul>
|
||||
</Body>
|
||||
</Trans>
|
||||
)
|
||||
|
||||
const RémunérationPrimesPopoverContent = () => (
|
||||
<Trans i18nKey="pages.simulateurs.réduction-générale.options.rémunération-primes.popover">
|
||||
<Body>
|
||||
Indiquez ici les éléments de rémunération non affectés par l'absence,
|
||||
comme les primes.
|
||||
</Body>
|
||||
</Trans>
|
||||
)
|
||||
|
||||
const RémunérationHeuresSupPopoverContent = () => (
|
||||
<Trans i18nKey="pages.simulateurs.réduction-générale.options.rémunération-heures-sup.popover">
|
||||
<Body>
|
||||
Indiquez ici la rémunération afférente au paiement des heures
|
||||
supplémentaires ou complémentaires.
|
||||
</Body>
|
||||
</Trans>
|
||||
)
|
||||
|
||||
const FlexDiv = styled.div`
|
||||
${FlexCenter}
|
||||
justify-content: end;
|
||||
`
|
||||
const StyledSmallBody = styled(SmallBody)`
|
||||
const StyledLabel = styled(SmallBody)`
|
||||
margin: 0;
|
||||
color: ${({ theme }) => theme.colors.bases.primary[800]};
|
||||
`
|
||||
|
@ -131,3 +322,13 @@ const NumberFieldContainer = styled.div`
|
|||
}
|
||||
}
|
||||
`
|
||||
const StyledButton = styled(SmallBody)`
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
color: ${({ theme }) => theme.colors.bases.primary[800]};
|
||||
margin-top: ${({ theme }) => theme.spacings.xs};
|
||||
margin-bottom: 0;
|
||||
svg {
|
||||
fill: ${({ theme }) => theme.colors.bases.primary[800]} !important;
|
||||
}
|
||||
`
|
||||
|
|
Loading…
Reference in New Issue