diff --git a/src/app.tsx b/src/app.tsx
index 8f90578..17bbb82 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -24,11 +24,9 @@ function App() {
-
}>
-
diff --git a/src/auth/utility.ts b/src/auth/utility.ts
index 68c5ac6..d267c1d 100644
--- a/src/auth/utility.ts
+++ b/src/auth/utility.ts
@@ -56,7 +56,6 @@ export const setSession = (token: string | null) => {
localStorage.setItem(LOCAL_STORAGE.TOKEN, token)
axios.defaults.headers.common.Authorization = `${token}`
- console.log(axios.defaults.headers.common.Authorization, 'axios.defaults.headers.common.Authorization')
const { exp } = jwtDecode(token)
tokenExpired(exp)
} else {
diff --git a/src/component/button/back/back.tsx b/src/component/button/back/back.tsx
new file mode 100644
index 0000000..4c69d04
--- /dev/null
+++ b/src/component/button/back/back.tsx
@@ -0,0 +1,86 @@
+import { useState, useEffect, useRef, Fragment, MouseEvent } from 'react'
+import { m } from 'framer-motion'
+import { useNavigate, useLocation } from 'react-router-dom'
+import { ICON_NAME, useIcon } from 'hook'
+import { useSettingContext } from 'component/setting'
+import { Typography } from '@mui/material'
+import { useTheme } from '@mui/material/styles'
+import { KEY, LABEL, TYPOGRAPHY, VARIANT } from 'constant'
+import { SPopover, SBackIconButton } from 'component/button'
+
+const BackButton = () => {
+ const [open, setOpen] = useState(false)
+ const [anchorEl, setAnchorEl] = useState(null)
+
+ const { themeMode } = useSettingContext()
+ const { pathname } = useLocation()
+ const navigate = useNavigate()
+ const navRef = useRef(null)
+ const theme = useTheme()
+
+ const { Icon, iconSrc: backIconSrc } = useIcon(ICON_NAME.BACK)
+
+ const handleClick = (event: MouseEvent) => {
+ setAnchorEl(event.currentTarget)
+ navigate(-1)
+ }
+
+ useEffect(() => {
+ if (open) {
+ handleClose()
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [pathname])
+
+ useEffect(() => {
+ const appBarEl = Array.from(document.querySelectorAll('.MuiAppBar-root')) as HTMLElement[]
+
+ const styles = () => {
+ document.body.style.overflow = ''
+ document.body.style.padding = ''
+
+ appBarEl.forEach((elem) => {
+ elem.style.padding = ''
+ })
+ }
+
+ if (open) {
+ styles()
+ } else {
+ styles()
+ }
+ }, [open])
+
+ const handleOpen = (event: MouseEvent) => {
+ setAnchorEl(event.currentTarget)
+ setOpen(true)
+ }
+
+ const handleClose = () => {
+ setOpen(false)
+ }
+
+ return (
+
+
+
+
+
+
+
+ {LABEL.GO_BACK}
+
+
+
+
+ )
+}
+
+export default BackButton
diff --git a/src/component/button/back/index.ts b/src/component/button/back/index.ts
new file mode 100644
index 0000000..7b1ccf6
--- /dev/null
+++ b/src/component/button/back/index.ts
@@ -0,0 +1 @@
+export { default as BackButton } from './back'
diff --git a/src/component/button/index.ts b/src/component/button/index.ts
index 4cd34f4..885be90 100644
--- a/src/component/button/index.ts
+++ b/src/component/button/index.ts
@@ -1,2 +1,4 @@
export { default as Button } from './button'
+export { default as BackButton } from './back/back'
export { default as AnimatedButton } from './button-animated'
+export * from './style'
diff --git a/src/component/button/style.tsx b/src/component/button/style.tsx
new file mode 100644
index 0000000..a11d846
--- /dev/null
+++ b/src/component/button/style.tsx
@@ -0,0 +1,29 @@
+import { styled } from '@mui/material/styles'
+import { Popover, IconButton } from '@mui/material'
+
+export const SPopover = styled(Popover)(({ theme }) => ({
+ '& .MuiPaper-root': {
+ backgroundColor: 'transparent',
+ boxShadow: 'none',
+ size: '100%',
+ overflow: 'hidden',
+ borderRadius: 0
+ },
+ '& .MuiPopover-paper': {
+ overflow: 'hidden'
+ },
+ '& .MuiPopover-paper .MuiList-root': {
+ padding: '0px'
+ },
+ '& .MuiPopover-paper .MuiTypography-root': {
+ fontSize: '1rem'
+ },
+ boxShadow: 'none',
+ pointerEvents: 'none'
+}))
+
+export const SBackIconButton = styled(IconButton)(({ theme }) => ({
+ borderRadius: 2,
+ padding: 1,
+ marginBottom: 2
+}))
diff --git a/src/component/index.ts b/src/component/index.ts
index 7af293a..4e9d755 100644
--- a/src/component/index.ts
+++ b/src/component/index.ts
@@ -10,6 +10,7 @@ export { default as Paper } from './paper/paper'
export { default as Snackbar } from './snackbar/snackbar'
// button
export { default as Button } from './button/button'
+export { default as BackButton } from './button/back/back'
// typography
export { default as Typography } from './typography/typography'
// markdown
diff --git a/src/component/navbar/index.ts b/src/component/navbar/index.ts
index 9d6277d..24e3188 100644
--- a/src/component/navbar/index.ts
+++ b/src/component/navbar/index.ts
@@ -1,5 +1,6 @@
export { default as Navbar } from './navbar'
-export { default as AppNavBar } from './appbar'
+export { default as AppBar } from './appbar'
+export { default as AppNavBar } from './app-appbar'
export { default as AppFooter } from './footer'
export { default as NavDrawer } from './nav-drawer'
export { default as AccountPopover } from './account-popover'
diff --git a/src/component/navbar/nav-drawer.tsx b/src/component/navbar/nav-drawer.tsx
index ba8c7d2..0f8e08d 100644
--- a/src/component/navbar/nav-drawer.tsx
+++ b/src/component/navbar/nav-drawer.tsx
@@ -24,7 +24,7 @@ const NavDrawer = ({ open, onClose }: NavDrawerProps) => {
sx={{ pl: 0.5 }}
/>
-
+
Find a Bootcamp} />
@@ -53,7 +53,7 @@ const NavDrawer = ({ open, onClose }: NavDrawerProps) => {
-
+
Find a Course} />
diff --git a/src/config/icon-directory.ts b/src/config/icon-directory.ts
index e6b852b..75ceffe 100644
--- a/src/config/icon-directory.ts
+++ b/src/config/icon-directory.ts
@@ -20,14 +20,19 @@ function _getWebIcon(icon: string) {
const ICON_WEB = {
ALERT_OUTLINE: _getWebIcon('alert-triangle-outline'),
ARROW_FORWARD: _getWebIcon('arrow-ios-forward'),
+ BACK: _getWebIcon('arrow-ios-back-outline'),
CHEVRON_RIGHT: _getWebIcon('chevron-right-outline'),
CHEVRON_DOWN: _getWebIcon('chevron-down-outline'),
CLOSE: _getWebIcon('close-fill'),
CHECKMARK_CIRCLE: _getWebIcon('checkmark-circle-outline'),
+ CHECK_OUTLINE: _getWebIcon('checkmark-outline'),
+ CLOSE_OUTLINE: _getWebIcon('close-outline'),
CONTRAST_BOX: _getWebIcon('contrast-box'),
EDIT: _getWebIcon('edit-2-outline'),
ERROR_OUTLINE: _getWebIcon('alert-circle-outline'),
ERROR: _getWebIcon('alert-circle'),
+ PLUS: _getWebIcon('plus-outline'),
+ RETRACT: _getWebIcon('minus-outline'),
INFO: _getWebIcon('info'),
EYE_OFF: _getWebIcon('eye-off-outline'),
@@ -35,6 +40,8 @@ const ICON_WEB = {
FULLSCREEN: _getWebIcon('fullscreen'),
FULLSCREEN_EXIT: _getWebIcon('fullscreen-exit'),
+ GLOBE: _getWebIcon('globe-2-outline'),
+ PHONE: _getWebIcon('phone-outline'),
REFRESH: _getWebIcon('refresh'),
MODE_LIGHT: _getWebIcon('sun'),
@@ -69,7 +76,10 @@ export enum ICON_WEB_NAME {
// @web
ALERT_OUTLINE = 'ALERT_OUTLINE',
ARROW_FORWARD = 'ARROW_FORWARD',
+ BACK = 'BACK',
CHECKMARK_CIRCLE = 'CHECKMARK_CIRCLE',
+ CHECK_OUTLINE = 'CHECK_OUTLINE',
+ CLOSE_OUTLINE = 'CLOSE_OUTLINE',
CHEVRON_RIGHT = 'CHEVRON_RIGHT',
CHEVRON_DOWN = 'CHEVRON_DOWN',
CLOSE = 'CLOSE',
@@ -80,12 +90,15 @@ export enum ICON_WEB_NAME {
EYE_OFF = 'EYE_OFF',
EYE_HIDE = 'EYE_HIDE',
INFO = 'INFO',
-
+ PHONE = 'PHONE',
+ GLOBE = 'GLOBE',
MODE_LIGHT = 'MODE_LIGHT',
MODE_DARK = 'MODE_DARK',
FULLSCREEN = 'FULLSCREEN',
FULLSCREEN_EXIT = 'FULLSCREEN_EXIT',
+ PLUS = 'PLUS',
+ RETRACT = 'RETRACT',
REFRESH = 'REFRESH',
SAVE = 'SAVE',
diff --git a/src/config/layout.ts b/src/config/layout.ts
index 448da52..9fea9b9 100644
--- a/src/config/layout.ts
+++ b/src/config/layout.ts
@@ -1,3 +1,31 @@
+/**
+ * Layout configuration for the application
+ *
+ * Dimensions are in pixels
+ *
+ */
+export const HEADER = {
+ H_MOBILE: 64,
+ H_MAIN_DESKTOP: 88,
+ H_DASHBOARD_DESKTOP: 65,
+ H_DASHBOARD_DESKTOP_OFFSET: 92 - 32
+}
+
+export const FOOTER = {
+ H: 64
+}
+
+export const SPACING = {
+ XS: 4,
+ SM: 8,
+ MD: 16,
+ LG: 24,
+ XL: 32,
+ XXL: 40,
+ XXXL: 48,
+ DESKTOP: 80
+}
+
export const NAV = {
W_BASE: 260,
W_DASHBOARD: 300,
diff --git a/src/constant/aria.ts b/src/constant/aria.ts
index 59d587e..d1313ed 100644
--- a/src/constant/aria.ts
+++ b/src/constant/aria.ts
@@ -5,7 +5,8 @@ enum ARIA {
LAST_NAME = 'Last name',
TOGGLE_PASSWORD = 'toggle password visibility',
TABS = 'tabs',
- COMPANY_BADGE = 'company badge'
+ COMPANY_BADGE = 'company badge',
+ COURSE_TABLE = 'course table'
}
export default ARIA
diff --git a/src/constant/index.ts b/src/constant/index.ts
index d4637c2..1da3d85 100644
--- a/src/constant/index.ts
+++ b/src/constant/index.ts
@@ -12,7 +12,6 @@ export { default as MENU_POPOVER_ARROW } from './menu-popover-arrow'
export { default as TITLE } from './title'
export { default as ARIA } from './aria'
export { BUTTON } from './button'
-export * from './typography'
export * from './size'
export * from './color'
export * from './component'
diff --git a/src/constant/label.ts b/src/constant/label.ts
index 0743237..81f5b19 100644
--- a/src/constant/label.ts
+++ b/src/constant/label.ts
@@ -1,6 +1,7 @@
import { KEY } from 'constant'
const LABEL = {
+ GO_BACK: 'Go Back',
LOG_IN: 'Log In',
LOG_OUT: 'Log Out',
DISPLAY_SETTINGS: 'Display Settings',
@@ -12,20 +13,31 @@ const LABEL = {
},
REGISTER: 'Register',
RESET_PASSWORD: 'Reset Password',
+ COURSE_COVERED: 'Course certifications covered',
HOME: 'Home',
-
+ LOCATION: 'Location',
+ CAREER: 'Careers',
+ CONTACT: 'Contact',
ALREADY_MEMBER: `Already a member? `,
NOT_A_MEMBER: `Not a member yet? `,
LOGIN_Sub: 'Log in here ',
REGISTER_Sub: 'Register for free',
FORGOT_PASSWORD: 'Forgot password?',
-
+ RATING: 'Rating',
SELECT_ROLE: 'Select your role',
-
+ WEBSITE: 'Website',
+ VISIT_WEBSITE: 'Visit Website',
ADMIN: 'Admin',
STUDENT: 'Student',
TRAINER: 'Trainer',
+ TITLE: 'Title',
+ DESCRIPTION: 'Description',
+ DURATION: 'Duration',
+ COST: 'Cost',
+ SKILL_REQUIRED: 'Skill Required',
+ SCHOLARSHIP: 'Scholarship',
+
BOOTCAMP_PAGE_TITLE: 'Worldclass Bootcamps Worldwide',
COURSE_PAGE_TITLE: 'World Class Courses',
diff --git a/src/constant/placeholder.ts b/src/constant/placeholder.ts
index c815ec8..a17ccc9 100644
--- a/src/constant/placeholder.ts
+++ b/src/constant/placeholder.ts
@@ -14,6 +14,9 @@ enum PLACEHOLDER {
NO_DURATION = 'No duration specified',
NO_TUITION = 'No tuition specified',
NO_MINIMUM_SKILL = 'No minimum skill required',
+ NO_COURSE_AVAILABLE = 'No course available',
+ NO_LOCATION = 'No location provided',
+ NO_CAREER = 'No career provided',
// @bootcamp search form
MILES_FROM = 'Miles From',
diff --git a/src/constant/routing/routing.ts b/src/constant/routing/routing.ts
index 01f9371..2a3926a 100644
--- a/src/constant/routing/routing.ts
+++ b/src/constant/routing/routing.ts
@@ -1,6 +1,8 @@
enum ROUTING {
ROOT = '/',
+ ALL = 'all',
ID = ':id',
+ VIEW = 'view',
DASHBOARD = 'dashboard',
// :bootcamp
BOOTCAMP = 'bootcamp',
diff --git a/src/constant/typography.ts b/src/constant/typography.ts
deleted file mode 100644
index 5f9ab5d..0000000
--- a/src/constant/typography.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-export enum TYPOGRAPHY {
- H0 = 'h0',
- H1 = 'h1',
- H2 = 'h2',
- H3 = 'h3',
- H4 = 'h4',
- H5 = 'h5',
- H6 = 'h6',
- H7 = 'h7',
- BODY1 = 'body1',
- BODY2 = 'body2',
- SUBTITLE1 = 'subtitle1',
- SUBTITLE2 = 'subtitle2',
- OVERLINE = 'overline',
- CAPTION = 'caption',
- BUTTON = 'button',
- PARAGRAPH = 'paragraph'
-}
-
-export enum FONTWEIGHT {
- NORMAL = 'normal',
- LIGHT = 'light',
- REGULAR = 'regular',
- MEDIUM = 'medium',
- BOLD = 'bold',
- BLACK = 'black'
-}
diff --git a/src/constant/variant.ts b/src/constant/variant.ts
index c9e7f7c..4d57e68 100644
--- a/src/constant/variant.ts
+++ b/src/constant/variant.ts
@@ -4,21 +4,6 @@ export enum BUTTON_VARIANT {
TEXT = 'text'
}
-export enum TYPOGRAPHY_VARIANT {
- H1 = 'h1',
- H2 = 'h2',
- H3 = 'h3',
- H4 = 'h4',
- H5 = 'h5',
- H6 = 'h6',
- SUBTITLE1 = 'subtitle1',
- SUBTITLE2 = 'subtitle2',
- BODY1 = 'body1',
- BODY2 = 'body2',
- CAPTION = 'caption',
- OVERLINE = 'overline'
-}
-
export enum SKELETON_VARIANT {
RECTANGULAR = 'rectangular',
CIRCULAR = 'circular',
@@ -31,3 +16,34 @@ export enum VARIANT {
OUTLINED = 'outlined',
COVER = 'cover'
}
+
+export enum TYPOGRAPHY {
+ H0 = 'h0',
+ H1 = 'h1',
+ H2 = 'h2',
+ H3 = 'h3',
+ H4 = 'h4',
+ H5 = 'h5',
+ H6 = 'h6',
+ H7 = 'h7',
+ BODY1 = 'body1',
+ BODY2 = 'body2',
+ SUBTITLE1 = 'subtitle1',
+ SUBTITLE2 = 'subtitle2',
+ OVERLINE0 = 'overline0',
+ OVERLINE = 'overline',
+ OVERLINE1 = 'overline1',
+ OVERLINE2 = 'overline2',
+ CAPTION = 'caption',
+ BUTTON = 'button',
+ PARAGRAPH = 'paragraph'
+}
+
+export enum FONTWEIGHT {
+ NORMAL = 'normal',
+ LIGHT = 'light',
+ REGULAR = 'regular',
+ MEDIUM = 'medium',
+ BOLD = 'bold',
+ BLACK = 'black'
+}
diff --git a/src/hook/use-icon.tsx b/src/hook/use-icon.tsx
index aa3d275..4cdf71d 100644
--- a/src/hook/use-icon.tsx
+++ b/src/hook/use-icon.tsx
@@ -8,7 +8,7 @@
*
* @properties icon - The Icon component to render.
*
- * @param {ICON_NAME[]} iconName - The name of the icon to retrieve.
+ * @param iconName - The name of the icon to retrieve.
* @returns {Object} - An object containing the Icon component and the icon source.
*/
import { FC, useState, useEffect } from 'react'
diff --git a/src/page/app/app-layout.tsx b/src/page/app/app-layout.tsx
new file mode 100644
index 0000000..18b7100
--- /dev/null
+++ b/src/page/app/app-layout.tsx
@@ -0,0 +1,19 @@
+import { Fragment } from 'react'
+import { Outlet } from 'react-router-dom'
+import { AppNavBar, AppFooter } from 'component/navbar'
+import withRoot from 'withroot'
+import Main from './main'
+
+function AppLayout() {
+ return (
+
+
+
+
+
+
+
+ )
+}
+
+export default withRoot(AppLayout)
diff --git a/src/page/app/index.ts b/src/page/app/index.ts
new file mode 100644
index 0000000..17eecc6
--- /dev/null
+++ b/src/page/app/index.ts
@@ -0,0 +1 @@
+export { default as AppLayout } from './app-layout'
diff --git a/src/page/app/main.tsx b/src/page/app/main.tsx
new file mode 100644
index 0000000..f3323b2
--- /dev/null
+++ b/src/page/app/main.tsx
@@ -0,0 +1,27 @@
+import { FC, ReactNode } from 'react'
+import { Box } from '@mui/material'
+import { HEADER, SPACING } from 'config/layout'
+
+interface MainProps {
+ children: ReactNode
+ isDesktop: boolean
+}
+
+const Main: FC = ({ children, isDesktop }) => {
+ return (
+
+ {children}
+
+ )
+}
+
+export default Main
diff --git a/src/page/bootcamp/bootcamp.tsx b/src/page/bootcamp/bootcamp.tsx
index 18168e0..eddb46f 100644
--- a/src/page/bootcamp/bootcamp.tsx
+++ b/src/page/bootcamp/bootcamp.tsx
@@ -8,7 +8,7 @@ import { MotionLazyContainer } from 'component/motion'
import { SkeletonLoader } from 'component/skeleton'
import { Typography } from 'component/typography'
import { ASSET } from 'config'
-import { LABEL, PLACEHOLDER } from 'constant'
+import { FLEX, KEY, LABEL, PLACEHOLDER } from 'constant'
function Bootcamp() {
const [currentPage, setCurrentPage] = useState(1)
@@ -29,11 +29,11 @@ function Bootcamp() {
@@ -48,7 +48,7 @@ function Bootcamp() {
{
+ return
+}
+
+export default BootcampView
diff --git a/src/page/course/course.tsx b/src/page/course/course.tsx
index 3022637..971faf1 100644
--- a/src/page/course/course.tsx
+++ b/src/page/course/course.tsx
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
import { m } from 'framer-motion'
-import { useGetAllBootcampQuery } from 'store/slice'
+import { useGetAllBootcampQuery, useGetAllCourseQuery } from 'store/slice'
import { MotionLazyContainer } from 'component/motion'
import { Box, Grid, Pagination } from '@mui/material'
import { CourseCard } from 'section/course'
@@ -13,7 +13,7 @@ import { LABEL } from 'constant'
const Course = () => {
const [currentPage, setCurrentPage] = useState(1)
- const { data, error, isLoading, refetch } = useGetAllBootcampQuery()
+ const { data, error, isLoading, refetch } = useGetAllCourseQuery()
const handlePageChange = (event: any, value: any) => {
setCurrentPage(value)
@@ -43,7 +43,7 @@ const Course = () => {
{
{
return (
+
+
)
}
diff --git a/src/page/index.ts b/src/page/index.ts
index 07a552f..bf981bd 100644
--- a/src/page/index.ts
+++ b/src/page/index.ts
@@ -1,5 +1,6 @@
export { default as Home } from './home/home'
export { default as Fallback } from './fallback/fallback'
+export { default as AppLayout } from './app/app-layout'
// :auth
export { default as LogIn } from './auth/log-in/log-in'
export { default as Register } from './auth/register/register'
diff --git a/src/route/element.tsx b/src/route/element.tsx
index b93f493..1ec5f0d 100644
--- a/src/route/element.tsx
+++ b/src/route/element.tsx
@@ -22,6 +22,7 @@ export const RegisterPage = Loadable(() => import('page/auth/register/register')
export const UserAccountPage = Loadable(() => import('page/auth/account/user-account'))
// bootcamp
export const BootcampPage = Loadable(() => import('page/bootcamp/bootcamp'))
+export const BootcampViewPage = Loadable(() => import('page/bootcamp/view/view'))
// course
export const CoursePage = Loadable(() => import('page/course/course'))
// fallback
diff --git a/src/route/index.tsx b/src/route/index.tsx
index e754518..c6c4dae 100644
--- a/src/route/index.tsx
+++ b/src/route/index.tsx
@@ -1,6 +1,7 @@
import { CODE } from 'constant'
import { Navigate, useRoutes } from 'react-router-dom'
import { GuestGuard, AuthGuard } from 'auth'
+import { AppLayout } from 'page'
import {
HomePage,
DashboardPage,
@@ -10,6 +11,7 @@ import {
UserAccountPage,
// :bootcamp
BootcampPage,
+ BootcampViewPage,
// :course
CoursePage,
FallbackPage
@@ -21,16 +23,22 @@ import { FALLBACK } from 'constant'
const { ACCOUNT, AUTH, BOOTCAMP, COURSE, LOG_IN, REGISTER, RESET_PASSWORD } = ROUTING
function Router() {
+ /**
+ * @baseUrl {http://thecodecoachprojct.com}
+ * @path {baseUrl}/api/{apiVer}
+ */
return useRoutes([
{
path: ROUTING.ROOT,
element:
},
{
- // @auth
+ // /auth
path: AUTH,
+ element: ,
children: [
{
+ // /auth/log-in
path: LOG_IN,
element: (
@@ -39,10 +47,12 @@ function Router() {
)
},
{
+ // /auth/register
path: REGISTER,
element:
},
{
+ // /auth/account
path: ACCOUNT,
element: (
@@ -51,55 +61,119 @@ function Router() {
)
},
{
+ // /auth/reset-password
path: RESET_PASSWORD
// element: ,
}
]
},
{
+ // /bootcamp
path: BOOTCAMP,
- element: ,
+ element: ,
children: [
{
- path: ROUTING.ID
- // element: ,
+ // /bootcamp/all
+ path: ROUTING.ALL,
+ element:
+ },
+ {
+ // /bootcamp/:id
+ path: ':id/view',
+ element:
+ // children: [
+ // {
+ // // /:id/view
+ // path: ROUTING.VIEW,
+ // element:
+ // }
+ // ]
}
]
},
{
+ // /course
path: COURSE,
- element: ,
+ element: ,
children: [
{
- path: ROUTING.ID
- // element: ,
+ // /course/all
+ path: ROUTING.ALL,
+ element:
+ },
+ {
+ // /course/:id/view
+ path: ROUTING.ID,
+ children: [
+ {
+ // /course/:id/view
+ path: ROUTING.VIEW,
+ element:
+ }
+ ]
}
]
},
// @fallback
{
path: FallbackPath.NOT_AUTHORIZED,
- element:
+ element: ,
+ children: [
+ {
+ path: FallbackPath.NOT_AUTHORIZED,
+ element:
+ }
+ ]
},
{
path: FallbackPath.FORBIDDEN,
- element:
+ element: ,
+ children: [
+ {
+ path: FallbackPath.FORBIDDEN,
+ element:
+ }
+ ]
},
{
path: FallbackPath.NOT_FOUND,
- element:
+ element: ,
+ children: [
+ {
+ path: FallbackPath.NOT_FOUND,
+ element:
+ }
+ ]
},
{
path: FallbackPath.BAD_REQUEST,
- element:
+ element: ,
+ children: [
+ {
+ path: FallbackPath.BAD_REQUEST,
+ element:
+ }
+ ]
},
{
path: FallbackPath.UNPROCESSABLE_ENTITY,
- element:
+ element: ,
+ children: [
+ {
+ path: FallbackPath.UNPROCESSABLE_ENTITY,
+ element:
+ }
+ ]
},
{
path: FallbackPath.SERVER_ERROR,
- element:
+ element: ,
+ children: [
+ {
+ path: FallbackPath.SERVER_ERROR,
+ element:
+ }
+ ]
},
{ path: '*', element: }
])
diff --git a/src/route/path.ts b/src/route/path.ts
index b9bcdde..a2424a9 100644
--- a/src/route/path.ts
+++ b/src/route/path.ts
@@ -14,6 +14,7 @@ export class ServerPath {
static BOOTCAMP_ID = (bootcampId: string) => conNex(ROUTING.BOOTCAMP, bootcampId)
static COURSE = ROUTING.COURSE
static COURSE_ID = (courseId: string) => conNex(ROUTING.COURSE, courseId)
+ static COURSE_BY_BOOTCAMP = (bootcampId: string) => conNex(ROUTING.BOOTCAMP, bootcampId, ROUTING.COURSE)
static AUTH_LOG_IN = conNex(ROUTING.AUTH, ROUTING.LOG_IN)
static AUTH_LOG_OUT = conNex(ROUTING.AUTH, ROUTING.LOG_OUT)
static AUTH_REGISTER = conNex(ROUTING.AUTH, ROUTING.REGISTER)
@@ -49,8 +50,8 @@ export class BootcampPath {
throw new Error(RESPONSE.error.NotInstance)
}
- static BOOTCAMP = ROUTING.BOOTCAMP
- static BOOTCAMP_ID = conNex(ROUTING.BOOTCAMP, ROUTING.ID)
+ static BOOTCAMP = conNex(ROUTING.BOOTCAMP, ROUTING.ALL)
+ static BOOTCAMP_ID = (bootcampId: string | undefined) => conNex(ROUTING.BOOTCAMP, bootcampId, ROUTING.VIEW)
}
export class FallbackPath {
diff --git a/src/section/bootcamp/bootcamp-card.tsx b/src/section/bootcamp/bootcamp-card.tsx
index f1ebcdc..d27e13c 100644
--- a/src/section/bootcamp/bootcamp-card.tsx
+++ b/src/section/bootcamp/bootcamp-card.tsx
@@ -1,8 +1,10 @@
import { FC } from 'react'
+import { Link } from 'react-router-dom'
import { Box, CardContent, CardMedia, Grid, Typography, Rating } from '@mui/material'
import { GSContainerGrid, SBadgeHeader } from 'theme/style'
import { BootcampCareer } from 'section/bootcamp'
-import { ARIA, COMPONENT, FLEX, KEY, TYPOGRAPHY_VARIANT, VARIANT } from 'constant'
+import { ARIA, COMPONENT, FLEX, KEY, TYPOGRAPHY, VARIANT } from 'constant'
+import { BootcampPath } from 'route/path'
import { badgeLocation, photoLocation } from 'util/asset-loc'
const BootcampCard: FC = ({ bootcamp }) => {
@@ -11,8 +13,8 @@ const BootcampCard: FC = ({ bootcamp }) => {
= ({ bootcamp }) => {
-
- {bootcamp?.name}
-
+
+
+ {bootcamp?.name}
+
+
= ({ bootcamp }) => {
}
+ avatar={}
sx={{
p: 0,
py: 2
}}
/>
- {bootcamp.description}
+ {bootcamp?.description}
-
+
{bootcamp?.location?.city}, {bootcamp?.location?.state}
diff --git a/src/section/bootcamp/bootcamp-career.tsx b/src/section/bootcamp/bootcamp-career.tsx
index 26902b7..602cd09 100644
--- a/src/section/bootcamp/bootcamp-career.tsx
+++ b/src/section/bootcamp/bootcamp-career.tsx
@@ -2,6 +2,7 @@ import { FC } from 'react'
import { Chip } from '@mui/material'
import { SScrollBox } from 'theme/style'
import { SIZE, VARIANT } from 'constant'
+import { ChipPropsVariantOverrides } from '@mui/material'
const BootcampCareer: FC = ({ bootcamp }) => {
return (
diff --git a/src/section/bootcamp/index.ts b/src/section/bootcamp/index.ts
index 6ae88dc..eda532f 100644
--- a/src/section/bootcamp/index.ts
+++ b/src/section/bootcamp/index.ts
@@ -2,3 +2,5 @@ export { default as Bootcamp } from './bootcamp'
export { default as BootcampSearch } from './bootcamp-search'
export { default as BootcampCard } from './bootcamp-card'
export { default as BootcampCareer } from './bootcamp-career'
+export { default as BootcampViewSection } from './view/view'
+export * from './style'
diff --git a/src/section/bootcamp/style.tsx b/src/section/bootcamp/style.tsx
new file mode 100644
index 0000000..1551e8b
--- /dev/null
+++ b/src/section/bootcamp/style.tsx
@@ -0,0 +1,40 @@
+import { styled } from '@mui/material/styles'
+import { m } from 'framer-motion'
+import { TableRow, TableContainer, TableCell, Collapse } from '@mui/material'
+
+export const SRoot = styled(m.div)({
+ maxWidth: '100vw',
+ margin: '0 auto'
+})
+
+export const STableContainer = styled(TableContainer)({
+ boxShadow: '0 0 20px rgba(0, 0, 0, 0.1)',
+ borderRadius: 2,
+ overflow: 'hidden'
+})
+
+export const STableHeader = styled(TableRow)(({ theme }) => ({
+ backgroundColor: theme.palette.secondary.main,
+ color: theme.palette.common.white,
+ paddingRight: '1rem',
+ paddingLeft: '1rem'
+}))
+
+export const STableRow = styled(TableRow)(({ theme }) => ({
+ '&:nth-of-type(odd)': {
+ backgroundColor: theme.palette.action.hover
+ }
+}))
+
+export const SCollapse = styled(Collapse)(({ theme }) => ({
+ '& .MuiTableCell-root': {
+ padding: '1rem',
+ backgroundColor: 'transparent'
+ }
+}))
+
+export const STableHeadCell = styled(TableCell)(({ theme }) => ({
+ fontWeight: 'bold',
+ fontSize: '1rem',
+ backgroundColor: 'transparent'
+}))
diff --git a/src/section/bootcamp/view/course-row.tsx b/src/section/bootcamp/view/course-row.tsx
new file mode 100644
index 0000000..aa3f221
--- /dev/null
+++ b/src/section/bootcamp/view/course-row.tsx
@@ -0,0 +1,49 @@
+import { Fragment, FC, useState } from 'react'
+import { TableRow, TableCell, Box, IconButton, Typography } from '@mui/material'
+import { STableRow, SCollapse } from 'section/bootcamp'
+import { useIcon } from 'hook'
+import { ICON_WEB_NAME } from 'config'
+import { KEY, TYPOGRAPHY } from 'constant'
+import { capitalize } from 'util/format'
+
+interface CourseRowProps {
+ row: any
+}
+
+const CourseRow: FC = ({ row }) => {
+ const [open, setOpen] = useState(false)
+
+ const { Icon: WebIcon, iconSrc: checkSrc } = useIcon(ICON_WEB_NAME.CHECK_OUTLINE)
+ const { Icon, iconSrc: crossSrc } = useIcon(ICON_WEB_NAME.CLOSE_OUTLINE)
+ const { Icon: ExpandIcon, iconSrc: expandSrc } = useIcon(ICON_WEB_NAME.PLUS)
+ const { Icon: RetractIcon, iconSrc: retractSrc } = useIcon(ICON_WEB_NAME.RETRACT)
+ return (
+
+
+ {row?.title}
+ {row?.duration} weeks
+ ${row?.tuition}
+ {capitalize(row?.minimumSkill)}
+
+ {row?.scholarshipAvailable ? : }
+
+
+
+ setOpen(!open)}>{open ? : }
+
+
+
+
+
+
+
+ {row?.description}
+
+
+
+
+
+ )
+}
+
+export default CourseRow
diff --git a/src/section/bootcamp/view/course-table.tsx b/src/section/bootcamp/view/course-table.tsx
new file mode 100644
index 0000000..bf4fc19
--- /dev/null
+++ b/src/section/bootcamp/view/course-table.tsx
@@ -0,0 +1,37 @@
+import { FC, Fragment, useState } from 'react'
+import { Table, TableBody, TableCell, TableHead } from '@mui/material'
+import { SRoot, STableContainer, STableHeader } from 'section/bootcamp'
+import { ARIA, KEY, LABEL } from 'constant'
+import CourseRow from './course-row'
+
+interface CourseTableProps {
+ course: any
+}
+
+const CourseTable: FC = ({ course }) => {
+ return (
+
+
+
+
+
+ {LABEL.TITLE}
+ {LABEL.DURATION}
+ {LABEL.COST}
+ {LABEL.SKILL_REQUIRED}
+ {LABEL.SCHOLARSHIP}
+
+
+
+
+ {course?.map((row: any, index: any) => (
+
+ ))}
+
+
+
+
+ )
+}
+
+export default CourseTable
diff --git a/src/section/bootcamp/view/index.ts b/src/section/bootcamp/view/index.ts
new file mode 100644
index 0000000..26f050a
--- /dev/null
+++ b/src/section/bootcamp/view/index.ts
@@ -0,0 +1,3 @@
+export { default as BootcampViewSection } from './view'
+export { default as CourseTable } from './course-table'
+export { default as CourseRow } from './course-row'
diff --git a/src/section/bootcamp/view/view.tsx b/src/section/bootcamp/view/view.tsx
new file mode 100644
index 0000000..8fc9661
--- /dev/null
+++ b/src/section/bootcamp/view/view.tsx
@@ -0,0 +1,250 @@
+import { FC, useEffect } from 'react'
+import { useParams, Link } from 'react-router-dom'
+import { ICON_NAME, useIcon } from 'hook'
+import { useGetBootcampQuery, useGetAllCourseByBootcampQuery } from 'store/slice'
+import {
+ Box,
+ Grid,
+ Typography,
+ Container,
+ CardMedia,
+ Chip,
+ CardContent,
+ Divider,
+ Accordion,
+ AccordionSummary,
+ AccordionDetails,
+ List,
+ ListItem,
+ ListItemText
+} from '@mui/material'
+import { BackButton } from 'component'
+import { GSContainerGrid, SSpanBox } from 'theme/style'
+import { MotionLazyContainer } from 'component/motion'
+import { ICON_WEB_NAME } from 'config'
+import { FLEX, KEY, LABEL, PLACEHOLDER, TYPOGRAPHY, COMPONENT, ARIA, VARIANT, SIZE } from 'constant'
+import { badgeLocation, photoLocation } from 'util/asset-loc'
+import CourseTable from './course-table'
+
+interface BootcampViewSectionProps {
+ bootcamp?: Bootcamp
+}
+
+const BootcampViewSection: FC = () => {
+ const { id } = useParams<{ id: string }>()
+ const { data: bootcamp, error, isLoading } = useGetBootcampQuery(id)
+
+ const {
+ _id,
+ name,
+ description,
+ badge,
+ photo,
+ location,
+ careers,
+ averageRating,
+ user,
+ duration,
+ phone,
+ website,
+ slug,
+ housing,
+ jobAssistance,
+ jobGuarantee
+ } = bootcamp?.data || {}
+
+ const courseQueryResult = useGetAllCourseByBootcampQuery(_id)
+
+ const { data: course, error: courseError, isLoading: courseLoading } = courseQueryResult || { data: null, error: null, isLoading: false }
+
+ const { Icon: PhoneIcon, iconSrc: phoneSrc } = useIcon(ICON_WEB_NAME.PHONE)
+ const { Icon: RightIcon, iconSrc: rightSrc } = useIcon(ICON_WEB_NAME.CHEVRON_RIGHT)
+ const { Icon: GlobeIcon, iconSrc: globeSrc } = useIcon(ICON_WEB_NAME.GLOBE)
+ const { Icon, iconSrc: crossSrc } = useIcon(ICON_WEB_NAME.CLOSE_OUTLINE)
+ const { iconSrc: checkSrc } = useIcon(ICON_WEB_NAME.CHECK_OUTLINE)
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {name}
+
+ {description}
+ {slug && (
+
+
+ Tags:
+
+
+ {slug || '5'}
+
+
+ )}
+
+
+
+
+
+
+ Duration:
+
+ {duration}
+
+
+
+
+
+ Housing:
+
+ {housing ? : }
+
+
+
+
+
+ Job Assistance:
+
+ {jobAssistance ? : }
+
+
+
+
+
+ Job Guarantee:
+
+ {jobGuarantee ? : }
+
+
+
+
+
+
+
+ {user?.organization || 'TCCP'}
+
+
+
+
+
+
+
+ {LABEL.LOCATION}
+
+
+ {location?.city}, {location?.state}
+
+
+
+
+ {LABEL.CAREER}
+
+
+ {careers?.map((career: string, index: any) => (
+ // chip for each career
+ {career}}
+ size={SIZE.SMALL}
+ sx={{
+ margin: 0.5
+ }}
+ />
+ )) || PLACEHOLDER.NO_CAREER}
+
+
+
+ {LABEL.RATING}
+
+ {averageRating || '5'}
+
+
+
+
+
+ {LABEL.CONTACT}
+
+
+ {phone || '0'}
+
+
+
+
+ {LABEL.WEBSITE}
+
+
+
+
+
+
+ {LABEL.VISIT_WEBSITE}
+
+
+
+
+
+
+
+
+
+
+
+
+ {LABEL.COURSE_COVERED}
+
+
+ {course?.data?.length > 0 ? (
+
+ ) : (
+ {PLACEHOLDER.NO_COURSE_AVAILABLE}
+ )}
+
+
+
+
+
+ )
+}
+
+export default BootcampViewSection
diff --git a/src/section/course/course-card.tsx b/src/section/course/course-card.tsx
index ed177d9..d4641e5 100644
--- a/src/section/course/course-card.tsx
+++ b/src/section/course/course-card.tsx
@@ -1,6 +1,7 @@
import { FC, useEffect } from 'react'
import { useSelector } from 'react-redux'
import { dispatch } from 'store'
+import { useParams } from 'react-router-dom'
import { useGetBootcampQuery } from 'store/slice'
import { Box, CardContent, CardMedia, Chip, Grid, Typography, Rating } from '@mui/material'
import { ServerPath } from 'route/path'
@@ -15,7 +16,8 @@ interface CourseCardProps {
const CourseCard: FC = ({ course }) => {
const { data, error, isLoading, refetch } = useGetBootcampQuery(course?.bootcamp?._id)
- const { data: bootcamp } = data
+
+ const { _id, badge } = data?.data || {}
let minimumSkill = ''
@@ -55,7 +57,7 @@ const CourseCard: FC = ({ course }) => {
= ({ course }) => {
{course.description.charAt(0).toUpperCase() + course.description.slice(1)}
- {course?.bootcamp?.name.charAt(0).toUpperCase() + course?.bootcamp?.name.slice(1) || PLACEHOLDER.BOOTCAMP_NAME}
+ {(course && course?.bootcamp?.name.charAt(0).toUpperCase()) + course?.bootcamp?.name.slice(1) || PLACEHOLDER.BOOTCAMP_NAME}
diff --git a/src/section/dashboard/dashboard-bootcamp-rd.tsx b/src/section/dashboard/dashboard-bootcamp-rd.tsx
index 786cb48..e4522dd 100644
--- a/src/section/dashboard/dashboard-bootcamp-rd.tsx
+++ b/src/section/dashboard/dashboard-bootcamp-rd.tsx
@@ -4,7 +4,7 @@ import { Box, Grid, Divider, Tab, Tabs, Skeleton } from '@mui/material'
import { SScrollGrid, GSBox, GSDividerBox, GSRundownContainer } from 'theme/style'
import { useGetAllBootcampQuery } from 'store/slice'
import { Button, Typography } from 'component'
-import { BUTTON, LABEL, KEY, COLOR, COMPONENT, BUTTON_VARIANT, SIZE, VARIANT, FLEX, ARIA, TYPOGRAPHY_VARIANT, FONTWEIGHT } from 'constant'
+import { BUTTON, LABEL, KEY, COLOR, COMPONENT, BUTTON_VARIANT, SIZE, VARIANT, FLEX, ARIA, TYPOGRAPHY, FONTWEIGHT } from 'constant'
import { CATEGORY } from 'config'
import BootcampTile from './dashboard-bootcamp-tile'
import { AuthPath } from 'route/path'
@@ -33,7 +33,7 @@ function DashboardBootcampRundown() {
-
+
{LABEL.NEW_BOOTCAMPS}
diff --git a/src/section/dashboard/dashboard-bootcamp-tile.tsx b/src/section/dashboard/dashboard-bootcamp-tile.tsx
index d238dfc..6698f74 100644
--- a/src/section/dashboard/dashboard-bootcamp-tile.tsx
+++ b/src/section/dashboard/dashboard-bootcamp-tile.tsx
@@ -1,28 +1,30 @@
import { FC } from 'react'
-import { Card, CardContent, CardMedia, Typography, Box, Chip } from '@mui/material'
-import { useTheme, styled } from '@mui/material/styles'
-import { SScrollBox, SBadgeHeader, GSBadgeImg } from 'theme/style'
+import { CardContent, CardMedia, Typography, Box } from '@mui/material'
+import { useTheme } from '@mui/material/styles'
+import { SBadgeHeader, GSBadgeImg } from 'theme/style'
import { photoLocation, badgeLocation } from 'util/asset-loc'
-import { COMPONENT, FLEX, PLACEHOLDER, TYPOGRAPHY_VARIANT, VARIANT, SIZE } from 'constant'
+import { COMPONENT, FLEX, PLACEHOLDER, TYPOGRAPHY } from 'constant'
import { OPhotoCardMedia, SBootcampCard } from './option'
import { BootcampCareer } from 'section/bootcamp'
const BootcampTile: FC = ({ bootcamp }) => {
const theme = useTheme()
+ const { badge, _id, photo } = bootcamp || {}
+
return (
- } />
-
+ } />
+
-
- {bootcamp.name}
+
+ {bootcamp?.name}
-
- {bootcamp.location ? bootcamp.location.city + ', ' + bootcamp.location.country : PLACEHOLDER.NO_LOCATION}
+
+ {bootcamp?.location ? bootcamp?.location?.city + ', ' + bootcamp?.location?.country : PLACEHOLDER.NO_LOCATION}
= ({ bootcamp }) => {
justifyContent: FLEX.FLEX_END,
mt: 6
}}>
- {bootcamp.careers && bootcamp.careers.length > 0 ? (
+ {bootcamp?.careers && bootcamp?.careers.length > 0 ? (
) : (
-
+
)}
diff --git a/src/section/index.ts b/src/section/index.ts
index 693c483..7ad7671 100644
--- a/src/section/index.ts
+++ b/src/section/index.ts
@@ -1 +1,2 @@
export * from 'section/course'
+export * from 'section/bootcamp'
diff --git a/src/store/slice/course/endpoint.ts b/src/store/slice/course/endpoint.ts
index 392757c..da76467 100644
--- a/src/store/slice/course/endpoint.ts
+++ b/src/store/slice/course/endpoint.ts
@@ -19,6 +19,13 @@ export const courseSlice = apiSlice.injectEndpoints({
method: GET
})
}),
+ getAllCourseByBootcamp: builder.query({
+ query: (id) => ({
+ url: ServerPath.COURSE_BY_BOOTCAMP(id),
+ method: GET
+ }),
+ keepUnusedDataFor: 5
+ }),
createCourse: builder.mutation({
query: (data: any) => ({
url: ServerPath.COURSE,
@@ -42,4 +49,11 @@ export const courseSlice = apiSlice.injectEndpoints({
})
})
-export const { useGetAllCourseQuery, useGetCourseQuery, useCreateCourseMutation, useUpdateCourseMutation, useDeleteCourseMutation } = courseSlice
+export const {
+ useGetAllCourseQuery,
+ useGetCourseQuery,
+ useGetAllCourseByBootcampQuery,
+ useCreateCourseMutation,
+ useUpdateCourseMutation,
+ useDeleteCourseMutation
+} = courseSlice
diff --git a/src/store/store.ts b/src/store/store.ts
index 4a4ae8e..0672feb 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -11,9 +11,8 @@ const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
- serializableCheck: {
- ignoredActions: [PERSIST, REHYDRATE]
- }
+ serializableCheck: GLOBAL.APP_ENV === KEY.PRODUCTION ? undefined : false,
+ immutableCheck: false
}).concat(apiSlice.middleware),
devTools: GLOBAL.APP_ENV !== KEY.PRODUCTION
diff --git a/src/theme/palette.ts b/src/theme/palette.ts
index 395b818..10d818b 100644
--- a/src/theme/palette.ts
+++ b/src/theme/palette.ts
@@ -38,21 +38,23 @@ const ERROR = {
contrastText: '#F2EED8'
}
+const ACTION = {
+ hover: alpha(GREY[500], 0.08),
+ selected: alpha(GREY[300], 0.16),
+ disabled: alpha(GREY[300], 0.8),
+ disabledBackground: alpha(GREY[400], 0.24),
+ focus: alpha(GREY[500], 0.24),
+ hoverOpacity: 0.08,
+ disabledOpacity: 0.48
+}
+
const COMMON = {
common: COMMON_COLOR,
primary: PRIMARY,
error: ERROR,
grey: GREY,
divider: alpha(GREY[500], 0.24),
- action: {
- hover: alpha(GREY[500], 0.08),
- selected: alpha(GREY[300], 0.16),
- disabled: alpha(GREY[300], 0.8),
- disabledBackground: alpha(GREY[400], 0.24),
- focus: alpha(GREY[500], 0.24),
- hoverOpacity: 0.08,
- disabledOpacity: 0.48
- },
+ action: ACTION,
background: BRAND.background
}
diff --git a/src/theme/style/main.ts b/src/theme/style/main.ts
index fefbdb5..369f6b1 100644
--- a/src/theme/style/main.ts
+++ b/src/theme/style/main.ts
@@ -24,6 +24,12 @@ export const SToolbar = styled(Toolbar)(({ theme }) => ({
}
}))
+export const SSpanBox = styled(Box)(({ theme }) => ({
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center'
+}))
+
// @bootcamp -- card
export const SBadgeHeader = styled(CardHeader)({
position: 'relative',
@@ -40,6 +46,7 @@ export const SScrollBox = styled(Box)(({ theme }) => ({
overflowX: 'auto',
display: 'flex',
marginRight: theme.spacing(2),
+ marginLeft: theme.spacing(2),
flexDirection: 'row',
flexWrap: 'nowrap',
'&::-webkit-scrollbar': {
diff --git a/src/theme/theme.ts b/src/theme/theme.ts
index fd224ec..ae0e407 100644
--- a/src/theme/theme.ts
+++ b/src/theme/theme.ts
@@ -3,6 +3,7 @@ import { blue, green, grey, red } from '@mui/material/colors'
import { Theme } from '@mui/material/styles'
import ComponentOverride from './override'
import { ASSET } from 'config'
+import { KEY } from 'constant'
export const COLORS = ['primary', 'secondary', 'info', 'success', 'warning', 'error']
@@ -75,6 +76,19 @@ const BRAND = {
success: green[500]
}
+export const GREY = {
+ 0: '#F2EED8',
+ 100: '#F2EED8',
+ 200: '#F5F5F5',
+ 300: '#DFDFDF',
+ 400: '#DFE3E8',
+ 500: '#919EAB',
+ 600: '#637381',
+ 700: '#454F5B',
+ 800: '#212B36',
+ 900: '#161C24'
+}
+
export const COMMON = {
light: '#F2EED8',
main: '#D9D9D9',
@@ -83,6 +97,7 @@ export const COMMON = {
red: red[500],
green: green[500],
dark: '#1E1E1F',
+ grey: GREY,
black: '#000000',
white: '#F2EED8'
}
@@ -101,7 +116,7 @@ const theme = {
},
common: COMMON,
brand: BRAND,
- mode: 'light',
+ mode: KEY.LIGHT,
backgroundImage: ASSET.PATTERN_BG
},
shape: {
@@ -156,7 +171,24 @@ const theme = {
...rawTheme.typography.subtitle1,
fontSize: 18
},
+ overline0: {
+ ...rawTheme.typography.overline,
+ fontSize: 10,
+ fontWeight: 'bold',
+ textTransform: 'uppercase'
+ },
overline: {
+ ...rawTheme.typography.overline,
+ fontSize: 12,
+ fontWeight: 'bold',
+ textTransform: 'uppercase'
+ },
+ overline1: {
+ ...rawTheme.typography.overline,
+ fontSize: 14,
+ textTransform: 'uppercase'
+ },
+ overline2: {
...rawTheme.typography.overline,
fontSize: 16,
textTransform: 'uppercase'
diff --git a/src/theme/typography.ts b/src/theme/typography.ts
index 0566f9d..6c9cde3 100644
--- a/src/theme/typography.ts
+++ b/src/theme/typography.ts
@@ -106,12 +106,24 @@ const typography = {
lineHeight: 0.5,
fontSize: pxToRem(12)
},
+ overline0: {
+ fontWeight: 900,
+ lineHeight: 1.5,
+ fontSize: pxToRem(10),
+ textTransform: 'uppercase'
+ },
overline: {
fontWeight: 700,
lineHeight: 1.5,
fontSize: pxToRem(12),
textTransform: 'uppercase'
},
+ overline1: {
+ fontWeight: 700,
+ lineHeight: 1.5,
+ fontSize: pxToRem(13),
+ textTransform: 'uppercase'
+ },
overline2: {
fontWeight: 700,
lineHeight: 1.5,
diff --git a/src/types/global.d.ts b/src/types/global.d.ts
index 86323e7..29e3e11 100644
--- a/src/types/global.d.ts
+++ b/src/types/global.d.ts
@@ -90,36 +90,36 @@ declare global {
}
interface Bootcamp {
- _id: Schema.Types.ObjectId
+ _id?: Schema.Types.ObjectId
name: string
- slug: string
- description: string
- website: string
- phone: string
- email: string
- address: string
- location: {
- type: string
- coordinates: [number | undefined, number | undefined]
- formattedAddress: string
- street: string
- city: string
- state: string
- zipcode: string
- country: string
+ slug?: string
+ description?: string
+ website?: string
+ phone?: string
+ email?: string
+ address?: string
+ location?: {
+ type?: string
+ coordinates?: [number | undefined, number | undefined]
+ formattedAddress?: string
+ street?: string
+ city?: string
+ state?: string
+ zipcode?: string
+ country?: string
}
- careers: [string]
- duration: string
- averageRating: number
- averageCost: number
- photo: string
- badge: string
- housing: boolean
- jobAssistance: boolean
- jobGuarantee: boolean
- acceptGi: boolean
- createdAt: Date
- user: Schema.Types.ObjectId
+ careers?: [string]
+ duration?: string
+ averageRating?: number
+ averageCost?: number
+ photo?: string | undefined
+ badge?: string | undefined
+ housing?: boolean | undefined
+ jobAssistance?: boolean
+ jobGuarantee?: boolean
+ acceptGi?: boolean
+ createdAt?: Date
+ user?: Schema.Types.ObjectId
}
interface IResponse {
@@ -151,7 +151,7 @@ declare global {
location?: Location
website: string
photo: string
- rating: number
+ rating?: number
careers?: string[] | null
}
@@ -167,7 +167,7 @@ declare global {
}
interface UploadLocationProps {
- bootcamp: BootcampCardProps
+ bootcamp?: Bootcamp | undefined
}
interface IDefaultAvatar {
diff --git a/src/types/mui.d.ts b/src/types/mui.d.ts
new file mode 100644
index 0000000..73172e7
--- /dev/null
+++ b/src/types/mui.d.ts
@@ -0,0 +1,12 @@
+import '@mui/material'
+
+declare module '@mui/material/Typography' {
+ interface TypographyPropsVariantOverrides {
+ overline0: true
+ overline1: true
+ overline2: true
+ h0: true
+ h7: true
+ body0: true
+ }
+}
diff --git a/src/util/asset-loc.ts b/src/util/asset-loc.ts
index ca8ecef..14bfc66 100644
--- a/src/util/asset-loc.ts
+++ b/src/util/asset-loc.ts
@@ -1,14 +1,16 @@
import { ServerPath } from 'route/path'
import { KEY } from 'constant'
-export function photoLocation({ bootcamp }: UploadLocationProps) {
- return bootcamp?.photo === KEY.PHOTO_DEFAULT
- ? ServerPath.ORIGIN + `/upload/` + bootcamp?.photo
- : ServerPath.ORIGIN + `/upload/${bootcamp._id}/` + bootcamp?.photo
+export interface AssetLocation {
+ _id: string
+ photo?: string
+ badge?: string
}
-export function badgeLocation({ bootcamp }: UploadLocationProps) {
- return bootcamp?.badge === KEY.BADGE_DEFAULT
- ? ServerPath.ORIGIN + `/upload/badge/` + bootcamp?.badge
- : ServerPath.ORIGIN + `/upload/badge/${bootcamp._id}/` + bootcamp?.badge
+export function photoLocation({ _id, photo }: AssetLocation) {
+ return photo === KEY.PHOTO_DEFAULT ? ServerPath.ORIGIN + `/upload/` + photo : ServerPath.ORIGIN + `/upload/${_id}/` + photo
+}
+
+export function badgeLocation({ _id, badge }: AssetLocation) {
+ return badge === KEY.BADGE_DEFAULT ? ServerPath.ORIGIN + `/upload/badge/` + badge : ServerPath.ORIGIN + `/upload/badge/${_id}/` + badge
}