dev day #100 - WE ARE FUCKING DONE, hotfixes incoming but we did it in 100 days, lets fucking go guys, anyone reading this...i love you

This commit is contained in:
Tomas Dvorak
2025-11-22 21:30:10 +01:00
parent f5b6f83974
commit aa036b6550
47 changed files with 3607 additions and 2177 deletions
+58 -59
View File
@@ -88,17 +88,17 @@ type Article struct {
OGImageURL string `json:"og_image_url"`
// Optional: link to external content or embedded media
ExternalLink string `json:"external_link"`
ViewCount int `gorm:"default:0;index" json:"view_count"`
ReadTime int `gorm:"default:0" json:"read_time"` // estimated reading time in minutes
UniqueViews int `gorm:"default:0" json:"unique_views"` // Unique visitors (tracked by IP/session)
ViewCount int `gorm:"default:0;index" json:"view_count"`
ReadTime int `gorm:"default:0" json:"read_time"` // estimated reading time in minutes
UniqueViews int `gorm:"default:0" json:"unique_views"` // Unique visitors (tracked by IP/session)
// Store the category name directly to simplify queries (denormalized)
CategoryName string `json:"category_name"`
Attachments string `gorm:"type:text" json:"attachments"` // JSON array: ["url1", "url2", ...]
Attachments string `gorm:"type:text" json:"attachments"` // JSON array: ["url1", "url2", ...]
// Gallery association (optional)
GalleryAlbumID string `json:"gallery_album_id"`
GalleryAlbumURL string `json:"gallery_album_url"`
GalleryAlbumID string `json:"gallery_album_id"`
GalleryAlbumURL string `json:"gallery_album_url"`
// Stored as JSON string or comma-separated list; frontend normalizes
GalleryPhotoIDs string `gorm:"type:text" json:"gallery_photo_ids"`
GalleryPhotoIDs string `gorm:"type:text" json:"gallery_photo_ids"`
// YouTube video association (optional)
YouTubeVideoID string `json:"youtube_video_id"`
YouTubeVideoTitle string `gorm:"type:text" json:"youtube_video_title"`
@@ -108,10 +108,10 @@ type Article struct {
// Removed omitempty to always include in JSON (even if null)
MatchLink *ArticleMatchLink `gorm:"-" json:"match_link"`
// Computed helpers (not persisted)
CategorySlug string `gorm:"-" json:"category_slug,omitempty"`
CompetitionAlias string `gorm:"-" json:"competition_alias,omitempty"`
NormalizedCategory string `gorm:"-" json:"normalized_category,omitempty"`
URL string `gorm:"-" json:"url,omitempty"`
CategorySlug string `gorm:"-" json:"category_slug,omitempty"`
CompetitionAlias string `gorm:"-" json:"competition_alias,omitempty"`
NormalizedCategory string `gorm:"-" json:"normalized_category,omitempty"`
URL string `gorm:"-" json:"url,omitempty"`
}
// ArticleTeamLink represents a link from an article to a team identified by an external FACR ID
@@ -143,7 +143,7 @@ type Team struct {
ShortName string
Description string
LogoURL string `json:"logo_url"`
IsActive bool `gorm:"default:true"`
IsActive bool `gorm:"default:true"`
}
// Player represents a football player
@@ -184,15 +184,15 @@ type Sponsor struct {
// VideoTitleOverride represents a per-video title override (for auto YouTube source)
type VideoTitleOverride struct {
VideoID string `json:"video_id"`
Title string `json:"title"`
VideoID string `json:"video_id"`
Title string `json:"title"`
}
// CustomNavLink represents a simple custom navigation link stored in settings.custom_nav
type CustomNavLink struct {
Label string `json:"label"`
URL string `json:"url"`
External bool `json:"external"`
Label string `json:"label"`
URL string `json:"url"`
External bool `json:"external"`
}
type Settings struct {
@@ -257,7 +257,7 @@ type Settings struct {
// FrontendBaseURL: e.g. https://club.example.com
FrontendBaseURL string `json:"frontend_base_url"`
// APIBaseURL: full API root, e.g. https://api.example.com/api/v1 or https://backend.example.com/api/v1
APIBaseURL string `json:"api_base_url"`
APIBaseURL string `json:"api_base_url"`
// Social profiles
FacebookURL string `json:"facebook_url"`
@@ -279,10 +279,10 @@ type Settings struct {
VideosItemsJSON string `gorm:"type:text" json:"-"`
// Title overrides for auto-fetched videos (stored as JSON array of {video_id,title})
VideosOverridesJSON string `gorm:"type:text" json:"-"`
VideosOverrides []VideoTitleOverride `gorm:"-" json:"videos_overrides,omitempty"`
VideosOverridesJSON string `gorm:"type:text" json:"-"`
VideosOverrides []VideoTitleOverride `gorm:"-" json:"videos_overrides,omitempty"`
// Derived helper for API responses (map form used by frontend/admin): video_id -> title
VideosTitleOverrides map[string]string `gorm:"-" json:"videos_title_overrides,omitempty"`
VideosTitleOverrides map[string]string `gorm:"-" json:"videos_title_overrides,omitempty"`
// Merch module configuration
MerchModuleEnabled bool `json:"merch_module_enabled"`
@@ -313,25 +313,25 @@ type Settings struct {
NewsletterQuietEnd int `json:"newsletter_quiet_end"` // 0-23
// Contact/Location information for map
ContactAddress string `json:"contact_address"`
ContactCity string `json:"contact_city"`
ContactZip string `json:"contact_zip"`
ContactCountry string `json:"contact_country"`
ContactPhone string `json:"contact_phone"`
ContactEmail string `json:"contact_email"`
ContactAddress string `json:"contact_address"`
ContactCity string `json:"contact_city"`
ContactZip string `json:"contact_zip"`
ContactCountry string `json:"contact_country"`
ContactPhone string `json:"contact_phone"`
ContactEmail string `json:"contact_email"`
// Contact form auto-forwarding
ContactForwardEnabled bool `json:"contact_forward_enabled"`
ContactForwardList string `gorm:"type:text" json:"contact_forward_list"` // comma/space/semicolon-separated emails
LocationLatitude float64 `json:"location_latitude"`
LocationLongitude float64 `json:"location_longitude"`
MapZoomLevel int `gorm:"default:15" json:"map_zoom_level"`
MapStyle string `json:"map_style"`
ShowMapOnHomepage bool `json:"show_map_on_homepage"`
ContactForwardEnabled bool `json:"contact_forward_enabled"`
ContactForwardList string `gorm:"type:text" json:"contact_forward_list"` // comma/space/semicolon-separated emails
LocationLatitude float64 `json:"location_latitude"`
LocationLongitude float64 `json:"location_longitude"`
MapZoomLevel int `gorm:"default:15" json:"map_zoom_level"`
MapStyle string `json:"map_style"`
ShowMapOnHomepage bool `json:"show_map_on_homepage"`
// Homepage matches display configuration
FinishedMatchDisplayDays int `gorm:"default:2" json:"finished_match_display_days"`
StorageQuotaMB int `json:"storage_quota_mb"`
StorageWarnThreshold int `json:"storage_warn_threshold"`
StorageQuotaMB int `json:"storage_quota_mb"`
StorageWarnThreshold int `json:"storage_warn_threshold"`
StorageCriticalThreshold int `json:"storage_critical_threshold"`
// External error-review integration
@@ -345,7 +345,6 @@ type Settings struct {
// TableName specifies table name for Settings model
func (Settings) TableName() string { return "settings" }
// LoadCustomNav hydrates the in-memory CustomNav slice from the persisted JSON string.
func (s *Settings) LoadCustomNav() {
if s.CustomNavJSON == "" {
@@ -416,14 +415,14 @@ func (Club) TableName() string {
// ContactCategory represents a category for organizing contacts (e.g., "Management", "Coaches", "Office")
type ContactCategory struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"`
Name string `gorm:"not null;uniqueIndex" json:"name"`
Description string `json:"description"`
DisplayOrder int `gorm:"default:0" json:"display_order"`
IsActive bool `gorm:"default:true" json:"is_active"`
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"`
Name string `gorm:"not null;uniqueIndex" json:"name"`
Description string `json:"description"`
DisplayOrder int `gorm:"default:0" json:"display_order"`
IsActive bool `gorm:"default:true" json:"is_active"`
}
// TableName specifies the table name for the ContactCategory model
@@ -433,20 +432,20 @@ func (ContactCategory) TableName() string {
// Contact represents a contact person (e.g., coach, manager, office staff)
type Contact struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"`
CategoryID *uint `gorm:"index" json:"category_id,omitempty"`
Category *ContactCategory `gorm:"foreignKey:CategoryID" json:"category,omitempty"`
Name string `gorm:"not null" json:"name"`
Position string `json:"position"` // e.g., "Head Coach", "President"
Email string `json:"email"`
Phone string `json:"phone"`
ImageURL string `json:"image_url"`
Description string `gorm:"type:text" json:"description"`
DisplayOrder int `gorm:"default:0" json:"display_order"`
IsActive bool `gorm:"default:true" json:"is_active"`
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"`
CategoryID *uint `gorm:"index" json:"category_id,omitempty"`
Category *ContactCategory `gorm:"foreignKey:CategoryID" json:"category,omitempty"`
Name string `gorm:"not null" json:"name"`
Position string `json:"position"` // e.g., "Head Coach", "President"
Email string `json:"email"`
Phone string `json:"phone"`
ImageURL string `json:"image_url"`
Description string `gorm:"type:text" json:"description"`
DisplayOrder int `gorm:"default:0" json:"display_order"`
IsActive bool `gorm:"default:true" json:"is_active"`
}
// TableName specifies the table name for the Contact model