Загрузка данных
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>
);
};