168 lines
5.1 KiB
TypeScript
168 lines
5.1 KiB
TypeScript
import React, { useEffect, Suspense, useRef, useState } from 'react'
|
|
import { Routes, Route, useNavigate } from 'react-router-dom'
|
|
import { Provider } from 'react-redux'
|
|
import { getNavigationValue } from '@brojs/cli'
|
|
import { Box, Container, Spinner, VStack, useColorMode } from '@chakra-ui/react'
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import {
|
|
CourseListPage,
|
|
LessonDetailsPage,
|
|
LessonListPage,
|
|
UserPage,
|
|
AttendancePage,
|
|
} from './pages'
|
|
import { ErrorBoundary, AppHeader, BreadcrumbsProvider, useBreadcrumbs } from './components'
|
|
import { keycloak } from './__data__/kc'
|
|
|
|
const MENU_SCRIPT_URL = 'https://admin.bro-js.ru/remote-assets/lib/serviceMenu/serviceMenu.js'
|
|
|
|
const loadServiceMenu = () => {
|
|
return new Promise((resolve, reject) => {
|
|
const script = document.createElement('script')
|
|
script.src = MENU_SCRIPT_URL
|
|
script.onload = () => setTimeout(() => resolve(true), 1000)
|
|
script.onerror = reject
|
|
document.body.appendChild(script)
|
|
})
|
|
}
|
|
|
|
declare global {
|
|
interface Window {
|
|
createServiceMenu?: (options: any) => {
|
|
show: () => void;
|
|
hide: () => void;
|
|
update: () => void;
|
|
destroy: () => void;
|
|
};
|
|
}
|
|
}
|
|
|
|
const Wrapper = ({ children }: { children: React.ReactElement }) => (
|
|
<Suspense
|
|
fallback={
|
|
<ErrorBoundary>
|
|
<Container>
|
|
<VStack>
|
|
<Box mt="150">
|
|
<Spinner
|
|
thickness="4px"
|
|
speed="0.65s"
|
|
emptyColor="gray.200"
|
|
color="blue.500"
|
|
size="xl"
|
|
/>
|
|
</Box>
|
|
</VStack>
|
|
</Container>
|
|
</ErrorBoundary>
|
|
}
|
|
>
|
|
{children}
|
|
</Suspense>
|
|
)
|
|
|
|
// Компонент, который соединяет хлебные крошки с AppHeader
|
|
const HeaderWithBreadcrumbs = ({ serviceMenuContainerRef }: { serviceMenuContainerRef: React.RefObject<HTMLDivElement> }) => {
|
|
const { breadcrumbs } = useBreadcrumbs();
|
|
return <AppHeader serviceMenuContainerRef={serviceMenuContainerRef} breadcrumbs={breadcrumbs} />;
|
|
};
|
|
|
|
interface DashboardProps {
|
|
store: any; // Используем any, поскольку точный тип store не указан
|
|
}
|
|
|
|
export const Dashboard = ({ store }: DashboardProps) => {
|
|
const serviceMenuContainerRef = useRef<HTMLDivElement>(null);
|
|
const serviceMenuInstanceRef = useRef<any>(null);
|
|
const [serviceMenu, setServiceMenu] = useState(false);
|
|
const { colorMode } = useColorMode();
|
|
const { t } = useTranslation();
|
|
|
|
useEffect(() => {
|
|
loadServiceMenu().then(() => {
|
|
setServiceMenu(true)
|
|
}).catch(console.error)
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
// Проверяем, что библиотека загружена и есть контейнер для меню
|
|
if (window.createServiceMenu && serviceMenuContainerRef.current && serviceMenu) {
|
|
// Создаем меню сервисов
|
|
serviceMenuInstanceRef.current = window.createServiceMenu({
|
|
accessToken: keycloak.token,
|
|
apiUrl: 'https://admin.bro-js.ru',
|
|
targetElement: serviceMenuContainerRef.current,
|
|
styles: {
|
|
dotColor: colorMode === 'light' ? '#333' : '#ccc',
|
|
hoverColor: colorMode === 'light' ? '#eee' : '#444',
|
|
backgroundColor: colorMode === 'light' ? '#fff' : '#2D3748',
|
|
textColor: colorMode === 'light' ? '#333' : '#fff',
|
|
},
|
|
translations: {
|
|
menuTitle: t('journal.pl.serviceMenu.title'),
|
|
menuAriaLabel: t('journal.pl.serviceMenu.ariaLabel'),
|
|
}
|
|
});
|
|
}
|
|
|
|
// Очистка при размонтировании
|
|
return () => {
|
|
if (serviceMenuInstanceRef.current) {
|
|
serviceMenuInstanceRef.current.destroy();
|
|
serviceMenuInstanceRef.current = null;
|
|
}
|
|
};
|
|
}, [keycloak.token, serviceMenu, colorMode, t]);
|
|
|
|
return (
|
|
<Provider store={store}>
|
|
<BreadcrumbsProvider>
|
|
<HeaderWithBreadcrumbs serviceMenuContainerRef={serviceMenuContainerRef} />
|
|
<Routes>
|
|
<Route
|
|
path={getNavigationValue('journal.main')}
|
|
element={
|
|
<Wrapper>
|
|
<CourseListPage />
|
|
</Wrapper>
|
|
}
|
|
/>
|
|
<Route
|
|
path={`${getNavigationValue('journal.main')}/lessons-list/:courseId`}
|
|
element={
|
|
<Wrapper>
|
|
<LessonListPage />
|
|
</Wrapper>
|
|
}
|
|
/>
|
|
<Route
|
|
path={`${getNavigationValue('journal.main')}/u/:lessonId/:accessId`}
|
|
element={
|
|
<Wrapper>
|
|
<UserPage />
|
|
</Wrapper>
|
|
}
|
|
/>
|
|
<Route
|
|
path={`${getNavigationValue('journal.main')}/lesson/:courseId/:lessonId`}
|
|
element={
|
|
<Wrapper>
|
|
<LessonDetailsPage />
|
|
</Wrapper>
|
|
}
|
|
/>
|
|
<Route
|
|
path={`${getNavigationValue('journal.main')}${getNavigationValue('link.journal.attendance')}`}
|
|
element={
|
|
<Wrapper>
|
|
<AttendancePage />
|
|
</Wrapper>
|
|
}
|
|
/>
|
|
</Routes>
|
|
</BreadcrumbsProvider>
|
|
</Provider>
|
|
)
|
|
}
|