New Frontend Preps

This commit is contained in:
root
2025-10-15 14:57:39 +00:00
parent d776b80fe0
commit f8209c3712
102 changed files with 4065 additions and 65 deletions
+3
View File
@@ -0,0 +1,3 @@
export * from "@/widgets/cards/statistics-card";
export * from "@/widgets/cards/profile-info-card";
export * from "@/widgets/cards/message-card";
@@ -0,0 +1,45 @@
import PropTypes from "prop-types";
import { Avatar, Typography } from "@material-tailwind/react";
export function MessageCard({ img, name, message, action }) {
return (
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-4">
<Avatar
src={img}
alt={name}
variant="rounded"
className="shadow-lg shadow-blue-gray-500/25"
/>
<div>
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-semibold"
>
{name}
</Typography>
<Typography className="text-xs font-normal text-blue-gray-400">
{message}
</Typography>
</div>
</div>
{action}
</div>
);
}
MessageCard.defaultProps = {
action: null,
};
MessageCard.propTypes = {
img: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
message: PropTypes.node.isRequired,
action: PropTypes.node,
};
MessageCard.displayName = "/src/widgets/cards/message-card.jsx";
export default MessageCard;
@@ -0,0 +1,79 @@
import PropTypes from "prop-types";
import {
Card,
CardHeader,
CardBody,
Typography,
} from "@material-tailwind/react";
export function ProfileInfoCard({ title, description, details, action }) {
return (
<Card color="transparent" shadow={false}>
<CardHeader
color="transparent"
shadow={false}
floated={false}
className="mx-0 mt-0 mb-4 flex items-center justify-between gap-4"
>
<Typography variant="h6" color="blue-gray">
{title}
</Typography>
{action}
</CardHeader>
<CardBody className="p-0">
{description && (
<Typography
variant="small"
className="font-normal text-blue-gray-500"
>
{description}
</Typography>
)}
{description && details ? (
<hr className="my-8 border-blue-gray-50" />
) : null}
{details && (
<ul className="flex flex-col gap-4 p-0">
{Object.keys(details).map((el, key) => (
<li key={key} className="flex items-center gap-4">
<Typography
variant="small"
color="blue-gray"
className="font-semibold capitalize"
>
{el}:
</Typography>
{typeof details[el] === "string" ? (
<Typography
variant="small"
className="font-normal text-blue-gray-500"
>
{details[el]}
</Typography>
) : (
details[el]
)}
</li>
))}
</ul>
)}
</CardBody>
</Card>
);
}
ProfileInfoCard.defaultProps = {
action: null,
description: null,
details: {},
};
ProfileInfoCard.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.node,
details: PropTypes.object,
};
ProfileInfoCard.displayName = "/src/widgets/cards/profile-info-card.jsx";
export default ProfileInfoCard;
@@ -0,0 +1,75 @@
import {
Card,
CardHeader,
CardBody,
CardFooter,
Typography,
} from "@material-tailwind/react";
import PropTypes from "prop-types";
export function StatisticsCard({ color, icon, title, value, footer }) {
return (
<Card className="border border-blue-gray-100 shadow-sm">
<CardHeader
variant="gradient"
color={color}
floated={false}
shadow={false}
className="absolute grid h-12 w-12 place-items-center"
>
{icon}
</CardHeader>
<CardBody className="p-4 text-right">
<Typography variant="small" className="font-normal text-blue-gray-600">
{title}
</Typography>
<Typography variant="h4" color="blue-gray">
{value}
</Typography>
</CardBody>
{footer && (
<CardFooter className="border-t border-blue-gray-50 p-4">
{footer}
</CardFooter>
)}
</Card>
);
}
StatisticsCard.defaultProps = {
color: "blue",
footer: null,
};
StatisticsCard.propTypes = {
color: PropTypes.oneOf([
"white",
"blue-gray",
"gray",
"brown",
"deep-orange",
"orange",
"amber",
"yellow",
"lime",
"light-green",
"green",
"teal",
"cyan",
"light-blue",
"blue",
"indigo",
"deep-purple",
"purple",
"pink",
"red",
]),
icon: PropTypes.node.isRequired,
title: PropTypes.node.isRequired,
value: PropTypes.node.isRequired,
footer: PropTypes.node,
};
StatisticsCard.displayName = "/src/widgets/cards/statistics-card.jsx";
export default StatisticsCard;
+1
View File
@@ -0,0 +1 @@
export * from "@/widgets/charts/statistics-chart";
@@ -0,0 +1,70 @@
import {
Card,
CardHeader,
CardBody,
CardFooter,
Typography,
} from "@material-tailwind/react";
import PropTypes from "prop-types";
import Chart from "react-apexcharts";
export function StatisticsChart({ color, chart, title, description, footer }) {
return (
<Card className="border border-blue-gray-100 shadow-sm">
<CardHeader variant="gradient" color={color} floated={false} shadow={false}>
<Chart {...chart} />
</CardHeader>
<CardBody className="px-6 pt-0">
<Typography variant="h6" color="blue-gray">
{title}
</Typography>
<Typography variant="small" className="font-normal text-blue-gray-600">
{description}
</Typography>
</CardBody>
{footer && (
<CardFooter className="border-t border-blue-gray-50 px-6 py-5">
{footer}
</CardFooter>
)}
</Card>
);
}
StatisticsChart.defaultProps = {
color: "blue",
footer: null,
};
StatisticsChart.propTypes = {
color: PropTypes.oneOf([
"white",
"blue-gray",
"gray",
"brown",
"deep-orange",
"orange",
"amber",
"yellow",
"lime",
"light-green",
"green",
"teal",
"cyan",
"light-blue",
"blue",
"indigo",
"deep-purple",
"purple",
"pink",
"red",
]),
chart: PropTypes.object.isRequired,
title: PropTypes.node.isRequired,
description: PropTypes.node.isRequired,
footer: PropTypes.node,
};
StatisticsChart.displayName = "/src/widgets/charts/statistics-chart.jsx";
export default StatisticsChart;
@@ -0,0 +1,237 @@
import React from "react";
import { XMarkIcon } from "@heroicons/react/24/outline";
import {
Button,
IconButton,
Switch,
Typography,
Chip,
} from "@material-tailwind/react";
import {
useMaterialTailwindController,
setOpenConfigurator,
setSidenavColor,
setSidenavType,
setFixedNavbar,
} from "@/context";
function formatNumber(number, decPlaces) {
decPlaces = Math.pow(10, decPlaces);
const abbrev = ["K", "M", "B", "T"];
for (let i = abbrev.length - 1; i >= 0; i--) {
var size = Math.pow(10, (i + 1) * 3);
if (size <= number) {
number = Math.round((number * decPlaces) / size) / decPlaces;
if (number == 1000 && i < abbrev.length - 1) {
number = 1;
i++;
}
number += abbrev[i];
break;
}
}
return number;
}
export function Configurator() {
const [controller, dispatch] = useMaterialTailwindController();
const { openConfigurator, sidenavColor, sidenavType, fixedNavbar } =
controller;
const [stars, setStars] = React.useState(0);
const sidenavColors = {
white: "from-gray-100 to-gray-100 border-gray-200",
dark: "from-black to-black border-gray-200",
green: "from-green-400 to-green-600",
orange: "from-orange-400 to-orange-600",
red: "from-red-400 to-red-600",
pink: "from-pink-400 to-pink-600",
};
React.useEffect(() => {
const stars = fetch(
"https://api.github.com/repos/creativetimofficial/material-tailwind-dashboard-react"
)
.then((response) => response.json())
.then((data) => setStars(formatNumber(data.stargazers_count, 1)));
}, []);
return (
<aside
className={`fixed top-0 right-0 z-50 h-screen w-96 bg-white px-2.5 shadow-lg transition-transform duration-300 ${
openConfigurator ? "translate-x-0" : "translate-x-96"
}`}
>
<div className="flex items-start justify-between px-6 pt-8 pb-6">
<div>
<Typography variant="h5" color="blue-gray">
Dashboard Configurator
</Typography>
<Typography className="font-normal text-blue-gray-600">
See our dashboard options.
</Typography>
</div>
<IconButton
variant="text"
color="blue-gray"
onClick={() => setOpenConfigurator(dispatch, false)}
>
<XMarkIcon strokeWidth={2.5} className="h-5 w-5" />
</IconButton>
</div>
<div className="py-4 px-6">
<div className="mb-12">
<Typography variant="h6" color="blue-gray">
Sidenav Colors
</Typography>
<div className="mt-3 flex items-center gap-2">
{Object.keys(sidenavColors).map((color) => (
<span
key={color}
className={`h-6 w-6 cursor-pointer rounded-full border bg-gradient-to-br transition-transform hover:scale-105 ${
sidenavColors[color]
} ${
sidenavColor === color ? "border-black" : "border-transparent"
}`}
onClick={() => setSidenavColor(dispatch, color)}
/>
))}
</div>
</div>
<div className="mb-12">
<Typography variant="h6" color="blue-gray">
Sidenav Types
</Typography>
<Typography variant="small" color="gray">
Choose between 3 different sidenav types.
</Typography>
<div className="mt-3 flex items-center gap-2">
<Button
variant={sidenavType === "dark" ? "gradient" : "outlined"}
onClick={() => setSidenavType(dispatch, "dark")}
>
Dark
</Button>
<Button
variant={sidenavType === "transparent" ? "gradient" : "outlined"}
onClick={() => setSidenavType(dispatch, "transparent")}
>
Transparent
</Button>
<Button
variant={sidenavType === "white" ? "gradient" : "outlined"}
onClick={() => setSidenavType(dispatch, "white")}
>
White
</Button>
</div>
</div>
<div className="mb-12">
<hr />
<div className="flex items-center justify-between py-5">
<Typography variant="h6" color="blue-gray">
Navbar Fixed
</Typography>
<Switch
id="navbar-fixed"
value={fixedNavbar}
onChange={() => setFixedNavbar(dispatch, !fixedNavbar)}
/>
</div>
<hr />
<div className="my-8 flex flex-col gap-4">
<a
href="https://www.creative-tim.com/product/material-tailwind-dashboard-react?rel=mtdr"
target="_black"
>
<Button variant="gradient" fullWidth>
Free Download
</Button>
</a>
<a
href="https://www.material-tailwind.com/docs/react/installation?rel=mtdr"
target="_black"
>
<Button variant="outlined" color="blue-gray" fullWidth>
View Documentation
</Button>
</a>
<a
href="https://www.material-tailwind.com/blocks/react?rel=mtdr"
target="_black"
>
<Button variant="outlined" color="blue-gray" fullWidth>
Material Tailwind PRO
</Button>
</a>
</div>
<a
className="mx-auto flex items-center justify-center gap-2"
href="https://github.com/creativetimofficial/material-tailwind-dashboard-react"
target="_blank"
rel="noreferrer"
>
<Chip
value={`${stars} - Stars`}
icon={
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="mt-px ml-1.5 h-4 w-4"
>
<path
fillRule="evenodd"
d="M10.868 2.884c-.321-.772-1.415-.772-1.736 0l-1.83 4.401-4.753.381c-.833.067-1.171 1.107-.536 1.651l3.62 3.102-1.106 4.637c-.194.813.691 1.456 1.405 1.02L10 15.591l4.069 2.485c.713.436 1.598-.207 1.404-1.02l-1.106-4.637 3.62-3.102c.635-.544.297-1.584-.536-1.65l-4.752-.382-1.831-4.401z"
clipRule="evenodd"
/>
</svg>
}
className="bg-blue-gray-900 px-4"
/>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
</a>
</div>
<div className="text-center">
<Typography variant="h6" color="blue-gray">
Thank you for sharing
</Typography>
<div className="mt-4 flex justify-center gap-2">
<Button
variant="gradient"
className="flex items-center gap-2"
>
<i className="fa-brands fa-twitter text-white" />
Tweet
</Button>
<Button
variant="gradient"
className="flex items-center gap-2"
>
<i className="fa-brands fa-facebook text-white" />
Share
</Button>
</div>
</div>
</div>
</aside>
);
}
Configurator.displayName = "/src/widgets/layout/configurator.jsx";
export default Configurator;
@@ -0,0 +1,196 @@
import { useLocation, Link } from "react-router-dom";
import {
Navbar,
Typography,
Button,
IconButton,
Breadcrumbs,
Input,
Menu,
MenuHandler,
MenuList,
MenuItem,
Avatar,
} from "@material-tailwind/react";
import {
UserCircleIcon,
Cog6ToothIcon,
BellIcon,
ClockIcon,
CreditCardIcon,
Bars3Icon,
} from "@heroicons/react/24/solid";
import {
useMaterialTailwindController,
setOpenConfigurator,
setOpenSidenav,
} from "@/context";
export function DashboardNavbar() {
const [controller, dispatch] = useMaterialTailwindController();
const { fixedNavbar, openSidenav } = controller;
const { pathname } = useLocation();
const [layout, page] = pathname.split("/").filter((el) => el !== "");
return (
<Navbar
color={fixedNavbar ? "white" : "transparent"}
className={`rounded-xl transition-all ${
fixedNavbar
? "sticky top-4 z-40 py-3 shadow-md shadow-blue-gray-500/5"
: "px-0 py-1"
}`}
fullWidth
blurred={fixedNavbar}
>
<div className="flex flex-col-reverse justify-between gap-6 md:flex-row md:items-center">
<div className="capitalize">
<Breadcrumbs
className={`bg-transparent p-0 transition-all ${
fixedNavbar ? "mt-1" : ""
}`}
>
<Link to={`/${layout}`}>
<Typography
variant="small"
color="blue-gray"
className="font-normal opacity-50 transition-all hover:text-blue-500 hover:opacity-100"
>
{layout}
</Typography>
</Link>
<Typography
variant="small"
color="blue-gray"
className="font-normal"
>
{page}
</Typography>
</Breadcrumbs>
<Typography variant="h6" color="blue-gray">
{page}
</Typography>
</div>
<div className="flex items-center">
<div className="mr-auto md:mr-4 md:w-56">
<Input label="Search" />
</div>
<IconButton
variant="text"
color="blue-gray"
className="grid xl:hidden"
onClick={() => setOpenSidenav(dispatch, !openSidenav)}
>
<Bars3Icon strokeWidth={3} className="h-6 w-6 text-blue-gray-500" />
</IconButton>
<Link to="/auth/sign-in">
<Button
variant="text"
color="blue-gray"
className="hidden items-center gap-1 px-4 xl:flex normal-case"
>
<UserCircleIcon className="h-5 w-5 text-blue-gray-500" />
Sign In
</Button>
<IconButton
variant="text"
color="blue-gray"
className="grid xl:hidden"
>
<UserCircleIcon className="h-5 w-5 text-blue-gray-500" />
</IconButton>
</Link>
<Menu>
<MenuHandler>
<IconButton variant="text" color="blue-gray">
<BellIcon className="h-5 w-5 text-blue-gray-500" />
</IconButton>
</MenuHandler>
<MenuList className="w-max border-0">
<MenuItem className="flex items-center gap-3">
<Avatar
src="https://demos.creative-tim.com/material-dashboard/assets/img/team-2.jpg"
alt="item-1"
size="sm"
variant="circular"
/>
<div>
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-normal"
>
<strong>New message</strong> from Laur
</Typography>
<Typography
variant="small"
color="blue-gray"
className="flex items-center gap-1 text-xs font-normal opacity-60"
>
<ClockIcon className="h-3.5 w-3.5" /> 13 minutes ago
</Typography>
</div>
</MenuItem>
<MenuItem className="flex items-center gap-4">
<Avatar
src="https://demos.creative-tim.com/material-dashboard/assets/img/small-logos/logo-spotify.svg"
alt="item-1"
size="sm"
variant="circular"
/>
<div>
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-normal"
>
<strong>New album</strong> by Travis Scott
</Typography>
<Typography
variant="small"
color="blue-gray"
className="flex items-center gap-1 text-xs font-normal opacity-60"
>
<ClockIcon className="h-3.5 w-3.5" /> 1 day ago
</Typography>
</div>
</MenuItem>
<MenuItem className="flex items-center gap-4">
<div className="grid h-9 w-9 place-items-center rounded-full bg-gradient-to-tr from-blue-gray-800 to-blue-gray-900">
<CreditCardIcon className="h-4 w-4 text-white" />
</div>
<div>
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-normal"
>
Payment successfully completed
</Typography>
<Typography
variant="small"
color="blue-gray"
className="flex items-center gap-1 text-xs font-normal opacity-60"
>
<ClockIcon className="h-3.5 w-3.5" /> 2 days ago
</Typography>
</div>
</MenuItem>
</MenuList>
</Menu>
<IconButton
variant="text"
color="blue-gray"
onClick={() => setOpenConfigurator(dispatch, true)}
>
<Cog6ToothIcon className="h-5 w-5 text-blue-gray-500" />
</IconButton>
</div>
</div>
</Navbar>
);
}
DashboardNavbar.displayName = "/src/widgets/layout/dashboard-navbar.jsx";
export default DashboardNavbar;
+62
View File
@@ -0,0 +1,62 @@
import PropTypes from "prop-types";
import { Typography } from "@material-tailwind/react";
import { HeartIcon } from "@heroicons/react/24/solid";
export function Footer({ brandName, brandLink, routes }) {
const year = new Date().getFullYear();
return (
<footer className="py-2">
<div className="flex w-full flex-wrap items-center justify-center gap-6 px-2 md:justify-between">
<Typography variant="small" className="font-normal text-inherit">
&copy; {year}, made with{" "}
<HeartIcon className="-mt-0.5 inline-block h-3.5 w-3.5 text-red-600" /> by{" "}
<a
href={brandLink}
target="_blank"
className="transition-colors hover:text-blue-500 font-bold"
>
{brandName}
</a>{" "}
for a better web.
</Typography>
<ul className="flex items-center gap-4">
{routes.map(({ name, path }) => (
<li key={name}>
<Typography
as="a"
href={path}
target="_blank"
variant="small"
className="py-0.5 px-1 font-normal text-inherit transition-colors hover:text-blue-500"
>
{name}
</Typography>
</li>
))}
</ul>
</div>
</footer>
);
}
Footer.defaultProps = {
brandName: "Creative Tim",
brandLink: "https://www.creative-tim.com",
routes: [
{ name: "Creative Tim", path: "https://www.creative-tim.com" },
{ name: "About Us", path: "https://www.creative-tim.com/presentation" },
{ name: "Blog", path: "https://www.creative-tim.com/blog" },
{ name: "License", path: "https://www.creative-tim.com/license" },
],
};
Footer.propTypes = {
brandName: PropTypes.string,
brandLink: PropTypes.string,
routes: PropTypes.arrayOf(PropTypes.object),
};
Footer.displayName = "/src/widgets/layout/footer.jsx";
export default Footer;
+5
View File
@@ -0,0 +1,5 @@
export * from "@/widgets/layout/sidenav";
export * from "@/widgets/layout/dashboard-navbar";
export * from "@/widgets/layout/configurator";
export * from "@/widgets/layout/footer";
export * from "@/widgets/layout/navbar";
+107
View File
@@ -0,0 +1,107 @@
import React from "react";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import {
Navbar as MTNavbar,
Collapse,
Typography,
Button,
IconButton,
} from "@material-tailwind/react";
import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline";
export function Navbar({ brandName, routes, action }) {
const [openNav, setOpenNav] = React.useState(false);
React.useEffect(() => {
window.addEventListener(
"resize",
() => window.innerWidth >= 960 && setOpenNav(false)
);
}, []);
const navList = (
<ul className="mb-4 mt-2 flex flex-col gap-2 lg:mb-0 lg:mt-0 lg:flex-row lg:items-center lg:gap-6">
{routes.map(({ name, path, icon }) => (
<Typography
key={name}
as="li"
variant="small"
color="blue-gray"
className="capitalize"
>
<Link to={path} className="flex items-center gap-1 p-1 font-normal">
{icon &&
React.createElement(icon, {
className: "w-[18px] h-[18px] opacity-50 mr-1",
})}
{name}
</Link>
</Typography>
))}
</ul>
);
return (
<MTNavbar className="p-3">
<div className="container mx-auto flex items-center justify-between text-blue-gray-900">
<Link to="/">
<Typography
variant="small"
className="mr-4 ml-2 cursor-pointer py-1.5 font-bold"
>
{brandName}
</Typography>
</Link>
<div className="hidden lg:block">{navList}</div>
{React.cloneElement(action, {
className: "hidden lg:inline-block",
})}
<IconButton
variant="text"
size="sm"
className="ml-auto text-inherit hover:bg-transparent focus:bg-transparent active:bg-transparent lg:hidden"
onClick={() => setOpenNav(!openNav)}
>
{openNav ? (
<XMarkIcon strokeWidth={2} className="h-6 w-6" />
) : (
<Bars3Icon strokeWidth={2} className="h-6 w-6" />
)}
</IconButton>
</div>
<Collapse open={openNav}>
<div className="container mx-auto">
{navList}
{React.cloneElement(action, {
className: "w-full block lg:hidden",
})}
</div>
</Collapse>
</MTNavbar>
);
}
Navbar.defaultProps = {
brandName: "Material Tailwind React",
action: (
<a
href="https://www.creative-tim.com/product/material-tailwind-dashboard-react"
target="_blank"
>
<Button variant="gradient" size="sm" fullWidth>
free download
</Button>
</a>
),
};
Navbar.propTypes = {
brandName: PropTypes.string,
routes: PropTypes.arrayOf(PropTypes.object).isRequired,
action: PropTypes.node,
};
Navbar.displayName = "/src/widgets/layout/navbar.jsx";
export default Navbar;
+111
View File
@@ -0,0 +1,111 @@
import PropTypes from "prop-types";
import { Link, NavLink } from "react-router-dom";
import { XMarkIcon } from "@heroicons/react/24/outline";
import {
Avatar,
Button,
IconButton,
Typography,
} from "@material-tailwind/react";
import { useMaterialTailwindController, setOpenSidenav } from "@/context";
export function Sidenav({ brandImg, brandName, routes }) {
const [controller, dispatch] = useMaterialTailwindController();
const { sidenavColor, sidenavType, openSidenav } = controller;
const sidenavTypes = {
dark: "bg-gradient-to-br from-gray-800 to-gray-900",
white: "bg-white shadow-sm",
transparent: "bg-transparent",
};
return (
<aside
className={`${sidenavTypes[sidenavType]} ${
openSidenav ? "translate-x-0" : "-translate-x-80"
} fixed inset-0 z-50 my-4 ml-4 h-[calc(100vh-32px)] w-72 rounded-xl transition-transform duration-300 xl:translate-x-0 border border-blue-gray-100`}
>
<div
className={`relative`}
>
<Link to="/" className="py-6 px-8 text-center">
<Typography
variant="h6"
color={sidenavType === "dark" ? "white" : "blue-gray"}
>
{brandName}
</Typography>
</Link>
<IconButton
variant="text"
color="white"
size="sm"
ripple={false}
className="absolute right-0 top-0 grid rounded-br-none rounded-tl-none xl:hidden"
onClick={() => setOpenSidenav(dispatch, false)}
>
<XMarkIcon strokeWidth={2.5} className="h-5 w-5 text-white" />
</IconButton>
</div>
<div className="m-4">
{routes.map(({ layout, title, pages }, key) => (
<ul key={key} className="mb-4 flex flex-col gap-1">
{title && (
<li className="mx-3.5 mt-4 mb-2">
<Typography
variant="small"
color={sidenavType === "dark" ? "white" : "blue-gray"}
className="font-black uppercase opacity-75"
>
{title}
</Typography>
</li>
)}
{pages.map(({ icon, name, path }) => (
<li key={name}>
<NavLink to={`/${layout}${path}`}>
{({ isActive }) => (
<Button
variant={isActive ? "gradient" : "text"}
color={
isActive
? sidenavColor
: sidenavType === "dark"
? "white"
: "blue-gray"
}
className="flex items-center gap-4 px-4 capitalize"
fullWidth
>
{icon}
<Typography
color="inherit"
className="font-medium capitalize"
>
{name}
</Typography>
</Button>
)}
</NavLink>
</li>
))}
</ul>
))}
</div>
</aside>
);
}
Sidenav.defaultProps = {
brandImg: "/img/logo-ct.png",
brandName: "Material Tailwind React",
};
Sidenav.propTypes = {
brandImg: PropTypes.string,
brandName: PropTypes.string,
routes: PropTypes.arrayOf(PropTypes.object).isRequired,
};
Sidenav.displayName = "/src/widgets/layout/sidnave.jsx";
export default Sidenav;