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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user