Skip to content

Commit 42fc504

Browse files
authored
Merge pull request #998 from nqviet/dev
V5 challenge management
2 parents ac7a909 + c20c266 commit 42fc504

File tree

99 files changed

+4418
-14
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+4418
-14
lines changed

src/apps/admin/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './src'

src/apps/admin/src/AdminApp.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
FC,
3+
JSXElementConstructor,
4+
PropsWithChildren,
5+
useContext,
6+
useEffect,
7+
useMemo,
8+
} from 'react'
9+
import { Outlet, Routes, useLocation } from 'react-router-dom'
10+
11+
import { routerContext, RouterContextData } from '~/libs/core'
12+
13+
import { NullLayout, SWRConfigProvider } from './lib'
14+
import { adminRoutes, toolTitle } from './admin-app.routes'
15+
import ChallengeManagement from './challenge-management/ChallengeManagement'
16+
import './lib/styles/index.scss'
17+
18+
/**
19+
* The admin app.
20+
*/
21+
const AdminApp: FC = () => {
22+
const { getChildRoutes }: RouterContextData = useContext(routerContext)
23+
// eslint-disable-next-line react-hooks/exhaustive-deps -- missing dependency: getChildRoutes
24+
const childRoutes = useMemo(() => getChildRoutes(toolTitle), [])
25+
const AppLayout = useAppLayout()
26+
27+
useEffect(() => {
28+
document.body.classList.add('admin-app')
29+
return () => {
30+
document.body.classList.remove('admin-app')
31+
}
32+
}, [])
33+
34+
return (
35+
<div>
36+
<SWRConfigProvider>
37+
<AppLayout>
38+
<Outlet />
39+
<Routes>{childRoutes}</Routes>
40+
</AppLayout>
41+
</SWRConfigProvider>
42+
</div>
43+
)
44+
}
45+
46+
function useAppLayout(): JSXElementConstructor<PropsWithChildren> {
47+
const challengeManagementPath = adminRoutes[0].children?.find(
48+
r => r.id === 'challenge-management',
49+
)?.route
50+
const locationPath = useLocation().pathname
51+
52+
if (
53+
challengeManagementPath
54+
&& locationPath.includes(challengeManagementPath)
55+
) {
56+
return ChallengeManagement.Layout
57+
}
58+
59+
return NullLayout
60+
}
61+
62+
export default AdminApp
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { AppSubdomain, EnvironmentConfig, ToolTitle } from '~/config'
2+
import {
3+
lazyLoad,
4+
LazyLoadedComponent,
5+
PlatformRoute,
6+
Rewrite,
7+
UserRole,
8+
} from '~/libs/core'
9+
10+
const AdminApp: LazyLoadedComponent = lazyLoad(() => import('./AdminApp'))
11+
12+
const ChallengeManagement: LazyLoadedComponent = lazyLoad(
13+
() => import('./challenge-management/ChallengeManagement'),
14+
)
15+
const ChallengeManagementPage: LazyLoadedComponent = lazyLoad(
16+
() => import('./challenge-management/ChallengeManagementPage'),
17+
'ChallengeManagementPage',
18+
)
19+
const ManageUserPage: LazyLoadedComponent = lazyLoad(
20+
() => import('./challenge-management/ManageUserPage'),
21+
'ManageUserPage',
22+
)
23+
24+
export const toolTitle: string = ToolTitle.admin
25+
export const rootRoute: string
26+
= EnvironmentConfig.SUBDOMAIN === AppSubdomain.admin
27+
? '/'
28+
: `/${AppSubdomain.admin}`
29+
30+
export const adminRoutes: ReadonlyArray<PlatformRoute> = [
31+
// Admin App Root
32+
{
33+
authRequired: true,
34+
children: [
35+
{
36+
element: <Rewrite to='challenge-management' />,
37+
route: '',
38+
},
39+
// Challenge Management Module
40+
{
41+
children: [
42+
{
43+
element: <ChallengeManagementPage />,
44+
id: 'challenge-management-page',
45+
route: '',
46+
},
47+
{
48+
element: <ManageUserPage />,
49+
id: 'manage-user',
50+
route: ':challengeId/manage-user',
51+
},
52+
],
53+
element: <ChallengeManagement />,
54+
id: 'challenge-management',
55+
route: 'challenge-management',
56+
},
57+
],
58+
domain: AppSubdomain.admin,
59+
element: <AdminApp />,
60+
id: toolTitle,
61+
rolesRequired: [UserRole.administrator],
62+
route: rootRoute,
63+
title: toolTitle,
64+
},
65+
]
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { FC, PropsWithChildren, useContext, useMemo } from 'react'
2+
import { Outlet, Routes } from 'react-router-dom'
3+
4+
import { routerContext, RouterContextData } from '~/libs/core'
5+
6+
import { Layout } from '../lib/components'
7+
import { ChallengeManagementContextProvider } from '../lib/contexts'
8+
import { adminRoutes } from '../admin-app.routes'
9+
10+
/**
11+
* The router outlet with layout.
12+
*/
13+
export const ChallengeManagement: FC & {
14+
Layout: FC<PropsWithChildren>
15+
} = () => {
16+
const childRoutes = useChildRoutes()
17+
18+
return (
19+
<ChallengeManagementContextProvider>
20+
<Outlet />
21+
<Routes>{childRoutes}</Routes>
22+
</ChallengeManagementContextProvider>
23+
)
24+
}
25+
26+
function useChildRoutes(): Array<JSX.Element> | undefined {
27+
const { getRouteElement }: RouterContextData = useContext(routerContext)
28+
const childRoutes = useMemo(
29+
() => adminRoutes[0].children
30+
?.find(r => r.id === 'challenge-management')
31+
?.children?.map(getRouteElement),
32+
[], // eslint-disable-line react-hooks/exhaustive-deps -- missing dependency: getRouteElement
33+
)
34+
return childRoutes
35+
}
36+
37+
/**
38+
* The outlet layout.
39+
*/
40+
ChallengeManagement.Layout = function ChallengeManagementLayout(
41+
props: PropsWithChildren,
42+
) {
43+
return <Layout>{props.children}</Layout>
44+
}
45+
46+
export default ChallengeManagement
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.loadingSpinnerContainer {
2+
position: relative;
3+
height: 100px;
4+
margin-top: -30px;
5+
6+
.spinner {
7+
background: none;
8+
}
9+
}
10+
11+
.noRecordFound {
12+
padding: 16px 16px 32px;
13+
text-align: center;
14+
}

0 commit comments

Comments
 (0)