diff --git a/src/App.tsx b/src/App.tsx index ba55eac..544b7a3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,22 +1,23 @@ -import { useEffect } from 'react'; +import { useEffect, lazy, Suspense } from 'react'; import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import { useAuthStore } from '@/stores/auth'; import Layout from '@/components/Layout'; -import LoginPage from '@/pages/LoginPage'; -import DashboardPage from '@/pages/DashboardPage'; -import ClientsPage from '@/pages/ClientsPage'; -import ClientDetailPage from '@/pages/ClientDetailPage'; -import EventsPage from '@/pages/EventsPage'; -import EmailsPage from '@/pages/EmailsPage'; -import SettingsPage from '@/pages/SettingsPage'; -import AdminPage from '@/pages/AdminPage'; -import NetworkPage from '@/pages/NetworkPage'; -import ReportsPage from '@/pages/ReportsPage'; -import InvitePage from '@/pages/InvitePage'; -import ForgotPasswordPage from '@/pages/ForgotPasswordPage'; -import ResetPasswordPage from '@/pages/ResetPasswordPage'; import { PageLoader } from '@/components/LoadingSpinner'; +const LoginPage = lazy(() => import('@/pages/LoginPage')); +const DashboardPage = lazy(() => import('@/pages/DashboardPage')); +const ClientsPage = lazy(() => import('@/pages/ClientsPage')); +const ClientDetailPage = lazy(() => import('@/pages/ClientDetailPage')); +const EventsPage = lazy(() => import('@/pages/EventsPage')); +const EmailsPage = lazy(() => import('@/pages/EmailsPage')); +const SettingsPage = lazy(() => import('@/pages/SettingsPage')); +const AdminPage = lazy(() => import('@/pages/AdminPage')); +const NetworkPage = lazy(() => import('@/pages/NetworkPage')); +const ReportsPage = lazy(() => import('@/pages/ReportsPage')); +const InvitePage = lazy(() => import('@/pages/InvitePage')); +const ForgotPasswordPage = lazy(() => import('@/pages/ForgotPasswordPage')); +const ResetPasswordPage = lazy(() => import('@/pages/ResetPasswordPage')); + function ProtectedRoute({ children }: { children: React.ReactNode }) { const { isAuthenticated, isLoading } = useAuthStore(); if (isLoading) return ; @@ -33,29 +34,31 @@ export default function App() { return ( - - : - } /> - } /> - } /> - } /> - - - - }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - + }> + + : + } /> + } /> + } /> + } /> + + + + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + ); } diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index 85d2ec9..8a1b685 100644 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -1,13 +1,13 @@ import { cn } from '@/lib/utils'; const colorMap: Record = { - blue: 'bg-blue-50 text-blue-700 border-blue-200', - green: 'bg-emerald-50 text-emerald-700 border-emerald-200', - yellow: 'bg-amber-50 text-amber-700 border-amber-200', - red: 'bg-red-50 text-red-700 border-red-200', - purple: 'bg-purple-50 text-purple-700 border-purple-200', - gray: 'bg-slate-50 text-slate-600 border-slate-200', - pink: 'bg-pink-50 text-pink-700 border-pink-200', + blue: 'bg-blue-50 text-blue-700 border-blue-200 dark:bg-blue-900/50 dark:text-blue-300 dark:border-blue-800', + green: 'bg-emerald-50 text-emerald-700 border-emerald-200 dark:bg-emerald-900/50 dark:text-emerald-300 dark:border-emerald-800', + yellow: 'bg-amber-50 text-amber-700 border-amber-200 dark:bg-amber-900/50 dark:text-amber-300 dark:border-amber-800', + red: 'bg-red-50 text-red-700 border-red-200 dark:bg-red-900/50 dark:text-red-300 dark:border-red-800', + purple: 'bg-purple-50 text-purple-700 border-purple-200 dark:bg-purple-900/50 dark:text-purple-300 dark:border-purple-800', + gray: 'bg-slate-50 text-slate-600 border-slate-200 dark:bg-slate-700 dark:text-slate-300 dark:border-slate-600', + pink: 'bg-pink-50 text-pink-700 border-pink-200 dark:bg-pink-900/50 dark:text-pink-300 dark:border-pink-800', }; interface BadgeProps { @@ -26,7 +26,7 @@ export default function Badge({ children, color = 'gray', className, onClick, ac 'inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium border', colorMap[color] || colorMap.gray, onClick && 'cursor-pointer hover:opacity-80', - active && 'ring-2 ring-blue-400 ring-offset-1', + active && 'ring-2 ring-blue-400 ring-offset-1 dark:ring-offset-slate-900', className, )} > diff --git a/src/components/CSVImportModal.tsx b/src/components/CSVImportModal.tsx index 2d2f2a7..7a81a6e 100644 --- a/src/components/CSVImportModal.tsx +++ b/src/components/CSVImportModal.tsx @@ -125,13 +125,13 @@ export default function CSVImportModal({ isOpen, onClose, onComplete }: CSVImpor
fileRef.current?.click()} - className="border-2 border-dashed border-slate-300 rounded-xl p-8 text-center cursor-pointer hover:border-blue-400 hover:bg-blue-50/50 transition-all" + className="border-2 border-dashed border-slate-300 dark:border-slate-600 rounded-xl p-8 text-center cursor-pointer hover:border-blue-400 dark:hover:border-blue-500 hover:bg-blue-50/50 dark:hover:bg-blue-900/20 transition-all" > - -

+ +

Click to select a CSV file

-

+

Must include at least First Name and Last Name columns

@@ -145,11 +145,11 @@ export default function CSVImportModal({ isOpen, onClose, onComplete }: CSVImpor {loading && (
- Parsing CSV... + Parsing CSV...
)} {error && ( -
+
{error}
@@ -160,25 +160,25 @@ export default function CSVImportModal({ isOpen, onClose, onComplete }: CSVImpor {/* Step: Column Mapping */} {step === 'mapping' && preview && (
-
+
{preview.totalRows} rows found in {file?.name}
{/* Column mapping */}
-

Map columns to client fields:

+

Map columns to client fields:

{preview.headers.map((header, index) => (
- + {header} - +