refactor: réduction générale mois par mois
parent
2c0ed9b5d0
commit
e070a1c506
|
@ -1,39 +1,22 @@
|
|||
import { formatValue, PublicodesExpression } from 'publicodes'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { styled } from 'styled-components'
|
||||
|
||||
import { ExplicableRule } from '@/components/conversation/Explicable'
|
||||
import NumberInput from '@/components/conversation/NumberInput'
|
||||
import { Condition } from '@/components/EngineValue/Condition'
|
||||
import { useEngine } from '@/components/utils/EngineContext'
|
||||
import { SearchIcon, WarningIcon } from '@/design-system/icons'
|
||||
import { Tooltip } from '@/design-system/tooltip'
|
||||
|
||||
import Répartition from './components/Répartition'
|
||||
import RéductionGénéraleMoisParMoisRow from './components/RéductionGénéraleMoisParMoisRow'
|
||||
import Warnings from './components/Warnings'
|
||||
import WarningSalaireTrans from './components/WarningSalaireTrans'
|
||||
import {
|
||||
MonthState,
|
||||
réductionGénéraleDottedName,
|
||||
rémunérationBruteDottedName,
|
||||
} from './utils'
|
||||
import { MonthState, réductionGénéraleDottedName } from './utils'
|
||||
|
||||
type RémunérationBruteInput = {
|
||||
unité: string
|
||||
valeur: number
|
||||
type Props = {
|
||||
data: MonthState[]
|
||||
onChange: (monthIndex: number, rémunérationBrute: number) => void
|
||||
}
|
||||
|
||||
export default function RéductionGénéraleMoisParMois({
|
||||
data,
|
||||
onChange,
|
||||
}: {
|
||||
data: MonthState[]
|
||||
onChange: (monthIndex: number, rémunérationBrute: number) => void
|
||||
}) {
|
||||
const engine = useEngine()
|
||||
const { t, i18n } = useTranslation()
|
||||
const language = i18n.language
|
||||
const displayedUnit = '€'
|
||||
}: Props) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const months = [
|
||||
t('janvier'),
|
||||
|
@ -50,31 +33,6 @@ export default function RéductionGénéraleMoisParMois({
|
|||
t('décembre'),
|
||||
]
|
||||
|
||||
const onRémunérationChange = (
|
||||
monthIndex: number,
|
||||
rémunérationBrute: RémunérationBruteInput
|
||||
) => {
|
||||
onChange(monthIndex, rémunérationBrute.valeur)
|
||||
}
|
||||
|
||||
// TODO: enlever les 4 premières props après résolution de #3123
|
||||
const ruleInputProps = {
|
||||
dottedName: rémunérationBruteDottedName,
|
||||
suggestions: {},
|
||||
description: undefined,
|
||||
question: undefined,
|
||||
engine,
|
||||
'aria-labelledby': 'simu-update-explaining',
|
||||
formatOptions: {
|
||||
maximumFractionDigits: 0,
|
||||
},
|
||||
displayedUnit,
|
||||
unit: {
|
||||
numerators: ['€'],
|
||||
denominators: [],
|
||||
},
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledTable style={{ width: '100%' }}>
|
||||
|
@ -95,102 +53,17 @@ export default function RéductionGénéraleMoisParMois({
|
|||
</thead>
|
||||
<tbody>
|
||||
{data.length > 0 &&
|
||||
months.map((monthName, monthIndex) => {
|
||||
const tooltip = (
|
||||
<Répartition
|
||||
contexte={{
|
||||
[rémunérationBruteDottedName]:
|
||||
data[monthIndex].rémunérationBrute,
|
||||
[réductionGénéraleDottedName]:
|
||||
data[monthIndex].réductionGénérale +
|
||||
data[monthIndex].régularisation,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<tr key={`month-${monthIndex}`}>
|
||||
<th scope="row">{monthName}</th>
|
||||
<td>
|
||||
<NumberInput
|
||||
{...ruleInputProps}
|
||||
id={`${rémunérationBruteDottedName.replace(
|
||||
/\s|\./g,
|
||||
'_'
|
||||
)}-${monthName}`}
|
||||
aria-label={`${engine.getRule(rémunérationBruteDottedName)
|
||||
?.title} (${monthName})`}
|
||||
onChange={(rémunérationBrute?: PublicodesExpression) =>
|
||||
onRémunérationChange(
|
||||
monthIndex,
|
||||
rémunérationBrute as RémunérationBruteInput
|
||||
)
|
||||
}
|
||||
value={data[monthIndex].rémunérationBrute}
|
||||
formatOptions={{
|
||||
maximumFractionDigits: 2,
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<td
|
||||
id={`${réductionGénéraleDottedName.replace(
|
||||
/\s|\./g,
|
||||
'_'
|
||||
)}-${monthName}`}
|
||||
>
|
||||
{data[monthIndex].réductionGénérale ? (
|
||||
<Tooltip tooltip={tooltip}>
|
||||
<StyledDiv>
|
||||
{formatValue(
|
||||
{
|
||||
nodeValue: data[monthIndex].réductionGénérale,
|
||||
},
|
||||
{
|
||||
displayedUnit,
|
||||
language,
|
||||
}
|
||||
)}
|
||||
<SearchIcon />
|
||||
</StyledDiv>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<StyledDiv>
|
||||
{formatValue(0, { displayedUnit, language })}
|
||||
|
||||
<Condition
|
||||
expression={`${rémunérationBruteDottedName} > 1.6 * SMIC`}
|
||||
contexte={{
|
||||
[rémunérationBruteDottedName]:
|
||||
data[monthIndex].rémunérationBrute,
|
||||
}}
|
||||
>
|
||||
<Tooltip tooltip={<WarningSalaireTrans />}>
|
||||
<span className="sr-only">{t('Attention')}</span>
|
||||
<StyledWarningIcon aria-label={t('Attention')} />
|
||||
</Tooltip>
|
||||
</Condition>
|
||||
</StyledDiv>
|
||||
)}
|
||||
</td>
|
||||
<td
|
||||
id={`${réductionGénéraleDottedName.replace(
|
||||
/\s|\./g,
|
||||
'_'
|
||||
)}__régularisation-${monthName}`}
|
||||
>
|
||||
{formatValue(
|
||||
{
|
||||
nodeValue: data[monthIndex].régularisation,
|
||||
},
|
||||
{
|
||||
displayedUnit,
|
||||
language,
|
||||
}
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
months.map((monthName, monthIndex) => (
|
||||
<RéductionGénéraleMoisParMoisRow
|
||||
key={`month-${monthIndex}`}
|
||||
monthName={monthName}
|
||||
data={data[monthIndex]}
|
||||
index={monthIndex}
|
||||
onChange={(monthIndex: number, rémunérationBrute: number) => {
|
||||
onChange(monthIndex, rémunérationBrute)
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</StyledTable>
|
||||
|
||||
|
@ -220,13 +93,3 @@ const StyledTable = styled.table`
|
|||
font-weight: normal;
|
||||
}
|
||||
`
|
||||
|
||||
const StyledDiv = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: ${({ theme }) => theme.spacings.sm};
|
||||
`
|
||||
|
||||
const StyledWarningIcon = styled(WarningIcon)`
|
||||
margin-top: ${({ theme }) => theme.spacings.xxs};
|
||||
`
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
import { formatValue, PublicodesExpression } from 'publicodes'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { styled } from 'styled-components'
|
||||
|
||||
import NumberInput from '@/components/conversation/NumberInput'
|
||||
import { Condition } from '@/components/EngineValue/Condition'
|
||||
import { useEngine } from '@/components/utils/EngineContext'
|
||||
import { SearchIcon, WarningIcon } from '@/design-system/icons'
|
||||
import { Tooltip } from '@/design-system/tooltip'
|
||||
|
||||
import {
|
||||
MonthState,
|
||||
réductionGénéraleDottedName,
|
||||
rémunérationBruteDottedName,
|
||||
} from '../utils'
|
||||
import Répartition from './Répartition'
|
||||
import WarningSalaireTrans from './WarningSalaireTrans'
|
||||
|
||||
type Props = {
|
||||
monthName: string
|
||||
data: MonthState
|
||||
index: number
|
||||
onChange: (monthIndex: number, rémunérationBrute: number) => void
|
||||
}
|
||||
|
||||
type RémunérationBruteInput = {
|
||||
unité: string
|
||||
valeur: number
|
||||
}
|
||||
|
||||
export default function RéductionGénéraleMoisParMoisRow({
|
||||
monthName,
|
||||
data,
|
||||
index,
|
||||
onChange,
|
||||
}: Props) {
|
||||
const { t, i18n } = useTranslation()
|
||||
const language = i18n.language
|
||||
const displayedUnit = '€'
|
||||
const engine = useEngine()
|
||||
|
||||
const onRémunérationChange = (
|
||||
monthIndex: number,
|
||||
rémunérationBrute: RémunérationBruteInput
|
||||
) => {
|
||||
onChange(monthIndex, rémunérationBrute.valeur)
|
||||
}
|
||||
|
||||
// TODO: enlever les 4 premières props après résolution de #3123
|
||||
const ruleInputProps = {
|
||||
dottedName: rémunérationBruteDottedName,
|
||||
suggestions: {},
|
||||
description: undefined,
|
||||
question: undefined,
|
||||
engine,
|
||||
'aria-labelledby': 'simu-update-explaining',
|
||||
formatOptions: {
|
||||
maximumFractionDigits: 0,
|
||||
},
|
||||
displayedUnit,
|
||||
unit: {
|
||||
numerators: ['€'],
|
||||
denominators: [],
|
||||
},
|
||||
}
|
||||
|
||||
const tooltip = (
|
||||
<Répartition
|
||||
contexte={{
|
||||
[rémunérationBruteDottedName]: data.rémunérationBrute,
|
||||
[réductionGénéraleDottedName]:
|
||||
data.réductionGénérale + data.régularisation,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<th scope="row">{monthName}</th>
|
||||
<td>
|
||||
<NumberInput
|
||||
{...ruleInputProps}
|
||||
id={`${rémunérationBruteDottedName.replace(
|
||||
/\s|\./g,
|
||||
'_'
|
||||
)}-${monthName}`}
|
||||
aria-label={`${engine.getRule(rémunérationBruteDottedName)
|
||||
?.title} (${monthName})`}
|
||||
onChange={(rémunérationBrute?: PublicodesExpression) =>
|
||||
onRémunérationChange(
|
||||
index,
|
||||
rémunérationBrute as RémunérationBruteInput
|
||||
)
|
||||
}
|
||||
value={data.rémunérationBrute}
|
||||
formatOptions={{
|
||||
maximumFractionDigits: 2,
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<td
|
||||
id={`${réductionGénéraleDottedName.replace(
|
||||
/\s|\./g,
|
||||
'_'
|
||||
)}-${monthName}`}
|
||||
>
|
||||
{data.réductionGénérale ? (
|
||||
<Tooltip tooltip={tooltip}>
|
||||
<StyledDiv>
|
||||
{formatValue(
|
||||
{
|
||||
nodeValue: data.réductionGénérale,
|
||||
},
|
||||
{
|
||||
displayedUnit,
|
||||
language,
|
||||
}
|
||||
)}
|
||||
<SearchIcon />
|
||||
</StyledDiv>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<StyledDiv>
|
||||
{formatValue(0, { displayedUnit, language })}
|
||||
|
||||
<Condition
|
||||
expression={`${rémunérationBruteDottedName} > 1.6 * SMIC`}
|
||||
contexte={{
|
||||
[rémunérationBruteDottedName]: data.rémunérationBrute,
|
||||
}}
|
||||
>
|
||||
<Tooltip tooltip={<WarningSalaireTrans />}>
|
||||
<span className="sr-only">{t('Attention')}</span>
|
||||
<StyledWarningIcon aria-label={t('Attention')} />
|
||||
</Tooltip>
|
||||
</Condition>
|
||||
</StyledDiv>
|
||||
)}
|
||||
</td>
|
||||
<td
|
||||
id={`${réductionGénéraleDottedName.replace(
|
||||
/\s|\./g,
|
||||
'_'
|
||||
)}__régularisation-${monthName}`}
|
||||
>
|
||||
{formatValue(
|
||||
{
|
||||
nodeValue: data.régularisation,
|
||||
},
|
||||
{
|
||||
displayedUnit,
|
||||
language,
|
||||
}
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
const StyledDiv = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: ${({ theme }) => theme.spacings.sm};
|
||||
`
|
||||
|
||||
const StyledWarningIcon = styled(WarningIcon)`
|
||||
margin-top: ${({ theme }) => theme.spacings.xxs};
|
||||
`
|
Loading…
Reference in New Issue