diff --git a/src/app/error.tsx b/src/app/error.tsx new file mode 100644 index 0000000..173f151 --- /dev/null +++ b/src/app/error.tsx @@ -0,0 +1,83 @@ +'use client'; + +import React, { useEffect } from 'react'; +import AnimatedBackground from '@/components/ui/AnimatedBackground'; +import { FiRefreshCcw, FiHome, FiAlertTriangle } from 'react-icons/fi'; +import Link from 'next/link'; + +export default function GlobalError({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + // Log the error to an error reporting service if needed + console.error('Application Error:', error); + }, [error]); + + return ( +
+ {/* Background */} +
+ +
+ + {/* Decorative gradient overlay - Red tinted for error */} +
+ +
+ {/* Error Icon / Illustration */} +
+ +
+ + {/* Text Content */} +

+ Oops! Something tripped up. +

+ +

+ The BrowsePing engine hit an unexpected bump. Don't worry, your data is safe. We can try to reload the current view or head back to safety. +

+ + {/* Technical Hint (Subtle) */} + {process.env.NODE_ENV === 'development' && ( +
+

Error Log:

+

{error.message || 'No description available.'}

+ {error.digest &&

Digest: {error.digest}

} +
+ )} + + {/* Action Buttons */} +
+ + + + + Back to Homepage + +
+ + {/* Footer Link */} +
+ Persistent problem? Report it to us +
+
+ + {/* Bottom accent line */} +
+
+ ); +} diff --git a/src/app/leaderboard/loading.tsx b/src/app/leaderboard/loading.tsx new file mode 100644 index 0000000..0047890 --- /dev/null +++ b/src/app/leaderboard/loading.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import LeaderboardSkeleton from '@/components/leaderboard/LeaderboardSkeleton'; + +export default function LeaderboardLoading() { + return ( +
+
+ {/* Skeleton Header */} +
+
+
+
+ + {/* Skeleton Toolbar */} +
+
+
+ + +
+
+ ); +} diff --git a/src/app/loading.tsx b/src/app/loading.tsx new file mode 100644 index 0000000..31bad24 --- /dev/null +++ b/src/app/loading.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import AnimatedBackground from '@/components/ui/AnimatedBackground'; + +export default function Loading() { + return ( +
+ {/* Background with higher opacity for the loading screen */} +
+ +
+ + {/* Decorative gradient overlay */} +
+ + {/* Main Content */} +
+ {/* Logo/Brand element */} +
+
+
+
+ + {/* Subtle glow effect */} +
+
+ + {/* Text */} +

+ BrowsePing +

+
+
+
+
+ Launching Social Experience... +
+
+ + {/* Modern bottom indicator (Subtle) */} +
+
+ Syncing Data +
+
+
+ ); +} diff --git a/src/components/leaderboard/LeaderboardSkeleton.tsx b/src/components/leaderboard/LeaderboardSkeleton.tsx new file mode 100644 index 0000000..5be647c --- /dev/null +++ b/src/components/leaderboard/LeaderboardSkeleton.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { FiRefreshCw, FiClock } from 'react-icons/fi'; + +const LeaderboardSkeleton = () => { + return ( +
+ {/* Skeleton Table */} +
+ {/* Header Row Skeleton */} +
+
+
+
+
+
+
+
+ + {/* Body Rows Skeleton */} +
+ {[...Array(5)].map((_, i) => ( +
+
+ {/* Rank Skeleton */} +
+
+
+ + {/* User Info Skeleton */} +
+
+
+
+
+
+
+ + {/* Stats Skeletons */} +
+ +
+
+
+
+
+
+
+ ))} +
+ + {/* Footer Syncing State */} +
+
+ + Syncing browser data... +
+
+
+
+ ); +}; + +export default LeaderboardSkeleton; diff --git a/src/components/leaderboard/PublicLeaderboard.tsx b/src/components/leaderboard/PublicLeaderboard.tsx index 67f4d15..a2029b6 100644 --- a/src/components/leaderboard/PublicLeaderboard.tsx +++ b/src/components/leaderboard/PublicLeaderboard.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { FiClock, FiUser, FiRefreshCw, FiAward } from 'react-icons/fi'; +import LeaderboardSkeleton from './LeaderboardSkeleton'; interface LeaderboardUser { rank: number; @@ -28,6 +29,8 @@ const PublicLeaderboard = () => { try { setLoading(true); setError(null); + // Artificial delay for visual verification of the skeleton + await new Promise(resolve => setTimeout(resolve, 1500)); const apiUrl = process.env.NEXT_PUBLIC_API_URL; const url = `${apiUrl}/api/leaderboard/public-top`; const response = await fetch(url, { @@ -103,13 +106,7 @@ const PublicLeaderboard = () => { Community Leaderboard
- -
-
-
-
+
);