chore: build backend frontend web
Frontend Web - Build & Lint / build (push) Has been cancelled
Backend - Build & Lint / build (push) Has been cancelled

This commit is contained in:
2026-06-20 20:14:18 +02:00
parent 26f4e75314
commit 74f3d4815e
5 changed files with 64 additions and 9 deletions
+17 -2
View File
@@ -13,6 +13,7 @@ type Category struct {
Name string `json:"name" gorm:"column:name"`
Color string `json:"color" gorm:"column:color"`
IsComingSoon bool `json:"is_coming_soon" gorm:"column:is_coming_soon"`
Position int `json:"position" gorm:"column:position"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
}
@@ -30,7 +31,7 @@ func ValidateCategoryColor(color string) error {
func (d *Database) GetAllCategories() ([]Category, error) {
var categories []Category
if err := d.GDB.Order("name ASC").Find(&categories).Error; err != nil {
if err := d.GDB.Order("position ASC, name ASC").Find(&categories).Error; err != nil {
return nil, err
}
if categories == nil {
@@ -43,7 +44,9 @@ func (d *Database) CreateCategory(name, color string, isComingSoon bool) (*Categ
if color == "" {
color = "#7c3aed"
}
c := Category{Name: name, Color: color, IsComingSoon: isComingSoon}
var maxPos int
d.GDB.Model(&Category{}).Select("COALESCE(MAX(position), 0)").Scan(&maxPos)
c := Category{Name: name, Color: color, IsComingSoon: isComingSoon, Position: maxPos + 1}
if err := d.GDB.Create(&c).Error; err != nil {
return nil, err
}
@@ -82,6 +85,18 @@ func (d *Database) DeleteCategory(id int) error {
return nil
}
// ReorderCategories met à jour les positions selon l'ordre du tableau d'IDs fourni.
func (d *Database) ReorderCategories(ids []int) error {
tx := d.GDB.Begin()
for i, id := range ids {
if err := tx.Model(&Category{}).Where("id = ?", id).Update("position", i+1).Error; err != nil {
tx.Rollback()
return err
}
}
return tx.Commit().Error
}
func (d *Database) CategoryExists(name string) (bool, error) {
var count int64
err := d.GDB.Model(&Category{}).Where("name = ?", name).Count(&count).Error
+17
View File
@@ -165,6 +165,23 @@ func InitDB() *Database {
log.Fatalf("❌ Erreur migration categories.is_coming_soon: %v", err)
}
// Migration: position d'affichage des catégories
if _, err = database.Exec(`ALTER TABLE categories ADD COLUMN IF NOT EXISTS position INTEGER NOT NULL DEFAULT 0`); err != nil {
log.Fatalf("❌ Erreur migration categories.position: %v", err)
}
// Backfill: attribuer des positions aux catégories existantes (ordre alphabétique)
if _, err = database.Exec(`
UPDATE categories c
SET position = sub.rn
FROM (
SELECT id, ROW_NUMBER() OVER (ORDER BY name ASC) AS rn
FROM categories
) sub
WHERE c.id = sub.id AND c.position = 0
`); err != nil {
log.Fatalf("❌ Erreur backfill categories.position: %v", err)
}
// Migration: table paramètres globaux de l'application
if _, err = database.Exec(`CREATE TABLE IF NOT EXISTS app_settings (
key VARCHAR(100) PRIMARY KEY,
+20
View File
@@ -109,6 +109,26 @@ func UpdateCategory(c *gin.Context) {
})
}
func ReorderCategories(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
var req struct {
IDs []int `json:"ids" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil || len(req.IDs) == 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "Liste d'IDs requise"})
return
}
if err := database.ReorderCategories(req.IDs); err != nil {
log.Printf("❌ [CATEGORIES] Reorder erreur: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur lors du réordonnancement"})
return
}
c.JSON(http.StatusOK, gin.H{"success": true})
}
func DeleteCategory(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
+1
View File
@@ -201,6 +201,7 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
// CATÉGORIES - GESTION ADMIN
// ============================================
adminGroupV2.POST("/categories", handlers.CreateCategory)
adminGroupV2.PUT("/categories/reorder", handlers.ReorderCategories)
adminGroupV2.PUT("/categories/:id", handlers.UpdateCategory)
adminGroupV2.DELETE("/categories/:id", handlers.DeleteCategory)
// ============================================