"use client" import { useEffect, useRef, useState } from "react" import { Progress } from "@/components/ui/progress" function PageProgressContent() { const [progress, setProgress] = useState(0) const [isVisible, setIsVisible] = useState(false) const [navigationKey, setNavigationKey] = useState(0) const intervalRef = useRef | null>(null) const navigationUrlRef = useRef(null) // Start progress on click useEffect(() => { const handleClick = (e: MouseEvent) => { const target = (e.target as HTMLElement).closest("a") if (!target) return const href = target.getAttribute("href") if (!href) return // Check if it's an internal link const isInternal = href.startsWith("/") || href.startsWith(window.location.origin) const isSamePage = href === window.location.pathname || href.startsWith(window.location.pathname + "#") || href === window.location.href // Only show progress for actual page transitions if (isInternal && !isSamePage && target.getAttribute("target") !== "_blank") { navigationUrlRef.current = window.location.href setIsVisible(true) setProgress(15) // Simulate progress while waiting for route change // Uses a decaying approach so it slows down as it gets closer to 95% const interval = setInterval(() => { setProgress((prev) => { if (prev >= 95) { clearInterval(interval) return prev } return prev + (95 - prev) * 0.1 }) }, 100) intervalRef.current = interval } } document.addEventListener("click", handleClick) return () => document.removeEventListener("click", handleClick) }, []) // Detect completion without reading Next.js URL hooks during prerendering. useEffect(() => { if (!isVisible || !navigationUrlRef.current) return const initialUrl = navigationUrlRef.current const checkInterval = window.setInterval(() => { if (window.location.href !== initialUrl) { window.clearInterval(checkInterval) setNavigationKey((key) => key + 1) } }, 50) const fallback = window.setTimeout(() => { window.clearInterval(checkInterval) setNavigationKey((key) => key + 1) }, 10_000) return () => { window.clearInterval(checkInterval) window.clearTimeout(fallback) } }, [isVisible]) // Finish progress on route change useEffect(() => { if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } if (isVisible) { const finishTimeout = setTimeout(() => setProgress(100), 0) const timeout = setTimeout(() => { setIsVisible(false) setTimeout(() => setProgress(0), 300) // Reset after hiding navigationUrlRef.current = null }, 400) return () => { clearTimeout(finishTimeout) clearTimeout(timeout) } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [navigationKey]) if (!isVisible && progress === 0) return null return (
) } export function PageProgress() { return }