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


import { BarIcon, CandleStickIcon, LineIcon } from '@src/components/Icon';

import { MenuList, MenuOption } from '@src/components/Menu/MenuList';
import { t } from '@src/translations';
import { ChartSeriesType } from '@src/types';

interface SeriesMenuProps {
  selectedType?: ChartSeriesType;
  seriesTypes: ChartSeriesType[];
  onClick: (next: ChartSeriesType) => void;
}

const seriesOptions = (): Partial<Record<ChartSeriesType, MenuOption<ChartSeriesType>>> => {
  return {
    Candlestick: {
      icon: <CandleStickIcon />,
      value: 'Candlestick',
      label: t('Candles'),
    },
    Line: {
      icon: <LineIcon />,
      value: 'Line',
      label: t('Line'),
    },
    Bar: {
      icon: <BarIcon />,
      value: 'Bar',
      label: t('Bars'),
    },
  };
};

export function SeriesMenu({ selectedType, seriesTypes, onClick }: SeriesMenuProps) {
  const options: MenuOption<ChartSeriesType>[] = seriesTypes.map((type) => ({
    value: type,
    icon: seriesOptions()[type]?.icon,
    label: seriesOptions()[type]?.label,
  }));

  return (
    <MenuList
      mode="single"
      value={selectedType}
      options={options}
      onClick={onClick}
    />
  );
}

















import { Button, Divider } from 'exchange-elements/v2';
import { useEffect, useState } from 'react';

import { type Observable, of } from 'rxjs';

import { IndicatorsSelect } from '@components/IndicatorsSelect';

import { IndicatorsIds } from '@src/constants';
import { FullscreenController } from '@src/core/Fullscreen';
import { UndoRedo, type UndoRedoState } from '@src/core/UndoRedo';
import { t } from '@src/translations';
import { ChartSeriesType } from '@src/types';
import { Timeframes } from '@src/types/timeframes';

import { useObservable } from '@src/utils';

import { Dropdown } from '../Dropdown';
import {
  BarIcon,
  BurgerMenuIcon,
  CandleStickIcon,
  FullscreenIcon,
  LineIcon,
  PlusCircleIcon,
  RedoIcon,
  SearchIcon,
  UndoIcon,
} from '../Icon';
import { SeriesMenu, TimeframesMenu } from '../Menu';

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

const defaultUndoRedoState: UndoRedoState = {
  canUndo: false,
  canRedo: false,
};

const defaultUndoRedoState$ = of(defaultUndoRedoState);

interface HeaderProps {
  timeframes: Timeframes[];
  selectedTimeframeObs: Observable<Timeframes>;
  setTimeframe: (value: Timeframes) => void;
  seriesTypes: ChartSeriesType[];
  setSelectedSeries: (next: ChartSeriesType) => void;
  selectedSeriesObs: Observable<ChartSeriesType>;
  showSettingsModal: (() => void) | undefined;
  addIndicatorToChart: (id: IndicatorsIds) => void;
  toggleToolbarVisible: () => boolean;
  showCompareButton: boolean;
  showSymbolSearchButton: boolean;
  undoRedo: UndoRedo | undefined;
  showMenuButton?: boolean;
  showFullscreenButton?: boolean;
  fullscreen: FullscreenController;
  openCompareModal?: () => void;
  openSymbolSearchModal?: () => void;
  isMXT: boolean;
}

export function Header({
  setTimeframe,
  selectedTimeframeObs,
  setSelectedSeries,
  selectedSeriesObs,
  timeframes,
  seriesTypes,
  showSettingsModal,
  addIndicatorToChart,
  toggleToolbarVisible,
  showCompareButton,
  showSymbolSearchButton,
  fullscreen,
  undoRedo,
  showFullscreenButton,
  showMenuButton,
  openCompareModal,
  openSymbolSearchModal,
  isMXT,
}: HeaderProps) {
  const [isToolbarOpen, setIsToolbarOpen] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(fullscreen.isFullscreen);
  const undoRedoState = useObservable(undoRedo?.getState() ?? defaultUndoRedoState$, defaultUndoRedoState);

  useEffect(() => {
    const unsubscribe = fullscreen.onChange(() => {
      setIsFullscreen(fullscreen.isFullscreen);
    });

    return unsubscribe;
  }, [fullscreen]);

  const selectedTimeframe = useObservable(selectedTimeframeObs);
  const selectedSeries = useObservable(selectedSeriesObs);

  const seriesDropdownValue =
    selectedSeries === 'Line' ? <LineIcon /> : selectedSeries === 'Bar' ? <BarIcon /> : <CandleStickIcon />;

  const handleOpenToolbar = (): void => {
    setIsToolbarOpen(toggleToolbarVisible());
  };

  return (
    <header className={styles.header}>
      <div className={styles.group}>
        {showMenuButton && (
          <Button
            size="sm"
            className={`${styles.button} ${isToolbarOpen ? styles.pressed : ''}`}
            onClick={handleOpenToolbar}
            label={<BurgerMenuIcon />}
          />
        )}
        {showSymbolSearchButton && (
          <Button
            size="sm"
            className={styles.button}
            onClick={openSymbolSearchModal}
            label={<SearchIcon />}
          />
        )}
        {showCompareButton && (
          <Button
            size="sm"
            className={styles.button}
            onClick={openCompareModal}
            label={<PlusCircleIcon />}
          />
        )}
      </div>

      {(showMenuButton || showCompareButton) && (
        <Divider
          direction="vertical"
          pt={{ divider: { className: styles.divider } }}
        />
      )}

      <Dropdown
        menuClassName={styles.menu}
        selectedValue={selectedTimeframe ? t(selectedTimeframe) : selectedTimeframe}
      >
        <TimeframesMenu
          onClick={setTimeframe}
          {...{ selectedTimeframe, timeframes }}
        />
      </Dropdown>

      <Divider
        direction="vertical"
        pt={{ divider: { className: styles.divider } }}
      />

      <div className={styles.group}>
        <IndicatorsSelect
          addIndicatorToChart={addIndicatorToChart}
          isMXT={isMXT}
        />
        {showSettingsModal && (
          <Button
            size="sm"
            className={styles.button}
            onClick={showSettingsModal}
            label={t('Settings')}
          />
        )}
        <Dropdown
          menuClassName={styles.menu}
          selectedValue={seriesDropdownValue}
        >
          <SeriesMenu
            selectedType={selectedSeries}
            seriesTypes={seriesTypes}
            onClick={setSelectedSeries}
          />
        </Dropdown>
      </div>

      {(undoRedo || showFullscreenButton) && (
        <Divider
          direction="vertical"
          pt={{ divider: { className: styles.divider } }}
        />
      )}

      {undoRedo && (
        <div className={styles.group}>
          <Button
            size="sm"
            className={styles.button}
            onClick={undoRedo.undo}
            disabled={!undoRedoState?.canUndo}
            label={<UndoIcon />}
          />
          <Button
            size="sm"
            className={styles.button}
            onClick={undoRedo.redo}
            disabled={!undoRedoState?.canRedo}
            label={<RedoIcon />}
          />
        </div>
      )}

      {showFullscreenButton && (
        <Button
          size="sm"
          className={`${styles.button} ${isFullscreen ? styles.pressed : ''}`}
          onClick={() => fullscreen.toggle()}
          label={<FullscreenIcon />}
        />
      )}
    </header>
  );
}

















export const russian = {
  Indicators: 'Индикаторы',
  Settings: 'Настройки',
  'Add volume indicator': 'Добавить индикатор объёма',
  tick: 'тик',
  ticks: 'тики',
  tick_few: 'тика',
  tick_many: 'тиков',
  second: 'секунда',
  seconds: 'секунды',
  second_few: 'секунды',
  second_many: 'секунд',
  minute: 'минута',
  minutes: 'минуты',
  minute_few: 'минуты',
  minute_many: 'минут',
  hour: 'час',
  hours: 'часы',
  hour_few: 'часа',
  hour_many: 'часов',
  day: 'день',
  days: 'дни',
  day_few: 'дня',
  day_many: 'дней',
  week: 'неделя',
  weeks: 'недели',
  week_few: 'недели',
  week_many: 'недель',
  month: 'месяц',
  months: 'месяцы',
  month_few: 'месяца',
  month_many: 'месяцев',
  Bars: 'Бары',
  Line: 'Линия',
  Candles: 'Свечи',
  'Time format': 'Формат времени',
  'Date format': 'Формат даты',
  'Line start': 'Начало линии',
  'Line end': 'Конец линии',
  Normal: 'Обычный',
  Crosshair: 'Перекрестие',
  Arrow: 'Стрелка',
  'Trend line': 'Линия тренда',
  Ray: 'Луч',
  'Horizontal line': 'Горизонтальная линия',
  'Horizontal ray': 'Горизонтальный луч',
  'Vertical line': 'Вертикальная линия',
  'Vertical ray': 'Вертикальный луч',
  'Long position': 'Длинная позиция',
  'Short position': 'Короткая позиция',
  'Dates range': 'Диапазон дат',
  'Prices range': 'Диапазон цен',
  'Fixed range volume profile': 'Профиль объема в заданном диапазоне',
  'Anchored volume profile': 'Профиль объема с привязкой',
  'Fibonacci retracement': 'Коррекция Фибоначчи',
  Rectangle: 'Прямоугольник',
  Traectory: 'Траектория',
  'Geometric shapes': 'Геометрические фигуры',
  Text: 'Текст',
  'XABCD template': 'Шаблон XABCD',
  'Measurement tools': 'Инструменты для измерения и прогнозирования',
  Ruler: 'Линейка',
  Upscale: 'Увеличить масштаб',
  Downscale: 'Уменьшить масштаб',
  'Gann and Fibonacci': 'Инструменты Ганна и Фибоначчи',
  'Endless drawing mode': 'Продолжить в режиме рисования',
  'Fix all objects': 'Зафиксировать все объекты',
  'Hide all drawing objects': 'Скрыть все объекты рисования',
  'Clear objects': 'Удалить объекты',
  'DOM tree': 'Дерево объектов',
  'Magnet allows you to attract objects points to the nearest bar prices':
    'Магнит позволяет притягивать точки объектов к ближайшим ценам (откр., макс., мин., закр.) баров',
  Pin: 'Значок',
  Open: 'Откр.',
  High: 'Макс.',
  Low: 'Мин.',
  Close: 'Закр.',
  Change: 'Изм.',
  Time: 'Время',
  Arguments: 'Аргументы',

  'Account size': 'Размер счёта',
  'Lot size': 'Размер лота',
  Risk: 'Риск',
  'Entry price': 'Цена открытия',
  Leverage: 'Кредитное плечо',
  'Profit price': 'Цена цели',
  'Stop price': 'Цена стоп-уровня',
  'QTY precision': 'Точность количества',
  'Line width': 'Толщина линии',
  'Stop color': 'Цвет стоп-уровня',
  'Target color': 'Цвет цели',

  // settings
  Area: 'Область',
  Border: 'Граница',
  'Font size': 'Размер текста',
  Bold: 'Жирный',
  Italic: 'Курсив',
  'Text color': 'Цвет текста',
  'Background color': 'Цвет фона',
  Lock: 'Заблокировать',
  Unlock: 'Разблокировать',
  Remove: 'Удалить',
  Style: 'Стиль',
  'Background transparency': 'Прозрачность фона',
  Background: 'Фон',
  Opacity: 'Прозрачность',
  Reverse: 'Переворот',
  'Labels position': 'Положение меток',
  'Show prices': 'Отображать цену',
  'Show level values': 'Отображать уровень',
  Color: 'Цвет',
  Levels: 'Уровни',
  Level: 'Уровень',
  Left: 'Слева',
  Right: 'Справа',
  'Enter text': 'Введите текст',
  'Profit zone': 'Зона прибыли',
  'Loss zone': 'Зона убытка',
  'Line color': 'Цвет линии',
  'Growing volume': 'Растущий объём',
  'Decreasing volume': 'Снижающий объём',
  'POC-line': 'POC-линия',
  'Parallel channel': 'Параллельный канал',
  'Regression trend': 'Регрессионный тренд',
  'Middle line': 'Средняя линия',
  'Channel line': 'Граница канала',
  'Upper area': 'Верхняя зона',
  'Lower area': 'Нижняя зона',
  'Show middle line': 'Показывать среднюю линию',
  'Show correlation': 'Показывать корреляцию',
  Length: 'Длинна',
  Data: 'Данные',
  'Open price': 'Цена открытия',
  Max: 'Максимум',
  Min: 'Минимум',
  'Close price': 'Цена закрытия',
  Offset: 'Отступ',
  'Fast length': 'Длина Fast',
  'Slow length': 'Длина Slow',
  'Signal length': 'Длина сигнала',
  'Oscillator MA type': 'Тип осцилятора MA',
  'Signal MA type': 'Тип сигнала MA',
  'MA length': 'Длина MA',
  Save: 'Сохранить',
  Reject: 'Отменить',
  Volume: 'Объём',
  '1D': '1Д',
  '5D': '5Д',
  '1M': '1М',
  '3M': '3М',
  '6M': '6М',
  '1Y': '1Г',
  All: 'Всё',
  '12h': '12ч',
  '24h': '24ч',
  'Mon Q3 \'97': 'Пн кв3 \'97',
  'Mon Q3 1997': 'Пн кв3 1997',
  'Mon 29 Sep \'97': 'Пн 29 сен. \'97',
  'Mon Sep \'97': 'Пн сен. \'97',
  'Mon Sep 29, 1997': 'Пн сен. 29, 1997',
  'Mon Sep 1997': 'Пн сен. 1997',
  'Mon Sep 29': 'Пн сен. 29',
  'Mon 29 Sep': 'Пн 29 сен.',
  'Mon 1997-09-29': 'Пн 1997-09-29',
  'Mon 97-09-29': 'Пн 97-09-29',
  'Mon 97/09/29': 'Пн 97/09/29',
  'Mon 1997/09/29': 'Пн 1997/09/29',
  'Mon 29-09-1997': 'Пн 29-09-1997',
  'Mon 29-09-97': 'Пн 29-09-97',
  'Mon 29/09/97': 'Пн 29/09/97',
  'Mon 29/09/1997': 'Пн 29/09/1997',
  'Mon 09/29/97': 'Пн 09/29/97',
  'Mon 09/29/1997': 'Пн 09/29/1997',
  '09.29.1997 00:00:00': '09.29.1997 00:00:00',
  'interval for': 'интервал для',
  timeframe: 'таймфрейма',
  'Open P&L': 'Откр. поз. П/Л',
  Qty: 'Кол-во',
  'Risk/Reward Ratio': 'Соотношение риск/прибыль',
  Target: 'Цель',
  Amount: 'Количество',
  Stop: 'Стоп',
  Vol: 'Объем',
  bars: 'бары',
  AutoScale: 'Автомасштаб',
  Logarithmic: 'Логарифмическая',

  '1t': '1т',
  '10t': '10т',
  '100t': '100т',
  '1000t': '1000т',

  '1s': '1с',
  '5s': '5с',
  '10s': '10с',
  '15s': '15с',
  '30s': '30с',
  '45s': '45с',

  '1m': '1м',
  '2m': '2м',
  '3m': '3м',
  '5m': '5м',
  '10m': '10м',
  '15m': '15м',
  '30m': '30м',
  '45m': '45м',

  '1h': '1ч',
  '2h': '2ч',
  '3h': '3ч',
  '4h': '4ч',
  '8h': '8ч',

  '1d': '1д',
  '3d': '3д',
  '5d': '5д',

  '1w': '1н',

  '1М': '1M',
  '3М': '3M',

  'Add a main instrument to display indicators': 'Добавьте основной инструмент для отображения индикаторов',
};