aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/src/components/loading.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/components/loading.tsx')
-rw-r--r--frontend/src/components/loading.tsx111
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