переезд на панель

This commit is contained in:
gorbenko.pavel
2026-08-19 15:18:41 +05:00
parent 30fb3fa2b1
commit 101ca975e0
7 changed files with 135 additions and 210 deletions
@@ -1,6 +1,8 @@
import * as React from 'react';
import styles from './AdminApp.module.scss';
import { TopNav } from './TopNav';
import '@tnsu/ui-kit/styles.css';
import { IconSprite, Sidebar, SidebarToggle } from '@tnsu/ui-kit';
import type { ISidebarItem } from '@tnsu/ui-kit';
import { ScreenKey } from './types';
import { ApprovalRouteApi } from '../../services/api';
import { PortalDictionaryClient } from '../../services/portalDictionary';
@@ -8,6 +10,7 @@ import { SharePointListsClient } from '../../services/sharePointLists';
import { RequestManageService } from '../../services/requestManageService';
import { RequestType, TemplateRoute } from '../../models';
import { navigate, useRoute } from '../../routing';
import { texts } from '../../texts';
import { DashboardScreen } from '../screens/DashboardScreen';
import { RequestTypesScreen } from '../screens/RequestTypesScreen';
import { RoutesScreen } from '../screens/RoutesScreen';
@@ -15,6 +18,22 @@ import { RouteStepsScreen } from '../screens/RouteStepsScreen';
import { ResolveScreen } from '../screens/ResolveScreen';
import { ManageRequestsScreen } from '../screens/ManageRequestsScreen';
// Тот же боковой рейл (@tnsu/ui-kit Sidebar), что и в request-portal — единый
// стиль навигации во всех веб-частях Tnsu. 'routeSteps' сюда не входит: это не
// отдельная вкладка URL, а состояние вкладки 'routes' при открытых шагах
// конкретного маршрута (см. routing.ts) — подсвечиваем в этом случае 'routes'.
const NAV_ITEMS: ISidebarItem[] = [
{ id: 'dashboard', title: texts.nav.dashboard, icon: 'chart' },
{ id: 'requestTypes', title: texts.nav.requestTypes, icon: 'document' },
{ id: 'routes', title: texts.nav.routes, icon: 'send' },
{ id: 'resolve', title: texts.nav.resolve, icon: 'search' },
{ id: 'manageRequests', title: texts.nav.manageRequests, icon: 'clipboard' }
];
function sidebarActiveId(tab: ScreenKey): string {
return tab === 'routeSteps' ? 'routes' : tab;
}
export interface IAdminAppProps {
api: ApprovalRouteApi;
/** Undefined, пока SPFx выдаёт AAD-клиент для api.tnsu.kz. */
@@ -28,8 +47,13 @@ export const AdminApp: React.FC<IAdminAppProps> = ({ api, dictionary, sharePoint
const route = useRoute();
const [selectedRoute, setSelectedRoute] = React.useState<TemplateRoute | undefined>();
const [selectedRequestType, setSelectedRequestType] = React.useState<RequestType | undefined>();
const [navCollapsed, setNavCollapsed] = React.useState(false);
const [mobileNavOpen, setMobileNavOpen] = React.useState(false);
const navigateTab = (key: ScreenKey): void => navigate({ tab: key });
const navigateTab = (key: ScreenKey): void => {
setMobileNavOpen(false);
navigate({ tab: key });
};
const openSteps = (r: TemplateRoute): void => {
setSelectedRoute(r);
@@ -76,41 +100,58 @@ export const AdminApp: React.FC<IAdminAppProps> = ({ api, dictionary, sharePoint
return (
<div className={styles.shell}>
<TopNav active={route.tab} onSelect={navigateTab} />
<div className={styles.content}>
{route.tab === 'dashboard' && <DashboardScreen api={api} onNavigate={navigateTab} />}
{route.tab === 'requestTypes' && <RequestTypesScreen api={api} sharePoint={sharePoint} />}
{route.tab === 'routes' && !route.routeId && (
<RoutesScreen
api={api}
dictionary={dictionary}
initialFilterRequestTypeId={route.routesFilter}
onOpenSteps={openSteps}
/>
)}
{route.tab === 'routes' && route.routeId && selectedRoute && (
<RouteStepsScreen
api={api}
route={selectedRoute}
requestType={selectedRequestType}
dictionary={dictionary}
sharePoint={sharePoint}
onBack={() => navigate({ tab: 'routes', routesFilter: route.routesFilter })}
/>
)}
{route.tab === 'resolve' && (
<ResolveScreen
api={api}
dictionary={dictionary}
sharePoint={sharePoint}
currentUserEmail={currentUserEmail}
route={route.resolve}
/>
)}
{route.tab === 'manageRequests' && (
<ManageRequestsScreen api={api} dictionary={dictionary} requestManage={requestManage} route={route.manage} />
)}
<IconSprite />
<div className={styles.side}>
<Sidebar
items={NAV_ITEMS}
activeId={sidebarActiveId(route.tab)}
onChange={id => navigateTab(id as ScreenKey)}
brand={texts.nav.title}
collapsed={navCollapsed}
onToggleCollapsed={() => setNavCollapsed(v => !v)}
mobileOpen={mobileNavOpen}
onMobileClose={() => setMobileNavOpen(false)}
/>
</div>
<main className={styles.main}>
<div className={styles.mobileNav}>
<SidebarToggle onClick={() => setMobileNavOpen(true)} />
</div>
<div className={styles.content}>
{route.tab === 'dashboard' && <DashboardScreen api={api} onNavigate={navigateTab} />}
{route.tab === 'requestTypes' && <RequestTypesScreen api={api} sharePoint={sharePoint} />}
{route.tab === 'routes' && !route.routeId && (
<RoutesScreen
api={api}
dictionary={dictionary}
initialFilterRequestTypeId={route.routesFilter}
onOpenSteps={openSteps}
/>
)}
{route.tab === 'routes' && route.routeId && selectedRoute && (
<RouteStepsScreen
api={api}
route={selectedRoute}
requestType={selectedRequestType}
dictionary={dictionary}
sharePoint={sharePoint}
onBack={() => navigate({ tab: 'routes', routesFilter: route.routesFilter })}
/>
)}
{route.tab === 'resolve' && (
<ResolveScreen
api={api}
dictionary={dictionary}
sharePoint={sharePoint}
currentUserEmail={currentUserEmail}
route={route.resolve}
/>
)}
{route.tab === 'manageRequests' && (
<ManageRequestsScreen api={api} dictionary={dictionary} requestManage={requestManage} route={route.manage} />
)}
</div>
</main>
</div>
);
};