mon-entreprise/source/components/EngineValue.tsx

66 lines
1.6 KiB
TypeScript

import Engine from 'Engine'
import { formatValue } from 'Engine/format'
import { EvaluatedNode } from 'Engine/types'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { DottedName } from 'Rules'
import { coerceArray } from '../utils'
import RuleLink from './RuleLink'
import { EngineContext } from './utils/EngineContext'
export type ValueProps = {
expression: string
unit?: string
displayedUnit?: string
precision?: number
engine?: Engine<DottedName>
linkToRule?: boolean
} & React.HTMLProps<HTMLSpanElement>
export default function Value({
expression,
unit,
displayedUnit,
precision,
engine,
linkToRule = true,
...props
}: ValueProps) {
const { language } = useTranslation().i18n
if (expression === null) {
throw new TypeError('expression cannot be null')
}
const evaluation = (engine ?? useContext(EngineContext)).evaluate(
expression,
{ unit }
)
const nodeValue = evaluation.nodeValue
const value = formatValue({
nodeValue,
unit:
displayedUnit ?? (evaluation as EvaluatedNode<DottedName, number>).unit,
language,
precision
})
if ('dottedName' in evaluation && linkToRule) {
return (
<RuleLink {...evaluation}>
<span {...props}>{value}</span>
</RuleLink>
)
}
return <span {...props}>{value}</span>
}
type ConditionProps = {
expression: string | string[]
children: React.ReactNode
}
export function Condition({ expression, children }: ConditionProps) {
const engine = useContext(EngineContext)
if (!coerceArray(expression).every(expr => engine.evaluate(expr).nodeValue)) {
return null
}
return <>{children}</>
}