Загрузка данных
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, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
//TO DO вынести в отдельный файл с типами
type LocationEvent = ChangeEvent<{ name?: string; value: unknown }>;
type LocationFiltersProps = {
'data-fui-tid'?: string;
isRooms?: boolean;
ids?: number[];
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;
onLocationIdsChange: (locationIds: number[]) => void;
};
// TO DO refactor вместо locationId будет treeId
export const LocationFilters = ({
'data-fui-tid': tid,
isRooms = false,
ids,
regionId,
cityId,
placeId,
floorId,
roomId,
setRegionId,
setCityId,
setFloorId,
setPlaceId,
setRoomId,
onLocationIdsChange,
}: LocationFiltersProps) => {
const { t } = useTranslation('locations');
useEffect(() => {
if (ids?.length === 0) {
setRegionId([]);
setCityId([]);
setPlaceId([]);
setFloorId([]);
setRoomId([]);
}
}, [ids]);
const locationIds =
roomId?.length > 0
? roomId
: floorId?.length > 0
? floorId
: placeId?.length > 0
? placeId
: cityId?.length > 0
? cityId
: regionId;
useEffect(() => {
if (locationIds?.length >= 0) {
onLocationIdsChange(Helpers.convertStringsToNumbers(locationIds));
}
}, [locationIds]);
const updateLocationIds = (newLocationIds: number[]) => {
onLocationIdsChange(newLocationIds);
};
const handleChangeRegion = (event: LocationEvent) => {
const { value } = event.target;
const newRegionId = value as string[];
setRegionId(newRegionId);
setCityId([]);
setPlaceId([]);
setFloorId([]);
setRoomId([]);
};
const handleChangeCity = (event: LocationEvent) => {
const { value } = event.target;
const newCityId = value as string[];
setCityId(newCityId);
setPlaceId([]);
setFloorId([]);
setRoomId([]);
};
const handleChangePlace = (event: LocationEvent) => {
const { value } = event.target;
const newPlaceId = value as string[];
setPlaceId(newPlaceId);
setFloorId([]);
setRoomId([]);
};
const handleChangeFloor = (event: LocationEvent) => {
const { value } = event.target;
const newFloorId = value as string[];
setFloorId(newFloorId);
setRoomId([]);
};
const handleChangeRoom = (event: LocationEvent) => {
const { value } = event.target;
const newRoomId = value as string[];
setRoomId(newRoomId);
};
const handleReset = () => {
setRegionId([]);
setCityId([]);
setPlaceId([]);
setFloorId([]);
setRoomId([]);
updateLocationIds([]);
};
const [anchorElement, setAnchorElement] = useState(null);
const handleOpen = (event: any) => {
setAnchorElement(event.currentTarget);
};
const handleClose = (event: any) => {
event.preventDefault();
setAnchorElement(null);
};
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}
>
<SideFilterSelect
value={regionId}
label={t('region')}
onChange={handleChangeRegion}
multiple
isRoot
/>
<SideFilterSelect
value={cityId}
parentIds={regionId}
label={t('city')}
onChange={handleChangeCity}
multiple
/>
<SideFilterSelect
value={placeId}
parentIds={cityId}
label={t('place')}
onChange={handleChangePlace}
multiple
/>
<SideFilterSelect
value={floorId}
parentIds={placeId}
label={t('floor')}
onChange={handleChangeFloor}
multiple
isFloor
/>
{isRooms && (
<SideFilterSelect
value={roomId}
parentIds={floorId}
label={t('room')}
onChange={handleChangeRoom}
multiple
/>
)}
<Button size='small' onClick={handleReset}>
{t('common:buttons.reset')}
</Button>
</Box>
</Dropdown>
</Badge>
);
};
import {
Location,
useGetLocationChildrenQuery,
} from '@/shared/api/location/client';
import { Helpers } from '@/shared/lib';
import {
useResetLocationFilterSelect,
useSetLocation,
} from '@entities/LocationFiltersList/lib/hooks';
import { Select, SelectProps } from '@shared/components';
import { useState } from 'react';
export type SideFilterSelectProps = {
value: string[] | string;
onChange: SelectProps['onChange'];
parentIds?: string[] | string;
isRoot?: boolean;
isFloor?: boolean;
} & Omit<SelectProps, 'onChange' | 'value' | 'options'>;
export const SideFilterSelect = ({
value,
onChange,
disabled,
label,
parentIds,
isRoot = false,
isFloor = false,
...rest
}: SideFilterSelectProps) => {
const [location, setLocation] = useState<Location[]>([]);
const requestParams = isRoot
? {}
: {
parentId:
typeof parentIds === 'object'
? Helpers.convertStringsToNumbers(parentIds)
: [Number(parentIds)],
};
const requestOptions = isRoot
? {}
: {
skip: typeof parentIds === 'object' ? !parentIds?.length : !parentIds,
};
const { data, status } = useGetLocationChildrenQuery(requestParams, {
...requestOptions,
refetchOnMountOrArgChange: true,
});
useSetLocation({
entity: data,
status,
setter: setLocation,
isFloor,
});
useResetLocationFilterSelect({
setter: setLocation,
ids: parentIds ?? '',
});
const innerOption = location?.map((option) => ({
value: String(option.treeId),
label:
isFloor && parentIds && Array.isArray(parentIds) && parentIds.length > 1
? `${option.name}, ${option.pathName ?? ''}`
: option.name,
}));
return (
<Select
label={label}
options={innerOption}
value={value}
onChange={onChange}
disabled={!isRoot && !location.length}
{...rest}
/>
);
};