From e1b8aa936ef3a62350128d48a11076139598fd86 Mon Sep 17 00:00:00 2001
From: "Shruthi deepika.v"
<151644213+shruthideepikareddy@users.noreply.github.com>
Date: Sun, 1 Mar 2026 19:20:21 +0530
Subject: [PATCH] feat: implement global loading and error states (#76)
---
src/app/error.tsx | 83 +++++++++++++++++++
src/app/leaderboard/loading.tsx | 23 +++++
src/app/loading.tsx | 47 +++++++++++
.../leaderboard/LeaderboardSkeleton.tsx | 63 ++++++++++++++
.../leaderboard/PublicLeaderboard.tsx | 11 +--
5 files changed, 220 insertions(+), 7 deletions(-)
create mode 100644 src/app/error.tsx
create mode 100644 src/app/leaderboard/loading.tsx
create mode 100644 src/app/loading.tsx
create mode 100644 src/components/leaderboard/LeaderboardSkeleton.tsx
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) */}
+
+
+ );
+}
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
-
-
-
-
- Loading leaderboard...
-
-
+
);