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

56
src/NavBars.tsx Normal file
View File

@@ -0,0 +1,56 @@
import { USERS } from './data';
interface TopNavbarProps {
title: string;
filterUser: string | null;
onFilterChange: (uid: string | null) => void;
searchQuery: string;
onSearch: (q: string) => void;
onNewTask: () => void;
}
export function TopNavbar({ title, filterUser, onFilterChange, searchQuery, onSearch, onNewTask }: TopNavbarProps) {
return (
<div className="top-navbar">
<span className="navbar-title">{title}</span>
<div className="navbar-search">
<span className="navbar-search-icon">🔍</span>
<input placeholder="Search tasks..." value={searchQuery} onChange={e => onSearch(e.target.value)} />
</div>
<div className="navbar-right">
<div className="filter-chips">
<span className={`filter-chip filter-chip-all ${!filterUser ? 'active' : ''}`} onClick={() => onFilterChange(null)}>All</span>
{USERS.map(u => (
<div key={u.id} className={`filter-chip ${filterUser === u.id ? 'active' : ''}`}
style={{ background: u.color, borderColor: filterUser === u.id ? u.color : 'transparent' }}
title={u.name} onClick={() => onFilterChange(u.id === filterUser ? null : u.id)}>
{u.avatar}
</div>
))}
</div>
<button className="notif-btn">🔔<span className="notif-badge">3</span></button>
<button className="new-task-btn" onClick={onNewTask}>+ New Task</button>
</div>
</div>
);
}
interface BottomToggleBarProps {
activeView: string;
onViewChange: (v: string) => void;
}
export function BottomToggleBar({ activeView, onViewChange }: BottomToggleBarProps) {
return (
<div className="bottom-bar">
<div className="toggle-pill">
{[{ id: 'calendar', icon: '📅', label: 'Calendar' }, { id: 'kanban', icon: '▦', label: 'Kanban' }, { id: 'list', icon: '☰', label: 'List' }].map(v => (
<button key={v.id} className={`toggle-btn ${activeView === v.id ? 'active' : ''}`} onClick={() => onViewChange(v.id)}>
{v.icon} {v.label}
</button>
))}
</div>
</div>
);
}