Session 2026-05-29: shared dashboard, team tasks page, requests card style, copy/paste files, loading modals, avatar cache bust
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import PageLoader from './PageLoader';
|
||||
import { NavLink, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
@@ -25,8 +26,8 @@ function TeamNav({ onNav }) {
|
||||
const location = useLocation();
|
||||
|
||||
const primaryLinks = [
|
||||
{ to: '/team/dashboard', label: 'Dashboard', icon: ICONS.dashboard },
|
||||
{ to: '/requests', label: 'Requests', icon: ICONS.requests },
|
||||
{ to: '/dashboard', label: 'Dashboard', icon: ICONS.dashboard },
|
||||
{ to: '/team/tasks', label: 'Tasks', icon: ICONS.requests },
|
||||
{ to: '/projects', label: 'Projects', icon: ICONS.projects },
|
||||
{ to: '/invoices', label: 'Finances', icon: ICONS.invoices },
|
||||
{ to: '/file-sharing', label: 'File Sharing', icon: ICONS.fileSharing },
|
||||
@@ -140,12 +141,18 @@ export default function Layout({ children }) {
|
||||
const firstName = currentUser?.name?.split(' ')[0] || '';
|
||||
const isProfileRoute = location.pathname === '/profile' || location.pathname.startsWith('/profile/');
|
||||
const isFileSharingRoute = location.pathname === '/file-sharing';
|
||||
const headerTitle = isProfileRoute ? 'Profile' : isFileSharingRoute ? 'File Sharing' : `Good ${timeOfDay}${firstName ? `, ${firstName}` : ''}`;
|
||||
const isRequestsRoute = location.pathname === '/requests';
|
||||
const isTasksRoute = location.pathname === '/team/tasks';
|
||||
const headerTitle = isProfileRoute ? 'Profile' : isFileSharingRoute ? 'File Sharing' : isTasksRoute ? 'Tasks & Projects' : isRequestsRoute ? 'Requests' : `Good ${timeOfDay}${firstName ? `, ${firstName}` : ''}`;
|
||||
const headerSubtitle = isProfileRoute
|
||||
? 'Account details and security settings.'
|
||||
: isFileSharingRoute
|
||||
? 'Browse, share and manage files.'
|
||||
: "Here's what's happening today.";
|
||||
: isTasksRoute
|
||||
? 'Browse and manage all tasks and projects.'
|
||||
: isRequestsRoute
|
||||
? 'Browse and manage all your requests.'
|
||||
: "Here's what's happening today.";
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
@@ -174,6 +181,9 @@ export default function Layout({ children }) {
|
||||
return () => document.removeEventListener('mousedown', handler);
|
||||
}, [avatarOpen]);
|
||||
|
||||
const [navigating, setNavigating] = useState(false);
|
||||
const navTimerRef = useRef(null);
|
||||
|
||||
const [lastPathname, setLastPathname] = useState(location.pathname);
|
||||
if (lastPathname !== location.pathname) {
|
||||
setLastPathname(location.pathname);
|
||||
@@ -181,6 +191,13 @@ export default function Layout({ children }) {
|
||||
setAvatarOpen(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setNavigating(true);
|
||||
clearTimeout(navTimerRef.current);
|
||||
navTimerRef.current = setTimeout(() => setNavigating(false), 500);
|
||||
return () => clearTimeout(navTimerRef.current);
|
||||
}, [location.pathname]);
|
||||
|
||||
const toggleTheme = () => setTheme(t => t === 'dark' ? 'light' : 'dark');
|
||||
const handleLogout = async () => { await logout(); navigate('/'); };
|
||||
|
||||
@@ -188,6 +205,7 @@ export default function Layout({ children }) {
|
||||
|
||||
return (
|
||||
<div className="app-layout">
|
||||
{navigating && <PageLoader />}
|
||||
{menuOpen && <div className="sidebar-overlay" onClick={() => setMenuOpen(false)} />}
|
||||
|
||||
<aside className={`sidebar${menuOpen ? ' sidebar-open' : ''}`}>
|
||||
|
||||
Reference in New Issue
Block a user