package handlers import ( "strings" "server/internal/models" "github.com/gofiber/fiber/v2" "gorm.io/gorm" ) // GET /api/app-templates func ListAppTemplatesHandler(db *gorm.DB) fiber.Handler { return func(c *fiber.Ctx) error { var rows []models.AppTemplate if err := db.Order("name asc").Find(&rows).Error; err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"data": rows}) } } // POST /api/app-templates func CreateAppTemplateHandler(db *gorm.DB) fiber.Handler { return func(c *fiber.Ctx) error { var req struct { Name string `json:"name"` Description string `json:"description"` Keywords string `json:"keywords"` } if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid payload"}) } name := strings.TrimSpace(req.Name) if name == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "name required"}) } keywords := normalizeKeywordCSV(req.Keywords) if keywords == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "keywords required"}) } row := models.AppTemplate{ Name: name, Description: strings.TrimSpace(req.Description), Keywords: keywords, } if err := db.Create(&row).Error; err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"ok": true, "data": row}) } } // PATCH /api/app-templates/:id func UpdateAppTemplateHandler(db *gorm.DB) fiber.Handler { return func(c *fiber.Ctx) error { var row models.AppTemplate if err := db.First(&row, c.Params("id")).Error; err != nil { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "not found"}) } var req struct { Name *string `json:"name"` Description *string `json:"description"` Keywords *string `json:"keywords"` } if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid payload"}) } if req.Name != nil { name := strings.TrimSpace(*req.Name) if name == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "name required"}) } row.Name = name } if req.Description != nil { row.Description = strings.TrimSpace(*req.Description) } if req.Keywords != nil { keywords := normalizeKeywordCSV(*req.Keywords) if keywords == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "keywords required"}) } row.Keywords = keywords } if err := db.Save(&row).Error; err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"ok": true, "data": row}) } } // DELETE /api/app-templates/:id func DeleteAppTemplateHandler(db *gorm.DB) fiber.Handler { return func(c *fiber.Ctx) error { if err := db.Delete(&models.AppTemplate{}, c.Params("id")).Error; err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"ok": true}) } } func normalizeKeywordCSV(raw string) string { parts := strings.Split(raw, ",") seen := make(map[string]struct{}) var out []string for _, p := range parts { kw := strings.ToLower(strings.TrimSpace(p)) if kw == "" { continue } if _, ok := seen[kw]; ok { continue } seen[kw] = struct{}{} out = append(out, kw) } return strings.Join(out, ", ") }