All files / src/form/fields RangedSeriesInput.tsx

81.81% Statements 27/33
58.33% Branches 7/12
88.88% Functions 8/9
80.64% Lines 25/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83                              67x 5x 5x   5x 2x       2x 2x 2x     5x 1x     1x 1x 4x 3x   1x   1x 1x     5x 4x   4x     5x 4x     5x           8x             10x                              
import React, { CSSProperties, ReactElement, useEffect, useState } from "react";
import { InputNumber } from "antd";
import SeriesInput from "./SeriesInput";
 
interface RangedSeriesInputProps {
  value: string
  style?: CSSProperties;
  defaultLabels?: string[]
  defaultValues?: number[]
  max: number
  labelSuffix?: string
  valueSuffix?: string
  onChange: (value: string) => void
}
 
const RangedSeriesInput = (props: RangedSeriesInputProps): ReactElement => {
  const [data, setData] = useState<Map<string, string>>(new Map<string, string>());
  const [maxValidLabel, setMaxValidLabel] = useState<number>(0.1);
 
  useEffect(() => {
    Iif (props.value === undefined) {
      setData(new Map(Object.entries({ '0': '0', '0.1': '0' })));
      return;
    }
    setData(new Map(Object.entries(JSON.parse(props.value))));
    const _maxValidLabel = ((new Map(Object.entries(JSON.parse(props.value)))).size - 1) / 10;
    setMaxValidLabel(_maxValidLabel);
  }, [props.value]);
 
  const onMaxChange = (max: string | number | null | undefined): void => {
    Iif (max === undefined) {
      return;
    }
    setMaxValidLabel(Number(max));
    for (let i = 0; i <= Number(max); i = (i * 10 + 1) / 10) {
      if (data.has(String(i))) {
        continue;
      }
      data.set(String(i), '0');
    }
    props.onChange(JSON.stringify(Object.fromEntries(getActiveData(data, Number(max)))));
    setData(data);
  };
 
  const parseFunc = (value: string | undefined): number => {
    const strVal: string = (value == null) ?
          '' : value.replace(props.labelSuffix || '', '');
    return parseFloat(strVal);
  };
 
  const getActiveData = (data: Map<string, string>, max: number): Map<string, string> => {
    return new Map([...data].filter(item => Number(item[0]) <= max));
  };
 
  return (
    <div style={props.style}>
      <InputNumber max={props.max}
        min={0.1}
        step={0.1}
        precision={1}
        formatter={value => `${value}${props.labelSuffix || ''}`}
        parser={parseFunc}
        style={{ marginBottom: 30 }}
        onChange={onMaxChange}
        defaultValue={0.1}
        value={maxValidLabel}
      />
      <SeriesInput labels={Array.from(data.keys()).filter(key => Number(key) <= maxValidLabel)}
        values={Array.from(data.values())}
        onChange={(label, value) => {
          data.set(String(label), String(value));
          props.onChange(JSON.stringify(Object.fromEntries(getActiveData(data, maxValidLabel))));
          setData(new Map(data));
        }}
        labelSuffix={props.labelSuffix}
        valueSuffix={props.valueSuffix}
      />
    </div>
  );
};
 
export default RangedSeriesInput;