Merge branch 'feature/team-utilization' into feature/holiday-calendar-integration

This commit is contained in:
Chamika J
2025-07-28 10:01:24 +05:30
committed by GitHub
2 changed files with 39 additions and 9 deletions

View File

@@ -1,6 +1,9 @@
import React, { ReactNode, Suspense } from 'react'; import React, { ReactNode, Suspense } from 'react';
import { InlineSuspenseFallback } from '@/components/suspense-fallback/suspense-fallback'; import { InlineSuspenseFallback } from '@/components/suspense-fallback/suspense-fallback';
import i18n from '@/i18n'; import i18n from '@/i18n';
import { hasFinanceViewPermission } from '@/utils/finance-permissions';
import { ILocalSession } from '@/types/auth/local-session.types';
import { IProjectViewModel } from '@/types/project/projectViewModel.types';
// Import core components synchronously to avoid suspense in main tabs // Import core components synchronously to avoid suspense in main tabs
import ProjectViewEnhancedBoard from '@/pages/projects/projectView/enhancedBoard/project-view-enhanced-board'; import ProjectViewEnhancedBoard from '@/pages/projects/projectView/enhancedBoard/project-view-enhanced-board';
@@ -164,3 +167,21 @@ export const updateTabLabels = () => {
console.error('Error updating tab labels:', error); console.error('Error updating tab labels:', error);
} }
}; };
// Function to get filtered tab items based on user permissions
export const getFilteredTabItems = (
currentSession: ILocalSession | null,
currentProject?: IProjectViewModel | null
): TabItems[] => {
const hasFinancePermission = hasFinanceViewPermission(currentSession, currentProject);
return tabItems.filter(item => {
// Always show all tabs except finance
if (item.key !== 'finance') {
return true;
}
// Only show finance tab if user has permission
return hasFinancePermission;
});
};

View File

@@ -28,7 +28,7 @@ import { resetSelection } from '@/features/task-management/selection.slice';
import { resetFields } from '@/features/task-management/taskListFields.slice'; import { resetFields } from '@/features/task-management/taskListFields.slice';
import { fetchLabels } from '@/features/taskAttributes/taskLabelSlice'; import { fetchLabels } from '@/features/taskAttributes/taskLabelSlice';
import { deselectAll } from '@/features/projects/bulkActions/bulkActionSlice'; import { deselectAll } from '@/features/projects/bulkActions/bulkActionSlice';
import { tabItems, updateTabLabels } from '@/lib/project/project-view-constants'; import { tabItems, updateTabLabels, getFilteredTabItems } from '@/lib/project/project-view-constants';
import { import {
setSelectedTaskId, setSelectedTaskId,
setShowTaskDrawer, setShowTaskDrawer,
@@ -39,6 +39,7 @@ import { setProjectId as setInsightsProjectId } from '@/features/projects/insigh
import { SuspenseFallback } from '@/components/suspense-fallback/suspense-fallback'; import { SuspenseFallback } from '@/components/suspense-fallback/suspense-fallback';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useTimerInitialization } from '@/hooks/useTimerInitialization'; import { useTimerInitialization } from '@/hooks/useTimerInitialization';
import { useAuthService } from '@/hooks/useAuth';
// Import critical components synchronously to avoid suspense interruptions // Import critical components synchronously to avoid suspense interruptions
import TaskDrawer from '@components/task-drawer/task-drawer'; import TaskDrawer from '@components/task-drawer/task-drawer';
@@ -73,14 +74,21 @@ const ProjectView = React.memo(() => {
// Optimize document title updates // Optimize document title updates
useDocumentTitle(selectedProject?.name || t('projectView')); useDocumentTitle(selectedProject?.name || t('projectView'));
// Get auth service and current session
const authService = useAuthService();
const currentSession = useMemo(() => authService.getCurrentSession(), [authService]);
// Memoize URL params to prevent unnecessary state updates // Memoize URL params to prevent unnecessary state updates
const urlParams = useMemo( const urlParams = useMemo(
() => ({ () => {
tab: searchParams.get('tab') || tabItems[0].key, const filteredTabItems = getFilteredTabItems(currentSession, selectedProject);
return {
tab: searchParams.get('tab') || filteredTabItems[0]?.key || 'tasks-list',
pinnedTab: searchParams.get('pinned_tab') || '', pinnedTab: searchParams.get('pinned_tab') || '',
taskId: searchParams.get('task') || '', taskId: searchParams.get('task') || '',
}), };
[searchParams] },
[searchParams, currentSession, selectedProject]
); );
const [activeTab, setActiveTab] = useState<string>(urlParams.tab); const [activeTab, setActiveTab] = useState<string>(urlParams.tab);
@@ -266,7 +274,8 @@ const ProjectView = React.memo(() => {
return []; return [];
} }
const menuItems = tabItems.map(item => ({ const filteredTabItems = getFilteredTabItems(currentSession, selectedProject);
const menuItems = filteredTabItems.map(item => ({
key: item.key, key: item.key,
label: ( label: (
<Flex align="center" gap={6} style={{ color: 'inherit' }}> <Flex align="center" gap={6} style={{ color: 'inherit' }}>
@@ -320,7 +329,7 @@ const ProjectView = React.memo(() => {
})); }));
return menuItems; return menuItems;
}, [pinnedTab, pinToDefaultTab, t, translationsReady]); }, [pinnedTab, pinToDefaultTab, t, translationsReady, currentSession, selectedProject]);
// Optimized secondary components loading with better UX // Optimized secondary components loading with better UX
const [shouldLoadSecondaryComponents, setShouldLoadSecondaryComponents] = useState(false); const [shouldLoadSecondaryComponents, setShouldLoadSecondaryComponents] = useState(false);