perf: complete industry-standard optimization for frontend & backend
This commit is contained in:
164
src/App.tsx
164
src/App.tsx
@@ -1,29 +1,35 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, lazy, Suspense } from 'react';
|
||||
import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { AuthProvider } from '@/context/AuthContext';
|
||||
import ProtectedRoute from '@/components/Auth/ProtectedRoute';
|
||||
import MainLayout from '@/layouts/MainLayout';
|
||||
import Home from '@/pages/Home/Home';
|
||||
import Notes from '@/pages/Notes/Notes';
|
||||
import Toolkit from '@/pages/Toolkit/Toolkit';
|
||||
import AIAssistant from '@/pages/AIAssistant/AIAssistant';
|
||||
import Campus from '@/pages/Campus/Campus';
|
||||
import Events from '@/pages/Events/Events';
|
||||
import Community from '@/pages/Community/Community';
|
||||
import BusRoutes from '@/pages/BusRoutes/BusRoutes';
|
||||
import Faculty from '@/pages/Faculty/Faculty';
|
||||
import DevCollab from '@/pages/DevCollab/DevCollab';
|
||||
import LeetcodeLeaderboard from '@/pages/LeetcodeLeaderboard/LeetcodeLeaderboard';
|
||||
import AdminDashboard from '@/pages/Admin/AdminDashboard';
|
||||
import Raise from '@/pages/Raise/Raise';
|
||||
import StudentDashboard from '@/pages/StudentDashboard/StudentDashboard';
|
||||
import PageLoader from '@/components/PageLoader/PageLoader';
|
||||
import ErrorBoundary from '@/components/ErrorBoundary/ErrorBoundary';
|
||||
|
||||
// Code-split route components with dynamic imports for minimal initial bundle size
|
||||
const Home = lazy(() => import('@/pages/Home/Home'));
|
||||
const Notes = lazy(() => import('@/pages/Notes/Notes'));
|
||||
const Toolkit = lazy(() => import('@/pages/Toolkit/Toolkit'));
|
||||
const AIAssistant = lazy(() => import('@/pages/AIAssistant/AIAssistant'));
|
||||
const Campus = lazy(() => import('@/pages/Campus/Campus'));
|
||||
const Events = lazy(() => import('@/pages/Events/Events'));
|
||||
const Community = lazy(() => import('@/pages/Community/Community'));
|
||||
const BusRoutes = lazy(() => import('@/pages/BusRoutes/BusRoutes'));
|
||||
const Faculty = lazy(() => import('@/pages/Faculty/Faculty'));
|
||||
const DevCollab = lazy(() => import('@/pages/DevCollab/DevCollab'));
|
||||
const LeetcodeLeaderboard = lazy(() => import('@/pages/LeetcodeLeaderboard/LeetcodeLeaderboard'));
|
||||
const AdminDashboard = lazy(() => import('@/pages/Admin/AdminDashboard'));
|
||||
const Raise = lazy(() => import('@/pages/Raise/Raise'));
|
||||
const StudentDashboard = lazy(() => import('@/pages/StudentDashboard/StudentDashboard'));
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 5 * 60 * 1000,
|
||||
gcTime: 10 * 60 * 1000,
|
||||
refetchOnWindowFocus: false,
|
||||
retry: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -40,72 +46,76 @@ function ScrollToTop() {
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter>
|
||||
<AuthProvider>
|
||||
<ScrollToTop />
|
||||
<Routes>
|
||||
{/* Standalone Admin Route */}
|
||||
<Route path="/admin" element={<AdminDashboard />} />
|
||||
<Route path="/admin/*" element={<AdminDashboard />} />
|
||||
<ErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter>
|
||||
<AuthProvider>
|
||||
<ScrollToTop />
|
||||
<Suspense fallback={<PageLoader />}>
|
||||
<Routes>
|
||||
{/* Standalone Admin Route */}
|
||||
<Route path="/admin" element={<AdminDashboard />} />
|
||||
<Route path="/admin/*" element={<AdminDashboard />} />
|
||||
|
||||
{/* Standalone RAISE Route */}
|
||||
<Route path="/raise" element={<Raise />} />
|
||||
{/* Standalone RAISE Route */}
|
||||
<Route path="/raise" element={<Raise />} />
|
||||
|
||||
<Route element={<MainLayout />}>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/notes" element={<Notes />} />
|
||||
<Route path="/toolkit" element={<Toolkit />} />
|
||||
<Route path="/ai-assistant" element={<AIAssistant />} />
|
||||
<Route path="/campus" element={<Campus />} />
|
||||
<Route path="/bus-routes" element={<BusRoutes />} />
|
||||
<Route path="/faculty" element={<Faculty />} />
|
||||
<Route path="/events" element={<Events />} />
|
||||
<Route element={<MainLayout />}>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/notes" element={<Notes />} />
|
||||
<Route path="/toolkit" element={<Toolkit />} />
|
||||
<Route path="/ai-assistant" element={<AIAssistant />} />
|
||||
<Route path="/campus" element={<Campus />} />
|
||||
<Route path="/bus-routes" element={<BusRoutes />} />
|
||||
<Route path="/faculty" element={<Faculty />} />
|
||||
<Route path="/events" element={<Events />} />
|
||||
|
||||
{/* Student Dashboard & Timetable — Real IMS Reg No & Password */}
|
||||
<Route path="/dashboard" element={<StudentDashboard />} />
|
||||
<Route path="/timetable" element={<StudentDashboard />} />
|
||||
{/* Student Dashboard & Timetable — Real IMS Reg No & Password */}
|
||||
<Route path="/dashboard" element={<StudentDashboard />} />
|
||||
<Route path="/timetable" element={<StudentDashboard />} />
|
||||
|
||||
{/* Protected Routes — Require Google Sign-In */}
|
||||
<Route
|
||||
path="/community"
|
||||
element={
|
||||
<ProtectedRoute
|
||||
title="RIT Q&A Community"
|
||||
description="Connect with fellow RIT students and ask senior helpers any question about campus life and academics."
|
||||
>
|
||||
<Community />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/collab"
|
||||
element={
|
||||
<ProtectedRoute
|
||||
title="Developer Collab Hub"
|
||||
description="Post open-source projects, search for co-developers, and connect with fellow programmers."
|
||||
requireVerifiedStudent={true}
|
||||
>
|
||||
<DevCollab />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/leetcode"
|
||||
element={
|
||||
<ProtectedRoute
|
||||
title="RIT LeetCode Leaderboard"
|
||||
description="Track campus competitive programming rankings and see top RIT coders."
|
||||
>
|
||||
<LeetcodeLeaderboard />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Routes>
|
||||
</AuthProvider>
|
||||
</BrowserRouter>
|
||||
</QueryClientProvider>
|
||||
{/* Protected Routes — Require Google Sign-In */}
|
||||
<Route
|
||||
path="/community"
|
||||
element={
|
||||
<ProtectedRoute
|
||||
title="RIT Q&A Community"
|
||||
description="Connect with fellow RIT students and ask senior helpers any question about campus life and academics."
|
||||
>
|
||||
<Community />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/collab"
|
||||
element={
|
||||
<ProtectedRoute
|
||||
title="Developer Collab Hub"
|
||||
description="Post open-source projects, search for co-developers, and connect with fellow programmers."
|
||||
requireVerifiedStudent={true}
|
||||
>
|
||||
<DevCollab />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/leetcode"
|
||||
element={
|
||||
<ProtectedRoute
|
||||
title="RIT LeetCode Leaderboard"
|
||||
description="Track campus competitive programming rankings and see top RIT coders."
|
||||
>
|
||||
<LeetcodeLeaderboard />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</AuthProvider>
|
||||
</BrowserRouter>
|
||||
</QueryClientProvider>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
91
src/components/ErrorBoundary/ErrorBoundary.tsx
Normal file
91
src/components/ErrorBoundary/ErrorBoundary.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import { Component, type ErrorInfo, type ReactNode } from 'react';
|
||||
import { AlertTriangle, RefreshCw, Home } from 'lucide-react';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
fallback?: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
export class ErrorBoundary extends Component<Props, State> {
|
||||
public state: State = {
|
||||
hasError: false,
|
||||
error: null,
|
||||
};
|
||||
|
||||
public static getDerivedStateFromError(error: Error): State {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error('[ErrorBoundary caught error]:', error, errorInfo);
|
||||
}
|
||||
|
||||
private handleReset = () => {
|
||||
this.setState({ hasError: false, error: null });
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
private handleGoHome = () => {
|
||||
this.setState({ hasError: false, error: null });
|
||||
window.location.href = '/';
|
||||
};
|
||||
|
||||
public render() {
|
||||
if (this.state.hasError) {
|
||||
if (this.props.fallback) {
|
||||
return this.props.fallback;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-[70vh] flex items-center justify-center p-6">
|
||||
<div className="max-w-md w-full bg-card/80 backdrop-blur-xl border border-destructive/20 rounded-2xl p-8 shadow-2xl text-center space-y-6">
|
||||
<div className="w-16 h-16 mx-auto rounded-2xl bg-destructive/10 border border-destructive/20 flex items-center justify-center text-destructive shadow-inner">
|
||||
<AlertTriangle className="w-8 h-8 animate-bounce" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-xl font-bold tracking-tight text-foreground">
|
||||
Something went wrong
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
An unexpected error occurred while rendering this section. You can try refreshing the page or navigating back home.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{this.state.error && (
|
||||
<div className="p-3 rounded-lg bg-muted/50 border border-border text-left overflow-x-auto text-xs font-mono text-muted-foreground max-h-24">
|
||||
{this.state.error.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-3 pt-2">
|
||||
<button
|
||||
onClick={this.handleReset}
|
||||
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl bg-orange-600 hover:bg-orange-700 text-white text-sm font-medium transition-all shadow-lg shadow-orange-600/25 hover:shadow-orange-600/40 active:scale-95 cursor-pointer"
|
||||
>
|
||||
<RefreshCw className="w-4 h-4" />
|
||||
Try Again
|
||||
</button>
|
||||
<button
|
||||
onClick={this.handleGoHome}
|
||||
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl bg-secondary hover:bg-secondary/80 text-foreground text-sm font-medium transition-all active:scale-95 border border-border cursor-pointer"
|
||||
>
|
||||
<Home className="w-4 h-4" />
|
||||
Go to Home
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorBoundary;
|
||||
24
src/components/PageLoader/PageLoader.tsx
Normal file
24
src/components/PageLoader/PageLoader.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
|
||||
const PageLoader: React.FC = () => {
|
||||
return (
|
||||
<div className="min-h-[60vh] flex flex-col items-center justify-center p-6 space-y-4">
|
||||
<div className="relative flex items-center justify-center">
|
||||
{/* Outer glowing ripple */}
|
||||
<div className="absolute w-16 h-16 rounded-full bg-orange-500/20 animate-ping" />
|
||||
{/* Spinning gradient ring */}
|
||||
<div className="w-12 h-12 rounded-full border-3 border-transparent border-t-orange-500 border-r-orange-400 animate-spin" />
|
||||
{/* Center dot */}
|
||||
<div className="absolute w-4 h-4 rounded-full bg-gradient-to-tr from-orange-600 to-amber-400 shadow-lg shadow-orange-500/50" />
|
||||
</div>
|
||||
<div className="flex flex-col items-center space-y-1">
|
||||
<p className="text-sm font-semibold tracking-wide bg-gradient-to-r from-orange-600 via-amber-500 to-orange-400 bg-clip-text text-transparent animate-pulse">
|
||||
Loading Freshers Hub
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">Preparing your campus experience...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PageLoader;
|
||||
Reference in New Issue
Block a user