feat(brand): add brand sort order and drag-to-reorder

Add a sort_order column to brands with a migration, expose a
PUT /api/tenant/brands/order reorder endpoint, and wire the
admin-web BrandsView with drag-and-drop reordering plus i18n.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-08 21:48:20 +08:00
parent fbc69c01b0
commit 71233b6715
16 changed files with 608 additions and 31 deletions
@@ -50,6 +50,20 @@ func (h *BrandHandler) Create(c *gin.Context) {
response.SuccessWithStatus(c, 201, data)
}
func (h *BrandHandler) Reorder(c *gin.Context) {
var req app.BrandReorderRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, response.ErrBadRequest(40001, "invalid_params", err.Error()))
return
}
data, err := h.svc.Reorder(c.Request.Context(), req)
if err != nil {
response.Error(c, err)
return
}
response.Success(c, data)
}
func (h *BrandHandler) Detail(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -235,6 +235,7 @@ func RegisterRoutes(app *bootstrap.App) {
brands.GET("", brandHandler.List)
brands.GET("/library-summary", brandHandler.Summary)
brands.POST("", brandHandler.Create)
brands.PUT("/order", brandHandler.Reorder)
brands.GET("/:id", brandHandler.Detail)
brands.PUT("/:id", brandHandler.Update)
brands.DELETE("/:id", brandHandler.Delete)
@@ -43,6 +43,7 @@ func TestProtectedRoutes_RequireAuth(t *testing.T) {
{http.MethodGet, "/api/tenant/articles"},
{http.MethodGet, "/api/tenant/brands"},
{http.MethodGet, "/api/tenant/brands/library-summary"},
{http.MethodPut, "/api/tenant/brands/order"},
{http.MethodGet, "/api/tenant/monitoring/brands/:brand_id/questions/:question_id/detail"},
{http.MethodGet, "/api/tenant/monitoring/marked-articles"},
{http.MethodPost, "/api/tenant/monitoring/marked-articles"},