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


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}
    />
  );
};