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


import {
  WithLocationFilter,
  WithLocationFilterQuery,
} from '@/app/router/queries';
import { auditRoute } from '@/app/router/routes/audit';
import { AppConsts } from '@/shared';
import {
  useGetApiV1MessageQuery,
  useGetApiV1MessageTypesQuery,
} from '@/shared/api/audit/client';
import {
  useGetUserByIdQuery,
  useGetUsersQuery,
} from '@/shared/api/user/client';
import { RouterConsts } from '@/shared/consts/RouterConsts';
import { useUpdateSearchParams } from '@/shared/hooks';
import { Helpers } from '@/shared/lib';
import {
  ChangeEvent,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import { useTranslation } from 'react-i18next';
import { AuditLib } from '../../lib/AuditLib';
import { AUDIT_TYPE_ORDER } from './messagesOrder';

type ModelSelectValue = string | number | boolean;

type AuditSideFilterSearch = WithLocationFilterQuery & {
  modelIds?: string[];
};

export const useAuditSideFilter = () => {
  const { t } = useTranslation('common');
  const updateSearchParams = useUpdateSearchParams();

  const searchParams = auditRoute.useSearch<AuditSideFilterSearch>();
  const { cityId, floorId, placeId, regionId, roomId, treeId } = searchParams;

  const { refetch } = useGetApiV1MessageQuery(searchParams);

  const [searchUser, setSearchUser] = useState('');
  const [smartRoomId, setSmartRoomId] = useState(
    searchParams.smartroomId || '',
  );
  const [smartRoomIdError, setSmartRoomIdError] = useState(false);
  const [isLocationFiltersOpen, setIsLocationFiltersOpen] = useState(false);

  const { data: auditTypesData } = useGetApiV1MessageTypesQuery();

  const { data: usersData, isFetching: isFetchingUsers } = useGetUsersQuery({
    limit: 10,
    sortType: 'asc',
    sortColumn: 'full_name',
    search: searchUser,
  });

  const { data: user } = useGetUserByIdQuery(
    { userId: searchParams.userId ?? '' },
    { skip: false },
  );

  const hasFetchedUser = useRef(false);

  useEffect(() => {
    if (searchParams.userId && user) {
      hasFetchedUser.current = true;
    }
  }, [user, searchParams.userId]);

  const resetPage = useCallback(() => {
    updateSearchParams({ paramName: 'offset', value: 0 });
  }, [updateSearchParams]);

  const handleChange =
    (paramName: string) =>
    (event: ChangeEvent<{ name?: string | undefined; value: unknown }>) => {
      const { value } = event.target;

      updateSearchParams({ paramName, value });
      resetPage();
    };

  const handleChangeUser = useCallback(
    (value: string) => {
      updateSearchParams({ paramName: 'userId', value });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const handleChangeTimeFrom = useCallback(
    (time: Date) => {
      const dateMs = new Date(time).getTime() / AppConsts.THOUSAND;

      updateSearchParams({ paramName: 'tmMin', value: dateMs });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const handleChangeTimeMax = useCallback(
    (time: Date) => {
      const dateMs = new Date(time).getTime() / AppConsts.THOUSAND;

      updateSearchParams({ paramName: 'tmMax', value: dateMs });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  useEffect(() => {
    const valid = Helpers.isUUID(smartRoomId);

    setSmartRoomIdError(smartRoomId !== '' && !valid);

    if (valid || smartRoomId === '') {
      updateSearchParams({ paramName: 'smartroomId', value: smartRoomId });
      resetPage();
      return;
    }

    updateSearchParams({ paramName: 'smartroomId', value: '' });
  }, [resetPage, smartRoomId, updateSearchParams]);

  const handleSmartRoomIdChange = useCallback(
    (e: ChangeEvent<HTMLInputElement>) => {
      setSmartRoomId(e.target.value);
    },
    [],
  );

  const modelIds = useMemo(() => searchParams.modelIds || [], [
    searchParams.modelIds,
  ]);

  const handleChangeModels = useCallback(
    (value: ModelSelectValue[]) => {
      updateSearchParams({
        paramName: 'modelIds',
        value: value.map(String),
      });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const setRegionId = useCallback(
    (value: string[]) => {
      updateSearchParams({
        paramName: WithLocationFilter.WITH_LOCATION_FILTER_QUERY.regionId,
        value: Helpers.convertNumbersToString(value as unknown as number[]),
      });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const setCityId = useCallback(
    (value: string[]) => {
      updateSearchParams({
        paramName: WithLocationFilter.WITH_LOCATION_FILTER_QUERY.cityId,
        value: Helpers.convertNumbersToString(value as unknown as number[]),
      });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const setPlaceId = useCallback(
    (value: string[]) => {
      updateSearchParams({
        paramName: WithLocationFilter.WITH_LOCATION_FILTER_QUERY.placeId,
        value: Helpers.convertNumbersToString(value as unknown as number[]),
      });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const setFloorId = useCallback(
    (value: string[]) => {
      updateSearchParams({
        paramName: WithLocationFilter.WITH_LOCATION_FILTER_QUERY.floorId,
        value: Helpers.convertNumbersToString(value as unknown as number[]),
      });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const setRoomId = useCallback(
    (value: string[]) => {
      updateSearchParams({
        paramName: WithLocationFilter.WITH_LOCATION_FILTER_QUERY.roomId,
        value: Helpers.convertNumbersToString(value as unknown as number[]),
      });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const changeTreeId = useCallback(
    (value: number[]) => {
      updateSearchParams({
        paramName: WithLocationFilter.WITH_LOCATION_FILTER_QUERY.treeId,
        value,
      });
      resetPage();
    },
    [resetPage, updateSearchParams],
  );

  const handleLocationFiltersToggle = useCallback(() => {
    setIsLocationFiltersOpen((prev) => !prev);
  }, []);

  const typeOptions = useMemo(() => {
    const types = auditTypesData?.types;

    if (!Array.isArray(types)) {
      return [];
    }

    const typeSet = new Set<string>(types);
    const orderedTypes = AUDIT_TYPE_ORDER.filter((type) => typeSet.has(type));
    const unknownTypes = types.filter(
      (type) =>
        !AUDIT_TYPE_ORDER.includes(type as (typeof AUDIT_TYPE_ORDER)[number]),
    );
    const allTypes = [...orderedTypes, ...unknownTypes];

    return [
      { label: t('all'), value: undefined },
      ...allTypes.map((type) => ({
        value: type,
        label: t(`audit:${type}`, { defaultValue: type }),
      })),
    ];
  }, [auditTypesData, t]);

  const userOptions = useMemo(() => {
    let options = usersData?.users
      ? AuditLib.mapUsersToOptions(usersData.users)
      : [];

    if (searchParams.userId && user) {
      options = [...options, { label: user.fullName!, value: user.id! }];
    }

    return options;
  }, [searchParams.userId, user, usersData]);

  const resetFilters = useCallback(() => {
    updateSearchParams({
      queryObject: { ...RouterConsts.AUDIT_DEFAULT_QUERY },
    });
    setSmartRoomId('');
    setSmartRoomIdError(false);
  }, [updateSearchParams]);

  const refetchQuery = useCallback(() => {
    refetch();
  }, [refetch]);

  return {
    searchParams,
    isFetchingUsers,
    typeOptions,
    userOptions,
    searchUser,
    smartRoomId,
    smartRoomIdError,
    hasFetchedUser,
    modelIds,
    cityId,
    floorId,
    placeId,
    regionId,
    roomId,
    treeId,
    isLocationFiltersOpen,
    setSearchUser,
    refetchQuery,
    resetFilters,
    handleChange,
    handleChangeUser,
    handleChangeTimeFrom,
    handleChangeTimeMax,
    handleSmartRoomIdChange,
    handleLocationFiltersToggle,
    handleChangeModels,
    setRegionId,
    setCityId,
    setPlaceId,
    setFloorId,
    setRoomId,
    changeTreeId,
  };
};