diff options
Diffstat (limited to 'frontend/src/components/loading.tsx')
-rw-r--r-- | frontend/src/components/loading.tsx | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/frontend/src/components/loading.tsx b/frontend/src/components/loading.tsx new file mode 100644 index 0000000..cbd5c15 --- /dev/null +++ b/frontend/src/components/loading.tsx @@ -0,0 +1,111 @@ +"use client"; + +import { useEffect, useState } from "react"; +import Image from "next/image"; + +export function LoadingScreen() { + const [isVisible, setIsVisible] = useState(true); + + useEffect(() => { + // Hide loading screen after a short delay to ensure everything is ready + const timer = setTimeout(() => { + setIsVisible(false); + }, 1000); + + return () => clearTimeout(timer); + }, []); + + if (!isVisible) return null; + + return ( + <div className="fixed inset-0 z-[9999] bg-background flex items-center justify-center"> + {/* Background pattern */} + <div className="absolute inset-0 bg-gradient-to-br from-background via-background to-muted/20" /> + + {/* Loading content */} + <div className="relative z-10 flex flex-col items-center space-y-4"> + {/* Logo with animation */} + <div className="relative"> + <div className="animate-pulse"> + <Image + src="/black-logo.png" + alt="blcklst" + width={160} + height={50} + className="h-12 w-auto block dark:hidden" + priority + /> + <Image + src="/white-logo.png" + alt="blcklst" + width={160} + height={50} + className="h-12 w-auto hidden dark:block" + priority + /> + </div> + </div> + + {/* Loading text - closer to logo */} + <div className="text-center space-y-3 -mt-2"> + <p className="text-sm text-muted-foreground animate-pulse"> + not everyone gets blcklsted + </p> + + {/* Loading dots */} + <div className="flex items-center justify-center space-x-1"> + <div className="w-2 h-2 bg-foreground/60 rounded-full animate-bounce [animation-delay:-0.3s]"></div> + <div className="w-2 h-2 bg-foreground/60 rounded-full animate-bounce [animation-delay:-0.15s]"></div> + <div className="w-2 h-2 bg-foreground/60 rounded-full animate-bounce"></div> + </div> + </div> + + {/* Progress bar */} + <div className="w-64 h-1 bg-muted rounded-full overflow-hidden"> + <div className="h-full bg-foreground rounded-full animate-[loading_1s_ease-in-out_infinite]"></div> + </div> + </div> + </div> + ); +} + +export function PageWrapper({ children }: { children: React.ReactNode }) { + const [isLoading, setIsLoading] = useState(true); + const [showContent, setShowContent] = useState(false); + + useEffect(() => { + // Check if page is ready + const checkReady = () => { + if (document.readyState === 'complete') { + setTimeout(() => { + setIsLoading(false); + setTimeout(() => setShowContent(true), 100); + }, 800); + } + }; + + if (document.readyState === 'complete') { + checkReady(); + } else { + window.addEventListener('load', checkReady); + } + + return () => { + window.removeEventListener('load', checkReady); + }; + }, []); + + return ( + <> + {isLoading && <LoadingScreen />} + <div + className={`transition-opacity duration-500 ${ + showContent ? 'opacity-100' : 'opacity-0' + }`} + suppressHydrationWarning + > + {children} + </div> + </> + ); +}
\ No newline at end of file |