Initial Claude Run
This commit is contained in:
327
frontend/src/App.js
Normal file
327
frontend/src/App.js
Normal file
@@ -0,0 +1,327 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { Toaster } from 'react-hot-toast';
|
||||
|
||||
import { AuthProvider } from './contexts/AuthContext';
|
||||
import { useAuth } from './hooks/useAuth';
|
||||
|
||||
// Layout components
|
||||
import Layout from './components/Layout/Layout';
|
||||
import AuthLayout from './components/Layout/AuthLayout';
|
||||
|
||||
// Auth pages
|
||||
import Login from './pages/Auth/Login';
|
||||
import Register from './pages/Auth/Register';
|
||||
import ForgotPassword from './pages/Auth/ForgotPassword';
|
||||
|
||||
// Main app pages
|
||||
import Dashboard from './pages/Dashboard/Dashboard';
|
||||
import Properties from './pages/Properties/Properties';
|
||||
import PropertyDetail from './pages/Properties/PropertyDetail';
|
||||
import Equipment from './pages/Equipment/Equipment';
|
||||
import Products from './pages/Products/Products';
|
||||
import Applications from './pages/Applications/Applications';
|
||||
import ApplicationPlan from './pages/Applications/ApplicationPlan';
|
||||
import ApplicationLog from './pages/Applications/ApplicationLog';
|
||||
import History from './pages/History/History';
|
||||
import Weather from './pages/Weather/Weather';
|
||||
import Profile from './pages/Profile/Profile';
|
||||
|
||||
// Admin pages
|
||||
import AdminDashboard from './pages/Admin/AdminDashboard';
|
||||
import AdminUsers from './pages/Admin/AdminUsers';
|
||||
import AdminProducts from './pages/Admin/AdminProducts';
|
||||
|
||||
// Error pages
|
||||
import NotFound from './pages/Error/NotFound';
|
||||
import Unauthorized from './pages/Error/Unauthorized';
|
||||
|
||||
// Loading component
|
||||
import LoadingSpinner from './components/UI/LoadingSpinner';
|
||||
|
||||
// Create a client for React Query
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: (failureCount, error) => {
|
||||
// Don't retry on 401 (unauthorized) or 403 (forbidden)
|
||||
if (error?.response?.status === 401 || error?.response?.status === 403) {
|
||||
return false;
|
||||
}
|
||||
return failureCount < 2;
|
||||
},
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
cacheTime: 10 * 60 * 1000, // 10 minutes
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Protected Route component
|
||||
const ProtectedRoute = ({ children, adminOnly = false }) => {
|
||||
const { user, loading } = useAuth();
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<LoadingSpinner size="lg" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return <Navigate to="/login" replace />;
|
||||
}
|
||||
|
||||
if (adminOnly && user.role !== 'admin') {
|
||||
return <Navigate to="/unauthorized" replace />;
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
// Public Route component (redirects to dashboard if already authenticated)
|
||||
const PublicRoute = ({ children }) => {
|
||||
const { user, loading } = useAuth();
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<LoadingSpinner size="lg" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (user) {
|
||||
return <Navigate to="/dashboard" replace />;
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider>
|
||||
<Router>
|
||||
<div className="App">
|
||||
<Routes>
|
||||
{/* Public Routes */}
|
||||
<Route
|
||||
path="/login"
|
||||
element={
|
||||
<PublicRoute>
|
||||
<AuthLayout>
|
||||
<Login />
|
||||
</AuthLayout>
|
||||
</PublicRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/register"
|
||||
element={
|
||||
<PublicRoute>
|
||||
<AuthLayout>
|
||||
<Register />
|
||||
</AuthLayout>
|
||||
</PublicRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/forgot-password"
|
||||
element={
|
||||
<PublicRoute>
|
||||
<AuthLayout>
|
||||
<ForgotPassword />
|
||||
</AuthLayout>
|
||||
</PublicRoute>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Protected Routes */}
|
||||
<Route
|
||||
path="/dashboard"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<Dashboard />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/properties"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<Properties />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/properties/:id"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<PropertyDetail />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/equipment"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<Equipment />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/products"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<Products />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/applications"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<Applications />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/applications/plan"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<ApplicationPlan />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/applications/log"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<ApplicationLog />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/history"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<History />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/weather"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<Weather />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/profile"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<Layout>
|
||||
<Profile />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Admin Routes */}
|
||||
<Route
|
||||
path="/admin"
|
||||
element={
|
||||
<ProtectedRoute adminOnly>
|
||||
<Layout>
|
||||
<AdminDashboard />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/admin/users"
|
||||
element={
|
||||
<ProtectedRoute adminOnly>
|
||||
<Layout>
|
||||
<AdminUsers />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/admin/products"
|
||||
element={
|
||||
<ProtectedRoute adminOnly>
|
||||
<Layout>
|
||||
<AdminProducts />
|
||||
</Layout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Error Routes */}
|
||||
<Route path="/unauthorized" element={<Unauthorized />} />
|
||||
<Route path="/404" element={<NotFound />} />
|
||||
|
||||
{/* Redirects */}
|
||||
<Route path="/" element={<Navigate to="/dashboard" replace />} />
|
||||
<Route path="*" element={<Navigate to="/404" replace />} />
|
||||
</Routes>
|
||||
|
||||
{/* Global Toast Notifications */}
|
||||
<Toaster
|
||||
position="top-right"
|
||||
toastOptions={{
|
||||
duration: 4000,
|
||||
style: {
|
||||
background: '#fff',
|
||||
color: '#374151',
|
||||
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
||||
borderRadius: '0.5rem',
|
||||
border: '1px solid #e5e7eb',
|
||||
},
|
||||
success: {
|
||||
iconTheme: {
|
||||
primary: '#10b981',
|
||||
secondary: '#fff',
|
||||
},
|
||||
},
|
||||
error: {
|
||||
iconTheme: {
|
||||
primary: '#ef4444',
|
||||
secondary: '#fff',
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Router>
|
||||
</AuthProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
Reference in New Issue
Block a user