package responses import ( "strings" "time" "github.com/treytartt/honeydue-api/internal/models" ) // TaskTemplateResponse represents a task template in the API response type TaskTemplateResponse struct { ID uint `json:"id"` Title string `json:"title"` Description string `json:"description"` CategoryID *uint `json:"category_id"` Category *TaskCategoryResponse `json:"category,omitempty"` FrequencyID *uint `json:"frequency_id"` Frequency *TaskFrequencyResponse `json:"frequency,omitempty"` IconIOS string `json:"icon_ios"` IconAndroid string `json:"icon_android"` Tags []string `json:"tags"` DisplayOrder int `json:"display_order"` IsActive bool `json:"is_active"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // TaskTemplateCategoryGroup represents templates grouped by category type TaskTemplateCategoryGroup struct { CategoryName string `json:"category_name"` CategoryID *uint `json:"category_id"` Templates []TaskTemplateResponse `json:"templates"` Count int `json:"count"` } // TaskTemplatesGroupedResponse represents all templates grouped by category type TaskTemplatesGroupedResponse struct { Categories []TaskTemplateCategoryGroup `json:"categories"` TotalCount int `json:"total_count"` } // NewTaskTemplateResponse creates a TaskTemplateResponse from a model func NewTaskTemplateResponse(t *models.TaskTemplate) TaskTemplateResponse { resp := TaskTemplateResponse{ ID: t.ID, Title: t.Title, Description: t.Description, CategoryID: t.CategoryID, FrequencyID: t.FrequencyID, IconIOS: t.IconIOS, IconAndroid: t.IconAndroid, Tags: parseTags(t.Tags), DisplayOrder: t.DisplayOrder, IsActive: t.IsActive, CreatedAt: t.CreatedAt, UpdatedAt: t.UpdatedAt, } if t.Category != nil { resp.Category = NewTaskCategoryResponse(t.Category) } if t.Frequency != nil { resp.Frequency = NewTaskFrequencyResponse(t.Frequency) } return resp } // NewTaskTemplateListResponse creates a list of task template responses func NewTaskTemplateListResponse(templates []models.TaskTemplate) []TaskTemplateResponse { results := make([]TaskTemplateResponse, len(templates)) for i, t := range templates { results[i] = NewTaskTemplateResponse(&t) } return results } // NewTaskTemplatesGroupedResponse creates a grouped response from templates func NewTaskTemplatesGroupedResponse(templates []models.TaskTemplate) TaskTemplatesGroupedResponse { // Group by category categoryMap := make(map[string]*TaskTemplateCategoryGroup) categoryOrder := []string{} // To maintain order for _, t := range templates { categoryName := "Uncategorized" var categoryID *uint if t.Category != nil { categoryName = t.Category.Name categoryID = &t.Category.ID } if _, exists := categoryMap[categoryName]; !exists { categoryMap[categoryName] = &TaskTemplateCategoryGroup{ CategoryName: categoryName, CategoryID: categoryID, Templates: []TaskTemplateResponse{}, } categoryOrder = append(categoryOrder, categoryName) } categoryMap[categoryName].Templates = append(categoryMap[categoryName].Templates, NewTaskTemplateResponse(&t)) } // Build ordered result categories := make([]TaskTemplateCategoryGroup, len(categoryOrder)) totalCount := 0 for i, name := range categoryOrder { group := categoryMap[name] group.Count = len(group.Templates) totalCount += group.Count categories[i] = *group } return TaskTemplatesGroupedResponse{ Categories: categories, TotalCount: totalCount, } } // parseTags splits a comma-separated tags string into a slice func parseTags(tags string) []string { if tags == "" { return []string{} } parts := strings.Split(tags, ",") result := make([]string, 0, len(parts)) for _, p := range parts { trimmed := strings.TrimSpace(p) if trimmed != "" { result = append(result, trimmed) } } return result }