Files
MyClub/internal/models/navigation.go
T
Tomas Dvorak 087f30e82c dev day #80
2025-11-02 21:31:00 +01:00

149 lines
4.8 KiB
Go

package models
import (
"gorm.io/gorm"
)
// NavigationItemType defines the type of navigation item
type NavigationItemType string
const (
NavTypeInternal NavigationItemType = "internal" // Direct URL
NavTypeExternal NavigationItemType = "external" // External link
NavTypeDropdown NavigationItemType = "dropdown" // Has children
NavTypePage NavigationItemType = "page" // Links to predefined page
)
// NavigationItem represents a single navigation menu item
type NavigationItem struct {
gorm.Model
Label string `gorm:"not null" json:"label"`
URL string `json:"url,omitempty"`
Icon string `json:"icon,omitempty"`
Type NavigationItemType `gorm:"not null;default:'internal'" json:"type"`
PageType string `json:"page_type,omitempty"` // e.g., 'blog', 'about', 'calendar'
PageID *uint `json:"page_id,omitempty"` // optional reference to specific content
Visible bool `gorm:"not null;default:true" json:"visible"`
DisplayOrder int `gorm:"not null;default:0" json:"display_order"`
ParentID *uint `json:"parent_id,omitempty"`
Parent *NavigationItem `gorm:"foreignKey:ParentID" json:"parent,omitempty"`
Children []NavigationItem `gorm:"foreignKey:ParentID" json:"children,omitempty"`
Target string `gorm:"default:'_self'" json:"target"` // _self or _blank
CSSClass string `json:"css_class,omitempty"`
RequiresAuth bool `gorm:"default:false" json:"requires_auth"`
RequiresAdmin bool `gorm:"default:false" json:"requires_admin"`
}
// TableName specifies the table name for the NavigationItem model
func (NavigationItem) TableName() string {
return "navigation_items"
}
// GetURL returns the computed URL based on type and page_type
func (n *NavigationItem) GetURL() string {
if n.URL != "" {
return n.URL
}
// Map page types to URLs for frontend
if n.Type == NavTypePage && n.PageType != "" {
pageURLMap := map[string]string{
"home": "/",
"about": "/o-klubu",
"calendar": "/kalendar",
"matches": "/zapasy",
"activities": "/aktivity",
"players": "/hraci",
"tables": "/tabulky",
"blog": "/blog",
"videos": "/videa",
"gallery": "/galerie",
"sponsors": "/sponzori",
"contact": "/kontakt",
"search": "/hledat",
}
if url, ok := pageURLMap[n.PageType]; ok {
return url
}
}
// Map admin page types to URLs
if (n.Type == NavTypeInternal || n.Type == NavTypePage) && n.PageType != "" && n.RequiresAdmin {
adminURLMap := map[string]string{
"dashboard": "/admin",
"analytics": "/admin/analytika",
"teams": "/admin/tymy",
"matches": "/admin/zapasy",
"activities": "/admin/aktivity",
"players": "/admin/hraci",
"articles": "/admin/clanky",
"categories": "/admin/kategorie",
"about": "/admin/o-klubu",
"videos": "/admin/videa",
"gallery": "/admin/galerie",
"scoreboard": "/admin/scoreboard",
"scoreboard_remote": "/admin/scoreboard/remote",
"clothing": "/admin/obleceni",
"sponsors": "/admin/sponzori",
"banners": "/admin/bannery",
"messages": "/admin/zpravy",
"contacts": "/admin/kontakty",
"newsletter": "/admin/newsletter",
"polls": "/admin/ankety",
"sweepstakes": "/admin/sweepstakes",
"navigation": "/admin/navigace",
"competition_aliases": "/admin/aliasy-soutezi",
"prefetch": "/admin/prefetch",
"users": "/admin/uzivatele",
"settings": "/admin/nastaveni",
"shortlinks": "/admin/shortlinks",
"files": "/admin/soubory",
"docs": "/admin/docs",
}
if url, ok := adminURLMap[n.PageType]; ok {
return url
}
}
return "#"
}
// SocialLink represents a social media link
type SocialLink struct {
gorm.Model
Platform string `gorm:"not null" json:"platform"` // facebook, instagram, youtube, etc.
URL string `gorm:"not null" json:"url"`
DisplayOrder int `gorm:"not null;default:0" json:"display_order"`
Visible bool `gorm:"not null;default:true" json:"visible"`
Icon string `json:"icon,omitempty"` // optional custom icon
}
// TableName specifies the table name for the SocialLink model
func (SocialLink) TableName() string {
return "social_links"
}
// GetIconName returns the React Icons name for the platform
func (s *SocialLink) GetIconName() string {
if s.Icon != "" {
return s.Icon
}
iconMap := map[string]string{
"facebook": "FaFacebook",
"instagram": "FaInstagram",
"youtube": "FaYoutube",
"twitter": "FaTwitter",
"tiktok": "FaTiktok",
"linkedin": "FaLinkedin",
"discord": "FaDiscord",
"twitch": "FaTwitch",
}
if icon, ok := iconMap[s.Platform]; ok {
return icon
}
return "FaLink"
}