diff --git a/web/package.json b/web/package.json
index 2bfcfe9..9be89ca 100644
--- a/web/package.json
+++ b/web/package.json
@@ -12,6 +12,7 @@
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
+ "@mui/icons-material": "^5.14.6",
"@mui/material": "^5.14.3",
"@types/node": "20.4.8",
"@types/react": "18.2.18",
diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx
index 73c0a4b..ddbd120 100644
--- a/web/src/app/layout.tsx
+++ b/web/src/app/layout.tsx
@@ -1,7 +1,8 @@
import type { Metadata } from 'next'
-import { Inter } from 'next/font/google'
+import { ThemeProvider } from '@mui/material'
-const inter = Inter({ subsets: ['latin'] })
+import { theme } from '@/assets/theme'
+import Wrapper from './wrapper';
export const metadata: Metadata = {
title: 'Create Next App',
@@ -15,7 +16,9 @@ export default function RootLayout({
}) {
return (
-
{children}
+
+ {children}
+
)
}
diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx
index 1d790e1..6c76689 100644
--- a/web/src/app/page.tsx
+++ b/web/src/app/page.tsx
@@ -1,11 +1,11 @@
-import Button from '@mui/material/Button';
+import { Box, Typography } from "@mui/material";
export default function Home() {
return (
-
-
-
+
+ Content goes here
+
)
}
diff --git a/web/src/app/wrapper.tsx b/web/src/app/wrapper.tsx
new file mode 100644
index 0000000..e0f4dd0
--- /dev/null
+++ b/web/src/app/wrapper.tsx
@@ -0,0 +1,50 @@
+'use client'
+
+import { FC, useState } from 'react';
+import { Open_Sans } from 'next/font/google'
+import { Box, Container } from '@mui/material'
+
+import Header from '@/components/organisms/Header';
+import NavBar from '@/components/organisms/Navbar';
+
+const openSansFont = Open_Sans({
+ subsets: ["latin"],
+ weight: ["300", "400", "500", "600", "700"],
+});
+
+interface Props {
+ children: React.ReactNode
+}
+
+export const Wrapper:FC = ({
+ children
+ }) => {
+
+ const [isExpanded, setIsExpanded] = useState(true)
+ let isOpen = true;
+
+ const handleToggle = () => {
+ setIsExpanded(!isExpanded)
+ isOpen = !isOpen
+ }
+
+ return (
+
+
+
+
+
+ {children}
+
+
+
+ )
+}
+
+export default Wrapper
\ No newline at end of file
diff --git a/web/src/assets/colors.ts b/web/src/assets/colors.ts
new file mode 100644
index 0000000..191791e
--- /dev/null
+++ b/web/src/assets/colors.ts
@@ -0,0 +1,24 @@
+import { PaletteOptions } from "@mui/material";
+
+export const customColors: PaletteOptions = {
+ primary: {
+ main: "#2A3F52",
+ 100: "#F0F9FF",
+ 200: "#DAEFFC",
+ 300: "#B9DBF1",
+ 400: "#86B1CC",
+ 500: "#5B829B",
+ 700: "#3E5367",
+ 900: "#2A3F52",
+ },
+ secondary: {
+ main: "#5B829B",
+ },
+ dark: "#293743",
+ neutral: "#65707A",
+ disabled: "#999999",
+ light: "#ACB5BD",
+ white: "#FFFFFF",
+ "background-primary": "#F0F0F0",
+ "background-secondary": "#F6F6F6",
+};
diff --git a/web/src/assets/icons/Logo.tsx b/web/src/assets/icons/Logo.tsx
new file mode 100644
index 0000000..088c7a6
--- /dev/null
+++ b/web/src/assets/icons/Logo.tsx
@@ -0,0 +1,12 @@
+export const Logo = () => (
+
+
+)
\ No newline at end of file
diff --git a/web/src/assets/theme.ts b/web/src/assets/theme.ts
new file mode 100644
index 0000000..703245e
--- /dev/null
+++ b/web/src/assets/theme.ts
@@ -0,0 +1,215 @@
+"use client";
+
+import { createTheme } from "@mui/material/styles";
+import { Open_Sans } from "next/font/google";
+
+import { customColors } from "./colors";
+
+const openSansFont = Open_Sans({
+ subsets: ["latin"],
+ weight: ["300", "400", "500", "600", "700"],
+});
+
+declare module "@mui/material/styles" {
+ interface TypographyVariants {
+ body1r: React.CSSProperties;
+ body1b: React.CSSProperties;
+ body2r: React.CSSProperties;
+ body2b: React.CSSProperties;
+ body3r: React.CSSProperties;
+ body3b: React.CSSProperties;
+ label1r: React.CSSProperties;
+ label1b: React.CSSProperties;
+ label2r: React.CSSProperties;
+ label2b: React.CSSProperties;
+ label3r: React.CSSProperties;
+ label3b: React.CSSProperties;
+ label4r: React.CSSProperties;
+ label4b: React.CSSProperties;
+ }
+
+ // allow configuration using `createTheme`
+ interface TypographyVariantsOptions {
+ body1r: React.CSSProperties;
+ body1b: React.CSSProperties;
+ body2r: React.CSSProperties;
+ body2b: React.CSSProperties;
+ body3r: React.CSSProperties;
+ body3b: React.CSSProperties;
+ label1r: React.CSSProperties;
+ label1b: React.CSSProperties;
+ label2r: React.CSSProperties;
+ label2b: React.CSSProperties;
+ label3r: React.CSSProperties;
+ label3b: React.CSSProperties;
+ label4r: React.CSSProperties;
+ label4b: React.CSSProperties;
+ }
+
+ interface Palette {
+ dark: string;
+ neutral: string;
+ disabled: string;
+ light: string;
+ white: string;
+ "background-primary": string;
+ "background-secondary": string;
+ }
+ interface PaletteOptions {
+ dark?: string;
+ neutral?: string;
+ disabled?: string;
+ light?: string;
+ white?: string;
+ "background-primary"?: string;
+ "background-secondary"?: string;
+ }
+}
+
+// Update the Typography's variant prop options
+declare module "@mui/material/Typography" {
+ interface TypographyPropsVariantOverrides {
+ body1r: true;
+ body1b: true;
+ body2r: true;
+ body2b: true;
+ body3r: true;
+ body3b: true;
+ label1r: true;
+ label1b: true;
+ label2r: true;
+ label2b: true;
+ label3r: true;
+ label3b: true;
+ label4r: true;
+ label4b: true;
+ }
+}
+
+const customDefaultFontFamily = {
+ fontFamily: openSansFont.style.fontFamily,
+};
+
+export const theme = createTheme({
+ palette: { ...customColors },
+ typography: {
+ allVariants: {
+ ...customDefaultFontFamily,
+ color: customColors.dark,
+ },
+ label1r: {
+ fontSize: 16,
+ fontWeight: 400,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ label1b: {
+ fontSize: 16,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ label2r: {
+ fontSize: 14,
+ fontWeight: 400,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ label2b: {
+ fontSize: 14,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ label3r: {
+ fontSize: 12,
+ fontWeight: 400,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ label3b: {
+ fontSize: 12,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ label4r: {
+ fontSize: 10,
+ fontWeight: 400,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ label4b: {
+ fontSize: 10,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ body1r: {
+ fontSize: 16,
+ fontWeight: 400,
+ lineHeight: "150%",
+ color: customColors.dark,
+ },
+ body1b: {
+ fontSize: 16,
+ fontWeight: 500,
+ lineHeight: "150%",
+ color: customColors.dark,
+ },
+ body2r: {
+ fontSize: 14,
+ fontWeight: 400,
+ lineHeight: "150%",
+ color: customColors.dark,
+ },
+ body2b: {
+ fontSize: 14,
+ fontWeight: 500,
+ lineHeight: "150%",
+ color: customColors.dark,
+ },
+ body3r: {
+ fontSize: 12,
+ fontWeight: 400,
+ lineHeight: "150%",
+ color: customColors.dark,
+ },
+ body3b: {
+ fontSize: 12,
+ fontWeight: 500,
+ lineHeight: "150%",
+ color: customColors.dark,
+ },
+ h1: {
+ fontSize: 40,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ h2: {
+ fontSize: 32,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ h3: {
+ fontSize: 24,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ h4: {
+ fontSize: 18,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ h5: {
+ fontSize: 14,
+ fontWeight: 600,
+ lineHeight: "125%",
+ color: customColors.dark,
+ },
+ },
+});
diff --git a/web/src/components/molecules/NavBarItem.tsx b/web/src/components/molecules/NavBarItem.tsx
new file mode 100644
index 0000000..9ad1c54
--- /dev/null
+++ b/web/src/components/molecules/NavBarItem.tsx
@@ -0,0 +1,64 @@
+import Link from 'next/link'
+import React, { FC } from 'react'
+import { Box, Typography } from '@mui/material'
+import {SvgIconComponent} from '@mui/icons-material'
+
+interface Props {
+ label: string,
+ Icon: SvgIconComponent
+ active?: boolean,
+ width?: number | string,
+ height?: number | string,
+ paddingX?: number | string,
+ gap?: number,
+ linkTo?: string
+}
+
+const NavBarItem: FC = ({
+ label,
+ Icon,
+ active = false,
+ width = 200,
+ height = 40,
+ paddingX = 2,
+ gap = 1,
+ linkTo = "/"
+ }) => {
+
+ const backgroundColor = active ? 'primary.100' : 'primary.700'
+ const textColor = active? 'dark': 'white'
+
+ return(
+
+ div > span": {
+ color: 'dark',
+ },
+ "> div > svg": {
+ color: 'dark',
+ },
+ }
+ }}>
+
+
+
+ {label}
+
+
+
+ )
+}
+
+export default NavBarItem
diff --git a/web/src/components/organisms/Header.tsx b/web/src/components/organisms/Header.tsx
new file mode 100644
index 0000000..3d751f8
--- /dev/null
+++ b/web/src/components/organisms/Header.tsx
@@ -0,0 +1,35 @@
+import React, { FC } from 'react'
+import { Box, Stack, Typography } from '@mui/material'
+
+import {Logo} from '../../assets/icons/Logo'
+import HeaderProfile from './HeaderProfile'
+
+interface Props {
+ height?: number | string,
+}
+
+const Header: FC = ({height = 64}) => {
+ return(
+
+
+
+ MeetsOne
+
+
+
+ )
+}
+
+export default Header
diff --git a/web/src/components/organisms/HeaderProfile.tsx b/web/src/components/organisms/HeaderProfile.tsx
new file mode 100644
index 0000000..e620be6
--- /dev/null
+++ b/web/src/components/organisms/HeaderProfile.tsx
@@ -0,0 +1,125 @@
+'use client'
+
+import React, { FC } from 'react'
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import {Create, Logout, ArrowDropDown} from '@mui/icons-material'
+import { Box, Typography, Paper, Button, Stack, Avatar, Popper, Grow, IconButton } from '@mui/material'
+
+interface Props {
+ name?: string,
+ email?: string,
+ avatar?: string,
+}
+
+const HeaderProfile: FC = ({
+ name = "John Doe",
+ email = "johndoe@sun-asterisk.com"
+}) => {
+ const [open, setOpen] = React.useState(false);
+ const anchorRef = React.useRef(null);
+
+ const handleToggle = () => {
+ setOpen((prevOpen) => !prevOpen);
+ };
+
+ const handleClose = (event: Event | React.SyntheticEvent) => {
+ if (
+ anchorRef.current &&
+ anchorRef.current.contains(event.target as HTMLElement)
+ ) {
+ return;
+ }
+
+ setOpen(false);
+ };
+
+ return(
+
+
+
+
+
+
+
+
+
+ {({ TransitionProps }) => (
+
+
+
+
+
+
+
+
+ {name}
+ {email}
+
+
+ } fullWidth>
+ Logout
+
+
+
+
+
+ )}
+
+
+ )
+}
+
+export default HeaderProfile
diff --git a/web/src/components/organisms/Navbar.tsx b/web/src/components/organisms/Navbar.tsx
new file mode 100644
index 0000000..0fa7687
--- /dev/null
+++ b/web/src/components/organisms/Navbar.tsx
@@ -0,0 +1,72 @@
+"use client"
+
+import React, { FC } from 'react'
+import { Menu } from '@mui/icons-material'
+import { Box, ButtonBase } from '@mui/material'
+
+import NavBarItem from '../molecules/NavBarItem'
+import { Menus } from '@/utils/constants/navbarMenu'
+
+interface Props {
+ expanded?: boolean,
+ width?: number |string,
+ height?: number | string,
+ paddingY?: number |string,
+ rowGap?: number |string,
+ handleToggle: () => void
+}
+
+const NavBar: FC = ({
+ expanded = true,
+ width = 200,
+ paddingY = 2,
+ rowGap = 2,
+ handleToggle
+ }) => {
+
+ return(
+
+
+
+
+
+
+
+
+ {Menus.map((item, index) => (
+
+
+
+ )
+ )}
+
+
+ )
+}
+
+export default NavBar
diff --git a/web/src/utils/constants/navbarMenu.ts b/web/src/utils/constants/navbarMenu.ts
new file mode 100644
index 0000000..1d2cfc2
--- /dev/null
+++ b/web/src/utils/constants/navbarMenu.ts
@@ -0,0 +1,30 @@
+import {
+ Home,
+ CalendarMonth,
+ Person,
+ SvgIconComponent,
+} from "@mui/icons-material";
+
+export interface IMenu {
+ name: string;
+ Icon: SvgIconComponent;
+ href: string;
+}
+
+export const Menus: IMenu[] = [
+ {
+ name: "Job List",
+ Icon: Home,
+ href: "/",
+ },
+ {
+ name: "Calendar",
+ Icon: CalendarMonth,
+ href: "/",
+ },
+ {
+ name: "Customer",
+ Icon: Person,
+ href: "/",
+ },
+];
diff --git a/web/yarn.lock b/web/yarn.lock
index f7604ce..8662640 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -270,6 +270,13 @@
dependencies:
regenerator-runtime "^0.14.0"
+"@babel/runtime@^7.22.10":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.11.tgz#7a9ba3bbe406ad6f9e8dd4da2ece453eb23a77a4"
+ integrity sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
"@babel/template@^7.22.5", "@babel/template@^7.3.3":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
@@ -675,6 +682,13 @@
resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.4.tgz#a517265647ee9660170107d68905db5e400576c5"
integrity sha512-pW2XghSi3hpYKX57Wu0SCWMTSpzvXZmmucj3TcOJWaCiFt4xr05w2gcwBZi36dAp9uvd9//9N51qbblmnD+GPg==
+"@mui/icons-material@^5.14.6":
+ version "5.14.6"
+ resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.14.6.tgz#0efdcba2c30d6b22e6ead787b67247da173bd11a"
+ integrity sha512-7Cujy7lRGTj2T3SvY9C9ZOTFDtrXJogeNnRcU/ODyNoxwskMNPFOcc15F+98MAdJenBVLJPYu+vPP6DUvEpNrA==
+ dependencies:
+ "@babel/runtime" "^7.22.10"
+
"@mui/material@^5.14.3":
version "5.14.4"
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.14.4.tgz#9d4d1834a929a4acc59e550e34ca64c0fd60b3a6"