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


import React from 'react';

import { Icon } from '@uikit/Icon';
import { BUTTON_MORE_ROW_KEY } from '@widgets/TradingResult/components/Repo/constants';
import { LoadMoreButton } from '@widgets/TradingResult/components/Repo/repo-table/component/loadMoreButton';
import { DataInfoByGroup } from '@widgets/TradingResult/components/Repo/repo-table/logic/table/useLoadGroupSubRowsData';
import { GroupFiltersStruct } from '@widgets/TradingResult/components/Repo/types/group';
import { Group } from 'types/MonitorRepo';

import repoTableStyles from '../styles/repoTable.module.scss';

type TableRow = Record<string, unknown>;

interface CreateInitialGroupFiltersRecord {
  key: string;
  rowData: TableRow;
}

interface ExpandIconProps {
  onExpand: (
    record: TableRow,
    event: React.MouseEvent<HTMLElement>,
  ) => void;
  record: TableRow;
}

export const createInitialGroupFilters = (
  record: CreateInitialGroupFiltersRecord,
): GroupFiltersStruct =>
  Object.keys(record.rowData).reduce<GroupFiltersStruct>((acc, dataKey) => {
    const dataValue = record.rowData[dataKey];
    const isObject =
      typeof dataValue === 'object' &&
      dataValue !== null &&
      !Array.isArray(dataValue);

    if (!isObject || !('value' in dataValue) || typeof dataValue.value !== 'string') {
      return acc;
    }

    const groupValue = record.key;

    return {
      ...acc,
      [groupValue]: {
        ...acc[groupValue],
        [dataKey]: dataValue.value,
      },
    };
  }, {});

export const ExpandIcon = ({
  onExpand,
  record,
}: ExpandIconProps) =>
  record.children ? (
    <div
      className={repoTableStyles.expandIconWrapper}
      onClick={(event: React.MouseEvent<HTMLElement>) =>
        onExpand(record, event)
      }
    >
      <Icon variant="chevron-down" />
    </div>
  ) : null;

export const unifyGroupAndChildrenRows = (
  groupSubRowsData: Record<string, DataInfoByGroup>,
  groupsData: TableRow[],
  buttonMargin: number,
  loadMore: (groupValue: string) => Promise<void>,
): TableRow[] => {
  // ищем значения групп по которым существуют данные подстрок
  const groupValues = Object.keys(groupSubRowsData);

  if (groupValues.length === 0) {
    return groupsData;
  }

  groupValues.forEach((groupValue) => {
    const searchedGroup = groupsData.find(
      (groupData) => groupData.key === groupValue,
    );

    if (!searchedGroup) {
      return;
    }

    const { data, page, size, total } = groupSubRowsData[groupValue];
    const isEmptyChildrenRows = data.length === 0;
    const loadedRowsNumber = (page + 1) * size;
    const itemsCount = data.length;
    const totalValues = total || 0;

    // подгруженные данные репо по группировке заносим в общую структуру групп как children
    searchedGroup.children = [
      ...data,
      {
        key: `${BUTTON_MORE_ROW_KEY}${groupValue}`,
        forceToSort: true,
        secId: (
          <LoadMoreButton
            styles={{ marginLeft: buttonMargin }}
            onClick={() => loadMore(groupValue)}
            loaded={
              !isEmptyChildrenRows
                ? Math.min(loadedRowsNumber, totalValues, itemsCount)
                : 0
            }
            shouldDisplayButton={itemsCount === loadedRowsNumber}
            total={!isEmptyChildrenRows ? totalValues || loadedRowsNumber : 0}
          />
        ),
      },
    ];
  });

  return [...groupsData];
};

/** Обновляем только пересчитываемые значения */
export const refreshRowAggValues = (
  oldGroup: Group,
  newGroup: Group,
): Group => {
  const valuesToNeedRefresh: (keyof Group)[] = [
    'aggPrice',
    'aggQuantity',
    'aggAccint',
    'aggValue',
    'aggRepoRate',
    'aggRepoValue',
  ];

  return valuesToNeedRefresh.reduce(
    (refreshRow, key) => ({
      ...refreshRow,
      [key]: newGroup[key],
    }),
    oldGroup,
  );
};