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


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

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

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

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

interface IndicatorNumberFieldProps {
  label: string;
  initialValue: string;
  onValueChange: (value: string) => void;
  allowNegative?: boolean;
}

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

const IndicatorNumberField = memo(function IndicatorNumberField({
  label,
  initialValue,
  onValueChange,
  allowNegative = false,
}: IndicatorNumberFieldProps) {
  const [value, setValue] = useState(initialValue);

  return (
    <InputText
      className={styles.input}
      value={value}
      onChange={(event) => {
        const rawValue = event.currentTarget.value;
        const nextValue = allowNegative ? rawValue.replace(/[^\d-]/g, '') : rawValue.replace(/[^\d]/g, '');

        setValue(nextValue);
        onValueChange(nextValue);
      }}
      label={label}
      labelPos="top"
      size="sm"
    />
  );
});

interface IndicatorSourceFieldProps {
  initialValue: MaSource;
  onValueChange: (value: MaSource) => void;
}

const IndicatorSourceField = memo(function IndicatorSourceField({
  initialValue,
  onValueChange,
}: IndicatorSourceFieldProps) {
  const [value, setValue] = useState<MaSource>(initialValue);

  return (
    <Select
      classNames={{ dropdown: styles.dropdown, input: styles.input_wrapper }}
      value={value}
      onChange={(nextSource: MaSource) => {
        setValue(nextSource);
        onValueChange(nextSource);
      }}
      options={sourceOptions}
      label="Данные"
      labelPos="top"
      size="sm"
    />
  );
});

export function IndicatorSettingsModal({ settings, onSettingsChange }: IndicatorSettingsModalProps) {
  const draftSettingsRef = useRef<MaIndicatorSettings>({ ...settings });

  const emitSettingsChange = (): void => {
    onSettingsChange?.({ ...draftSettingsRef.current });
  };

  return (
    <Flex
      direction="column"
      divider={null}
      spacing="0500"
      wrap="nowrap"
    >
      <IndicatorNumberField
        label="Длина"
        initialValue={String(settings.length)}
        onValueChange={(nextLengthValue) => {
          const nextLength = Number(nextLengthValue);

          draftSettingsRef.current = {
            ...draftSettingsRef.current,
            length: Number.isFinite(nextLength) && nextLength > 0 ? nextLength : 1,
          };

          emitSettingsChange();
        }}
      />

      <IndicatorSourceField
        initialValue={settings.source}
        onValueChange={(nextSource) => {
          draftSettingsRef.current = {
            ...draftSettingsRef.current,
            source: nextSource,
          };

          emitSettingsChange();
        }}
      />

      <IndicatorNumberField
        label="Отступ"
        initialValue={String(settings.offset)}
        allowNegative
        onValueChange={(nextOffsetValue) => {
          const nextOffset = Number(nextOffsetValue);

          draftSettingsRef.current = {
            ...draftSettingsRef.current,
            offset: Number.isFinite(nextOffset) ? nextOffset : 0,
          };

          emitSettingsChange();
        }}
      />
    </Flex>
  );
}