1
0
Fork 0
mirror of https://github.com/betagouv/mon-entreprise synced 2025-02-09 00:35:00 +00:00
mon-entreprise/source/engine/units.js
Mael 1431c02f34 Introduction du faux pourcentage (%)
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%.
2019-07-23 19:07:40 +02:00

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
)