Загрузка данных


import { Flex, InputText, Select } from 'exchange-elements/v2';
import { ChangeEventHandler, useRef, useState } from 'react';

import { MaIndicatorSettings, MaSource } from '@src/core/Indicators/settings';

import styles from './index.module.scss';

interface IndicatorSettingsModalProps {
  settings: MaIndicatorSettings;
  onSettingsChange?: (settings: MaIndicatorSettings) => void;
}

interface IndicatorSettingsFormValues {
  length: string;
  offset: string;
  source: MaSource;
}

const sourceOptions: { label: string; value: MaSource }[] = [
  { label: 'Цена открытия', value: 'open' },
  { label: 'Максимум', value: 'high' },
  { label: 'Минимум', value: 'low' },
  { label: 'Цена закрытия', value: 'close' },
];

function normalizeLength(rawLength: string, fallbackLength: number): number {
  const parsedLength = Number(rawLength);

  if (Number.isFinite(parsedLength) && parsedLength > 0) {
    return parsedLength;
  }

  return fallbackLength;
}

function normalizeOffset(rawOffset: string, fallbackOffset: number): number {
  const parsedOffset = Number(rawOffset);

  if (Number.isFinite(parsedOffset)) {
    return parsedOffset;
  }

  return fallbackOffset;
}

export function IndicatorSettingsModal({ settings, onSettingsChange }: IndicatorSettingsModalProps) {
  const [formValues, setFormValues] = useState<IndicatorSettingsFormValues>({
    length: String(settings.length),
    offset: String(settings.offset),
    source: settings.source,
  });

  const latestSettingsRef = useRef<MaIndicatorSettings>({ ...settings });

  const applyFormValues = (nextFormValues: IndicatorSettingsFormValues): void => {
    setFormValues(nextFormValues);

    const nextSettings: MaIndicatorSettings = {
      length: normalizeLength(nextFormValues.length, latestSettingsRef.current.length),
      offset: normalizeOffset(nextFormValues.offset, latestSettingsRef.current.offset),
      source: nextFormValues.source,
    };

    latestSettingsRef.current = nextSettings;
    onSettingsChange?.(nextSettings);
  };

  const handleLengthChange: ChangeEventHandler<HTMLInputElement> = (event) => {
    applyFormValues({
      ...formValues,
      length: event.currentTarget.value.replace(/[^\d]/g, ''),
    });
  };

  const handleOffsetChange: ChangeEventHandler<HTMLInputElement> = (event) => {
    applyFormValues({
      ...formValues,
      offset: event.currentTarget.value.replace(/[^\d-]/g, ''),
    });
  };

  const handleSourceChange = (nextSource: MaSource): void => {
    applyFormValues({
      ...formValues,
      source: nextSource,
    });
  };

  return (
    <Flex
      direction="column"
      divider={null}
      spacing="0500"
      wrap="nowrap"
    >
      <InputText
        className={styles.input}
        value={formValues.length}
        onChange={handleLengthChange}
        label="Длина"
        labelPos="top"
        size="sm"
      />

      <Select
        classNames={{ dropdown: styles.dropdown, input: styles.input_wrapper }}
        value={formValues.source}
        onChange={handleSourceChange}
        options={sourceOptions}
        label="Данные"
        labelPos="top"
        size="sm"
      />

      <InputText
        className={styles.input}
        value={formValues.offset}
        onChange={handleOffsetChange}
        label="Отступ"
        labelPos="top"
        size="sm"
      />
    </Flex>
  );
}