package httpapi import ( "net/http" "github.com/gin-gonic/gin" "productier/apps/backend/internal/store" ) func (s *Server) registerProductivityRoutes(group *gin.RouterGroup) { // Inbox group.GET("/inbox", func(c *gin.Context) { workspaceSlug := c.Query("workspaceSlug") if _, ok := s.requireWorkspaceMember(c, workspaceSlug); !ok { return } c.JSON(http.StatusOK, gin.H{"data": s.store.ListInboxItems(workspaceSlug)}) }) group.POST("/inbox", func(c *gin.Context) { var input store.CreateInboxItemInput if err := c.ShouldBindJSON(&input); err != nil { s.writeStatusError(c, http.StatusBadRequest, err.Error()) return } if _, ok := s.requireWorkspaceMember(c, input.WorkspaceSlug); !ok { return } item := s.store.CreateInboxItem(input) c.JSON(http.StatusCreated, gin.H{"data": item}) }) group.POST("/inbox/:itemId/process", func(c *gin.Context) { var input struct { EntityType string `json:"entityType" binding:"required"` EntityID string `json:"entityId" binding:"required"` } if err := c.ShouldBindJSON(&input); err != nil { s.writeStatusError(c, http.StatusBadRequest, err.Error()) return } if err := s.store.ProcessInboxItem(c.Param("itemId"), input.EntityType, input.EntityID); err != nil { s.writeStatusError(c, http.StatusInternalServerError, err.Error()) return } c.JSON(http.StatusOK, gin.H{"ok": true}) }) group.DELETE("/inbox/:itemId", func(c *gin.Context) { if err := s.store.DeleteInboxItem(c.Param("itemId")); err != nil { s.writeStatusError(c, http.StatusInternalServerError, err.Error()) return } c.JSON(http.StatusOK, gin.H{"ok": true}) }) // Time entries group.GET("/time-entries", func(c *gin.Context) { workspaceSlug := c.Query("workspaceSlug") if _, ok := s.requireWorkspaceMember(c, workspaceSlug); !ok { return } c.JSON(http.StatusOK, gin.H{"data": s.store.ListTimeEntries(workspaceSlug)}) }) group.POST("/time-entries", func(c *gin.Context) { var input store.CreateTimeEntryInput if err := c.ShouldBindJSON(&input); err != nil { s.writeStatusError(c, http.StatusBadRequest, err.Error()) return } if _, ok := s.requireWorkspaceMember(c, input.WorkspaceSlug); !ok { return } entry := s.store.CreateTimeEntry(input) c.JSON(http.StatusCreated, gin.H{"data": entry}) }) group.PATCH("/time-entries/:entryId", func(c *gin.Context) { var input store.UpdateTimeEntryInput if err := c.ShouldBindJSON(&input); err != nil { s.writeStatusError(c, http.StatusBadRequest, err.Error()) return } updated, err := s.store.UpdateTimeEntry(c.Param("entryId"), input) if err != nil { s.writeStatusError(c, http.StatusNotFound, err.Error()) return } c.JSON(http.StatusOK, gin.H{"data": updated}) }) group.DELETE("/time-entries/:entryId", func(c *gin.Context) { if err := s.store.DeleteTimeEntry(c.Param("entryId")); err != nil { s.writeStatusError(c, http.StatusInternalServerError, err.Error()) return } c.JSON(http.StatusOK, gin.H{"ok": true}) }) // Saved views group.GET("/saved-views", func(c *gin.Context) { workspaceSlug := c.Query("workspaceSlug") entityType := c.Query("entityType") if _, ok := s.requireWorkspaceMember(c, workspaceSlug); !ok { return } c.JSON(http.StatusOK, gin.H{"data": s.store.ListSavedViews(workspaceSlug, entityType)}) }) group.POST("/saved-views", func(c *gin.Context) { var input store.CreateSavedViewInput if err := c.ShouldBindJSON(&input); err != nil { s.writeStatusError(c, http.StatusBadRequest, err.Error()) return } if _, ok := s.requireWorkspaceMember(c, input.WorkspaceSlug); !ok { return } view := s.store.CreateSavedView(input) c.JSON(http.StatusCreated, gin.H{"data": view}) }) group.DELETE("/saved-views/:viewId", func(c *gin.Context) { if err := s.store.DeleteSavedView(c.Param("viewId")); err != nil { s.writeStatusError(c, http.StatusInternalServerError, err.Error()) return } c.JSON(http.StatusOK, gin.H{"ok": true}) }) }