143 lines
4.1 KiB
TypeScript
143 lines
4.1 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useState } from 'react';
|
|
import { useRouter, usePathname } from 'next/navigation';
|
|
import Link from 'next/link';
|
|
import {
|
|
Ship,
|
|
LayoutDashboard,
|
|
FileText,
|
|
BarChart3,
|
|
User,
|
|
LogOut,
|
|
Menu,
|
|
X,
|
|
} from 'lucide-react';
|
|
|
|
export default function CarrierDashboardLayout({ children }: { children: React.ReactNode }) {
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
|
const [carrierName, setCarrierName] = useState('Transporteur');
|
|
|
|
useEffect(() => {
|
|
// Vérifier l'authentification
|
|
const token = localStorage.getItem('carrier_access_token');
|
|
if (!token) {
|
|
router.push('/carrier/login');
|
|
}
|
|
}, [router]);
|
|
|
|
const handleLogout = () => {
|
|
localStorage.removeItem('carrier_access_token');
|
|
localStorage.removeItem('carrier_refresh_token');
|
|
router.push('/carrier/login');
|
|
};
|
|
|
|
const menuItems = [
|
|
{
|
|
name: 'Tableau de bord',
|
|
href: '/carrier/dashboard',
|
|
icon: LayoutDashboard,
|
|
},
|
|
{
|
|
name: 'Réservations',
|
|
href: '/carrier/dashboard/bookings',
|
|
icon: FileText,
|
|
},
|
|
{
|
|
name: 'Statistiques',
|
|
href: '/carrier/dashboard/stats',
|
|
icon: BarChart3,
|
|
},
|
|
{
|
|
name: 'Mon profil',
|
|
href: '/carrier/dashboard/profile',
|
|
icon: User,
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-50">
|
|
{/* Mobile Sidebar Toggle */}
|
|
<div className="lg:hidden fixed top-0 left-0 right-0 bg-white border-b z-20 p-4">
|
|
<button
|
|
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
|
className="text-gray-600 hover:text-gray-900"
|
|
>
|
|
{isSidebarOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
|
</button>
|
|
</div>
|
|
|
|
{/* Sidebar */}
|
|
<aside
|
|
className={`fixed top-0 left-0 h-full w-64 bg-white border-r z-30 transform transition-transform lg:transform-none ${
|
|
isSidebarOpen ? 'translate-x-0' : '-translate-x-full'
|
|
}`}
|
|
>
|
|
{/* Logo */}
|
|
<div className="p-6 border-b">
|
|
<div className="flex items-center space-x-3">
|
|
<Ship className="w-8 h-8 text-blue-600" />
|
|
<div>
|
|
<h1 className="font-bold text-lg text-gray-900">Xpeditis</h1>
|
|
<p className="text-sm text-gray-600">Portail Transporteur</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Navigation */}
|
|
<nav className="p-4">
|
|
<ul className="space-y-2">
|
|
{menuItems.map((item) => {
|
|
const Icon = item.icon;
|
|
const isActive = pathname === item.href || pathname.startsWith(item.href + '/');
|
|
|
|
return (
|
|
<li key={item.href}>
|
|
<Link
|
|
href={item.href}
|
|
className={`flex items-center space-x-3 px-4 py-3 rounded-lg transition-colors ${
|
|
isActive
|
|
? 'bg-blue-50 text-blue-600 font-medium'
|
|
: 'text-gray-700 hover:bg-gray-50'
|
|
}`}
|
|
onClick={() => setIsSidebarOpen(false)}
|
|
>
|
|
<Icon className="w-5 h-5" />
|
|
<span>{item.name}</span>
|
|
</Link>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</nav>
|
|
|
|
{/* Logout Button */}
|
|
<div className="absolute bottom-0 left-0 right-0 p-4 border-t">
|
|
<button
|
|
onClick={handleLogout}
|
|
className="flex items-center space-x-3 px-4 py-3 rounded-lg text-red-600 hover:bg-red-50 w-full"
|
|
>
|
|
<LogOut className="w-5 h-5" />
|
|
<span>Déconnexion</span>
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
|
|
{/* Main Content */}
|
|
<main className="lg:ml-64 pt-16 lg:pt-0">
|
|
<div className="p-6">{children}</div>
|
|
</main>
|
|
|
|
{/* Mobile Overlay */}
|
|
{isSidebarOpen && (
|
|
<div
|
|
className="fixed inset-0 bg-black bg-opacity-50 z-20 lg:hidden"
|
|
onClick={() => setIsSidebarOpen(false)}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|