miniITCS/backend/internal/handlers/menu.go

198 lines
5.3 KiB
Go

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)
}