Improve admin dashboard task status overview

- Add all task statuses: Pending, In Progress, On Hold, Completed
- Add active, archived, cancelled, and new_30d task counts
- Fix completed query to filter non-archived/non-cancelled tasks
- Update dashboard UI with better layout showing all statuses
- Show cancelled and archived counts in footer row

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-06 12:09:27 -06:00
parent 3b448abcbd
commit 83384db014
3 changed files with 122 additions and 30 deletions

View File

@@ -48,10 +48,24 @@ type ResidenceStats struct {
// TaskStats holds task-related statistics
type TaskStats struct {
Total int64 `json:"total"`
Pending int64 `json:"pending"`
Completed int64 `json:"completed"`
Overdue int64 `json:"overdue"`
Total int64 `json:"total"`
Active int64 `json:"active"` // Non-archived, non-cancelled
Archived int64 `json:"archived"`
Cancelled int64 `json:"cancelled"`
Overdue int64 `json:"overdue"`
New30d int64 `json:"new_30d"`
// By status
Pending int64 `json:"pending"`
InProgress int64 `json:"in_progress"`
Completed int64 `json:"completed"`
OnHold int64 `json:"on_hold"`
}
// TaskStatusCount holds a single status count
type TaskStatusCount struct {
StatusID uint `json:"status_id"`
StatusName string `json:"status_name"`
Count int64 `json:"count"`
}
// ContractorStats holds contractor-related statistics
@@ -103,17 +117,41 @@ func (h *AdminDashboardHandler) GetStats(c *gin.Context) {
// Task stats
h.db.Model(&models.Task{}).Count(&stats.Tasks.Total)
h.db.Model(&models.Task{}).Where("is_cancelled = ? AND is_archived = ?", false, false).
Joins("JOIN task_taskstatus ON task_taskstatus.id = task_task.status_id").
Where("task_taskstatus.name IN ?", []string{"pending", "in_progress"}).
Count(&stats.Tasks.Pending)
h.db.Model(&models.Task{}).Where("is_cancelled = ? AND is_archived = ?", false, false).Count(&stats.Tasks.Active)
h.db.Model(&models.Task{}).Where("is_archived = ?", true).Count(&stats.Tasks.Archived)
h.db.Model(&models.Task{}).Where("is_cancelled = ?", true).Count(&stats.Tasks.Cancelled)
h.db.Model(&models.Task{}).Where("created_at >= ?", thirtyDaysAgo).Count(&stats.Tasks.New30d)
// Task counts by status (using LEFT JOIN to handle tasks with no status)
h.db.Model(&models.Task{}).
Joins("JOIN task_taskstatus ON task_taskstatus.id = task_task.status_id").
Where("task_taskstatus.name = ?", "completed").
Where("is_cancelled = ? AND is_archived = ?", false, false).
Joins("LEFT JOIN task_taskstatus ON task_taskstatus.id = task_task.status_id").
Where("LOWER(task_taskstatus.name) = ? OR task_taskstatus.id IS NULL", "pending").
Count(&stats.Tasks.Pending)
h.db.Model(&models.Task{}).
Where("is_cancelled = ? AND is_archived = ?", false, false).
Joins("LEFT JOIN task_taskstatus ON task_taskstatus.id = task_task.status_id").
Where("LOWER(task_taskstatus.name) = ?", "in progress").
Count(&stats.Tasks.InProgress)
h.db.Model(&models.Task{}).
Where("is_cancelled = ? AND is_archived = ?", false, false).
Joins("LEFT JOIN task_taskstatus ON task_taskstatus.id = task_task.status_id").
Where("LOWER(task_taskstatus.name) = ?", "completed").
Count(&stats.Tasks.Completed)
h.db.Model(&models.Task{}).Where("due_date < ? AND is_cancelled = ? AND is_archived = ?", now, false, false).
Joins("JOIN task_taskstatus ON task_taskstatus.id = task_task.status_id").
Where("task_taskstatus.name NOT IN ?", []string{"completed", "cancelled"}).
h.db.Model(&models.Task{}).
Where("is_cancelled = ? AND is_archived = ?", false, false).
Joins("LEFT JOIN task_taskstatus ON task_taskstatus.id = task_task.status_id").
Where("LOWER(task_taskstatus.name) = ?", "on hold").
Count(&stats.Tasks.OnHold)
// Overdue: past due date, not completed, not cancelled, not archived
h.db.Model(&models.Task{}).
Where("next_due_date < ? AND is_cancelled = ? AND is_archived = ?", now, false, false).
Joins("LEFT JOIN task_taskstatus ON task_taskstatus.id = task_task.status_id").
Where("LOWER(task_taskstatus.name) NOT IN ? OR task_taskstatus.id IS NULL", []string{"completed", "cancelled"}).
Count(&stats.Tasks.Overdue)
// Contractor stats