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