package handlers // folders.go — Chat folder CRUD (v0.23.1) // // v0.29.0: Raw SQL replaced with FolderStore methods. import ( "net/http" "strings" "github.com/gin-gonic/gin" "git.gobha.me/xcaliber/chat-switchboard/models" "git.gobha.me/xcaliber/chat-switchboard/store" ) type FolderHandler struct { stores store.Stores } func NewFolderHandler(s store.Stores) *FolderHandler { return &FolderHandler{stores: s} } func (h *FolderHandler) List(c *gin.Context) { userID := getUserID(c) folders, err := h.stores.Folders.List(c.Request.Context(), userID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list folders"}) return } c.JSON(http.StatusOK, gin.H{"folders": folders}) } func (h *FolderHandler) Create(c *gin.Context) { userID := getUserID(c) var req struct { Name string `json:"name" binding:"required"` SortOrder int `json:"sort_order"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } req.Name = strings.TrimSpace(req.Name) if req.Name == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "name is required"}) return } f := &models.Folder{ UserID: userID, Name: req.Name, SortOrder: req.SortOrder, } if err := h.stores.Folders.Create(c.Request.Context(), f); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create folder"}) return } c.JSON(http.StatusCreated, gin.H{"folder": f}) } func (h *FolderHandler) Update(c *gin.Context) { userID := getUserID(c) folderID := c.Param("id") var req struct { Name string `json:"name"` SortOrder *int `json:"sort_order"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if req.Name != "" { req.Name = strings.TrimSpace(req.Name) } n, err := h.stores.Folders.Update(c.Request.Context(), folderID, userID, req.Name, req.SortOrder) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update folder"}) return } if n == 0 { c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"}) return } c.JSON(http.StatusOK, gin.H{"ok": true}) } func (h *FolderHandler) Delete(c *gin.Context) { userID := getUserID(c) folderID := c.Param("id") // Unassign chats before deleting folder _ = h.stores.Folders.UnassignChannels(c.Request.Context(), folderID, userID) n, err := h.stores.Folders.Delete(c.Request.Context(), folderID, userID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete folder"}) return } if n == 0 { c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"}) return } c.JSON(http.StatusOK, gin.H{"ok": true}) }