deckhearth/src/App.tsx
Randall Stillwell dc95d0d76d Implement complete user authentication and admin panel system
 Features Added:
- User registration and login with JWT authentication
- Role-based access control (user/admin)
- Comprehensive admin panel with user management
- Password hashing with bcrypt
- Session management and token storage
- Protected routes and public routes
- Modern login/register forms with validation

🗄️ Database Schema:
- Users table with profile information
- Roles and permissions system
- User-role junction tables
- Session management tables
- Database triggers and indexes

🎨 UI/UX Improvements:
- Updated navigation with user menu
- Admin badge and access controls
- Responsive authentication forms
- Loading states and error handling
- Role-based UI elements

🔧 API Endpoints:
- /api/auth/login - User authentication
- /api/auth/register - User registration
- /api/admin/users - User management (admin only)
- /api/setup-auth - Database schema setup

🚀 Admin Panel Features:
- User listing with search and pagination
- Role assignment (user/admin)
- User activation/deactivation
- System dashboard with stats
- Card management placeholder
- Real-time user management
2025-07-21 21:06:38 -05:00

166 lines
4.7 KiB
TypeScript

import React from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Analytics } from '@vercel/analytics/react';
import { SpeedInsights } from '@vercel/speed-insights/react';
import { AuthProvider, useAuth } from './contexts/AuthContext';
import Navbar from './components/Navbar';
import Dashboard from './pages/Dashboard';
import Collections from './pages/Collections';
import Decks from './pages/Decks';
import Cards from './pages/Cards';
import Scanner from './pages/Scanner';
import LoginForm from './components/auth/LoginForm';
import RegisterForm from './components/auth/RegisterForm';
import AdminPanel from './components/admin/AdminPanel';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 1,
refetchOnWindowFocus: false,
},
},
});
// Protected Route Component
const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { user, isLoading } = useAuth();
if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600"></div>
</div>
);
}
if (!user) {
return <Navigate to="/login" replace />;
}
return <>{children}</>;
};
// Public Route Component (redirect if authenticated)
const PublicRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { user, isLoading } = useAuth();
if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600"></div>
</div>
);
}
if (user) {
return <Navigate to="/dashboard" replace />;
}
return <>{children}</>;
};
// Layout Component
const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return (
<div className="min-h-screen bg-gray-50">
<Navbar />
<main className="container mx-auto px-4 py-8">
{children}
</main>
</div>
);
};
function App() {
return (
<QueryClientProvider client={queryClient}>
<AuthProvider>
<Router>
<Routes>
{/* Public Routes */}
<Route path="/login" element={
<PublicRoute>
<LoginForm />
</PublicRoute>
} />
<Route path="/register" element={
<PublicRoute>
<RegisterForm />
</PublicRoute>
} />
{/* Protected Routes */}
<Route path="/dashboard" element={
<ProtectedRoute>
<Layout>
<Dashboard />
</Layout>
</ProtectedRoute>
} />
<Route path="/collections" element={
<ProtectedRoute>
<Layout>
<Collections />
</Layout>
</ProtectedRoute>
} />
<Route path="/decks" element={
<ProtectedRoute>
<Layout>
<Decks />
</Layout>
</ProtectedRoute>
} />
<Route path="/cards" element={
<ProtectedRoute>
<Layout>
<Cards />
</Layout>
</ProtectedRoute>
} />
<Route path="/scanner" element={
<ProtectedRoute>
<Layout>
<Scanner />
</Layout>
</ProtectedRoute>
} />
{/* Admin Routes */}
<Route path="/admin" element={
<ProtectedRoute>
<AdminPanel />
</ProtectedRoute>
} />
{/* Default redirect */}
<Route path="/" element={<Navigate to="/dashboard" replace />} />
{/* 404 fallback */}
<Route path="*" element={
<Layout>
<div className="text-center py-12">
<h1 className="text-4xl font-bold text-gray-900 mb-4">404 - Page Not Found</h1>
<p className="text-gray-600 mb-8">The page you're looking for doesn't exist.</p>
<a href="/dashboard" className="bg-indigo-600 text-white px-6 py-3 rounded-lg hover:bg-indigo-700 transition-colors">
Go to Dashboard
</a>
</div>
</Layout>
} />
</Routes>
<Analytics />
<SpeedInsights />
</Router>
</AuthProvider>
</QueryClientProvider>
);
}
export default App;