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:
tusuii
2026-02-15 11:36:38 +05:30
commit e46d8773ee
26 changed files with 5410 additions and 0 deletions

48
src/ErrorBoundary.tsx Normal file
View 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;
}
}