diff --git a/package-lock.json b/package-lock.json index 756daf7..f2f0890 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7468,6 +7468,126 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz", + "integrity": "sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz", + "integrity": "sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz", + "integrity": "sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz", + "integrity": "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz", + "integrity": "sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz", + "integrity": "sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz", + "integrity": "sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz", + "integrity": "sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/src/components/layout/ClientLayout.tsx b/src/components/layout/ClientLayout.tsx index 03132bb..e68e978 100644 --- a/src/components/layout/ClientLayout.tsx +++ b/src/components/layout/ClientLayout.tsx @@ -10,6 +10,7 @@ import { usePathname } from "next/navigation"; import { PreferencesProvider } from "@/contexts/PreferencesContext"; import { registerServiceWorker } from "@/lib/registerSW"; import { NetworkStatus } from "../ui/NetworkStatus"; +import { LoadingBar } from "@/components/ui/loading-bar"; // Routes qui ne nécessitent pas d'authentification const publicRoutes = ["/login", "/register"]; @@ -63,6 +64,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
+ {!isPublicRoute &&
} {!isPublicRoute && }
{children}
diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 838a73e..616a366 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -106,13 +106,17 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) { }; const handleLinkClick = useCallback( - (path: string) => { + async (path: string) => { if (pathname === path) { onClose(); return; } + window.dispatchEvent(new Event("navigationStart")); router.push(path); onClose(); + // On attend que la page soit chargée + await new Promise((resolve) => setTimeout(resolve, 300)); + window.dispatchEvent(new Event("navigationComplete")); }, [pathname, router, onClose] ); diff --git a/src/components/ui/loading-bar.tsx b/src/components/ui/loading-bar.tsx new file mode 100644 index 0000000..e631d9d --- /dev/null +++ b/src/components/ui/loading-bar.tsx @@ -0,0 +1,59 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { cn } from "@/lib/utils"; +import { Loader2 } from "lucide-react"; + +export function LoadingBar() { + const [isLoading, setIsLoading] = useState(false); + const [shouldRender, setShouldRender] = useState(false); + + useEffect(() => { + if (isLoading) { + setShouldRender(true); + } else { + const timer = setTimeout(() => { + setShouldRender(false); + }, 500); + return () => clearTimeout(timer); + } + }, [isLoading]); + + useEffect(() => { + const handleStart = () => { + setIsLoading(true); + }; + + const handleStop = () => { + setTimeout(() => { + setIsLoading(false); + }, 300); + }; + + window.addEventListener("navigationStart", handleStart); + window.addEventListener("navigationComplete", handleStop); + + return () => { + window.removeEventListener("navigationStart", handleStart); + window.removeEventListener("navigationComplete", handleStop); + }; + }, []); + + if (!shouldRender) return null; + + return ( +
+
+ +

Chargement...

+
+
+ ); +}