From b9b496e81467c3fba7192b115b73ad7af208b3d9 Mon Sep 17 00:00:00 2001 From: JANGHYUNn Date: Wed, 31 Jan 2024 16:34:11 +0900 Subject: [PATCH] =?UTF-8?q?Router=20typescript=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 37 ++++ package.json | 3 +- .../components/layout-wrapper/index.js | 56 ++--- src/router/Router.tsx | 194 ++++++++++++++++++ src/router/routes/type.ts | 15 ++ 5 files changed, 278 insertions(+), 27 deletions(-) create mode 100644 src/router/Router.tsx create mode 100644 src/router/routes/type.ts diff --git a/package-lock.json b/package-lock.json index 469b1c59..6239d0f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4081,6 +4081,43 @@ "redux": "^4.0.0" } }, + "@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "dev": true, + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*" + }, + "dependencies": { + "@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "dev": true + } + } + }, + "@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dev": true, + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + }, + "dependencies": { + "@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "dev": true + } + } + }, "@types/redux-debounced": { "version": "0.2.19", "resolved": "https://registry.npmjs.org/@types/redux-debounced/-/redux-debounced-0.2.19.tgz", diff --git a/package.json b/package.json index 9b9e83f8..207f855c 100644 --- a/package.json +++ b/package.json @@ -132,6 +132,7 @@ "extends": "react-app" }, "devDependencies": { + "@types/react-router-dom": "5.3.3", "@types/sortablejs": "^1.10.6", "@typescript-eslint/eslint-plugin": "^4.28.1", "@typescript-eslint/parser": "^4.28.1", @@ -151,7 +152,7 @@ "react-app-rewired": "^2.1.6", "react-snap": "1.23.0", "sass-loader": "^8.0.2", - "typescript": "^4.3.5" + "typescript": "4.3.5" }, "browserslist": { "production": [ diff --git a/src/@core/layouts/components/layout-wrapper/index.js b/src/@core/layouts/components/layout-wrapper/index.js index 81ad7c77..43b46567 100644 --- a/src/@core/layouts/components/layout-wrapper/index.js +++ b/src/@core/layouts/components/layout-wrapper/index.js @@ -1,59 +1,64 @@ // ** React Imports -import { Fragment, useEffect } from 'react' +import { Fragment, useEffect } from 'react'; // ** Third Party Components -import classnames from 'classnames' +import classnames from 'classnames'; // ** Store & Actions -import { useSelector, useDispatch } from 'react-redux' -import { handleContentWidth, handleMenuCollapsed, handleMenuHidden } from '@store/actions/layout' +import { useSelector, useDispatch } from 'react-redux'; +import { + handleContentWidth, + handleMenuCollapsed, + handleMenuHidden +} from '@store/actions/layout'; // ** Styles -import 'animate.css/animate.css' +import 'animate.css/animate.css'; const LayoutWrapper = props => { // ** Props - const { layout, children, appLayout, wrapperClass, transition, routeMeta } = props + const { layout, children, appLayout, wrapperClass, transition, routeMeta } = + props; // ** Store Vars - const dispatch = useDispatch() - const store = useSelector(state => state) - const navbarStore = store.navbar - const contentWidth = store.layout.contentWidth + const dispatch = useDispatch(); + const store = useSelector(state => state); + const navbarStore = store.navbar; + const contentWidth = store.layout.contentWidth; //** Vars - const Tag = layout === 'HorizontalLayout' && !appLayout ? 'div' : Fragment + const Tag = layout === 'HorizontalLayout' && !appLayout ? 'div' : Fragment; // ** Clean Up Function const cleanUp = () => { if (routeMeta) { if (routeMeta.contentWidth) { - dispatch(handleContentWidth('full')) + dispatch(handleContentWidth('full')); } if (routeMeta.menuCollapsed) { - dispatch(handleMenuCollapsed(!routeMeta.menuCollapsed)) + dispatch(handleMenuCollapsed(!routeMeta.menuCollapsed)); } if (routeMeta.menuHidden) { - dispatch(handleMenuHidden(!routeMeta.menuHidden)) + dispatch(handleMenuHidden(!routeMeta.menuHidden)); } } - } + }; // ** ComponentDidMount useEffect(() => { if (routeMeta) { if (routeMeta.contentWidth) { - dispatch(handleContentWidth(routeMeta.contentWidth)) + dispatch(handleContentWidth(routeMeta.contentWidth)); } if (routeMeta.menuCollapsed) { - dispatch(handleMenuCollapsed(routeMeta.menuCollapsed)) + dispatch(handleMenuCollapsed(routeMeta.menuCollapsed)); } if (routeMeta.menuHidden) { - dispatch(handleMenuHidden(routeMeta.menuHidden)) + dispatch(handleMenuHidden(routeMeta.menuHidden)); } } - return () => cleanUp() - }, []) + return () => cleanUp(); + }, []); return (
{ 'content-wrapper': !appLayout, 'content-area-wrapper': appLayout, 'container p-0': contentWidth === 'boxed', - [`animate__animated animate__${transition}`]: transition !== 'none' && transition.length + [`animate__animated animate__${transition}`]: + transition !== 'none' && transition.length })} > {children}
- ) -} + ); +}; -export default LayoutWrapper +export default LayoutWrapper; diff --git a/src/router/Router.tsx b/src/router/Router.tsx new file mode 100644 index 00000000..725309fe --- /dev/null +++ b/src/router/Router.tsx @@ -0,0 +1,194 @@ +import { useCallback, lazy, Suspense, useEffect } from 'react'; +import { useDispatch } from 'react-redux'; +import { + BrowserRouter as AppRouter, + Redirect, + Route, + Switch, + RouteComponentProps +} from 'react-router-dom'; +import { useLayout } from '@hooks/useLayout'; +import { useRouterTransition } from '@hooks/useRouterTransition'; +import LayoutWrapper from '@layouts/components/layout-wrapper'; +import BlankLayout from '@layouts/BlankLayout'; +import HeaderLayout from '@layouts/HeaderLayout'; +import HorizontalLayout from '@src/layouts/HorizontalLayout'; +import VerticalLayout from '@src/layouts/VerticalLayout'; +import * as Actions from '../modules/account/auth/actions'; +import { Routes } from './routes'; +import { useSelector } from '@store/storeConfig/store'; +import { IRoute } from './routes/type'; + +const NotAuthorized = lazy(() => import('@src/views/NotAuthorized')); +const Error = lazy(() => import('@src/views/Error')); + +interface IFinalRoute extends RouteComponentProps { + route: IRoute; +} + +const Router = () => { + const [layout, setLayout] = useLayout(); + const [transition, setTransition] = useRouterTransition(); + const { isLogin } = useSelector(state => state.authState); + // const isLogin = true; + const dispatch = useDispatch(); + + useEffect(() => { + if (!isLogin) { + dispatch(Actions.check.request()); + } + }, [isLogin]); + + const DefaultLayout = + layout === 'horizontal' ? 'HorizontalLayout' : 'VerticalLayout'; + + const Layouts = { + BlankLayout, + VerticalLayout, + HorizontalLayout, + HeaderLayout + }; + + const currentActiveItem = null; + + const LayoutRoutesAndPaths = (layout: string) => { + const LayoutRoutes: IRoute[] = []; + const LayoutPaths: string[] = []; + + if (Routes) { + Routes.filter(route => { + if ( + route.layout === layout || + (route.layout === undefined && DefaultLayout === layout) + ) { + LayoutRoutes.push(route); + LayoutPaths.push(route.path); + } + }); + } + + return { LayoutRoutes, LayoutPaths }; + }; + + const FinalRoute = (props: IFinalRoute) => { + const route = props.route; + // let action, resource; + + // if (route.meta) { + // action = route.meta.action ? route.meta.action : null; + // resource = route.meta.resource ? route.meta.resource : null; + // } + + if (isLogin === false && !route.meta?.authRoute) { + return ; + } else { + const Component: (props: IFinalRoute) => JSX.Element = + route.component as (props: IFinalRoute) => JSX.Element; + // switch (props.route.path) { + // case '/account/register': + // case '/account/find': + // return ; + // default: + // return ; + // } + + return ; + } + }; + + const ResolveRoutes = useCallback(() => { + return Object.keys(Layouts).map((layout, index) => { + const LayoutTag = Layouts[layout]; + + const { LayoutRoutes, LayoutPaths } = LayoutRoutesAndPaths(layout); + const routerProps = {}; + + return ( + + + + {LayoutRoutes.map(route => { + return ( + { + Object.assign(routerProps, { + ...props, + meta: route.meta + }); + + return ( + + + + + + ); + }} + /> + ); + })} + + + + ); + }); + }, [Layouts]); + + return ( + + + { + return ; + }} + /> + + ( + + + + )} + /> + {ResolveRoutes()} + + + + + ); +}; + +export default Router; diff --git a/src/router/routes/type.ts b/src/router/routes/type.ts new file mode 100644 index 00000000..8280d274 --- /dev/null +++ b/src/router/routes/type.ts @@ -0,0 +1,15 @@ +import { FC, ReactElement, ReactNode } from 'react'; + +interface IRoute { + component: ReactNode; + layout?: string; + meta?: { + authRoute: boolean; + }; + path: string | undefined; + exact?: boolean; + appLayout?: string; + className?: string; +} + +export type { IRoute };