Backend: - Add dashboard API router with widget endpoints - Create dashboard schemas for widget data - Add dashboard tests Frontend: - Enhance Dashboard page with widget components - Add dashboard service for API calls - Create reusable dashboard components OpenSpec: - Archive add-dashboard-widgets change - Add dashboard capability specs 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
102 lines
4.8 KiB
Markdown
102 lines
4.8 KiB
Markdown
# Design: Dashboard Widgets
|
|
|
|
## Architecture Overview
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Dashboard Page │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────┐ │
|
|
│ │ My Tasks │ │ Due This │ │ Overdue │ │ Done % │ │
|
|
│ │ 12 │ │ Week: 5 │ │ 2 │ │ 78% │ │
|
|
│ └─────────────┘ └─────────────┘ └─────────────┘ └────────┘ │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ ┌──────────────────────────┐ ┌───────────────────────────┐ │
|
|
│ │ My Workload │ │ Project Health │ │
|
|
│ │ ┌────────────────────┐ │ │ ┌───────────────────────┐ │ │
|
|
│ │ │ 32h / 40h (80%) │ │ │ │ 8 Healthy | 2 At Risk │ │ │
|
|
│ │ │ ████████░░ │ │ │ │ Avg Score: 76% │ │ │
|
|
│ │ └────────────────────┘ │ │ └───────────────────────┘ │ │
|
|
│ └──────────────────────────┘ └───────────────────────────┘ │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Quick Actions: [Spaces] [Workload] [Health] [Audit*] │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## API Design
|
|
|
|
### GET /api/dashboard
|
|
|
|
Single endpoint aggregates all dashboard data to minimize frontend requests.
|
|
|
|
```typescript
|
|
interface DashboardResponse {
|
|
task_stats: {
|
|
assigned_count: number // Total tasks assigned to user
|
|
due_this_week: number // Tasks with due_date in current week
|
|
overdue_count: number // Tasks past due_date, not completed
|
|
completion_rate: number // Percentage (0-100)
|
|
}
|
|
workload: {
|
|
allocated_hours: number
|
|
capacity_hours: number
|
|
load_percentage: number
|
|
load_level: 'normal' | 'warning' | 'overloaded'
|
|
}
|
|
health_summary: {
|
|
total_projects: number
|
|
healthy_count: number
|
|
at_risk_count: number
|
|
critical_count: number
|
|
average_health_score: number
|
|
}
|
|
}
|
|
```
|
|
|
|
## Data Sources
|
|
|
|
| Widget | Source | Notes |
|
|
|--------|--------|-------|
|
|
| Task Statistics | `pjctrl_tasks` table | Filter by assignee_id = current user |
|
|
| Workload | Existing `WorkloadService` | Reuse get_user_workload_detail() |
|
|
| Health Summary | Existing `HealthService` | Reuse get_dashboard() summary |
|
|
|
|
## Performance Considerations
|
|
|
|
1. **Single API Call**: Frontend makes one request instead of three
|
|
2. **Query Optimization**: Task stats use COUNT queries, not full rows
|
|
3. **Caching**: Health summary already cached in Redis (5 min TTL)
|
|
4. **No N+1**: Avoid loading related entities for counts
|
|
|
|
## Component Structure
|
|
|
|
```
|
|
frontend/src/
|
|
├── pages/
|
|
│ └── Dashboard.tsx # Main page (modified)
|
|
├── components/
|
|
│ ├── dashboard/
|
|
│ │ ├── StatisticsCard.tsx # Single stat card
|
|
│ │ ├── WorkloadWidget.tsx # Workload progress bar
|
|
│ │ ├── HealthWidget.tsx # Health summary
|
|
│ │ └── QuickActions.tsx # Navigation links
|
|
└── services/
|
|
└── dashboard.ts # API service (new)
|
|
```
|
|
|
|
## Trade-offs
|
|
|
|
### Decision: Single vs Multiple API Endpoints
|
|
|
|
**Chosen**: Single `/api/dashboard` endpoint
|
|
|
|
**Rationale**:
|
|
- Reduces network round-trips (1 vs 3)
|
|
- Simpler frontend loading state management
|
|
- Data is always consistent (same timestamp)
|
|
|
|
**Rejected Alternative**: Use existing endpoints directly
|
|
- Would require 3 parallel requests
|
|
- More complex error handling
|
|
- Harder to ensure data consistency
|