Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suppression de redux-form #671

Merged
merged 7 commits into from Sep 23, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 1 addition & 4 deletions source/components/PeriodSwitch.js
Expand Up @@ -11,15 +11,12 @@ export default function PeriodSwitch() {
state => state.simulation?.config?.situation?.période || 'année'
)
const currentPeriod = situation.période
let periods = ['mois', 'année']
let periods = ['année', 'mois']
const updatePeriod = toPeriod => dispatch({ type: 'UPDATE_PERIOD', toPeriod })

if (!currentPeriod) {
updatePeriod(defaultPeriod)
}
if (defaultPeriod === 'année') {
periods.reverse()
}

return (
<span id="PeriodSwitch">
Expand Down
8 changes: 3 additions & 5 deletions source/components/TargetSelection.css
Expand Up @@ -106,8 +106,8 @@
text-decoration: none;
}

#targetSelection .targetInputOrValue > :not(.targetInput):not(.attractClick) {
margin: 0.2rem 0.6rem;
#targetSelection .targetInputOrValue > :not(.targetInput) {
margin: 0 0.6rem;
}

#targetSelection input {
Expand Down Expand Up @@ -136,11 +136,9 @@

#targetSelection .targetInputBottomBorder {
margin: 0;
padding: 0;
padding: 0 2px;
height: 0;
overflow: hidden;
position: relative;
top: -6px;
}

#targetSelection .editableTarget + .targetInputBottomBorder {
Expand Down
96 changes: 39 additions & 57 deletions source/components/TargetSelection.js
@@ -1,13 +1,11 @@
import { updateSituation } from 'Actions/actions'
import { T } from 'Components'
import InputSuggestions from 'Components/conversation/InputSuggestions'
import PercentageField from 'Components/PercentageField'
import PeriodSwitch from 'Components/PeriodSwitch'
import RuleLink from 'Components/RuleLink'
import { ThemeColoursContext } from 'Components/utils/withColours'
import withSitePaths from 'Components/utils/withSitePaths'
import { encodeRuleName } from 'Engine/rules'
import { serialiseUnit } from 'Engine/units'
import { isEmpty, isNil } from 'ramda'
import React, { useEffect, useState, useContext } from 'react'
import emoji from 'react-easy-emoji'
Expand Down Expand Up @@ -221,36 +219,9 @@ export const formatCurrency = (value, language) => {
.replace(/^€/, '€ ')
}

let clickableField = Input =>
function WrappedClickableField({ value, ...otherProps }) {
const colors = useContext(ThemeColoursContext)
const { language } = useTranslation().i18n
return (
<>
<AnimatedTargetValue value={value} />
<Input
value={value}
debounce={600}
style={{
color: colors.textColour,
borderColor: colors.textColour
}}
{...otherProps}
/>
<span className="targetInputBottomBorder">
{formatCurrency(value, language)}
</span>
</>
)
}

let unitToComponent = {
'€': clickableField(CurrencyInput),
'%': clickableField(PercentageField)
}

let TargetInputOrValue = ({ target, isActiveInput, isSmallTarget }) => {
const { i18n } = useTranslation()
const colors = useContext(ThemeColoursContext)
const dispatch = useDispatch()
const situationValue = useSituationValue(target.dottedName)
const targetWithValue = useTarget(target.dottedName)
Expand All @@ -259,39 +230,50 @@ let TargetInputOrValue = ({ target, isActiveInput, isSmallTarget }) => {
state => analysisWithDefaultsSelector(state)?.cache.inversionFail
)
const blurValue = inversionFail && !isActiveInput && value
const Component = unitToComponent[serialiseUnit(target.unit)]

return (
<span
className="targetInputOrValue"
style={blurValue ? { filter: 'blur(3px)' } : {}}>
{target.question ? (
<Component
name={target.dottedName}
value={situationValue || value}
className={
isActiveInput || isNil(value) ? 'targetInput' : 'editableTarget'
}
onChange={evt =>
dispatch(updateSituation(target.dottedName, evt.target.value))
}
onBlur={event => event.preventDefault()}
// We use onMouseDown instead of onClick because that's when the browser moves the cursor
onMouseDown={() => {
if (isSmallTarget) return
dispatch({
type: 'SET_ACTIVE_TARGET_INPUT',
name: target.dottedName
})
// TODO: This shouldn't be necessary: we don't need to recalculate the situation
// when the user just focus another field. Removing this line is almost working
// however there is a weird bug in the selection of the next question.
if (value) {
dispatch(updateSituation(target.dottedName, '' + value))
<>
{!isActiveInput && <AnimatedTargetValue value={value} />}
mquandalle marked this conversation as resolved.
Show resolved Hide resolved
<CurrencyInput
style={{
color: colors.textColour,
borderColor: colors.textColour
}}
debounce={600}
name={target.dottedName}
value={situationValue || value}
className={
isActiveInput || isNil(value) ? 'targetInput' : 'editableTarget'
}
onChange={evt =>
dispatch(updateSituation(target.dottedName, evt.target.value))
}
}}
{...(isActiveInput ? { autoFocus: true } : {})}
language={i18n.language}
/>
onBlur={event => event.preventDefault()}
// We use onMouseDown instead of onClick because that's when the browser moves the cursor
onMouseDown={() => {
if (isSmallTarget) return
dispatch({
type: 'SET_ACTIVE_TARGET_INPUT',
name: target.dottedName
})
// TODO: This shouldn't be necessary: we don't need to recalculate the situation
// when the user just focus another field. Removing this line is almost working
// however there is a weird bug in the selection of the next question.
if (value) {
dispatch(updateSituation(target.dottedName, '' + value))
}
}}
{...(isActiveInput ? { autoFocus: true } : {})}
language={i18n.language}
/>
<span className="targetInputBottomBorder">
{formatCurrency(value, i18n.language)}
</span>
</>
) : (
<span>
{Number.isNaN(value) ? '—' : formatCurrency(value, i18n.language)}
Expand Down
37 changes: 22 additions & 15 deletions source/components/ui/AnimatedTargetValue.js
@@ -1,29 +1,36 @@
/* @flow */
import React, { useEffect, useState } from 'react'
import React, { useRef } from 'react'
import ReactCSSTransitionGroup from 'react-addons-css-transition-group'
import { useTranslation } from 'react-i18next'
import './AnimatedTargetValue.css'
import { formatCurrency } from 'Components/TargetSelection'

type Props = {
value: ?number
}

function formatDifference(difference, language) {
const prefix = difference > 0 ? '+' : ''
const formatedValue = Intl.NumberFormat(language, {
style: 'currency',
currency: 'EUR',
maximumFractionDigits: 0,
minimumFractionDigits: 0
}).format(difference)
return prefix + formatedValue
}

export default function AnimatedTargetValue({ value, children }: Props) {
const [difference, setDifference] = useState(0)
const [previousValue, setPreviousValue] = useState()
useEffect(() => {
if (previousValue === value || Number.isNaN(value)) {
return
}
setDifference((value || 0) - (previousValue || 0))
setPreviousValue(value)
}, [previousValue, value])
const { i18n } = useTranslation()
const previousValue = useRef()
const { language } = useTranslation().i18n

const formattedDifference = formatCurrency(difference, i18n.language)
const difference =
previousValue.current === value || Number.isNaN(value)
? null
: (value || 0) - (previousValue.current || 0)
previousValue.current = value
const shouldDisplayDifference =
Math.abs(difference) > 1 && value != null && !Number.isNaN(value)
difference !== null && Math.abs(difference) > 1

return (
<>
<span className="Rule-value">
Expand All @@ -33,7 +40,7 @@ export default function AnimatedTargetValue({ value, children }: Props) {
color: difference > 0 ? 'chartreuse' : 'red',
pointerEvents: 'none'
}}>
{(difference > 0 ? '+' : '') + formattedDifference}
{formatDifference(difference, language)}
</Evaporate>
)}{' '}
{children}
Expand Down