Add landing page, redesign emails, and return updated task on completion
- Integrate landing page into Go app (served at root /) - Add STATIC_DIR config for static file serving - Redesign all email templates with modern dark theme styling - Add app icon to email headers - Return updated task with kanban_column in completion response - Update task DTO to include kanban column for client-side state updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -73,6 +73,7 @@ type TaskCompletionResponse struct {
|
||||
Rating *int `json:"rating"`
|
||||
Images []TaskCompletionImageResponse `json:"images"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Task *TaskResponse `json:"task,omitempty"` // Updated task after completion
|
||||
}
|
||||
|
||||
// TaskResponse represents a task in the API response
|
||||
@@ -99,10 +100,11 @@ type TaskResponse struct {
|
||||
ContractorID *uint `json:"contractor_id"`
|
||||
IsCancelled bool `json:"is_cancelled"`
|
||||
IsArchived bool `json:"is_archived"`
|
||||
ParentTaskID *uint `json:"parent_task_id"`
|
||||
CompletionCount int `json:"completion_count"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ParentTaskID *uint `json:"parent_task_id"`
|
||||
CompletionCount int `json:"completion_count"`
|
||||
KanbanColumn string `json:"kanban_column,omitempty"` // Which kanban column this task belongs to
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// Note: Pagination removed - list endpoints now return arrays directly
|
||||
@@ -340,3 +342,55 @@ func NewTaskCompletionListResponse(completions []models.TaskCompletion) []TaskCo
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// NewTaskCompletionWithTaskResponse creates a TaskCompletionResponse with the updated task included
|
||||
func NewTaskCompletionWithTaskResponse(c *models.TaskCompletion, task *models.Task, daysThreshold int) TaskCompletionResponse {
|
||||
resp := NewTaskCompletionResponse(c)
|
||||
|
||||
if task != nil {
|
||||
taskResp := NewTaskResponse(task)
|
||||
taskResp.KanbanColumn = DetermineKanbanColumn(task, daysThreshold)
|
||||
resp.Task = &taskResp
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// DetermineKanbanColumn determines which kanban column a task belongs to
|
||||
// Uses the same logic as task_repo.go GetKanbanData
|
||||
func DetermineKanbanColumn(task *models.Task, daysThreshold int) string {
|
||||
if daysThreshold <= 0 {
|
||||
daysThreshold = 30 // Default
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
threshold := now.AddDate(0, 0, daysThreshold)
|
||||
|
||||
// Priority order (same as GetKanbanData):
|
||||
// 1. Cancelled
|
||||
if task.IsCancelled {
|
||||
return "cancelled_tasks"
|
||||
}
|
||||
|
||||
// 2. Completed (has completions)
|
||||
if len(task.Completions) > 0 {
|
||||
return "completed_tasks"
|
||||
}
|
||||
|
||||
// 3. In Progress
|
||||
if task.Status != nil && task.Status.Name == "In Progress" {
|
||||
return "in_progress_tasks"
|
||||
}
|
||||
|
||||
// 4. Due date based
|
||||
if task.DueDate != nil {
|
||||
if task.DueDate.Before(now) {
|
||||
return "overdue_tasks"
|
||||
} else if task.DueDate.Before(threshold) {
|
||||
return "due_soon_tasks"
|
||||
}
|
||||
}
|
||||
|
||||
// Default: upcoming
|
||||
return "upcoming_tasks"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user