mon-entreprise/source/components/Distribution.js

160 lines
4.2 KiB
JavaScript

/* @flow */
import Observer from '@researchgate/react-intersection-observer'
import withColours from 'Components/utils/withColours'
import Value from 'Components/Value'
import { findRuleByDottedName } from 'Engine/rules'
import React, { useState } from 'react'
import emoji from 'react-easy-emoji'
import { Trans } from 'react-i18next'
import { connect } from 'react-redux'
import { config, Spring } from 'react-spring'
import { compose } from 'redux'
import { flatRulesSelector } from 'Selectors/analyseSelectors'
import répartitionSelector from 'Selectors/repartitionSelectors'
import { isIE } from '../utils'
import './Distribution.css'
import './PaySlip'
import RuleLink from './RuleLink'
import type { ThemeColours } from 'Components/utils/withColours'
import type { Répartition } from 'Types/ResultViewTypes.js'
type Props = ?Répartition & {
colours: ThemeColours
}
const ANIMATION_SPRING = config.gentle
function Distribution({
colours: { colour },
rules,
// $FlowFixMe
...distribution
}: Props) {
const [branchesInViewport, setBranchesInViewport] = useState([])
const handleBrancheInViewport = branche => (event, unobserve) => {
if (!event.isIntersecting) {
return
}
unobserve()
setBranchesInViewport(branchesInViewport => [
branche,
...branchesInViewport
])
}
if (!Object.values(distribution).length) {
return null
}
const {
répartition,
cotisationMaximum,
total,
salaireChargé,
salaireNet
} = distribution
return (
<>
<div className="distribution-chart__container">
{répartition.map(
([brancheDottedName, { partPatronale, partSalariale }]) => {
const branche = findRuleByDottedName(rules, brancheDottedName),
brancheInViewport =
branchesInViewport.indexOf(brancheDottedName) !== -1
const montant = brancheInViewport
? partPatronale + partSalariale
: 0
return (
<Observer
key={brancheDottedName}
threshold={[0.5]}
onChange={handleBrancheInViewport(brancheDottedName)}>
<Spring
config={ANIMATION_SPRING}
to={{
flex: montant / cotisationMaximum,
opacity: montant ? 1 : 0
}}>
{styles => (
<div
className="distribution-chart__item"
style={{
opacity: styles.opacity
}}>
<BranchIcône icône={branche.icons} />
<div className="distribution-chart__item-content">
<p className="distribution-chart__counterparts">
<span className="distribution-chart__branche-name">
<RuleLink {...branche} />
</span>
<br />
<small>{branche.summary}</small>
</p>
<ChartItemBar {...{ styles, colour, montant, total }} />
</div>
</div>
)}
</Spring>
</Observer>
)
}
)}
</div>
<div className="distribution-chart__total">
<span />
<RuleLink {...salaireNet} />
<Value {...salaireNet} unit="€" maximumFractionDigits={0} />
<span>+</span>
<Trans>Cotisations</Trans>
<Value maximumFractionDigits={0} unit="€">
{total.partPatronale + total.partSalariale}
</Value>
<span />
<div className="distribution-chart__total-border" />
<span>=</span>
<RuleLink {...salaireChargé} />
<Value {...salaireChargé} unit="€" maximumFractionDigits={0} />
</div>
</>
)
}
export default compose(
withColours,
connect(state => ({
...répartitionSelector(state),
rules: flatRulesSelector(state)
}))
)(Distribution)
let ChartItemBar = ({ styles, colour, montant, total }) => (
<div className="distribution-chart__bar-container">
<div
className="distribution-chart__bar"
style={{
backgroundColor: colour,
...(!isIE()
? { flex: styles.flex }
: { minWidth: styles.flex * 500 + 'px' })
}}
/>
<div
css={`
font-weight: bold;
margin-left: 1rem;
color: var(--textColourOnWhite);
`}>
<Value maximumFractionDigits={0} unit="€">
{montant}
</Value>
</div>
</div>
)
let BranchIcône = ({ icône }) => (
<div className="distribution-chart__legend">
<span className="distribution-chart__icon">{emoji(icône)}</span>
</div>
)