Files
tanami-admin-panel/src/Layout/DefaultLayout.jsx
2025-01-08 20:57:53 +05:30

796 lines
26 KiB
JavaScript

import React, { useContext, useEffect, useState } from "react";
import { CgProfile } from "react-icons/cg";
import { useDispatch } from "react-redux";
import logoMiniDark from "../assets/favicon.png";
import logoMini from "../assets/logo-min.png";
import logoDark from "../assets/logo.png";
import logo from "../assets/logo2.png";
import {
ArrowBackIcon,
ArrowLeftIcon,
ArrowRightIcon,
AtSignIcon,
} from "@chakra-ui/icons";
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Alert,
AlertIcon,
Box,
Button,
Image,
Text,
Tooltip
} from "@chakra-ui/react";
import Cookies from "js-cookie"; // Import the Cookies library
import { GrManual } from "react-icons/gr";
import { HiOutlineChartSquareBar } from "react-icons/hi";
import { LuContact } from "react-icons/lu";
import { MdNotificationsNone, MdOutlineAddChart } from "react-icons/md";
import {
RiBankLine,
RiExchangeBoxLine,
RiFileUserLine,
RiMoneyDollarBoxLine,
} from "react-icons/ri";
import {
TbListDetails,
TbReportMoney,
TbTransactionDollar
} from "react-icons/tb";
import { VscSymbolClass } from "react-icons/vsc";
import {
Link,
NavLink,
Route,
Routes,
useLocation,
useNavigate,
} from "react-router-dom";
import HeaderMain from "../Components/HeaderMain";
import GlobalStateContext from "../Contexts/GlobalStateContext";
import CreateRequest from "../Pages/Fawateer/CreateRequest";
import ApproveHistory from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker";
import ApproveHistoryMaker from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker";
import ApproveRequest from "../Pages/FawateerChecker/ApproveRequest/ApproveRequest";
import NotFound from "../Pages/NotFound";
import SplashScreen from "../Pages/SplashScreen";
import { nav } from "../Routes/Nav";
import { RouteLink } from "../Routes/Routes";
import { useProfileQuery } from "../Services/io.service";
import { useLogoutMutation } from "../Services/token.serivce";
const DashboardLayout = ({ isOnline }) => {
const navigate = useNavigate();
const location = useLocation();
const path = location.pathname;
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
const [openDrawerClick, setOpenDrawerClick] = useState(true);
const {
setIsAuthenticate,
colorMode,
toggleColorMode,
setSlideFormRight,
slideFromRight,
} = useContext(GlobalStateContext);
const [isSplashVisible, setSplashVisible] = useState(true);
const [openIndex, setOpenIndex] = useState(null);
const { data, refetch } = useProfileQuery();
// useEffect(() => {
// if (
// !localStorage.getItem("accessToken") &&
// !localStorage.getItem("refreshToken")
// ) {
// logOutHandler();
// return navigate("/login");
// }
// }, []);
useEffect(() => {
const savedIndex = localStorage.getItem("openAccordionIndex");
if (savedIndex !== null) {
setOpenIndex(parseInt(savedIndex));
}
}, []);
const handleAccordionChange = (index) => {
const newIndex = openIndex === index ? null : index;
setOpenIndex(newIndex);
localStorage.setItem("openAccordionIndex", newIndex);
};
useEffect(() => {
// Set a timer to hide the splash screen after 3 seconds
const timer = setTimeout(() => {
setSplashVisible(false);
}, 1000); // 3000ms = 3 seconds
refetch();
// Cleanup the timer
return () => clearTimeout(timer);
}, []);
const openDrawerOnClick = () => {
setOpenDrawerClick(!openDrawerClick);
};
const [logout] = useLogoutMutation();
const logOutHandler = async () => {
// dispach(loginUser(false));
setIsAuthenticate(false);
Cookies.remove("isAuthenticated");
try {
await logout();
localStorage.clear();
navigate("/login");
} catch (error) {
console.log(error);
}
};
// // Function to get the title based on the route
const getTitle = () => {
switch (true) {
case "/":
return "👋🏻 Hi, Admin";
case path.startsWith("/sponser"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0" /> Sponsor
</span>
);
case path.startsWith("/email"):
return (
<span className="d-flex align-items-end gap-2">
<AtSignIcon className="h4 m-0" /> Email Notification
</span>
);
case path.startsWith("/investment-type"):
return (
<span className="d-flex align-items-end gap-2">
<VscSymbolClass className="h4 m-0" /> Investment Type
</span>
);
case path.startsWith("/profile"):
return (
<span className="d-flex align-items-end gap-2">
<CgProfile className="h4 m-0" /> Profile
</span>
);
case path.startsWith("/exchange-rate"):
return (
<span className="d-flex align-items-end gap-2">
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
Exchange rate
</span>
);
case path.startsWith("/create-io"):
if (/^\/create-io\/[A-Za-z0-9_-]+$/.test(path)) {
return (
<span className="d-flex align-items-end gap-2">
<MdOutlineAddChart className="h4 m-0 fw-normal" />
Edit IO
</span>
);
}
return (
<span className="d-flex align-items-end gap-2">
<MdOutlineAddChart className="h4 m-0 fw-normal" />
Create IO
</span>
);
case path.startsWith("/view-io"):
return (
<span className="d-flex align-items-end gap-2">
<HiOutlineChartSquareBar className="h4 m-0 fw-normal" />
View IO
</span>
);
case path.startsWith("/investor-details"):
return (
<span className="d-flex align-items-end gap-2">
<TbListDetails className="h4 m-0 fw-normal" />
Investor Details
</span>
);
case path.startsWith("/investor-transactions"):
return (
<span className="d-flex align-items-end gap-2">
<TbTransactionDollar className="h4 m-0 fw-normal" />
Investor Transactions
</span>
);
case path.startsWith("/deposit-request"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Deposit Pending Request
</span>
);
case path.startsWith("/deposit-history"):
return (
<span className="d-flex align-items-end gap-2">
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
Deposite Request
</span>
);
case path.startsWith("/fawateer"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Fawateer Deposit
</span>
);
case path.startsWith("/fawateer-history"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Fawateer Deposit
</span>
);
case path.startsWith("/withdraw-request"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Withdrawal pending request
</span>
);
case path.startsWith("/withdraw-history"):
return (
<span className="d-flex align-items-end gap-2">
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
Withdrawal request
</span>
);
case path.startsWith("/investor-request"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Investor pending request
</span>
);
case path.startsWith("/investor-history"):
return (
<span className="d-flex align-items-end gap-2">
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
Investor request
</span>
);
case path.startsWith("/deletion-request"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Deletion pending request
</span>
);
case path.startsWith("/deletion-history"):
return (
<span className="d-flex align-items-end gap-2">
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
Deletion request
</span>
);
case path.startsWith("/bank-investor"):
return (
<span className="d-flex align-items-end gap-2">
<TbReportMoney className="h4 m-0 fw-normal" />
Ban / Unban Investor
</span>
);
case path.startsWith("/academy"):
return (
<span className="d-flex align-items-end gap-2">
<GrManual className="h4 m-0 fw-normal" />
Academy
</span>
);
case path.startsWith("/notification"):
return (
<span className="d-flex align-items-end gap-2">
<MdNotificationsNone className="h4 m-0 fw-normal" />
Push Notification
</span>
);
case path.startsWith("/contact"):
return (
<span className="d-flex align-items-end gap-2">
<LuContact className="h4 m-0 fw-normal" />
Contact Details
</span>
);
case path.startsWith("/users"):
return (
<span className="d-flex align-items-end gap-2">
<RiFileUserLine className="h4 m-0 fw-normal" />
Users
</span>
);
case path.startsWith("/bank-details"):
return (
<span className="d-flex align-items-end gap-2">
<RiBankLine className="h4 m-0 fw-normal" />
Bank Details
</span>
);
case path.startsWith("/deletion-request"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Deletion pending request
</span>
);
case path.startsWith("/deletion-history"):
return (
<span className="d-flex align-items-end gap-2">
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
Deletion request
</span>
);
case path.startsWith("/deletion-request"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Deletion pending request
</span>
);
case path.startsWith("/deletion-history"):
return (
<span className="d-flex align-items-end gap-2">
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
Deletion request
</span>
);
case path.startsWith("/subadmin"):
return (
<span className="d-flex align-items-end gap-2">
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
Manage SubAdmin
</span>
);
default:
if (path.startsWith("/community/view/")) {
return (
<span className="d-flex align-items-center">
<Link to={"/community/"}>
<ArrowBackIcon className="me-2 fs-3 link p-1 rounded-1" />
</Link>
Community
</span>
);
} else if (path.startsWith("/community/edit/")) {
return (
<span className="d-flex align-items-center">
<Link to={"/community/"}>
<ArrowBackIcon className="me-2 fs-3 link p-1 rounded-1" />
</Link>
Community
</span>
);
}
return "Tanami";
}
};
if (isSplashVisible) {
return <SplashScreen />;
}
const filteredNav = nav.map((item) => {
if (item.submenu) {
return {
...item,
submenu: item.submenu.filter(
(submenuItem) =>
!(!data?.data?.superAdmin && submenuItem.title === "Sub Admin")
),
};
}
return item;
});
return (
<Box
style={{
height: "100vh",
width: "100vw",
position: "relative",
overflow: "hidden",
}}
className="d-flex"
pe={0.5}
>
<Alert
transition={"0.5s"}
h={53}
transform={isOnline ? "translateY(-100px)" : "translateY(0px)"}
position={"absolute"}
zIndex={999}
status="info"
variant="solid"
bgGradient="linear(to-r, red.500, yellow.500, red.500)"
// bgGradient='linear(to-r, #1EBCA3, #22CAB3)'
color={"white"}
fontWeight={600}
fontSize={"md"}
>
<AlertIcon color={"white"} />
No Internet !
</Alert>
{/* <Box
bottom={4}
right={!slideFromRight ? 4 : "auto"}
left={slideFromRight ? 4 : "auto"}
backgroundColor={"#000"}
rounded={"full"}
p={2}
w={8}
h={8}
display={"flex"}
justifyContent={"center"}
alignItems={"center"}
color={"#004118"}
fontWeight={"800"}
cursor={"pointer"}
position={"absolute"}
transition={"0.5s"}
boxShadow={"md"}
onClick={() => setSlideFormRight(!slideFromRight)}
_hover={{
opacity: 1,
}}
zIndex={999}
>
<IoMdSwap />
</Box> */}
{slideFromRight ? null : (
<aside
className="h-100 position-relative sideBar"
// onMouseOver={() => setIsDrawerOpen(true)}
// onMouseLeave={() => setIsDrawerOpen(false)}
style={{
width: isDrawerOpen || openDrawerClick ? 230 : 74,
transition: "width 0.3s ease-in-out", // Smooth transition for width change
// overflow: "hidden",
backgroundColor: "#0041180A",
position: "relative",
// backgroundColor: "#002F0F",
}}
>
<div
className={`d-flex ${
isDrawerOpen || openDrawerClick
? "justify-content-start"
: "justify-content-center"
} p-3 pt-3 pb-3 position-relative `}
height={"10%"}
>
{isDrawerOpen || openDrawerClick ? (
<Image
style={{
width: 110,
}}
src={colorMode === "light" ? logo : logoDark}
alt="Logo"
onClick={() => navigate("/")}
cursor={"pointer"}
/>
) : (
<Image
style={{
width: 30,
}}
src={colorMode === "light" ? logoMini : logoMiniDark}
alt="Logo"
onClick={() => navigate("/")}
cursor={"pointer"}
/>
)}
</div>
<Box
className="ps-2 scroll-bar pe-1 pt-3"
style={{
height: "90%",
overflowY: "scroll",
overflowX: "hidden",
paddingBottom: "5rem",
}}
>
<Accordion
m={0}
allowToggle
defaultIndex={[0]}
index={openIndex}
onChange={handleAccordionChange}
>
{filteredNav.map(({ title, type, Icon, submenu, path }, index) => {
if (type === "accordion") {
return (
<AccordionItem key={index} border={"none"}>
<Tooltip
isDisabled={isDrawerOpen || openDrawerClick}
hasArrow
bg={"#fff"}
fontSize={"xs"}
label={title}
placement="top-start"
color={"blue.800"}
>
<AccordionButton
style={{ height: "auto" }}
className={`${
isDrawerOpen || openDrawerClick
? "p-2 web-text-medium ps-3 justify-content-between"
: "p-2 ps-1 web-text-xlarge justify-content-center"
} rounded-1 link d-flex align-items-center gap-2 w-100 mb-1`}
>
<Box
as="span"
display={"flex"}
gap={2}
alignItems={"center"}
>
{/* {Icon && title === "Admin" ? <Image w={15} src={shield} /> : <Icon className={`web-text-large`} />} */}
{Icon && (
<Icon
fontSize={title === "Admin" ? "18px" : "15px"}
/>
)}
<Text
as={"span"}
display={
isDrawerOpen || openDrawerClick
? "flex"
: "none"
}
alignItems="center"
overflow="hidden"
textAlign={"left"}
>
{title}
</Text>
</Box>
<AccordionIcon />
</AccordionButton>
</Tooltip>
<AccordionPanel
p={0}
pb={1}
display={"flex"}
flexDirection={"column"}
gap={1}
>
{submenu?.map(
(
{ title: subMenuTitle, path: link, icon: SubIcon },
i
) => (
<Tooltip
isDisabled={isDrawerOpen || openDrawerClick}
hasArrow
bg={"#fff"}
fontSize={"xs"}
label={subMenuTitle}
placement="right"
color={"blue.800"}
>
<Box
key={i}
style={{ height: "auto", position: "relative" }}
className={`${
isDrawerOpen || openDrawerClick
? " web-text-medium ps-4"
: " web-text-xlarge justify-content-center"
} d-flex align-items-center p-0`}
>
<Box
backgroundColor={"gray.300"}
style={{
position: "absolute",
top: 0,
width: 2,
left: 22,
height:
i === submenu?.length - 1
? "55%"
: "120%",
borderRadius: "0 0 10px 10px",
}}
/>
<Box
backgroundColor={"gray.300"}
style={{
position: "absolute",
width: 10,
left: 22,
height: 2,
}}
/>
<NavLink
className={`${
isDrawerOpen || openDrawerClick
? "p-2 ps-1 ms-2 web-text-medium "
: "p-2 ps-0 ms-0 zindex-3 ms-4 web-text-xlarge justify-content-center"
} rounded-1 link d-flex align-items-center gap-2 w-100 `}
to={link}
>
{SubIcon && (
<SubIcon
className="web-text-large ms-2"
style={{ zIndex: 111 }}
/>
)}
<Text
as={"span"}
display={
isDrawerOpen || openDrawerClick
? "flex"
: "none"
}
alignItems="center"
overflow="hidden"
>
{subMenuTitle === "Aprover Request"
? data?.data?.role === "Maker"
? "Create Request"
: "Aprover Request"
: subMenuTitle}
</Text>
</NavLink>
</Box>
</Tooltip>
)
)}
</AccordionPanel>
</AccordionItem>
);
} else if (type === "title") {
return (
<Text
as={"span"}
key={index}
className="web-text-xxsmall fw-600 text-secondary fw-bold"
>
{title}
</Text>
);
} else if (type === "single") {
return (
<Tooltip
hasArrow
bg={"#fff"}
fontSize={"xs"}
label={title}
placement="top-start"
color={"blue.800"}
>
<NavLink
key={index}
style={{ height: "auto", position: "relative" }}
className={`${
isDrawerOpen || openDrawerClick
? "p-2 web-text-medium"
: "p-2 ps-0 web-text-xlarge justify-content-start"
} rounded-1 link d-flex align-items-center gap-2 w-100`}
to={path}
>
{Icon && <Icon className="web-text-large ms-2" />}
<Text
as={"span"}
display={
isDrawerOpen || openDrawerClick ? "flex" : "none"
}
alignItems="center"
overflow="hidden"
>
{title}
</Text>
</NavLink>
</Tooltip>
);
} else {
return null;
}
})}
</Accordion>
</Box>
<Button
colorScheme={"forestGreen"}
rounded={"lg"}
// onMouseOver={() => setIsDrawerOpen(true)}
// onMouseLeave={() => setIsDrawerOpen(false)}
onClick={openDrawerOnClick}
style={{
width: 18,
height: 26,
position: "absolute",
right: -19,
bottom: 28,
zIndex: 99,
}}
>
{isDrawerOpen || openDrawerClick ? (
<ArrowLeftIcon className="web-text-small" />
) : (
<ArrowRightIcon className="web-text-small " />
)}
</Button>
{/* <Text textAlign={'center'} fontWeight={500} fontSize={'xs'} color={"gray.600"}>{getCountdownTimer(localStorage.getItem('accessTokenExp'))}</Text> */}
</aside>
)}
<main
className={`h-100 ${
slideFromRight ? "pe-3" : "ps-3"
} d-flex flex-column gap-0`}
style={{
width: `calc(100% - ${isDrawerOpen || openDrawerClick ? 230 : 74}px)`,
transition: "width 0.3s ease-in-out",
}}
>
{/* <header className="p-2 ps-0 pt-3 fw-400 border-bottom">
<span className="fs-5">{getTitle()}</span>
</header> */}
<HeaderMain
data={data}
slideDirecttion={slideFromRight}
logOutHandler={logOutHandler}
icon
title={getTitle()}
/>
{/* <CustomBreadcrumb /> */}
<AppContent data={data} />
</main>
</Box>
);
};
export default DashboardLayout;
const AppContent = ({ data }) => {
return (
<Routes>
{RouteLink.map(({ path, Component }, index) => (
<Route key={index} path={path} element={<Component />} />
))}
<Route
path="/fawateer"
element={
data?.data?.role === "Maker" ? <CreateRequest /> : <ApproveRequest />
}
/>
<Route
path="/fawateer-history"
element={
data?.data?.role === "Maker" ? (
<ApproveHistoryMaker />
) : (
<ApproveHistory />
)
}
/>
<Route path="*" element={<NotFound />} />
</Routes>
);
};