import React, {FC, ReactNode, useEffect} from "react"; import {MultiSelectSearch} from "./MultiSelectSearch"; import {NumericOptions} from "../tiers"; import {Field} from "../cards"; import {findKey, map} from "lodash"; import {NumberInput, NumberInputProps} from "./NumberInput"; import {__} from "../../globals"; import {lastChanged, NumberFieldType} from "./LastChanged"; import {ToolTip} from "../../ToolTip"; import classNames from "classnames"; import ReactDOM from "react-dom"; export type NumberProps = Pick & { id?: string, fieldMeta: { type?: Field, amount?: Field, range?: { minimum: Field, maxmimum: Field, }, }, hasAmountStructure?: boolean, // basically whether the field is field.amount or just field value: Omit & { type?: NumericOptions['type'] } | number, onChange: (fieldId: string, value: any) => void, labels?: { top?: string,z input?: NumberInputProps['labels'], // may add more placements in the future }, border?: boolean, bottomNoticesPortalRef?: React.MutableRefObject, showSingleOption?: boolean, persistDefaultOnMount?: boolean } export const Number: FC = ({ id, fieldMeta = {} as NumberProps['fieldMeta'], value, onChange, type, labels, input, size, hasAmountStructure = true, border = true, bottomNoticesPortalRef, showSingleOption = true, persistDefaultOnMount = false }) => { const options = map(fieldMeta?.type?.meta?._allowed, (one, two) => ({id: one, value: one, label: two})) const numberType = typeof value === 'object' && value !== null ? (value as Omit & { type?: NumericOptions['type'] }).type : undefined const change: typeof onChange = (field, newValue) => { let fieldType: NumberFieldType fieldType = field || 'amount' //range.minimum || range.maxmimum lastChanged.numberId = id lastChanged.fieldType = fieldType onChange(field, newValue) } const getNumberDefaultValue = (): number => { const rawDefaultValue = hasAmountStructure ? fieldMeta?.amount?.meta?._default : (fieldMeta as unknown as { meta?: { _default?: unknown } })?.meta?._default; if (rawDefaultValue === '' || rawDefaultValue === null || typeof rawDefaultValue === 'undefined') { return 1; } const parsedDefaultValue = globalThis.Number(rawDefaultValue); return globalThis.Number.isFinite(parsedDefaultValue) ? parsedDefaultValue : 1; } const numberDefaultValue = getNumberDefaultValue(); const numberValue = hasAmountStructure ? (value as Omit & { amount?: unknown })?.amount : value; const hasNumberValue = typeof numberValue === 'number' && !globalThis.Number.isNaN(numberValue); const renderedNumberValue = (persistDefaultOnMount && numberType !== 'range' && !hasNumberValue) ? numberDefaultValue : (numberValue as number); useEffect(() => { if (!persistDefaultOnMount || numberType === 'range' || hasNumberValue) { return; } change(hasAmountStructure ? 'amount' : '', numberDefaultValue); }, [persistDefaultOnMount, numberType, hasNumberValue, hasAmountStructure, numberDefaultValue]); const selectedType = typeof value === 'object' && value !== null ? (value as Omit & { type?: NumericOptions['type'] }).type : undefined; const floatingSelector = true; return
{labels?.top && {labels.top}}
{fieldMeta?.type?.meta?._allowed && (options.length === 1? showSingleOption : true) && 1 ? 'gray-lighter' : 'transparent-gray'} options={options} selectedValue={ options.find(({id}) => id === selectedType) } onSelectedValue={({id}) => { onChange('type', id) }}>}
{numberType !== 'range' && change(hasAmountStructure ? 'amount' : '', value)} type={type} labels={labels?.input} input={input} size={size} /> } {numberType === 'range' &&
change('range.minimum', value)} type={type} size={size}/> {__('Minimum')}
change('range.maxmimum', value)} type={type} size={size}/> {__('Maximum')}
}
{bottomNoticesPortalRef?.current && ReactDOM.createPortal(
{(fieldMeta?.type?.meta?.notes?.[selectedType || ''] as unknown as string[]) && ( ( type === selectedType )) || ''} content={(fieldMeta?.type?.meta?.notes?.[selectedType || ''] as unknown as string[])} style={'light'} width={'full'} animate={false} /> )} {(fieldMeta?.meta?.notes as unknown as string[]) && fieldMeta?.meta?.notes?.map(note => ( ))}
, bottomNoticesPortalRef?.current)}
};