Files
vip-coordinator/frontend/src/components/ErrorBoundary.tsx
kyle 3b0b1205df 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>
2026-02-01 19:30:41 +01:00

104 lines
3.1 KiB
TypeScript

import React, { Component, ReactNode } from 'react';
import { AlertTriangle, RefreshCw, Home } from 'lucide-react';
interface Props {
children: ReactNode;
}
interface State {
hasError: boolean;
error: Error | null;
errorInfo: React.ErrorInfo | null;
}
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null,
};
}
static getDerivedStateFromError(error: Error): State {
return {
hasError: true,
error,
errorInfo: null,
};
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('[ERROR BOUNDARY] Caught error:', error, errorInfo);
this.setState({
error,
errorInfo,
});
}
handleReload = () => {
window.location.reload();
};
handleGoHome = () => {
window.location.href = '/';
};
render() {
if (this.state.hasError) {
return (
<div className="min-h-screen bg-muted flex items-center justify-center p-4">
<div className="max-w-md w-full bg-card rounded-lg shadow-xl p-8">
<div className="flex justify-center mb-6">
<div className="rounded-full bg-red-100 p-4">
<AlertTriangle className="h-12 w-12 text-red-600" />
</div>
</div>
<h1 className="text-2xl font-bold text-foreground text-center mb-4">
Something went wrong
</h1>
<p className="text-muted-foreground text-center mb-6">
The application encountered an unexpected error. Please try refreshing the page or returning to the home page.
</p>
{process.env.NODE_ENV === 'development' && this.state.error && (
<div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-lg overflow-auto">
<p className="text-sm font-mono text-red-800 mb-2">
{this.state.error.toString()}
</p>
{this.state.errorInfo && (
<pre className="text-xs text-red-700 overflow-auto max-h-40">
{this.state.errorInfo.componentStack}
</pre>
)}
</div>
)}
<div className="flex gap-3">
<button
onClick={this.handleReload}
className="flex-1 inline-flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary hover:bg-primary/90"
>
<RefreshCw className="h-4 w-4 mr-2" />
Reload Page
</button>
<button
onClick={this.handleGoHome}
className="flex-1 inline-flex items-center justify-center px-4 py-2 border border-input text-sm font-medium rounded-md text-foreground bg-card hover:bg-accent"
>
<Home className="h-4 w-4 mr-2" />
Go Home
</button>
</div>
</div>
</div>
);
}
return this.props.children;
}
}