feat: enterprise notification & task management system

Phase N.1 — Data Model:
- Extend Notification model with category, priority, task fields (status, action,
  assignee, dueDate, completedAt/By), reminder fields (remindAt, recurrence,
  nextRemindAt), and targeting metadata (sourceId, senderId, channel)
- Add NotificationCategory, NotificationPriority, TaskStatus enums
- Add NotificationBroadcast model for group notifications
- Shared types with parseTaskAction()/buildTaskAction() helpers

Phase N.2 — API:
- Extend notification router: listTasks, taskCounts, updateTaskStatus,
  createReminder/update/delete/list, createBroadcast/listBroadcasts,
  createTask, assignTask, delete
- Broadcast targeting: resolve recipients by user/role/project/orgUnit/all
- Task-action registry: approve_vacation, reject_vacation, confirm_assignment
- Reminder scheduler: 60s poll interval, recurring support, catch-up on start
- SSE events: TASK_ASSIGNED, TASK_COMPLETED, TASK_STATUS_CHANGED,
  REMINDER_DUE, BROADCAST_SENT

Phase N.3 — AI Assistant:
- 7 new tools: list_tasks, get_task_detail, update_task_status,
  execute_task_action, create_reminder, create_task_for_user, send_broadcast
- execute_task_action dispatches to task-action registry with per-action
  permission checks, marks tasks as completed by AI

Phase N.4 — Frontend:
- Enhanced NotificationBell with task badge, tabs (All/Tasks/Reminders)
- TaskCard component with priority badges, due dates, action buttons
- ReminderModal for creating/editing personal reminders
- BroadcastModal for targeted group notifications (manager+)
- NotificationCenter full-page with 5 tabs and bulk actions
- TaskWidget dashboard widget showing open tasks
- Admin broadcast management page
- AppShell nav links for Notifications and Broadcasts
- SSE hook handlers for task/reminder events

Phase N.5 — Auto-Tasks:
- Vacation create → APPROVAL tasks for all managers
- Vacation approve/reject → mark approval tasks as DONE
- Demand create → TASK for managers to fill staffing needs

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-03-18 11:51:49 +01:00
parent 093e13b88f
commit d0f04f13f8
26 changed files with 3404 additions and 54 deletions
@@ -57,6 +57,12 @@ function ChargeabilityIcon() {
function GraphIcon() {
return <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="6" cy="6" r="2.5" strokeWidth={1.8} /><circle cx="18" cy="6" r="2.5" strokeWidth={1.8} /><circle cx="12" cy="18" r="2.5" strokeWidth={1.8} /><path strokeLinecap="round" strokeWidth={1.8} d="M8.5 7.5l2 7M15.5 7.5l-2 7M8.5 6h7" /></svg>;
}
function NotificationsIcon() {
return <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.8} d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6 6 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" /></svg>;
}
function BroadcastIcon() {
return <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.8} d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>;
}
function AdminIcon() {
return <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.8} d="M12 8a4 4 0 100 8 4 4 0 000-8zm8 4l-2.1.7a7.9 7.9 0 01-.6 1.5l1 2-2.1 2.1-2-1a7.9 7.9 0 01-1.5.6L12 20l-1.7-2.1a7.9 7.9 0 01-1.5-.6l-2 1-2.1-2.1 1-2a7.9 7.9 0 01-.6-1.5L4 12l2.1-1.7a7.9 7.9 0 01.6-1.5l-1-2 2.1-2.1 2 1a7.9 7.9 0 011.5-.6L12 4l1.7 2.1a7.9 7.9 0 011.5.6l2-1 2.1 2.1-1 2a7.9 7.9 0 01.6 1.5L20 12z" /></svg>;
}
@@ -72,6 +78,7 @@ const navSections: NavSection[] = [
{ href: "/timeline", label: "Timeline", icon: <TimelineIcon />, roles: ["ADMIN", "MANAGER", "CONTROLLER", "USER", "VIEWER"] },
{ href: "/allocations", label: "Allocations", icon: <AllocationsIcon />, roles: ["ADMIN", "MANAGER", "CONTROLLER"] },
{ href: "/staffing", label: "Staffing", icon: <StaffingIcon />, roles: ["ADMIN", "MANAGER"] },
{ href: "/notifications", label: "Notifications", icon: <NotificationsIcon />, roles: ["ADMIN", "MANAGER", "CONTROLLER", "USER", "VIEWER"] },
],
},
{
@@ -134,6 +141,7 @@ const adminNavEntries: AdminEntry[] = [
{ href: "/admin/users", label: "Users", icon: <AdminIcon /> },
{ href: "/admin/settings", label: "Settings", icon: <AdminIcon /> },
{ href: "/admin/skill-import", label: "Skill Import", icon: <AdminIcon /> },
{ href: "/admin/notifications", label: "Broadcasts", icon: <BroadcastIcon /> },
];
/**