diff --git a/frontend/src/webparts/approvalAdmin/components/app/AdminApp.tsx b/frontend/src/webparts/approvalAdmin/components/app/AdminApp.tsx index df02a0e..0db5ee1 100644 --- a/frontend/src/webparts/approvalAdmin/components/app/AdminApp.tsx +++ b/frontend/src/webparts/approvalAdmin/components/app/AdminApp.tsx @@ -9,8 +9,9 @@ import { PortalDictionaryClient } from '../../services/portalDictionary'; import { SharePointListsClient } from '../../services/sharePointLists'; import { RequestManageService } from '../../services/requestManageService'; import { RequestType, TemplateRoute } from '../../models'; -import { navigate, useRoute } from '../../routing'; +import { navigate, replaceRoute, useRoute } from '../../routing'; import { texts } from '../../texts'; +import { useLocalStorageState } from '../../hooks/useLocalStorageState'; import { DashboardScreen } from '../screens/DashboardScreen'; import { RequestTypesScreen } from '../screens/RequestTypesScreen'; import { RoutesScreen } from '../screens/RoutesScreen'; @@ -36,6 +37,12 @@ function sidebarActiveId(tab: ScreenKey): string { return tab === 'routeSteps' ? 'routes' : tab; } +// Последняя открытая вкладка. В адресе она и так живёт (aatab, см. routing.ts), +// но веб-часть часто открывают по «чистой» ссылке на страницу SharePoint, без +// query — и тогда пользователь каждый раз приземлялся на дашборд, даже если +// работает всегда в одном разделе. +const TAB_STORAGE_KEY = 'approvalAdmin.activeTab'; + export interface IAdminAppProps { api: ApprovalRouteApi; /** Undefined, пока SPFx выдаёт AAD-клиент для api.tnsu.kz. */ @@ -52,6 +59,24 @@ export const AdminApp: React.FC = ({ api, dictionary, sharePoint const [navCollapsed, setNavCollapsed] = React.useState(false); const [mobileNavOpen, setMobileNavOpen] = React.useState(false); + const [storedTab, setStoredTab] = useLocalStorageState(TAB_STORAGE_KEY, 'dashboard'); + + // Восстанавливаем последнюю вкладку ТОЛЬКО когда в адресе её нет: глубокая + // ссылка (в т.ч. присланная коллегой) всегда важнее запомненного выбора. + // Один раз на монтировании — дальше вкладку меняет только сам пользователь. + React.useEffect(() => { + const explicitTab = new URLSearchParams(window.location.search).get('aatab'); + if (explicitTab || storedTab === 'dashboard') return; + replaceRoute({ tab: storedTab }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + // 'routeSteps' сюда не попадёт: useRoute отдаёт только вкладки из TABS, а шаги + // маршрута — состояние вкладки 'routes' (см. routing.ts). + React.useEffect(() => { + setStoredTab(route.tab); + }, [route.tab, setStoredTab]); + const navigateTab = (key: ScreenKey): void => { setMobileNavOpen(false); navigate({ tab: key });