## 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>
104 lines
3.1 KiB
TypeScript
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;
|
|
}
|
|
}
|