mirror of
https://github.com/betagouv/mon-entreprise
synced 2025-02-09 02:55:01 +00:00
Quand une variable est destinée à être saisie par l'utilisateur, on veut qu'il saisisse 50, pas 0.5 pour exprimer 50%. On pourrait lui faire saisir 50 et convertir en direct vers la vraie valeur de 0.5, mais c'est compliqué aujourd'hui dans reduxForm (l'attribut "normalize" ne suffit pas, car la valeur 0.5 sera visible après un bref instant de debounce). Je pense qu'il serai quand même mieux que nous stockions les variables qui sont des ratios comme 0.5 et que l'UI se charge d'afficher et de faire saisir ces valeurs sous forme 50%.
79 lines
2 KiB
JavaScript
79 lines
2 KiB
JavaScript
import { remove, isEmpty, unnest } from 'ramda'
|
|
|
|
//TODO this function does not handle complex units like passenger-kilometer/flight
|
|
export let parseUnit = string => {
|
|
let [a, b = ''] = string.split('/'),
|
|
result = {
|
|
numerators: a !== '' ? [a] : [],
|
|
denominators: b !== '' ? [b] : []
|
|
}
|
|
return result
|
|
}
|
|
|
|
let printUnits = units => units.filter(unit => unit !== '%').join('-')
|
|
|
|
export let serialiseUnit = rawUnit => {
|
|
let unit = simplify(rawUnit),
|
|
{ numerators = [], denominators = [] } = unit
|
|
|
|
// the unit '%' is only displayed when it is the only unit
|
|
let merge = [...numerators, ...denominators]
|
|
if (merge.length === 1 && merge[0] === '%') return '%'
|
|
|
|
let n = !isEmpty(numerators)
|
|
let d = !isEmpty(denominators)
|
|
let string =
|
|
!n && !d
|
|
? ''
|
|
: n && !d
|
|
? printUnits(numerators)
|
|
: !n && d
|
|
? `/${printUnits(denominators)}`
|
|
: `${printUnits(numerators)} / ${printUnits(denominators)}`
|
|
|
|
return string
|
|
}
|
|
|
|
let noUnit = { numerators: [], denominators: [] }
|
|
export let inferUnit = (operator, rawUnits) => {
|
|
let units = rawUnits.map(u => u || noUnit)
|
|
if (operator === '*')
|
|
return simplify({
|
|
numerators: unnest(units.map(u => u.numerators)),
|
|
denominators: unnest(units.map(u => u.denominators))
|
|
})
|
|
if (operator === '/') {
|
|
if (units.length !== 2)
|
|
throw new Error('Infer units of a division with units.length !== 2)')
|
|
return inferUnit('*', [
|
|
units[0],
|
|
{
|
|
numerators: units[1].denominators,
|
|
denominators: units[1].numerators
|
|
}
|
|
])
|
|
}
|
|
|
|
if (operator === '-' || operator === '+') {
|
|
return rawUnits.find(u => u)
|
|
}
|
|
|
|
return null
|
|
}
|
|
export let removeOnce = element => list => {
|
|
let index = list.indexOf(element)
|
|
if (index > -1) return remove(index, 1)(list)
|
|
else return list
|
|
}
|
|
|
|
let simplify = unit =>
|
|
[...unit.numerators, ...unit.denominators].reduce(
|
|
({ numerators, denominators }, next) =>
|
|
numerators.includes(next) && denominators.includes(next)
|
|
? {
|
|
numerators: removeOnce(next)(numerators),
|
|
denominators: removeOnce(next)(denominators)
|
|
}
|
|
: { numerators, denominators },
|
|
unit
|
|
)
|