2
0
Files
bot/apps/builder/src/components/inputs/SmartNumberInput.tsx

117 lines
3.0 KiB
TypeScript
Raw Normal View History

import { VariablesButton } from '@/features/variables'
2021-12-23 13:49:24 +01:00
import {
NumberInputProps,
NumberInput,
NumberInputField,
NumberInputStepper,
NumberIncrementStepper,
NumberDecrementStepper,
HStack,
FormControl,
FormLabel,
2021-12-23 13:49:24 +01:00
} from '@chakra-ui/react'
import { Variable, VariableString } from 'models'
2022-03-09 15:12:00 +01:00
import { useEffect, useState } from 'react'
import { useDebouncedCallback } from 'use-debounce'
import { env } from 'utils'
import { MoreInfoTooltip } from '../MoreInfoTooltip'
2021-12-23 13:49:24 +01:00
type Value<HasVariable> = HasVariable extends undefined | true
? number | VariableString
: number
type Props<HasVariable extends boolean> = {
defaultValue?: Value<HasVariable>
2023-01-26 18:23:09 +01:00
debounceTimeout?: number
withVariableButton?: HasVariable
label?: string
moreInfoTooltip?: string
isRequired?: boolean
onValueChange: (value?: Value<HasVariable>) => void
} & Omit<NumberInputProps, 'defaultValue' | 'value' | 'onChange' | 'isRequired'>
2023-01-26 18:23:09 +01:00
export const SmartNumberInput = <HasVariable extends boolean>({
defaultValue,
2021-12-23 13:49:24 +01:00
onValueChange,
withVariableButton,
debounceTimeout = 1000,
label,
moreInfoTooltip,
isRequired,
2021-12-23 13:49:24 +01:00
...props
}: Props<HasVariable>) => {
const [value, setValue] = useState(defaultValue?.toString() ?? '')
const onValueChangeDebounced = useDebouncedCallback(
onValueChange,
2022-08-08 08:21:36 +02:00
env('E2E_TEST') === 'true' ? 0 : debounceTimeout
2022-03-09 15:12:00 +01:00
)
useEffect(
() => () => {
onValueChangeDebounced.flush()
},
[onValueChangeDebounced]
)
2021-12-23 13:49:24 +01:00
const handleValueChange = (value: string) => {
setValue(value)
2021-12-23 13:49:24 +01:00
if (value.endsWith('.') || value.endsWith(',')) return
if (value === '') return onValueChangeDebounced(undefined)
if (
value.startsWith('{{') &&
value.endsWith('}}') &&
value.length > 4 &&
(withVariableButton ?? true)
) {
onValueChangeDebounced(value as Value<HasVariable>)
return
}
2021-12-23 13:49:24 +01:00
const newValue = parseFloat(value)
if (isNaN(newValue)) return
onValueChangeDebounced(newValue)
}
2021-12-23 13:49:24 +01:00
const handleVariableSelected = (variable?: Variable) => {
if (!variable) return
const newValue = `{{${variable.name}}}`
handleValueChange(newValue)
}
const Input = (
<NumberInput onChange={handleValueChange} value={value} {...props}>
2022-05-24 14:25:15 -07:00
<NumberInputField placeholder={props.placeholder} />
2021-12-23 13:49:24 +01:00
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
)
return (
<FormControl
as={HStack}
isRequired={isRequired}
justifyContent="space-between"
width={label ? 'full' : 'auto'}
>
{label && (
<FormLabel mb="0" flexShrink={0}>
{label}{' '}
{moreInfoTooltip && (
<MoreInfoTooltip>{moreInfoTooltip}</MoreInfoTooltip>
)}
</FormLabel>
)}
{withVariableButton ?? true ? (
<HStack spacing={0}>
{Input}
<VariablesButton onSelectVariable={handleVariableSelected} />
</HStack>
) : (
Input
)}
</FormControl>
)
2021-12-23 13:49:24 +01:00
}