feat: complete Scrum-manager MVP — dark-themed multi-user task manager
- Login with role-based auth (CTO/Manager/Employee) - Calendar view (month/week) with task chips and quick-add - Kanban board with status columns - Sortable list view with action menus - Task detail drawer with subtasks, comments, activity - Add task modal with validation - Dashboard with stats, workload, priority breakdown - Team tasks grouped by assignee - Reports page with recharts (bar, pie, line, horizontal bar) - Members page with invite modal - Search and assignee filter across views - ErrorBoundary for production error handling - Full dark design system via index.css
This commit is contained in:
48
src/ErrorBoundary.tsx
Normal file
48
src/ErrorBoundary.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
|
||||
interface Props { children: React.ReactNode; }
|
||||
interface State { hasError: boolean; error: Error | null; }
|
||||
|
||||
export class ErrorBoundary extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { hasError: false, error: null };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): State {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
||||
console.error('ErrorBoundary caught:', error, errorInfo);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<div style={{
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
minHeight: '100vh', background: '#0a0f1a', color: '#e2e8f0',
|
||||
fontFamily: '"DM Sans", sans-serif', flexDirection: 'column', gap: 16,
|
||||
}}>
|
||||
<div style={{ fontSize: 48 }}>⚠️</div>
|
||||
<h1 style={{ fontSize: 24, fontWeight: 700 }}>Something went wrong</h1>
|
||||
<p style={{ color: '#94a3b8', maxWidth: 400, textAlign: 'center', lineHeight: 1.6 }}>
|
||||
{this.state.error?.message || 'An unexpected error occurred.'}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => { this.setState({ hasError: false, error: null }); window.location.reload(); }}
|
||||
style={{
|
||||
background: '#6366f1', color: '#fff', border: 'none', borderRadius: 8,
|
||||
padding: '10px 24px', fontSize: 14, fontWeight: 600, cursor: 'pointer',
|
||||
marginTop: 8,
|
||||
}}
|
||||
>
|
||||
Reload App
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user