File "hooks.ts"

Full Path: /var/www/html/gitep_front/src/shared/model/payments/hooks.ts
File size: 6.66 KB
MIME-type: text/x-java
Charset: utf-8

import { useState, useEffect } from "react";
import { useSearchParams } from "react-router";
import { setFilters } from "./events";
import { useUnit } from "effector-react";
import { $filterStore, $queryString, checkApprovalRights } from "./stores";
import { getPaymentsList } from "@/entities/payments-table/lib/getPaymentsList";
import { $roleStore, $permissionStore } from '@/features/roles/store/stores';
import { $profileStore } from '@/entities/user/model';
import { useMediaQuery } from 'react-responsive';

// Функция для получения доступных вкладок по роли
const getAvailableTabsByRole = (role: string | number, mobileToTable: boolean) => {
  const mobileAvailableTabs = ['my', 'approve', 'agreed', 'all'];
  
  let availableTabs: string[] = [];
  
  switch (role) {
    case 'collaborator':
    case 'employee':
      availableTabs = ['my', 'all'];
      break;
      
    case 'moderator':
    case 'approval':
      availableTabs = ['my', 'approve', 'agreed', 'all'];
      break;
      
    case 'accountant':
    case 'superAdmin':
    case 'superadmin':
      availableTabs = ['my', 'approve', 'agreed', 'pay', 'cash_payments', 'all'];
      break;
      
    default:
      availableTabs = ['my', 'all'];
      break;
  }
  
  if (mobileToTable) {
    availableTabs = availableTabs.filter(tab => mobileAvailableTabs.includes(tab));
  }
  
  return availableTabs;
};

const getFallbackTab = (availableTabs: string[]): string => {
  if (availableTabs.includes('all')) return 'all';
  if (availableTabs.includes('my')) return 'my';
  return availableTabs[0] || 'all';
};

export const useSyncWithURL = () => {
  const [searchParams, setSearchParams] = useSearchParams();
  const [isFiltersLoaded, setIsFiltersLoaded] = useState(false);
  const [currentRole, currentPermissions] = useUnit([$roleStore, $permissionStore]);
  const profile = useUnit($profileStore).profile;
  const [isFirstLoad, setIsFirstLoad] = useState(true);
  const mobileToTable = useMediaQuery({ query: '(max-width: 768px)' });

  // вкладки доступные в моб версии
  const mobileAvailableTabs = ['my', 'approve', 'agreed', 'all'];

  useEffect(() => {
    if (!currentRole.role) return;

    const filtersRaw = searchParams.get("filters");
    const filters = filtersRaw ? JSON.parse(filtersRaw) : {};
    const hasApprovalRights = checkApprovalRights(currentRole.role, currentPermissions.permissions);
    const availableTabs = getAvailableTabsByRole(currentRole.role, mobileToTable);
    const fallbackTab = getFallbackTab(availableTabs);
    
    // Обработка начальной загрузки
    if (!filters.tab && profile?.start_page && isFirstLoad) {
      let startTab = profile.start_page;
      
      // Проверяем, доступна ли стартовая страница для роли
      const canAccessStartPage = availableTabs.includes(profile.start_page) && 
                                (profile.start_page !== 'approve' && profile.start_page !== 'agreed' || 
                                (profile.start_page === 'approve' || profile.start_page === 'agreed') && hasApprovalRights);
      
      if (canAccessStartPage) {
        startTab = profile.start_page;
      } else {
        // Если стартовая страница недоступна, используем fallback
        startTab = fallbackTab;
      }
      
      // Дополнительная проверка для мобильных устройств
      if (mobileToTable && !mobileAvailableTabs.includes(startTab)) {
        startTab = 'all';
      }
      
      filters.tab = startTab;
      setIsFirstLoad(false);
    } 

    // ПРОВЕРКА ПРАВ ПРИ ЗАГРУЗКЕ ИЗ URL
    if (filters.tab) {
      const tabIsAvailable = availableTabs.includes(filters.tab);
      const hasRightsForTab = (filters.tab === 'approve' || filters.tab === 'agreed') ? hasApprovalRights : true;
      
      // если вкладка недоступна для роли или нет прав - исправляем
      if (!tabIsAvailable || !hasRightsForTab) {
        console.warn(`Tab "${filters.tab}" not available for role "${currentRole.role}", resetting to "${fallbackTab}"`);
        filters.tab = fallbackTab;
        
        // обновляем URL чтобы убрать запрещенную вкладку
        const correctedParams = new URLSearchParams();
        correctedParams.set('filters', JSON.stringify(filters));
        setSearchParams(correctedParams, { replace: true });
      }
      
      // Для сотрудников ограничиваем только "my" и "all"
      if (typeof currentRole.role === 'string' && ['collaborator', 'employee'].includes(currentRole.role)) {
        if (filters.tab !== 'my' && filters.tab !== 'all') {
          console.warn('Employee role cannot access this tab, resetting to "my"');
          filters.tab = 'my';
          
          const correctedParams = new URLSearchParams();
          correctedParams.set('filters', JSON.stringify(filters));
          setSearchParams(correctedParams, { replace: true });
        }
      }
      
      if (mobileToTable && !mobileAvailableTabs.includes(filters.tab)) {
        console.warn('Mobile device: tab not available, resetting to "all"');
        filters.tab = 'all';
        
        const correctedParams = new URLSearchParams();
        correctedParams.set('filters', JSON.stringify(filters));
        setSearchParams(correctedParams, { replace: true });
      }
    }

    setFilters({...filters});

    setIsFiltersLoaded(true); // Флаг, что фильтры загружены из URL
  }, [searchParams, currentRole, currentPermissions, profile, setSearchParams, mobileToTable]);

  useEffect(() => {
    const filtersRaw = searchParams.get("filters");
    const filters = filtersRaw ? JSON.parse(filtersRaw) : {};
     
    setFilters({
      ...filters,
      search: null
    });
    setIsFiltersLoaded(true); // Флаг, что фильтры загружены из URL

  }, []);
  const queryString = useUnit($queryString);
  const filtersStore = useUnit($filterStore);
  useEffect(() => {
    if (!isFiltersLoaded) return; // Ждём, пока загрузятся фильтры из URL

    setSearchParams(new URLSearchParams(queryString));

    // Если фильтры пустые, но они уже загружены из URL, делаем запрос
    if (filtersStore.filters && Object.keys(filtersStore.filters).length === 0) {
      getPaymentsList({}); // Передаём пустой объект, чтобы явно показать очистку
      return;
    }

    getPaymentsList(filtersStore.filters);
  }, [queryString, isFiltersLoaded]);

};