import { mdiAccountCircle, mdiAccountGroup, mdiBookOpenVariant, mdiClose, mdiFileDocumentEditOutline, mdiFormTextbox, mdiLogout, mdiMenu, mdiShieldAccountOutline, mdiViewDashboardOutline, } from '@mdi/js'; import jwt from 'jsonwebtoken'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { ReactNode, useEffect, useState } from 'react'; import BaseIcon from '../components/BaseIcon'; import { hasPermission } from '../helpers/userPermissions'; import { findMe, logoutUser } from '../stores/authSlice'; import { useAppDispatch, useAppSelector } from '../stores/hooks'; type Props = { children: ReactNode; permission?: string; }; const navItems = [ { href: '/dashboard', icon: mdiViewDashboardOutline, label: 'Dashboard', }, { href: '/clients', icon: mdiAccountGroup, label: 'Clients', }, { href: '/session-memory', icon: mdiFileDocumentEditOutline, label: 'Session Memory', }, { href: '/intake-leads', icon: mdiFormTextbox, label: 'Intake Leads', }, { href: '/client-portal', icon: mdiBookOpenVariant, label: 'Client Portal', }, { href: '/users/users-list', icon: mdiShieldAccountOutline, label: 'Team', permission: 'READ_USERS', }, { href: '/profile', icon: mdiAccountCircle, label: 'Profile', }, ]; export default function LayoutAuthenticated({ children, permission }: Props) { const dispatch = useAppDispatch(); const router = useRouter(); const { token, currentUser } = useAppSelector((state) => state.auth); const [isAsideOpen, setIsAsideOpen] = useState(false); const isClientUser = currentUser?.app_role?.name === 'Client'; function getLocalToken() { if (typeof window === 'undefined') { return null; } return localStorage.getItem('token'); } function isTokenValid() { const localToken = getLocalToken(); if (!localToken) { return false; } const decodedToken = jwt.decode(localToken); if (!decodedToken || typeof decodedToken === 'string') { return false; } if (!decodedToken.exp) { return false; } const now = new Date().getTime() / 1000; return now < decodedToken.exp; } useEffect(() => { dispatch(findMe()); if (!isTokenValid()) { dispatch(logoutUser()); router.push('/login'); } }, [token]); useEffect(() => { if (!permission || !currentUser) { return; } if (!hasPermission(currentUser, permission)) { router.push('/error'); } }, [currentUser, permission]); useEffect(() => { if (!isClientUser) { return; } if ( router.pathname === '/client-portal' || router.pathname === '/profile' ) { return; } router.push('/client-portal'); }, [isClientUser, router.pathname]); useEffect(() => { function closeAside() { setIsAsideOpen(false); } router.events.on('routeChangeStart', closeAside); return () => { router.events.off('routeChangeStart', closeAside); }; }, [router.events]); const visibleNavItems = navItems.filter((item) => { if (isClientUser) { return item.href === '/client-portal' || item.href === '/profile'; } if (!item.permission) { return true; } if (!currentUser) { return false; } return hasPermission(currentUser, item.permission); }); const activePath = router.pathname.split('/')[1]; return (