Improve dashboard prefetching and analytics charts
All checks were successful
Build Frontend / build (push) Successful in 1m14s
All checks were successful
Build Frontend / build (push) Successful in 1m14s
Removed dashboard prefetching from the login page to avoid unnecessary middleware redirects for unauthenticated users. Added delayed prefetching of dashboard routes after initial load for better navigation performance. Updated AdminAnalytics to use AreaChart instead of BarChart for daily metrics, improving visual clarity. Enhanced middleware to allow prefetch requests through without redirecting to login, supporting better caching and navigation.
This commit is contained in:
@@ -33,9 +33,7 @@ function LoginLoading() {
|
||||
export default function LoginPage() {
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
router.prefetch("/dashboard");
|
||||
}, [router]);
|
||||
// Removed prefetch to avoid middleware redirects when unauthenticated
|
||||
|
||||
return (
|
||||
<div className="relative flex items-center justify-center min-h-screen overflow-hidden">
|
||||
|
||||
@@ -6,6 +6,8 @@ import { Button } from "@/components/common/button";
|
||||
import { AlertCircle, RefreshCw } from "lucide-react";
|
||||
import { Skeleton } from "@/components/common/skeleton";
|
||||
import { Card, CardContent, CardHeader } from "@/components/common/card";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { sidebarConfig } from "@/config/sidebar";
|
||||
|
||||
// Error Boundary Component
|
||||
interface ErrorBoundaryState {
|
||||
@@ -91,14 +93,14 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
}
|
||||
|
||||
// Suspense wrapper with timeout
|
||||
function SuspenseWithTimeout({
|
||||
children,
|
||||
fallback,
|
||||
function SuspenseWithTimeout({
|
||||
children,
|
||||
fallback,
|
||||
timeout = 5000,
|
||||
timeoutFallback
|
||||
}: {
|
||||
children: ReactNode;
|
||||
fallback: ReactNode;
|
||||
timeoutFallback
|
||||
}: {
|
||||
children: ReactNode;
|
||||
fallback: ReactNode;
|
||||
timeout?: number;
|
||||
timeoutFallback?: ReactNode;
|
||||
}) {
|
||||
@@ -157,7 +159,7 @@ function DashboardContentSkeletonWithWarning() {
|
||||
// Import the skeleton from the page
|
||||
function DashboardContentSkeleton() {
|
||||
return (
|
||||
<div
|
||||
<div
|
||||
className="space-y-6 animate-in fade-in duration-500 relative"
|
||||
role="status"
|
||||
aria-label="Loading dashboard content"
|
||||
@@ -165,7 +167,7 @@ function DashboardContentSkeleton() {
|
||||
>
|
||||
{/* Subtle loading indicator */}
|
||||
<div className="absolute top-0 left-0 right-0 h-1 bg-muted overflow-hidden rounded-full">
|
||||
<div className="h-full bg-primary w-1/3"
|
||||
<div className="h-full bg-primary w-1/3"
|
||||
style={{
|
||||
background: 'linear-gradient(90deg, transparent, hsl(var(--primary)), transparent)',
|
||||
backgroundSize: '200% 100%',
|
||||
@@ -183,7 +185,7 @@ function DashboardContentSkeleton() {
|
||||
{/* Stats cards skeleton */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 lg:gap-6">
|
||||
{[...Array(4)].map((_, i) => (
|
||||
<Card
|
||||
<Card
|
||||
key={i}
|
||||
className="animate-in fade-in slide-in-from-bottom-4"
|
||||
style={{
|
||||
@@ -219,8 +221,8 @@ function DashboardContentSkeleton() {
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center gap-4 animate-in fade-in"
|
||||
style={{
|
||||
animationDelay: `${400 + i * 50}ms`,
|
||||
@@ -247,9 +249,29 @@ function DashboardContentSkeleton() {
|
||||
}
|
||||
|
||||
export default function DashboardContentWrapper({ children }: { children: ReactNode }) {
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
// Prefetch main dashboard routes for snappier navigation
|
||||
const prefetchRoutes = async () => {
|
||||
// Small delay to prioritize initial page load
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
sidebarConfig.forEach(section => {
|
||||
section.items.forEach(item => {
|
||||
if (item.href && item.href !== "/dashboard") {
|
||||
router.prefetch(item.href);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
prefetchRoutes();
|
||||
}, [router]);
|
||||
|
||||
return (
|
||||
<ErrorBoundary componentName="Dashboard Content">
|
||||
<SuspenseWithTimeout
|
||||
<SuspenseWithTimeout
|
||||
fallback={<DashboardContentSkeleton />}
|
||||
timeout={5000}
|
||||
timeoutFallback={<DashboardContentSkeletonWithWarning />}
|
||||
|
||||
Reference in New Issue
Block a user