More management tools
This commit is contained in:
@@ -1,15 +1,30 @@
|
||||
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { AppShell, Burger, Group, Text, NavLink, Button, Avatar, Stack, Badge } from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import {
|
||||
IconDashboard,
|
||||
IconUsers,
|
||||
IconWebhook,
|
||||
IconBrandWhatsapp,
|
||||
IconFileText,
|
||||
IconLogout
|
||||
} from '@tabler/icons-react';
|
||||
import { useAuthStore } from '../stores/authStore';
|
||||
import { Outlet, useNavigate, useLocation } from "react-router-dom";
|
||||
import {
|
||||
AppShell,
|
||||
Burger,
|
||||
Group,
|
||||
Text,
|
||||
NavLink,
|
||||
Button,
|
||||
Avatar,
|
||||
Stack,
|
||||
Badge,
|
||||
} from "@mantine/core";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import {
|
||||
IconDashboard,
|
||||
IconUsers,
|
||||
IconWebhook,
|
||||
IconBrandWhatsapp,
|
||||
IconSend,
|
||||
IconBuildingStore,
|
||||
IconTemplate,
|
||||
IconCategory,
|
||||
IconArrowsShuffle,
|
||||
IconFileText,
|
||||
IconLogout,
|
||||
} from "@tabler/icons-react";
|
||||
import { useAuthStore } from "../stores/authStore";
|
||||
|
||||
export default function DashboardLayout() {
|
||||
const { user, logout } = useAuthStore();
|
||||
@@ -19,27 +34,19 @@ export default function DashboardLayout() {
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
navigate('/login');
|
||||
navigate("/login");
|
||||
};
|
||||
|
||||
const isActive = (path: string) => {
|
||||
return location.pathname === path;
|
||||
};
|
||||
|
||||
const navItems = [
|
||||
{ path: '/dashboard', label: 'Dashboard', icon: IconDashboard },
|
||||
{ path: '/users', label: 'Users', icon: IconUsers },
|
||||
{ path: '/hooks', label: 'Hooks', icon: IconWebhook },
|
||||
{ path: '/accounts', label: 'WhatsApp Accounts', icon: IconBrandWhatsapp },
|
||||
{ path: '/event-logs', label: 'Event Logs', icon: IconFileText },
|
||||
];
|
||||
const isActive = (path: string) => location.pathname === path;
|
||||
const isAnyActive = (paths: string[]) =>
|
||||
paths.some((path) => location.pathname === path);
|
||||
|
||||
return (
|
||||
<AppShell
|
||||
header={{ height: 60 }}
|
||||
navbar={{
|
||||
width: 280,
|
||||
breakpoint: 'sm',
|
||||
breakpoint: "sm",
|
||||
collapsed: { mobile: !opened },
|
||||
}}
|
||||
padding="md"
|
||||
@@ -47,14 +54,25 @@ export default function DashboardLayout() {
|
||||
<AppShell.Header>
|
||||
<Group h="100%" px="md" justify="space-between">
|
||||
<Group>
|
||||
<Burger opened={opened} onClick={toggle} hiddenFrom="sm" size="sm" />
|
||||
<Text size="xl" fw={700}>WhatsHooked</Text>
|
||||
<Badge color="blue" variant="light">Admin</Badge>
|
||||
<Burger
|
||||
opened={opened}
|
||||
onClick={toggle}
|
||||
hiddenFrom="sm"
|
||||
size="sm"
|
||||
/>
|
||||
<Text size="xl" fw={700}>
|
||||
WhatsHooked
|
||||
</Text>
|
||||
<Badge color="blue" variant="light">
|
||||
Admin
|
||||
</Badge>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text size="sm" c="dimmed">{user?.username || 'User'}</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
{user?.username || "User"}
|
||||
</Text>
|
||||
<Avatar color="blue" radius="xl" size="sm">
|
||||
{user?.username?.[0]?.toUpperCase() || 'U'}
|
||||
{user?.username?.[0]?.toUpperCase() || "U"}
|
||||
</Avatar>
|
||||
</Group>
|
||||
</Group>
|
||||
@@ -63,20 +81,147 @@ export default function DashboardLayout() {
|
||||
<AppShell.Navbar p="md">
|
||||
<AppShell.Section grow>
|
||||
<Stack gap="xs">
|
||||
{navItems.map((item) => (
|
||||
<NavLink
|
||||
href="/dashboard"
|
||||
label="Dashboard"
|
||||
leftSection={<IconDashboard size={20} stroke={1.5} />}
|
||||
active={isActive("/dashboard")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/dashboard");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
<NavLink
|
||||
href="/users"
|
||||
label="Users"
|
||||
leftSection={<IconUsers size={20} stroke={1.5} />}
|
||||
active={isActive("/users")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/users");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
<NavLink
|
||||
href="/hooks"
|
||||
label="Hooks"
|
||||
leftSection={<IconWebhook size={20} stroke={1.5} />}
|
||||
active={isActive("/hooks")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/hooks");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
<NavLink
|
||||
label="WhatsApp Accounts"
|
||||
leftSection={<IconBrandWhatsapp size={20} stroke={1.5} />}
|
||||
defaultOpened
|
||||
active={isAnyActive([
|
||||
"/accounts",
|
||||
"/whatsapp-business",
|
||||
"/business-templates",
|
||||
"/catalogs",
|
||||
"/flows",
|
||||
])}
|
||||
>
|
||||
<NavLink
|
||||
key={item.path}
|
||||
href={item.path}
|
||||
label={item.label}
|
||||
leftSection={<item.icon size={20} stroke={1.5} />}
|
||||
active={isActive(item.path)}
|
||||
href="/accounts"
|
||||
label="Account List"
|
||||
active={isActive("/accounts")}
|
||||
leftSection={
|
||||
<IconBrandWhatsapp size={20} stroke={1.5} color="green" />
|
||||
}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate(item.path);
|
||||
navigate("/accounts");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<NavLink
|
||||
label="Business Management"
|
||||
leftSection={
|
||||
<IconBrandWhatsapp size={20} stroke={1.5} color="orange" />
|
||||
}
|
||||
defaultOpened
|
||||
active={isAnyActive([
|
||||
"/whatsapp-business",
|
||||
"/business-templates",
|
||||
"/catalogs",
|
||||
"/flows",
|
||||
])}
|
||||
>
|
||||
<NavLink
|
||||
href="/whatsapp-business"
|
||||
label="Business Management Tools"
|
||||
active={isActive("/whatsapp-business")}
|
||||
leftSection={<IconBuildingStore size={16} stroke={1.5} />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/whatsapp-business");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
<NavLink
|
||||
href="/business-templates"
|
||||
label="Templates"
|
||||
leftSection={<IconTemplate size={16} stroke={1.5} />}
|
||||
active={isActive("/business-templates")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/business-templates");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
<NavLink
|
||||
href="/catalogs"
|
||||
label="Catalogs"
|
||||
leftSection={<IconCategory size={16} stroke={1.5} />}
|
||||
active={isActive("/catalogs")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/catalogs");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
<NavLink
|
||||
href="/flows"
|
||||
label="Flows"
|
||||
leftSection={<IconArrowsShuffle size={16} stroke={1.5} />}
|
||||
active={isActive("/flows")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/flows");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
</NavLink>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
href="/send-message"
|
||||
label="Send Message"
|
||||
leftSection={<IconSend size={20} stroke={1.5} color="green" />}
|
||||
active={isActive("/send-message")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/send-message");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
<NavLink
|
||||
href="/event-logs"
|
||||
label="Event Logs"
|
||||
leftSection={
|
||||
<IconFileText size={20} stroke={1.5} color="maroon" />
|
||||
}
|
||||
active={isActive("/event-logs")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate("/event-logs");
|
||||
if (opened) toggle();
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
</AppShell.Section>
|
||||
|
||||
@@ -84,8 +229,12 @@ export default function DashboardLayout() {
|
||||
<Stack gap="xs">
|
||||
<Group justify="space-between" px="sm">
|
||||
<div>
|
||||
<Text size="sm" fw={500}>{user?.username || 'User'}</Text>
|
||||
<Text size="xs" c="dimmed">{user?.role || 'user'}</Text>
|
||||
<Text size="sm" fw={500}>
|
||||
{user?.username || "User"}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
{user?.role || "user"}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user