journal.pl/src/dashboard.tsx

168 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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