Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/apps/customer-portal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src'
37 changes: 37 additions & 0 deletions src/apps/customer-portal/src/CustomerPortalApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* The customer portal app.
*/
import { FC, useContext, useEffect, useMemo } from 'react'
import { Outlet, Routes } from 'react-router-dom'

import { routerContext, RouterContextData } from '~/libs/core'

import { CustomerPortalAppContextProvider, Layout, SWRConfigProvider } from './lib'
import { toolTitle } from './customer-portal.routes'
import './lib/styles/index.scss'

const CustomerPortalApp: FC = () => {
const { getChildRoutes }: RouterContextData = useContext(routerContext)
const childRoutes = useMemo(() => getChildRoutes(toolTitle), [getChildRoutes])

useEffect(() => {
document.body.classList.add('customer-portal-app')
return () => {
document.body.classList.remove('customer-portal-app')
}
}, [])

return (
<CustomerPortalAppContextProvider>
<SWRConfigProvider>
<Layout>
<Outlet />
<Routes>{childRoutes}</Routes>
</Layout>
</SWRConfigProvider>
</CustomerPortalAppContextProvider>

)
}

export default CustomerPortalApp
5 changes: 5 additions & 0 deletions src/apps/customer-portal/src/config/index.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const PRIVILEGED_ROLES = [
'administrator',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Consider normalizing role names to a consistent case (e.g., all lowercase) to avoid potential issues with case sensitivity when checking roles elsewhere in the application.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just how roles are configured in our system

'Project Manager',
'Talent Manager',
]
11 changes: 11 additions & 0 deletions src/apps/customer-portal/src/config/routes.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Common config for routes in Customer Portal app.
*/
import { AppSubdomain, EnvironmentConfig } from '~/config'

export const rootRoute: string
= EnvironmentConfig.SUBDOMAIN === AppSubdomain.customer

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The use of EnvironmentConfig.SUBDOMAIN assumes that SUBDOMAIN is always defined and valid. Consider adding validation or default values to handle potential undefined or incorrect configurations.

? ''
: `/${AppSubdomain.customer}`

export const talentSearchRouteId = 'talent-search'
39 changes: 39 additions & 0 deletions src/apps/customer-portal/src/customer-portal.routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* App routes
*/
import { AppSubdomain, ToolTitle } from '~/config'
import {
lazyLoad,
LazyLoadedComponent,
PlatformRoute,
Rewrite,
} from '~/libs/core'

import {
rootRoute,
talentSearchRouteId,
} from './config/routes.config'
import { customerPortalTalentSearchRoutes } from './pages/talent-search/talent-search.routes'

const CustomerPortalApp: LazyLoadedComponent = lazyLoad(() => import('./CustomerPortalApp'))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
Ensure that the lazy-loaded component CustomerPortalApp is properly handled for loading states and potential errors during the loading process.


export const toolTitle: string = ToolTitle.customer

export const customerPortalRoutes: ReadonlyArray<PlatformRoute> = [
// Customer portal App Root
{
children: [
{
authRequired: true,
element: <Rewrite to={talentSearchRouteId} />,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Consider verifying that talentSearchRouteId is a valid route identifier at runtime to prevent potential navigation errors.

route: '',
},
...customerPortalTalentSearchRoutes,
],
domain: AppSubdomain.customer,
element: <CustomerPortalApp />,
id: toolTitle,
route: rootRoute,
title: toolTitle,
},
]
2 changes: 2 additions & 0 deletions src/apps/customer-portal/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { customerPortalRoutes } from './customer-portal.routes'
export { rootRoute as customerPortalRootRoute } from './config/routes.config'
3 changes: 3 additions & 0 deletions src/apps/customer-portal/src/lib/assets/arrow-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/apps/customer-portal/src/lib/assets/chevron-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/apps/customer-portal/src/lib/assets/external-link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/apps/customer-portal/src/lib/assets/icon-file.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/apps/customer-portal/src/lib/assets/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ReactComponent as IconFile } from './icon-file.svg'
import { ReactComponent as IconChevronDown } from './selector.svg'
import { ReactComponent as IconArrowLeft } from './arrow-left.svg'
import { ReactComponent as IconExternalLink } from './external-link.svg'

export {
IconFile,
IconChevronDown,
IconArrowLeft,
IconExternalLink,
}
8 changes: 8 additions & 0 deletions src/apps/customer-portal/src/lib/assets/selector.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@import '@libs/ui/styles/includes';

.breadcrumb {
padding-bottom: $sp-6;
ul {
align-items: center;
display: flex;
flex-wrap: wrap;
li {
font-size: 14px;
line-height: 20px;
white-space: nowrap;
button,
a {
font-family: "Nunito Sans", sans-serif;
color: var(--GrayFontColor);
align-items: center;
display: flex;
&::after {
color: var(--GrayFontColor);
content: '/';
padding: 0 $sp-2;
}
}
span {
font-family: "Nunito Sans", sans-serif;
color: var(--FontColor);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FC } from 'react'
import { Link } from 'react-router-dom'

import { BreadCrumbData } from '../../models'
import { useAppNavigate } from '../../hooks'

import styles from './BreadCrumb.module.scss'

interface Props {
list: BreadCrumbData[]
}

export const BreadCrumb: FC<Props> = (props: Props) => {
const navigate = useAppNavigate()
return (
<div className={styles.breadcrumb}>
<ul>
{props.list.map(item => (
<li key={item.index}>
{item.path ? (
item.fallback ? (
<button
type='button'
onClick={function onClick() {
navigate(item.path as number, {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
The navigate function is called with item.path cast to a number. Ensure that item.path is always a number when item.fallback is present, as incorrect types could lead to runtime errors.

fallback: item.fallback,
})
}}
>
{item.label}
</button>
) : (
<Link to={item.path as string}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Casting item.path to a string for the Link component assumes that item.path is always a valid string when item.fallback is not present. Ensure that this assumption holds true to prevent potential navigation issues.

{item.label}
</Link>
)
) : (
<span>{item.label}</span>
)}
</li>
))}
</ul>
</div>
)
}

export default BreadCrumb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as BreadCrumb } from './BreadCrumb'
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@import '@libs/ui/styles/includes';

.layout {
position: relative;
font-family: $font-roboto;
color: var(--Primary);

.main {
@include ltelg {
padding: 36px 0;
}
}

h1,
h2,
h3,
h4 {
font-family: $font-roboto;
}
}

.contentLayoutOuter {
margin: $sp-6 auto !important;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
Avoid using !important unless absolutely necessary, as it can make styles difficult to override and maintain. Consider refactoring to achieve the desired styling without !important.

}

.contantentLayoutInner {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
There is a typo in the class name .contantentLayoutInner. It should likely be .contentLayoutInner. This could lead to issues with styling not being applied correctly.

box-sizing: border-box;
width: 100%;
}
27 changes: 27 additions & 0 deletions src/apps/customer-portal/src/lib/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { FC, PropsWithChildren } from 'react'

import { ContentLayout } from '~/libs/ui'

import { NavTabs } from '../NavTabs'

import styles from './Layout.module.scss'

export const NullLayout: FC<PropsWithChildren> = props => (
<>{props.children}</>
)

export const Layout: FC<PropsWithChildren> = props => (
<>
<NavTabs />
<ContentLayout
innerClass={styles.contantentLayoutInner}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
There is a typo in the class name contantentLayoutInner. It should likely be contentLayoutInner to match the intended naming convention.

outerClass={styles.contentLayoutOuter}
>
<div className={styles.layout}>
<div className={styles.main}>{props.children}</div>
</div>
</ContentLayout>
</>
)

export default Layout
2 changes: 2 additions & 0 deletions src/apps/customer-portal/src/lib/components/Layout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './Layout'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
Using both export * and named exports from the same module can lead to potential conflicts or unexpected behavior if there are overlapping exports. Consider using only named exports for clarity and to avoid such issues.

export { default as Layout } from './Layout'
Loading
Loading