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


import { useGetTopQuery } from '@/shared/api/notifications/client';
import {
  Box,
  DateDropdown,
  IconButton,
  MenuItem,
  Row,
  SegmentButton,
  SegmentItem,
  Select,
  Typography,
} from '@/shared/components';
import { CollapseTransition } from '@sber-friend/flamingo-core';
import {
  ChevronsDownIcon,
  ChevronsUpIcon,
} from '@sber-friend/flamingo-icons';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { mapTopDonutData } from '../model/mapTopDonutData';
import { mapTopTableRows } from '../model/mapTopTableRows';
import type { EventAnalysisEntityType } from '../model/types';
import {
  EntityFiltersState,
  useEntityFilters,
} from '../model/useEntityFilters';
import { EventDonut } from './EventDonut';
import { EventTable } from './EventTable';

type EntityBlockProps = {
  type: EventAnalysisEntityType;
};

const PAGINATION_LIMITS: number[] = [5, 10, 25, 50, 100];

export const EntityBlock = ({ type }: EntityBlockProps) => {
  const filtersModel = useEntityFilters();
  const { t } = useTranslation('eventAnalysis');
  const [version, setVersion] = useState<'table' | 'distribution'>(
    'table',
  );

  const { data, isLoading, isFetching } = useGetTopQuery({
    ...filtersModel.filters,
    type,
  });

  // @ts-ignore
  const handleChangeBtn = (_, newValue) => {
    setVersion(newValue);
  };

  const entities = useMemo(() => {
    switch (data?.type) {
      case 'controller':
        return data.controllers ?? [];

      case 'location':
        return data.locations ?? [];

      case 'device':
        return data.devices ?? [];

      case 'network-device':
        return data.networkDevices ?? [];

      case 'padlet':
        return data.padlets ?? [];

      default:
        return [];
    }
  }, [data]);

  const rows = useMemo(
    () => mapTopTableRows(entities),
    [entities],
  );

  const donutData = useMemo(
    () =>
      mapTopDonutData(entities, {
        info: t('info'),
        normal: t('normal'),
        important: t('important'),
        critical: t('critical'),
      }),
    [entities, t],
  );

  const donutTotal = useMemo(
    () => donutData.reduce((sum, item) => sum + item.value, 0),
    [donutData],
  );

  const [open, setOpen] = useState(false);

  const handleClick = () => {
    setOpen(!open);
  };

  const lastYear = new Date(
    new Date().getFullYear() - 1,
    new Date().getMonth(),
    new Date().getDate(),
  );

  return (
    <Box
      p={2}
      pl={3}
      pr={3}
      borderRadius={16}
      display='flex'
      flexDirection='column'
      gridGap='32px'
      border='solid 1px'
      borderColor='outline.outline'
      bgcolor='background.primary3'
    >
      <Box
        display='flex'
        flexDirection='column'
        gridGap={open ? '12px' : '0px'}
      >
        <Row
          justifyContent='space-between'
          onClick={handleClick}
        >
          <Row gridGap={36}>
            <Typography variant='h4'>
              {t(`${type}`)}
            </Typography>
          </Row>

          <Row>
            {open && (
              <Box onClick={(event) => event.stopPropagation()}>
                <Row>
                  <SegmentButton
                    size='small'
                    value={version}
                    onChange={handleChangeBtn}
                  >
                    <SegmentItem
                      label={t('version.table')}
                      value='table'
                    />

                    <SegmentItem
                      label={t('version.distribution')}
                      value='distribution'
                    />
                  </SegmentButton>

                  <Row>
                    <DateDropdown
                      dateFrom={filtersModel.filters.after}
                      dateTo={filtersModel.filters.before}
                      onDateFromChange={
                        filtersModel.handleAfterChange
                      }
                      onDateToChange={
                        filtersModel.handleBeforeChange
                      }
                      disableFuture
                      minDate={lastYear}
                    />

                    <Select
                      value={filtersModel.filters.limit}
                      size='small'
                      style={{ zIndex: 10000 }}
                      onChange={(event) =>
                        filtersModel.handleLimitChange(
                          event.target
                            .value as EntityFiltersState['limit'],
                        )
                      }
                    >
                      {PAGINATION_LIMITS.map((limit) => (
                        <MenuItem
                          size='small'
                          key={limit}
                          value={limit}
                        >
                          <Typography variant='caption2'>
                            по {limit}
                          </Typography>
                        </MenuItem>
                      ))}
                    </Select>
                  </Row>
                </Row>
              </Box>
            )}

            <IconButton onClick={handleClick}>
              {open ? (
                <ChevronsUpIcon />
              ) : (
                <ChevronsDownIcon />
              )}
            </IconButton>
          </Row>
        </Row>

        <CollapseTransition in={open} timeout={500}>
          <Box
            display='flex'
            flexDirection='column'
            gridGap='16px'
          >
            <Row gridGap={72} alignItems='start'>
              <Box minWidth={150}>
                <EventDonut
                  data={donutData}
                  total={donutTotal}
                  loading={isLoading || isFetching}
                  donutTitle={t('total')}
                />
              </Box>

              <EventTable
                rows={rows}
                type={type}
                loading={isLoading}
              />
            </Row>
          </Box>
        </CollapseTransition>
      </Box>
    </Box>
  );
};