2026-01-20 17:20:13 +01:00
|
|
|
'use client';
|
|
|
|
|
|
2026-01-20 17:46:14 +01:00
|
|
|
import { useRouter, usePathname } from 'next/navigation';
|
2026-01-20 17:20:13 +01:00
|
|
|
import { useState } from 'react';
|
2026-01-20 17:46:14 +01:00
|
|
|
import Image from 'next/image';
|
|
|
|
|
import Link from 'next/link';
|
2026-01-20 17:20:13 +01:00
|
|
|
|
|
|
|
|
interface User {
|
|
|
|
|
id: string;
|
|
|
|
|
email: string;
|
|
|
|
|
name: string | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface DashboardLayoutProps {
|
|
|
|
|
user: User;
|
|
|
|
|
children: React.ReactNode;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-20 17:46:14 +01:00
|
|
|
interface NavItem {
|
|
|
|
|
label: string;
|
|
|
|
|
href: string;
|
|
|
|
|
icon: React.ReactNode;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-20 17:20:13 +01:00
|
|
|
export default function DashboardLayout({ user, children }: DashboardLayoutProps) {
|
|
|
|
|
const router = useRouter();
|
2026-01-20 17:46:14 +01:00
|
|
|
const pathname = usePathname();
|
2026-01-20 17:20:13 +01:00
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
|
2026-01-20 17:46:14 +01:00
|
|
|
const navItems: NavItem[] = [
|
|
|
|
|
{
|
|
|
|
|
label: 'Tableau de Board',
|
|
|
|
|
href: '/dashboard',
|
|
|
|
|
icon: (
|
|
|
|
|
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 20 20">
|
|
|
|
|
<path d="M2 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1H3a1 1 0 01-1-1V4zM8 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1H9a1 1 0 01-1-1V4zM15 3a1 1 0 00-1 1v12a1 1 0 001 1h2a1 1 0 001-1V4a1 1 0 00-1-1h-2z" />
|
|
|
|
|
</svg>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: 'Calendrier',
|
|
|
|
|
href: '/dashboard/calendrier',
|
|
|
|
|
icon: (
|
|
|
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
|
|
|
|
</svg>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: 'Chauffeurs',
|
|
|
|
|
href: '/dashboard/chauffeurs',
|
|
|
|
|
icon: (
|
|
|
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 17a2 2 0 11-4 0 2 2 0 014 0zM19 17a2 2 0 11-4 0 2 2 0 014 0z" />
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1m8-1a1 1 0 01-1 1H9m4-1V8a1 1 0 011-1h2.586a1 1 0 01.707.293l3.414 3.414a1 1 0 01.293.707V16a1 1 0 01-1 1h-1m-6-1a1 1 0 001 1h1M5 17a2 2 0 104 0m-4 0a2 2 0 114 0m6 0a2 2 0 104 0m-4 0a2 2 0 114 0" />
|
|
|
|
|
</svg>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: 'Adhérents',
|
|
|
|
|
href: '/dashboard/adherents',
|
|
|
|
|
icon: (
|
|
|
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
|
|
|
|
|
</svg>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: 'Univers Pro',
|
|
|
|
|
href: '/dashboard/univers-pro',
|
|
|
|
|
icon: (
|
|
|
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
|
|
|
|
</svg>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: 'Messagerie',
|
|
|
|
|
href: '/dashboard/messagerie',
|
|
|
|
|
icon: (
|
|
|
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
|
|
|
|
|
</svg>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: 'Factures',
|
|
|
|
|
href: '/dashboard/factures',
|
|
|
|
|
icon: (
|
|
|
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
|
|
|
</svg>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
2026-01-20 17:20:13 +01:00
|
|
|
const handleLogout = async () => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
try {
|
|
|
|
|
await fetch('/api/auth/logout', { method: 'POST' });
|
|
|
|
|
router.push('/login');
|
|
|
|
|
router.refresh();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Logout error:', error);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
2026-01-20 17:46:14 +01:00
|
|
|
<div className="min-h-screen bg-cwhite flex">
|
|
|
|
|
{/* Sidebar */}
|
|
|
|
|
<aside className="w-64 bg-white flex flex-col h-screen sticky top-0 border-r border-gray-200">
|
|
|
|
|
{/* Logo Section */}
|
|
|
|
|
<div className="py-5 m-auto">
|
|
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<Image
|
|
|
|
|
src="/logo.svg"
|
|
|
|
|
alt="MAD Logo"
|
|
|
|
|
width={32}
|
|
|
|
|
height={32}
|
|
|
|
|
/>
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<span className="font-semibold text-gray-900">Association MAD</span>
|
2026-01-20 17:20:13 +01:00
|
|
|
</div>
|
2026-01-20 17:46:14 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Navigation */}
|
|
|
|
|
<nav className="flex-1 p-4 border-t border-gray-200">
|
|
|
|
|
<ul className="space-y-1">
|
|
|
|
|
{navItems.map((item) => {
|
|
|
|
|
const isActive = pathname === item.href;
|
|
|
|
|
return (
|
|
|
|
|
<li key={item.href}>
|
|
|
|
|
<Link
|
|
|
|
|
href={item.href}
|
|
|
|
|
className={`flex items-center gap-3 px-4 py-3 rounded-lg transition-colors ${
|
|
|
|
|
isActive
|
|
|
|
|
? 'bg-lblue text-white'
|
|
|
|
|
: 'text-gray-700 hover:bg-lblue/10'
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<span className={isActive ? 'text-white' : 'text-lblue'}>
|
|
|
|
|
{item.icon}
|
|
|
|
|
</span>
|
|
|
|
|
<span className={`text-sm font-medium ${isActive ? '' : ''}`}>
|
|
|
|
|
{item.label}
|
|
|
|
|
</span>
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</ul>
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
{/* Footer */}
|
|
|
|
|
<div className="p-6 border-t border-gray-200">
|
|
|
|
|
<p className="text-xs text-gray-500 text-center">
|
|
|
|
|
© 2025 MAD - <a href="https://legouix.dev" target="_blank" className="text-lblue hover:text-dblue">Propulsé par LGX</a>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</aside>
|
|
|
|
|
|
|
|
|
|
{/* Main Content Area */}
|
|
|
|
|
<div className="flex-1 flex flex-col">
|
|
|
|
|
{/* Top Navbar */}
|
|
|
|
|
<header className="bg-white border-b border-gray-200 px-6 py-4">
|
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
|
<h1 className="text-xl font-semibold text-gray-900"></h1>
|
|
|
|
|
<div className="flex items-center gap-4">
|
|
|
|
|
{/* Notification Icon */}
|
|
|
|
|
<button className="relative w-10 h-10 rounded-full bg-[#6B46C1] flex items-center justify-center hover:bg-[#5B21B6] transition-colors">
|
|
|
|
|
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
|
|
|
</svg>
|
|
|
|
|
<span className="absolute -top-0.5 -right-0.5 w-3 h-3 bg-red-500 rounded-full border-2 border-white"></span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
{/* Profile Avatar */}
|
|
|
|
|
<button className="w-10 h-10 rounded-full bg-[#6B46C1] flex items-center justify-center hover:bg-[#5B21B6] transition-colors">
|
|
|
|
|
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 20 20">
|
|
|
|
|
<path fillRule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clipRule="evenodd" />
|
|
|
|
|
</svg>
|
2026-01-20 17:20:13 +01:00
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-01-20 17:46:14 +01:00
|
|
|
</header>
|
2026-01-20 17:20:13 +01:00
|
|
|
|
2026-01-20 17:46:14 +01:00
|
|
|
{/* Page Content */}
|
|
|
|
|
<main className="flex-1 overflow-auto">
|
|
|
|
|
{children}
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
2026-01-20 17:20:13 +01:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|