Добавлено расширение темы Chakra UI, реализован компонент AppHeader с переключением темной/светлой темы, обновлены стили для поддержки темной темы, улучшена загрузка компонентов с учетом цветовой схемы.
This commit is contained in:
+121
-49
@@ -1,8 +1,8 @@
|
||||
import React, { useEffect, Suspense } from 'react'
|
||||
import React, { useEffect, Suspense, useRef, useState } from 'react'
|
||||
import { Routes, Route, useNavigate } from 'react-router-dom'
|
||||
import { Provider } from 'react-redux'
|
||||
import { getNavigationsValue } from '@brojs/cli'
|
||||
import { Box, Container, Spinner, VStack } from '@chakra-ui/react'
|
||||
import { getNavigationValue } from '@brojs/cli'
|
||||
import { Box, Container, Spinner, VStack, useColorMode } from '@chakra-ui/react'
|
||||
|
||||
import {
|
||||
CourseListPage,
|
||||
@@ -11,7 +11,31 @@ import {
|
||||
UserPage,
|
||||
AttendancePage,
|
||||
} from './pages'
|
||||
import { ErrorBoundary } from './components/error-boundary'
|
||||
import { ErrorBoundary, AppHeader } 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
|
||||
@@ -37,49 +61,97 @@ const Wrapper = ({ children }: { children: React.ReactElement }) => (
|
||||
</Suspense>
|
||||
)
|
||||
|
||||
export const Dashboard = ({ store }) => (
|
||||
<Provider store={store}>
|
||||
<Routes>
|
||||
<Route
|
||||
path={getNavigationsValue('journal.main')}
|
||||
element={
|
||||
<Wrapper>
|
||||
<CourseListPage />
|
||||
</Wrapper>
|
||||
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();
|
||||
|
||||
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: 'Сервисы BRO',
|
||||
menuAriaLabel: 'Сервисы BRO',
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={`${getNavigationsValue('journal.main')}/lessons-list/:courseId`}
|
||||
element={
|
||||
<Wrapper>
|
||||
<LessonListPage />
|
||||
</Wrapper>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={`${getNavigationsValue('journal.main')}/u/:lessonId/:accessId`}
|
||||
element={
|
||||
<Wrapper>
|
||||
<UserPage />
|
||||
</Wrapper>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={`${getNavigationsValue('journal.main')}/lesson/:courseId/:lessonId`}
|
||||
element={
|
||||
<Wrapper>
|
||||
<LessonDetailsPage />
|
||||
</Wrapper>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={`${getNavigationsValue('journal.main')}${getNavigationsValue('link.journal.attendance')}`}
|
||||
element={
|
||||
<Wrapper>
|
||||
<AttendancePage />
|
||||
</Wrapper>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</Provider>
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
// Очистка при размонтировании
|
||||
return () => {
|
||||
if (serviceMenuInstanceRef.current) {
|
||||
serviceMenuInstanceRef.current.destroy();
|
||||
serviceMenuInstanceRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [keycloak.token, serviceMenu, colorMode]);
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<AppHeader 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>
|
||||
</Provider>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user