diff --git a/package-lock.json b/package-lock.json index f8b745f..1da1d87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2446,10 +2446,6 @@ "node": ">= 6" } }, - "node_modules/eslint-plugin-import": { - "dev": true, - "peer": true - }, "node_modules/eslint-plugin-prettier": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx new file mode 100644 index 0000000..fb9a7bd --- /dev/null +++ b/src/app/dashboard/layout.tsx @@ -0,0 +1,32 @@ +import type { Metadata } from "next"; +import AppBar from "@/components/AppBar"; +import { getServerSession } from "next-auth"; +import { authOptions } from "@/config/authConfig"; +import { redirect } from "next/navigation"; + +export const metadata: Metadata = { + title: "Dashboard", +}; + +export default async function DashboardLayout({ + children, +}: { + children: React.ReactNode; +}) { + const session = await getServerSession(authOptions); + console.log(session); + + if (!session?.user) { + redirect("/login"); + } + + return ( + <> + +
{children}
+ + ); +} diff --git a/src/components/AppBar/AppBar.tsx b/src/components/AppBar/AppBar.tsx new file mode 100644 index 0000000..66d8f28 --- /dev/null +++ b/src/components/AppBar/AppBar.tsx @@ -0,0 +1,34 @@ +import MUIAppBar from "@mui/material/AppBar"; +import Toolbar from "@mui/material/Toolbar"; +import React from "react"; +import Profile from "./Profile"; +import Box from "@mui/material/Box"; +import NavigationToggle from "./NavigationToggle"; +import { I18nProvider } from "@/i18n"; + +export interface AppBarProps { + avatarImageSrc?: string; + profileName: string; +} + +const AppBar: React.FC = ({ avatarImageSrc, profileName }) => { + return ( + + + + + + + + + + + ); +}; + +export default AppBar; diff --git a/src/components/AppBar/NavigationToggle.tsx b/src/components/AppBar/NavigationToggle.tsx new file mode 100644 index 0000000..97b156b --- /dev/null +++ b/src/components/AppBar/NavigationToggle.tsx @@ -0,0 +1,47 @@ +"use client"; + +import IconButton from "@mui/material/IconButton"; +import MenuIcon from "@mui/icons-material/Menu"; +import NavigationContent from "../NavigationContent"; +import React from "react"; +import Drawer from "@mui/material/Drawer"; + +const NavigationToggle: React.FC = () => { + const [isOpened, setIsOpened] = React.useState(false); + + const openNavigation = () => { + setIsOpened(true); + }; + const closeNavigation = () => { + setIsOpened(false); + }; + + return ( + <> + + + + + + + + + + + ); +}; + +export default NavigationToggle; diff --git a/src/components/AppBar/Profile.tsx b/src/components/AppBar/Profile.tsx new file mode 100644 index 0000000..8cb49cf --- /dev/null +++ b/src/components/AppBar/Profile.tsx @@ -0,0 +1,61 @@ +"use client"; + +import IconButton from "@mui/material/IconButton"; +import Menu from "@mui/material/Menu"; +import MenuItem from "@mui/material/MenuItem"; +import Avatar from "@mui/material/Avatar"; +import React from "react"; +import { AppBarProps } from "./AppBar"; +import Divider from "@mui/material/Divider"; +import Typography from "@mui/material/Typography"; +import { useTranslation } from "react-i18next"; +import { signOut } from "next-auth/react"; + +type Props = Pick; + +const Profile: React.FC = ({ avatarImageSrc, profileName }) => { + const [profileMenuAnchorEl, setProfileMenuAnchorEl] = + React.useState(); + const openProfileMenu: React.MouseEventHandler = ( + event, + ) => { + setProfileMenuAnchorEl(event.currentTarget); + }; + const closeProfileMenu = () => { + setProfileMenuAnchorEl(undefined); + }; + + const { t } = useTranslation("login"); + + return ( + <> + + + + + + {profileName} + + + signOut()}>{t("Sign out")} + + + ); +}; + +export default Profile; diff --git a/src/components/AppBar/index.ts b/src/components/AppBar/index.ts new file mode 100644 index 0000000..cc81140 --- /dev/null +++ b/src/components/AppBar/index.ts @@ -0,0 +1 @@ +export { default } from "./AppBar"; diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx new file mode 100644 index 0000000..cb88a18 --- /dev/null +++ b/src/components/NavigationContent/NavigationContent.tsx @@ -0,0 +1,66 @@ +import Divider from "@mui/material/Divider"; +import Box from "@mui/material/Box"; +import React from "react"; +import List from "@mui/material/List"; +import ListItemButton from "@mui/material/ListItemButton"; +import ListItemText from "@mui/material/ListItemText"; +import ListItemIcon from "@mui/material/ListItemIcon"; +import WorkHistory from "@mui/icons-material/WorkHistory"; +import Dashboard from "@mui/icons-material/Dashboard"; +import RequestQuote from "@mui/icons-material/RequestQuote"; +import Task from "@mui/icons-material/Task"; +import Assignment from "@mui/icons-material/Assignment"; +import Settings from "@mui/icons-material/Settings"; +import Analytics from "@mui/icons-material/Analytics"; +import Payments from "@mui/icons-material/Payments"; +import { useTranslation } from "react-i18next"; +import Typography from "@mui/material/Typography"; +import { usePathname } from "next/navigation"; +import Link from "next/link"; + +interface NavigationItem { + icon: React.ReactNode; + label: string; + path: string; +} + +const navigationItems: NavigationItem[] = [ + { icon: , label: "User Workspace", path: "/workspace" }, + { icon: , label: "Dashboard", path: "/dashboard" }, + { icon: , label: "Expense Claim", path: "/claim" }, + { icon: , label: "Project Management", path: "/projects" }, + { icon: , label: "Task Template", path: "/tasks" }, + { icon: , label: "Invoice", path: "/invoice" }, + { icon: , label: "Analysis Report", path: "/analytics" }, + { icon: , label: "Setting", path: "/settings" }, +]; + +const NavigationContent: React.FC = () => { + const { t } = useTranslation("common"); + const pathname = usePathname(); + + return ( + + + {/* Replace this with company logo and/or name */} + TSMS + + + + {navigationItems.map(({ icon, label, path }, index) => { + return ( + + {icon} + {t(label)}} /> + + ); + })} + + + ); +}; + +export default NavigationContent; diff --git a/src/components/NavigationContent/index.ts b/src/components/NavigationContent/index.ts new file mode 100644 index 0000000..bcd4bfa --- /dev/null +++ b/src/components/NavigationContent/index.ts @@ -0,0 +1 @@ +export { default } from "./NavigationContent"; diff --git a/src/theme/devias-material-kit/components.ts b/src/theme/devias-material-kit/components.ts index e84e364..a6c8f6e 100644 --- a/src/theme/devias-material-kit/components.ts +++ b/src/theme/devias-material-kit/components.ts @@ -283,6 +283,51 @@ const components: ThemeOptions["components"] = { variant: "filled", }, }, + MuiMenuItem: { + styleOverrides: { + root: { + margin: "0.5rem", + borderRadius: 8, + }, + }, + }, + MuiList: { + styleOverrides: { + padding: { + paddingBlock: "1rem", + paddingInline: "1rem", + }, + }, + }, + MuiListItemButton: { + styleOverrides: { + root: { + borderRadius: 8, + marginBlockEnd: "0.5rem", + a: { + textDecoration: "none", + color: "inherit", + } + }, + }, + }, + MuiListItemText: { + styleOverrides: { + root: { + marginInlineEnd: "2rem", + }, + primary: { + fontWeight: 500, + }, + }, + }, + MuiListItemIcon: { + styleOverrides: { + root: { + color: "inherit", + }, + }, + }, }; export default components; diff --git a/src/theme/devias-material-kit/typography.ts b/src/theme/devias-material-kit/typography.ts index 1f2c7f2..ce5c840 100644 --- a/src/theme/devias-material-kit/typography.ts +++ b/src/theme/devias-material-kit/typography.ts @@ -79,12 +79,6 @@ const typography: TypographyOptions = { fontSize: "1.125rem", lineHeight: 1.2, }, - fontSize: 0, - fontWeightLight: undefined, - fontWeightRegular: undefined, - fontWeightMedium: undefined, - fontWeightBold: undefined, - htmlFontSize: 0, }; export default typography;