feat(shared): add centralized helper functions for templates

This commit is contained in:
2026-04-20 16:36:14 +02:00
parent 953e2a067e
commit 436686eed1
3 changed files with 66 additions and 0 deletions

43
web/shared/format.go Normal file
View File

@@ -0,0 +1,43 @@
package shared
import (
"fmt"
"net/url"
)
// BuildStreamURL constructs a stream URL from mode and token
func BuildStreamURL(mode string, token string) string {
if token == "" {
return ""
}
return fmt.Sprintf("/watch/proxy/stream?mode=%s&token=%s", url.QueryEscape(mode), url.QueryEscape(token))
}
// FormatProgressTime formats seconds into MM:SS format
func FormatProgressTime(seconds float64) string {
total := int(seconds)
if total < 0 {
total = 0
}
minutes := total / 60
remainingSeconds := total % 60
return fmt.Sprintf("%02d:%02d", minutes, remainingSeconds)
}
// FormatEstablishedDate extracts YYYY-MM-DD from ISO date string
func FormatEstablishedDate(date string) string {
if len(date) >= 10 {
return date[:10]
}
return date
}
// WatchlistURL builds the watchlist URL with query parameters
func WatchlistURL(view string, status string, sortBy string, sortOrder string) string {
return fmt.Sprintf("/watchlist?view=%s&status=%s&sort=%s&order=%s", view, status, sortBy, sortOrder)
}
// AnimeURL builds the anime detail URL
func AnimeURL(animeID int) string {
return fmt.Sprintf("/anime/%d", animeID)
}

13
web/shared/studio.go Normal file
View File

@@ -0,0 +1,13 @@
package shared
import "mal/integrations/jikan"
// GetProducerName extracts the default title from producer response
func GetProducerName(producer jikan.ProducerResponse) string {
for _, title := range producer.Data.Titles {
if title.Type == "Default" {
return title.Title
}
}
return "Studio"
}

10
web/shared/ui.go Normal file
View File

@@ -0,0 +1,10 @@
package shared
// TabClass returns the CSS class for watchlist filter tabs
func TabClass(active bool) string {
base := "shrink-0 whitespace-nowrap bg-(--panel-soft) px-2 py-1 text-xs text-(--text-muted) no-underline hover:bg-(--surface-tab-hover) hover:text-(--text) hover:no-underline"
if active {
return "shrink-0 whitespace-nowrap bg-(--surface-tab-active) px-2 py-1 text-xs text-(--accent) no-underline hover:no-underline"
}
return base
}