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


import { AxiosResponse } from 'axios';
import dayjs, { Dayjs } from 'dayjs';
import React, { useEffect, useRef, useState } from 'react';


import { frontExceptionController } from '@api/controllers/frontExceptionController';
import api from '@api/index';


import { standartDateFormat } from '@configs/standartDateFormat';
import { VirtualTableColumnType } from 'types/TableColumns';


export interface FixingData {
  caption: number | null;
  changed: number | null;
  high: number;
  last: number;
  low: number;
  openValue: number;
  prevPrice: number | null;
  ticker: string;
  tradeDate: string;
}

interface useFixingsFacadeResult {
  selectedFixing: FixingData[];
  filteredSelectedFixing: FixingData[];
  fixingsData?: FixingData[];
  selectedRow: FixingData | null;
  onRowClick: (record: FixingData) => void;
  onCloseButtonClick: () => void;
  onChangeDate: (date: Dayjs | null, from: boolean) => void;
  fromDate: string;
  toDate: string;
  columns: VirtualTableColumnType<FixingData>[];
}

const fixingsColumnsDefault: VirtualTableColumnType<FixingData>[] = [
  {
    key: 'caption',
    dataIndex: 'caption',
    title: 'Наименование',
    type: 'string',
    align: 'left',
    hidden: false,
    width: 100,
  },
  {
    key: 'ticker',
    dataIndex: 'ticker',
    title: 'Идентификатор',
    type: 'string',
    align: 'left',
    hidden: false,
    width: 100,
  },
  {
    key: 'openValue',
    dataIndex: 'openValue',
    title: 'Значение',
    type: 'number',
    align: 'right',
    numbersFormatter: true,
    hidden: false,
    width: 100,
  },
  {
    key: 'tradeDate',
    dataIndex: 'tradeDate',
    title: 'Дата и время обновления',
    type: 'date',
    align: 'left',
    hidden: false,
    width: 100,
    render: (text: string) => ({
      children: (
        <div style={{ marginLeft: 'auto' }}>
          {text ? dayjs(text).format(standartDateFormat.dateTimeFormat) : ''}
          {text && <span style={{ color: '#868479' }}> МСК</span>}
        </div>
      ),
    }),
  },
];

export const useFixingsFacade = function (): useFixingsFacadeResult {
  const [selectedFixing, setSelectedFixing] = useState<FixingData[]>([]);
  const [selectedRow, setSelectedRow] = useState<FixingData | null>(null);

  const [filteredSelectedFixing, setFilteredSelectedFixing] = useState<FixingData[]>([]);
  const [fixingsData, setFixingsData] = useState<FixingData[]>();
  const [fromDate, setFromDate] = useState<string>(new Date('01-01-2018').toString());
  const [toDate, setToDate] = useState<string>(new Date().toString());

  const updateFixings = () => {
    api.getFixingsList().then((res: AxiosResponse) => {
      const { data, status } = res;
      if (!!data && !Array.isArray(data)) {
        const serializedStrangeDataSource = JSON.stringify(data);
        frontExceptionController.handleException({
          name: 'FIXINGS_STRANGE_DATA',
          message: `Неожиданное значение в данных. Статус: ${status}. Данные: ${serializedStrangeDataSource}`,
        })
      }
      setFixingsData(data);
    });
  };
  const [customInterval, setCustomInterval] = useState<undefined | number>(undefined);

  const timerId = useRef<NodeJS.Timeout>();

  const onFixingsDataUpdate = () => {
    const gmtPlus3Time = new Date().toLocaleString('en-US', {
      timeZone: 'Europe/Moscow',
    });
    const time = gmtPlus3Time.split(',')[1].split(':');
    const intervalCount =
      gmtPlus3Time.includes('PM') &&
      ((time[0].trim() === '12' && Number(time[1]) >= 30) || (time[0].trim() === '1' && Number(time[1]) <= 30))
        ? 60000
        : 3600000;
    setCustomInterval(intervalCount);
  };

  useEffect(() => {
    clearInterval(timerId.current);
    if (customInterval) {
      timerId.current = setInterval(updateFixings, customInterval);
    }
  }, [customInterval]);

  useEffect(() => {
    updateFixings();
    setInterval(onFixingsDataUpdate, 60000);

    return () => {
      clearInterval(timerId.current);
    };
  }, []);

  const onChangeDate = (date: Dayjs | null, from: boolean) => {
    if (from) {setFromDate(date ? dayjs(date).format('YYYY-MM-DD') : '');}
    else {setToDate(date ? dayjs(date).format('YYYY-MM-DD') : '');}
  };

  useEffect(() => {
    if (fromDate === '' && toDate === '') {
      setFilteredSelectedFixing(selectedFixing);
    }
    if (fromDate !== '' && toDate !== '') {
      const filteredData = selectedFixing.filter(
        (item) =>
          new Date(item.tradeDate).getTime() > new Date(fromDate).getTime() &&
          new Date(item.tradeDate).getTime() < new Date(toDate).getTime(),
      );
      setFilteredSelectedFixing(filteredData);
    }
  }, [fromDate, toDate]);

  useEffect(() => {
    if (selectedFixing) {
      setFilteredSelectedFixing(selectedFixing);
    }
  }, [selectedFixing]);

  const onRowClick = (record: FixingData) => {
    setSelectedRow(record);
    api.getFixingById(record.ticker).then((res: AxiosResponse) => {
      setSelectedFixing(res.data);
    });
  };
  const onCloseButtonClick = () => {
    setSelectedFixing([]);
    setSelectedRow(null);
    setFromDate(new Date('01-01-2018').toString());
    setToDate(new Date().toString());
  };

  return {
    selectedFixing,
    filteredSelectedFixing,
    fixingsData,
    selectedRow,
    onRowClick,
    onCloseButtonClick,
    onChangeDate,
    fromDate,
    toDate,
    columns: fixingsColumnsDefault,
  };
};