package handlers import ( "database/sql" "net/http" "github.com/gin-gonic/gin" "admintemplate/internal/database" "admintemplate/internal/models" ) type MenuHandler struct { db *database.DB } func NewMenuHandler(db *database.DB) *MenuHandler { return &MenuHandler{db: db} } // GetMenuItems returns all menu items organized in a tree structure func (h *MenuHandler) GetMenuItems(c *gin.Context) { userRole := c.GetString("userRole") // Get all active menu items rows, err := h.db.Query(` SELECT id, parent_id, title, icon, route, sort_order, active, role_required FROM menu_items WHERE active = 1 ORDER BY sort_order `) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch menu items"}) return } defer rows.Close() var allItems []models.MenuItem for rows.Next() { var item models.MenuItem var parentID sql.NullInt64 err := rows.Scan(&item.ID, &parentID, &item.Title, &item.Icon, &item.Route, &item.SortOrder, &item.Active, &item.RoleReq) if err != nil { continue } if parentID.Valid { item.ParentID = &parentID.Int64 } // Filter by role if item.RoleReq != "" && item.RoleReq != userRole && userRole != "admin" { continue } allItems = append(allItems, item) } // Build tree structure menuTree := buildMenuTree(allItems, nil) c.JSON(http.StatusOK, menuTree) } // buildMenuTree creates a nested menu structure func buildMenuTree(items []models.MenuItem, parentID *int64) []models.MenuItem { var result []models.MenuItem for _, item := range items { if (parentID == nil && item.ParentID == nil) || (parentID != nil && item.ParentID != nil && *parentID == *item.ParentID) { item.Children = buildMenuTree(items, &item.ID) result = append(result, item) } } return result } // GetToolbarItems returns all toolbar items func (h *MenuHandler) GetToolbarItems(c *gin.Context) { rows, err := h.db.Query(` SELECT id, title, icon, action, shortcut, sort_order, active, separator FROM toolbar_items WHERE active = 1 ORDER BY sort_order `) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch toolbar items"}) return } defer rows.Close() var items []models.ToolbarItem for rows.Next() { var item models.ToolbarItem err := rows.Scan(&item.ID, &item.Title, &item.Icon, &item.Action, &item.Shortcut, &item.SortOrder, &item.Active, &item.Separator) if err != nil { continue } items = append(items, item) } c.JSON(http.StatusOK, items) } // GetUserSettings returns user settings func (h *MenuHandler) GetUserSettings(c *gin.Context) { userID := c.GetInt64("userID") var settings models.UserSettings err := h.db.QueryRow(` SELECT id, user_id, sidebar_position, sidebar_collapsed, theme FROM user_settings WHERE user_id = ? `, userID).Scan(&settings.ID, &settings.UserID, &settings.SidebarPosition, &settings.SidebarCollapsed, &settings.Theme) if err == sql.ErrNoRows { // Return default settings settings = models.UserSettings{ UserID: userID, SidebarPosition: "left", SidebarCollapsed: false, Theme: "light", } } else if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch settings"}) return } c.JSON(http.StatusOK, settings) } // UpdateUserSettings updates user settings func (h *MenuHandler) UpdateUserSettings(c *gin.Context) { userID := c.GetInt64("userID") var req models.UpdateSettingsRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Check if settings exist var existingID int64 err := h.db.QueryRow("SELECT id FROM user_settings WHERE user_id = ?", userID).Scan(&existingID) if err == sql.ErrNoRows { // Insert new settings position := "left" collapsed := false theme := "light" if req.SidebarPosition != nil { position = *req.SidebarPosition } if req.SidebarCollapsed != nil { collapsed = *req.SidebarCollapsed } if req.Theme != nil { theme = *req.Theme } _, err = h.db.Exec(` INSERT INTO user_settings (user_id, sidebar_position, sidebar_collapsed, theme) VALUES (?, ?, ?, ?) `, userID, position, collapsed, theme) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create settings"}) return } } else if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to check settings"}) return } else { // Update existing settings if req.SidebarPosition != nil { if _, err := h.db.Exec("UPDATE user_settings SET sidebar_position = ? WHERE user_id = ?", *req.SidebarPosition, userID); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update sidebar position"}) return } } if req.SidebarCollapsed != nil { if _, err := h.db.Exec("UPDATE user_settings SET sidebar_collapsed = ? WHERE user_id = ?", *req.SidebarCollapsed, userID); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update sidebar collapsed"}) return } } if req.Theme != nil { if _, err := h.db.Exec("UPDATE user_settings SET theme = ? WHERE user_id = ?", *req.Theme, userID); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update theme"}) return } } } // Return updated settings h.GetUserSettings(c) }