Refactor components to remove Layout wrapper and pass it in the App component , implemented a skeleton feedback while loading page and improved API calls related to Dashboard/User Profile
131 lines
3.6 KiB
TypeScript
131 lines
3.6 KiB
TypeScript
import { EntityWithRoles } from "@/interfaces/entity";
|
|
import { User } from "@/interfaces/user";
|
|
import clsx from "clsx";
|
|
import { useRouter } from "next/router";
|
|
import { ToastContainer } from "react-toastify";
|
|
import Navbar from "../Navbar";
|
|
import Sidebar from "../Sidebar";
|
|
import React, { useEffect, useState } from "react";
|
|
|
|
export const LayoutContext = React.createContext({
|
|
onFocusLayerMouseEnter: () => {},
|
|
setOnFocusLayerMouseEnter: (() => {}) as React.Dispatch<
|
|
React.SetStateAction<() => void>
|
|
>,
|
|
navDisabled: false,
|
|
setNavDisabled: (() => {}) as React.Dispatch<React.SetStateAction<boolean>>,
|
|
focusMode: false,
|
|
setFocusMode: (() => {}) as React.Dispatch<React.SetStateAction<boolean>>,
|
|
hideSidebar: false,
|
|
setHideSidebar: (() => {}) as React.Dispatch<React.SetStateAction<boolean>>,
|
|
bgColor: "bg-white",
|
|
setBgColor: (() => {}) as React.Dispatch<React.SetStateAction<string>>,
|
|
className: "",
|
|
setClassName: (() => {}) as React.Dispatch<React.SetStateAction<string>>,
|
|
});
|
|
|
|
interface Props {
|
|
user: User;
|
|
entities?: EntityWithRoles[];
|
|
children: React.ReactNode;
|
|
refreshPage?: boolean;
|
|
}
|
|
|
|
export default function Layout({
|
|
user,
|
|
entities,
|
|
children,
|
|
refreshPage,
|
|
}: Props) {
|
|
const [onFocusLayerMouseEnter, setOnFocusLayerMouseEnter] = useState(
|
|
() => () => {}
|
|
);
|
|
const [navDisabled, setNavDisabled] = useState(false);
|
|
const [focusMode, setFocusMode] = useState(false);
|
|
const [hideSidebar, setHideSidebar] = useState(false);
|
|
const [bgColor, setBgColor] = useState("bg-white");
|
|
const [className, setClassName] = useState("");
|
|
|
|
useEffect(() => {
|
|
if (refreshPage) {
|
|
setClassName("");
|
|
setBgColor("bg-white");
|
|
setFocusMode(false);
|
|
setHideSidebar(false);
|
|
setNavDisabled(false);
|
|
setOnFocusLayerMouseEnter(() => () => {});
|
|
}
|
|
}, [refreshPage]);
|
|
|
|
const LayoutContextValue = React.useMemo(
|
|
() => ({
|
|
onFocusLayerMouseEnter,
|
|
setOnFocusLayerMouseEnter,
|
|
navDisabled,
|
|
setNavDisabled,
|
|
focusMode,
|
|
setFocusMode,
|
|
hideSidebar,
|
|
setHideSidebar,
|
|
bgColor,
|
|
setBgColor,
|
|
className,
|
|
setClassName,
|
|
}),
|
|
[
|
|
bgColor,
|
|
className,
|
|
focusMode,
|
|
hideSidebar,
|
|
navDisabled,
|
|
onFocusLayerMouseEnter,
|
|
]
|
|
);
|
|
|
|
const router = useRouter();
|
|
|
|
return (
|
|
<LayoutContext.Provider value={LayoutContextValue}>
|
|
<main
|
|
className={clsx(
|
|
"w-full min-h-full h-screen flex flex-col bg-mti-gray-smoke relative"
|
|
)}
|
|
>
|
|
<ToastContainer />
|
|
{!hideSidebar && user && (
|
|
<Navbar
|
|
path={router.pathname}
|
|
user={user}
|
|
navDisabled={navDisabled}
|
|
focusMode={focusMode}
|
|
onFocusLayerMouseEnter={onFocusLayerMouseEnter}
|
|
/>
|
|
)}
|
|
<div className={clsx("h-full w-full flex gap-2")}>
|
|
{!hideSidebar && user && (
|
|
<Sidebar
|
|
path={router.pathname}
|
|
navDisabled={navDisabled}
|
|
focusMode={focusMode}
|
|
onFocusLayerMouseEnter={onFocusLayerMouseEnter}
|
|
className="-md:hidden"
|
|
user={user}
|
|
entities={entities}
|
|
/>
|
|
)}
|
|
<div
|
|
className={clsx(
|
|
`w-full min-h-full ${bgColor} shadow-md rounded-2xl p-4 xl:p-10 pb-8 flex flex-col gap-8 relative overflow-hidden mt-2`,
|
|
bgColor !== "bg-white" ? "justify-center" : "h-fit",
|
|
hideSidebar ? "md:mx-8" : "md:mr-8",
|
|
className
|
|
)}
|
|
>
|
|
{children}
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</LayoutContext.Provider>
|
|
);
|
|
}
|