Загрузка данных
import { SideFilterSelect } from '@/shared/components/SideFilterSelect/SideFilterSelect';
import { Helpers } from '@/shared/lib';
import { CheckIcon, SortIcon } from '@sber-friend/flamingo-icons';
import { Badge, Box, Button, Dropdown } from '@shared/components';
import { ChangeEvent, useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
type LocationEvent = ChangeEvent<{ name?: string; value: unknown }>;
type CommonLocationFiltersProps = {
'data-fui-tid'?: string;
withDropdown?: boolean;
isRooms?: boolean;
regionId: string[];
cityId: string[];
placeId: string[];
floorId: string[];
roomId: string[];
setRegionId: (regionId: string[]) => void;
setCityId: (cityId: string[]) => void;
setPlaceId: (placeId: string[]) => void;
setFloorId: (floorId: string[]) => void;
setRoomId: (roomId: string[]) => void;
};
type TreeIdLocationFiltersProps = CommonLocationFiltersProps & {
outputIdType?: 'treeId';
ids?: number[];
onLocationIdsChange: (locationIds: number[]) => void;
};
type IdLocationFiltersProps = CommonLocationFiltersProps & {
outputIdType: 'id';
ids?: string[];
onLocationIdsChange: (locationIds: string[]) => void;
};
type LocationFiltersProps =
| TreeIdLocationFiltersProps
| IdLocationFiltersProps;
const getDeepestTreeIds = ({
regionId,
cityId,
placeId,
floorId,
roomId,
}: Pick<
CommonLocationFiltersProps,
'regionId' | 'cityId' | 'placeId' | 'floorId' | 'roomId'
>) => {
if (roomId?.length > 0) {
return roomId;
}
if (floorId?.length > 0) {
return floorId;
}
if (placeId?.length > 0) {
return placeId;
}
if (cityId?.length > 0) {
return cityId;
}
return regionId;
};
export const LocationFilters = ({
'data-fui-tid': tid,
isRooms = false,
ids,
regionId,
cityId,
placeId,
floorId,
roomId,
setRegionId,
setCityId,
setFloorId,
setPlaceId,
setRoomId,
onLocationIdsChange,
withDropdown = true,
outputIdType = 'treeId',
}: LocationFiltersProps) => {
const { t } = useTranslation('locations');
const [anchorElement, setAnchorElement] = useState(null);
useEffect(() => {
if (ids?.length === 0) {
setRegionId([]);
setCityId([]);
setPlaceId([]);
setFloorId([]);
setRoomId([]);
}
}, [ids, setCityId, setFloorId, setPlaceId, setRegionId, setRoomId]);
const locationTreeIds = getDeepestTreeIds({
regionId,
cityId,
placeId,
floorId,
roomId,
});
useEffect(() => {
if (outputIdType === 'treeId') {
(onLocationIdsChange as (locationIds: number[]) => void)(
Helpers.convertStringsToNumbers(locationTreeIds),
);
}
}, [locationTreeIds, onLocationIdsChange, outputIdType]);
const handleSelectedLocationIdsChange = useCallback(
(locationIds: string[]) => {
if (outputIdType === 'id') {
(onLocationIdsChange as (locationIds: string[]) => void)(locationIds);
}
},
[onLocationIdsChange, outputIdType],
);
const handleChangeRegion = (event: LocationEvent) => {
const { value } = event.target;
setRegionId(value as string[]);
setCityId([]);
setPlaceId([]);
setFloorId([]);
setRoomId([]);
};
const handleChangeCity = (event: LocationEvent) => {
const { value } = event.target;
setCityId(value as string[]);
setPlaceId([]);
setFloorId([]);
setRoomId([]);
};
const handleChangePlace = (event: LocationEvent) => {
const { value } = event.target;
setPlaceId(value as string[]);
setFloorId([]);
setRoomId([]);
};
const handleChangeFloor = (event: LocationEvent) => {
const { value } = event.target;
setFloorId(value as string[]);
setRoomId([]);
};
const handleChangeRoom = (event: LocationEvent) => {
const { value } = event.target;
setRoomId(value as string[]);
};
const handleReset = () => {
setRegionId([]);
setCityId([]);
setPlaceId([]);
setFloorId([]);
setRoomId([]);
if (outputIdType === 'id') {
(onLocationIdsChange as (locationIds: string[]) => void)([]);
return;
}
(onLocationIdsChange as (locationIds: number[]) => void)([]);
};
const handleOpen = (event: any) => {
setAnchorElement(event.currentTarget);
};
const handleClose = (event: any) => {
event.preventDefault();
setAnchorElement(null);
};
const filtersContent = (
<>
<SideFilterSelect
value={regionId}
label={t('region')}
onChange={handleChangeRegion}
onSelectedLocationIdsChange={handleSelectedLocationIdsChange}
multiple
isRoot
/>
<SideFilterSelect
value={cityId}
parentIds={regionId}
label={t('city')}
onChange={handleChangeCity}
onSelectedLocationIdsChange={handleSelectedLocationIdsChange}
multiple
/>
<SideFilterSelect
value={placeId}
parentIds={cityId}
label={t('place')}
onChange={handleChangePlace}
onSelectedLocationIdsChange={handleSelectedLocationIdsChange}
multiple
/>
<SideFilterSelect
value={floorId}
parentIds={placeId}
label={t('floor')}
onChange={handleChangeFloor}
onSelectedLocationIdsChange={handleSelectedLocationIdsChange}
multiple
isFloor
/>
{isRooms && (
<SideFilterSelect
value={roomId}
parentIds={floorId}
label={t('room')}
onChange={handleChangeRoom}
onSelectedLocationIdsChange={handleSelectedLocationIdsChange}
multiple
/>
)}
<Button size='small' onClick={handleReset}>
{t('common:buttons.reset')}
</Button>
</>
);
if (!withDropdown) {
return filtersContent;
}
return (
<Badge
invisible={
!regionId?.length &&
!cityId?.length &&
!placeId?.length &&
!floorId?.length &&
!roomId?.length
}
badgeContent={<CheckIcon />}
color='primary'
>
<Dropdown
data-fui-tid={tid}
size='small'
icon={<SortIcon />}
onClickButton={handleOpen}
onClosePopover={handleClose}
zIndexMenu={100}
anchorElement={anchorElement}
>
<Box
display='flex'
gridGap={8}
flexDirection='column'
p={2}
minWidth={330}
maxWidth={330}
>
{filtersContent}
</Box>
</Dropdown>
</Badge>
);
};