feat: comprehensive update with Signal, Copilot, themes, and PDF features

## Signal Messaging Integration
- Added SignalService for sending messages to drivers via Signal
- SignalMessage model for tracking message history
- Driver chat modal for real-time messaging
- Send schedule via Signal (ICS + PDF attachments)

## AI Copilot
- Natural language interface for VIP Coordinator
- Capabilities: create VIPs, schedule events, assign drivers
- Help and guidance for users
- Floating copilot button in UI

## Theme System
- Dark/light/system theme support
- Color scheme selection (blue, green, purple, orange, red)
- ThemeContext for global state
- AppearanceMenu in header

## PDF Schedule Export
- VIPSchedulePDF component for schedule generation
- PDF settings (header, footer, branding)
- Preview PDF in browser
- Settings stored in database

## Database Migrations
- add_signal_messages: SignalMessage model
- add_pdf_settings: Settings model for PDF config
- add_reminder_tracking: lastReminderSent for events
- make_driver_phone_optional: phone field nullable

## Event Management
- Event status service for automated updates
- IN_PROGRESS/COMPLETED status tracking
- Reminder tracking for notifications

## UI/UX Improvements
- Driver schedule modal
- Improved My Schedule page
- Better error handling and loading states
- Responsive design improvements

## Other Changes
- AGENT_TEAM.md documentation
- Seed data improvements
- Ability factory updates
- Driver profile page

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-01 19:30:41 +01:00
parent 2d842ed294
commit 3b0b1205df
84 changed files with 12330 additions and 2103 deletions

View File

@@ -4,6 +4,7 @@ import { Auth0Provider } from '@auth0/auth0-react';
import { Toaster } from 'react-hot-toast';
import { AuthProvider } from '@/contexts/AuthContext';
import { AbilityProvider } from '@/contexts/AbilityContext';
import { ThemeProvider } from '@/contexts/ThemeContext';
import { ProtectedRoute } from '@/components/ProtectedRoute';
import { Layout } from '@/components/Layout';
import { ErrorBoundary } from '@/components/ErrorBoundary';
@@ -20,6 +21,20 @@ import { EventList } from '@/pages/EventList';
import { FlightList } from '@/pages/FlightList';
import { UserList } from '@/pages/UserList';
import { AdminTools } from '@/pages/AdminTools';
import { DriverProfile } from '@/pages/DriverProfile';
import { MySchedule } from '@/pages/MySchedule';
import { useAuth } from '@/contexts/AuthContext';
// Smart redirect based on user role
function HomeRedirect() {
const { backendUser } = useAuth();
// Drivers go to their schedule, everyone else goes to dashboard
if (backendUser?.role === 'DRIVER') {
return <Navigate to="/my-schedule" replace />;
}
return <Navigate to="/dashboard" replace />;
}
const queryClient = new QueryClient({
defaultOptions: {
@@ -37,6 +52,7 @@ const audience = import.meta.env.VITE_AUTH0_AUDIENCE;
function App() {
return (
<ErrorBoundary>
<ThemeProvider>
<Auth0Provider
domain={domain}
clientId={clientId}
@@ -61,22 +77,24 @@ function App() {
position="top-right"
toastOptions={{
duration: 4000,
className: 'bg-card text-card-foreground border border-border shadow-elevated',
style: {
background: '#333',
color: '#fff',
background: 'hsl(var(--card))',
color: 'hsl(var(--card-foreground))',
border: '1px solid hsl(var(--border))',
},
success: {
duration: 3000,
iconTheme: {
primary: '#10b981',
secondary: '#fff',
primary: 'hsl(142, 76%, 36%)',
secondary: 'hsl(0, 0%, 100%)',
},
},
error: {
duration: 5000,
iconTheme: {
primary: '#ef4444',
secondary: '#fff',
primary: 'hsl(0, 84%, 60%)',
secondary: 'hsl(0, 0%, 100%)',
},
},
}}
@@ -102,8 +120,10 @@ function App() {
<Route path="/flights" element={<FlightList />} />
<Route path="/users" element={<UserList />} />
<Route path="/admin-tools" element={<AdminTools />} />
<Route path="/" element={<Navigate to="/dashboard" replace />} />
<Route path="*" element={<Navigate to="/dashboard" replace />} />
<Route path="/profile" element={<DriverProfile />} />
<Route path="/my-schedule" element={<MySchedule />} />
<Route path="/" element={<HomeRedirect />} />
<Route path="*" element={<HomeRedirect />} />
</Routes>
</Layout>
</ProtectedRoute>
@@ -115,6 +135,7 @@ function App() {
</AuthProvider>
</QueryClientProvider>
</Auth0Provider>
</ThemeProvider>
</ErrorBoundary>
);
}