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


import { Button } from 'exchange-elements/v2';

import { GearIcon, TrashIcon } from '@src/components/Icon';

import { LegendValueItem } from '@src/types';

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

interface LegendSeriesRowProps {
  label: string;
  values?: LegendValueItem[];
  onRemove?: () => void;
  onEdit?: () => void;
}

export function LegendSeriesRow({ label, values, onRemove, onEdit }: LegendSeriesRowProps) {
  return (
    <div className={styles.item}>
      <div className={styles.symbol}>{label}</div>

      <div className={styles.priceWrapper}>
        {values?.map(({ id, value, color }) => (
          <span
            key={id}
            style={{ color }}
            className={styles.price}
          >
            {value}
          </span>
        ))}

        {onEdit && (
          <Button
            size="sm"
            className={styles.button}
            onClick={onEdit}
            label={<GearIcon />}
          />
        )}

        {onRemove && (
          <Button
            size="sm"
            className={styles.button}
            onClick={onRemove}
            label={<TrashIcon />}
          />
        )}
      </div>
    </div>
  );
}



import { Observable } from 'rxjs';

import { LegendSeriesRow } from '@src/components/LegendSeriesRow';

import { IndicatorsIds } from '@src/core/Indicators';

import { CompareMode, LegendVM, OHLCConfig } from '../../types';
import { formatPrice, getPriceColor, useObservable } from '../../utils';

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

export interface LegendProps {
  ohlcConfig?: OHLCConfig;
  viewModel: Observable<LegendVM>;
  onCompareRemove?: (symbol: string, mode: CompareMode) => void;
  onIndicatorEdit?: (indicator: IndicatorsIds) => void;
  onIndicatorRemove?: (indicatorId: IndicatorsIds) => void;
}

export const LegendComponent = ({
  ohlcConfig,
  viewModel: vm,
  onCompareRemove,
  onIndicatorRemove,
  onIndicatorEdit,
}: LegendProps) => {
  const viewModel = useObservable(vm);
  const ohlc = viewModel?.ohlc ?? null;
  const symbol = viewModel?.symbol ?? null;
  const compareItems = viewModel?.compareItems ?? [];
  const indicatorItems = viewModel?.indicatorItems ?? [];

  const showOhlc = ohlcConfig?.show;

  const priceColor = getPriceColor(ohlc);

  const renderLegendItem = (label: string, value?: string | number, show = true) => {
    if (!show || !value) return null;

    return (
      <div className={styles.item}>
        {label} <span style={{ color: priceColor }}>{value}</span>
      </div>
    );
  };

  return (
    <section className={styles.legend}>
      <div className={styles.row}>
        {symbol && <div className={styles.symbol}>{symbol}</div>}
        {showOhlc && (
          <>
            {renderLegendItem('Отк.', formatPrice(ohlc?.open), !!ohlc?.open)}
            {renderLegendItem('Макс.', formatPrice(ohlc?.high), !!ohlc?.high)}
            {renderLegendItem('Мин.', formatPrice(ohlc?.low), !!ohlc?.low)}
            {renderLegendItem('Закр.', formatPrice(ohlc?.close), !!ohlc?.close)}
            {renderLegendItem(
              'Изм.',
              `${formatPrice(ohlc?.percentageChange)}%`,
              !!ohlc?.absoluteChange && !!ohlc?.percentageChange,
            )}
          </>
        )}
      </div>
      {indicatorItems.map(({ id, label, values }) => (
        <LegendSeriesRow
          key={id}
          label={label}
          values={values}
          onEdit={() => onIndicatorEdit?.(id)}
          onRemove={() => onIndicatorRemove?.(id)}
        />
      ))}
      {compareItems.map(({ symbol: itemSymbol, mode, values }) => (
        <LegendSeriesRow
          key={`${itemSymbol}|${mode}`}
          label={itemSymbol}
          values={values}
          onRemove={() => onCompareRemove?.(itemSymbol, mode)}
        />
      ))}
    </section>
  );
};