UNPKG

react-antd-admin-panel

Version:

Modern TypeScript-first React admin panel builder with Ant Design 6

155 lines 5.43 kB
import React from 'react'; import { GlobalStore } from './Store'; import { UserState } from './UserState'; import { Get } from '../http/Get'; import { Post } from '../http/Post'; /** * Main context for accessing app instance throughout the component tree */ export const MainContext = React.createContext(null); /** * Hook to access the Main instance */ export function useMain() { const context = React.useContext(MainContext); if (!context) { throw new Error('useMain must be used within a MainProvider'); } return context; } /** * Hook to access the current user */ export function useUser() { const main = useMain(); const [user, setUser] = React.useState(main.User().get()); React.useEffect(() => { return main.User().subscribe(setUser); }, [main]); return user; } /** * Hook to access a store value */ export function useStore(key) { const main = useMain(); const [value, setValue] = React.useState(main.Store().get(key)); React.useEffect(() => { return main.Store().subscribe(key, setValue); }, [main, key]); return value; } /** * Hook to set store values */ export function useStoreActions() { const main = useMain(); return { set: (key, value) => main.Store().set(key, value), remove: (key) => main.Store().remove(key), clear: () => main.Store().clear(), }; } /** * MainProvider - Provides the Main context to the application */ export function MainProvider({ config, navigate, children }) { // Create stable instances const storeRef = React.useRef(new GlobalStore()); const userStateRef = React.useRef(new UserState()); const [booted, setBooted] = React.useState(false); const [bootError, setBootError] = React.useState(null); // Create the main instance const mainInstance = React.useMemo(() => ({ User: () => userStateRef.current, Store: () => storeRef.current, config: config.config, navigate, canAccess: (route) => { const user = userStateRef.current; // Check required role if (route.requiredRole && !user.hasRole(route.requiredRole)) { return false; } // Check required permissions if (route.requiredPermissions && !user.hasAllPermissions(route.requiredPermissions)) { return false; } return true; }, }), [config.config, navigate]); // Configure HTTP on mount React.useEffect(() => { const httpConfig = config.config.http; if (httpConfig) { Get.configure({ baseURL: httpConfig.baseURL || config.config.pathToApi, timeout: httpConfig.timeout, headers: httpConfig.headers, }); Post.configure({ baseURL: httpConfig.baseURL || config.config.pathToApi, timeout: httpConfig.timeout, headers: httpConfig.headers, }); // Set up interceptors if provided if (httpConfig.onRequest || httpConfig.onResponse || httpConfig.onError || httpConfig.onUnauthorized) { const axios = Get.getAxios(); if (httpConfig.onRequest) { axios.interceptors.request.use(httpConfig.onRequest); } if (httpConfig.onResponse || httpConfig.onError || httpConfig.onUnauthorized) { axios.interceptors.response.use(httpConfig.onResponse, (error) => { if (error.response?.status === 401 && httpConfig.onUnauthorized) { httpConfig.onUnauthorized(); } if (httpConfig.onError) { return httpConfig.onError(error); } return Promise.reject(error); }); } } } }, [config.config.http, config.config.pathToApi]); // Run boot sequence React.useEffect(() => { const runBoot = async () => { try { if (config.config.boot) { await config.config.boot(mainInstance); } setBooted(true); } catch (error) { setBootError(error); } }; runBoot(); }, [config.config.boot, mainInstance]); // Show loading or error during boot if (bootError) { return React.createElement('div', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', flexDirection: 'column', gap: 16, }, }, React.createElement('h2', {}, 'Application Error'), React.createElement('p', { style: { color: 'red' } }, bootError.message)); } if (!booted && config.config.boot) { return React.createElement('div', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', }, }, React.createElement('span', {}, 'Loading...')); } return React.createElement(MainContext.Provider, { value: mainInstance }, children); } //# sourceMappingURL=MainContext.js.map