Skip to content

Commit

Permalink
đŸ”„ Suppression de redux-form
Browse files Browse the repository at this point in the history
Supprime aussi redux-batched-action. Le code résultant est plus concis
(alors que l'on supprime une dépendance !), et plus clair car il y a moins
d'indirections pour se conformer aux API de redux-form.
  • Loading branch information
mquandalle committed Sep 13, 2019
1 parent 5129f83 commit e9eddce
Show file tree
Hide file tree
Showing 26 changed files with 320 additions and 594 deletions.
2 changes: 0 additions & 2 deletions package.json
Expand Up @@ -56,8 +56,6 @@
"react-virtualized-select": "^3.1.3",
"reduce-reducers": "^0.1.2",
"redux": "^3.7.2",
"redux-batched-actions": "^0.4.1",
"redux-form": "^8.2.0",
"redux-thunk": "^2.3.0",
"regenerator-runtime": "^0.13.3",
"reselect": "^4.0.0",
Expand Down
7 changes: 1 addition & 6 deletions source/Provider.js
Expand Up @@ -9,7 +9,6 @@ import { Provider as ReduxProvider } from 'react-redux'
import { Router } from 'react-router-dom'
import reducers from 'Reducers/rootReducer'
import { applyMiddleware, compose, createStore } from 'redux'
import { enableBatching } from 'redux-batched-actions'
import thunk from 'redux-thunk'
import { getIframeOption, inIframe } from './utils'

Expand Down Expand Up @@ -54,11 +53,7 @@ export default class Provider extends PureComponent {
if (this.props.initialStore)
this.props.initialStore.lang = this.props.language
}
this.store = createStore(
enableBatching(reducers),
this.props.initialStore,
storeEnhancer
)
this.store = createStore(reducers, this.props.initialStore, storeEnhancer)
this.props.onStoreCreated && this.props.onStoreCreated(this.store)

// Remove loader
Expand Down
14 changes: 9 additions & 5 deletions source/actions/actions.js
Expand Up @@ -7,8 +7,6 @@ import type {
SetSimulationConfigAction,
SetSituationBranchAction
} from 'Types/ActionsTypes'
// $FlowFixMe
import { change, reset } from 'redux-form'
import { deletePersistedSimulation } from '../storage/persistSimulation'
import type { Thunk } from 'Types/ActionsTypes'

Expand All @@ -18,19 +16,19 @@ export const resetSimulation = () => (dispatch: any => void): void => {
type: 'RESET_SIMULATION'
}: ResetSimulationAction)
)
dispatch(reset('conversation'))
}

export const goToQuestion = (question: string): StepAction => ({
type: 'STEP_ACTION',
name: 'unfold',
step: question
})

export const validateStepWithValue = (
dottedName,
value: any
): Thunk<StepAction> => dispatch => {
dispatch({ type: 'UPDATE_SITUATION', fieldName: dottedName, value })
dispatch(change('conversation', dottedName, value))
dispatch(updateSituation(dottedName, value))
dispatch({
type: 'STEP_ACTION',
name: 'fold',
Expand Down Expand Up @@ -63,6 +61,12 @@ export const deletePreviousSimulation = () => (
deletePersistedSimulation()
}

export const updateSituation = (fieldName, value) => ({
type: 'UPDATE_SITUATION',
fieldName,
value
})

// $FlowFixMe
export function setExample(name, situation, dottedName) {
return { type: 'SET_EXAMPLE', name, situation, dottedName }
Expand Down
24 changes: 11 additions & 13 deletions source/components/PercentageField.js
@@ -1,23 +1,21 @@
import React, { useState } from 'react'
import React, { useCallback, useState } from 'react'
import './PercentageField.css'

export default function PercentageField({ input, debounce }) {
const [localValue, setLocalValue] = useState(input?.value)

const debouncedOnChange = debounce
? debounce(debounce, input.onChange)
: input.onChange

const onChange = value => {
setLocalValue(value)
debouncedOnChange(value)
}
export default function PercentageField({ onChange, value, debounce }) {
const [localValue, setLocalValue] = useState(value)
const debouncedOnChange = useCallback(
debounce ? debounce(debounce, onChange) : onChange
)

return (
<div>
<input
className="range"
onChange={e => onChange(e.target.value)}
onChange={e => {
const value = e.target.value
setLocalValue(value)
debouncedOnChange(value)
}}
type="range"
value={localValue}
name="volume"
Expand Down
160 changes: 35 additions & 125 deletions source/components/PeriodSwitch.js
@@ -1,141 +1,51 @@
import { findRuleByDottedName, nestedSituationToPathMap } from 'Engine/rules'
import { compose, filter, map, toPairs } from 'ramda'
import { findRuleByDottedName } from 'Engine/rules'
import React, { useEffect } from 'react'
import { Trans } from 'react-i18next'
import { connect, useDispatch } from 'react-redux'
import { batchActions } from 'redux-batched-actions'
import { change, Field, reduxForm } from 'redux-form'
import { useDispatch, useSelector } from 'react-redux'
import {
flatRulesSelector,
situationSelector,
situationsWithDefaultsSelector
situationSelector
} from 'Selectors/analyseSelectors'
import './PeriodSwitch.css'

export default compose(
reduxForm({
form: 'conversation',
destroyOnUnmount: false
}),
connect(
state => {
let situation = situationsWithDefaultsSelector(state)
if (Array.isArray(situation)) {
situation = situation[0]
}

return {
rules: flatRulesSelector(state),
situation: nestedSituationToPathMap(situationSelector(state)),
initialPériode: situation.période
}
},
dispatch => ({
batchPeriodChange: actions => dispatch(batchActions(actions))
})
)
)(function PeriodSwitch({
situation,
rules,
batchPeriodChange,
initialPĂ©riode
}) {
export default function PeriodSwitch() {
const dispatch = useDispatch()
const rules = useSelector(flatRulesSelector)
const situation = useSelector(situationSelector)
const initialPeriod = useSelector(
state => state.simulation?.config?.situation?.période
)
useEffect(() => {
!situation.période &&
updateSituation(
initialPériode || 'année',
batchPeriodChange,
situation,
rules,
updatePeriod
)
return
})
const updatePeriod = (toPeriod, needConvertion) =>
dispatch({ type: 'UPDATE_PERIOD', toPeriod, needConvertion })
!currentPeriod && updatePeriod(initialPeriod || 'année')
}, [])
const currentPeriod = situation.période
const updatePeriod = toPeriod => {
const needConversion = Object.keys(situation).filter(dottedName => {
const rule = findRuleByDottedName(rules, dottedName)
return rule?.période === 'flexible'
})
dispatch({ type: 'UPDATE_PERIOD', toPeriod, needConversion })
}
const periods = ['mois', 'année']

return (
<span id="PeriodSwitch">
<span className="base ui__ small toggle">
<label>
<Field
name="période"
component="input"
type="radio"
value="année"
onChange={() =>
updateSituation(
'année',
batchPeriodChange,
situation,
rules,
updatePeriod
)
}
/>
<span>
<Trans>année</Trans>
</span>
</label>
<label>
<Field
name="période"
component="input"
type="radio"
value="mois"
onChange={() =>
updateSituation(
'mois',
batchPeriodChange,
situation,
rules,
updatePeriod
)
}
/>
<span>
<Trans>mois</Trans>
</span>
</label>
{periods.map(period => (
<label key={period}>
<input
name="période"
type="radio"
value={period}
onChange={() => updatePeriod(period)}
checked={currentPeriod === period}
/>
<span>
<Trans>{period}</Trans>
</span>
</label>
))}
</span>
</span>
)
})

let updateSituation = (
toPeriod,
batchPeriodChange,
situation,
rules,
updatePeriod
) => {
let needConvertion = filter(([dottedName, value]) => {
let rule = findRuleByDottedName(rules, dottedName)
return value != null && rule?.période === 'flexible'
})(toPairs(situation))

updatePeriod(toPeriod, needConvertion.map(([fieldName]) => fieldName))

let actions = [
...map(
([dottedName, value]) =>
change(
'conversation',
dottedName,
Math.round(
situation.période === 'mois' && toPeriod === 'année'
? value * 12
: situation.période === 'année' && toPeriod === 'mois'
? value / 12
: (function() {
throw new Error('Oups, changement de période invalide')
})()
) + ''
),
needConvertion
),
change('conversation', 'période', toPeriod)
]

batchPeriodChange(actions)
}
31 changes: 16 additions & 15 deletions source/components/SalaryExplanation.js
Expand Up @@ -6,7 +6,7 @@ import React, { useRef } from 'react'
import emoji from 'react-easy-emoji'
import { Trans } from 'react-i18next'
import { connect } from 'react-redux'
import { formValueSelector } from 'redux-form'
import { usePeriod } from 'Selectors/analyseSelectors'
import * as Animate from 'Ui/animate'

class ErrorBoundary extends React.Component {
Expand Down Expand Up @@ -89,20 +89,21 @@ export default compose(
)
})

const PaySlipSection = connect(state => ({
period: formValueSelector('conversation')(state, 'période')
}))(({ period }) => (
<section>
<h2>
<Trans>
{period === 'mois'
? 'Fiche de paie mensuelle'
: 'DĂ©tail annuel des cotisations'}
</Trans>
</h2>
<PaySlip />
</section>
))
function PaySlipSection() {
const period = usePeriod()
return (
<section>
<h2>
<Trans>
{period === 'mois'
? 'Fiche de paie mensuelle'
: 'DĂ©tail annuel des cotisations'}
</Trans>
</h2>
<PaySlip />
</section>
)
}

const DistributionSection = () => (
<section>
Expand Down

0 comments on commit e9eddce

Please sign in to comment.