package page import ( . "ersteller-lib" "fmt" "time" . "maragu.dev/gomponents" . "maragu.dev/gomponents/components" . "maragu.dev/gomponents/html" ) const DeIndexUrl = "/de/index" const EnIndexUrl = "/en/index" const DefaultLanguage = En var _texts *Texts func CreatePage(req HtmxContext, metadata PageWebsiteMetaData, content ...Node) { metadata.Lang = req.GetLanguage() var contentForFunction Node if len(content) > 0 { contentForFunction = Div(content...) } else if len(content) == 0 { contentForFunction = Div() } else if len(content) == 1 { contentForFunction = content[0] } styles := []string{ "/static/styles.css", } for _, src := range metadata.StyleSrcs { styles = append(styles, src) } scripts := []string{ "/static/scripts/language-select.js", "/static/htmx.js", } for _, src := range metadata.ScriptSrcs { scripts = append(scripts, src) } page := HTML5(HTML5Props{ Title: "White Label App " + metadata.Title.From(req), Language: string(metadata.Lang), Description: metadata.Description.From(req), Head: []Node{ Map(styles, func(s string) Node { return Link(Rel("stylesheet"), Href(s)) }), Map(scripts, func(s string) Node { return Script(Type("text/javascript"), Src(s)) }), addLanguageSelectScript(metadata), }, Body: []Node{ Header(Class("header"), Div(Class("header-content"), Div(Class("logo"), Span(Class("logo-icon"), Text("🚀")), Span(Class("logo-text"), Text("White Label App")), ), getNav(req, metadata), getLanguageSwitcher(req, metadata), ), ), Div(Class("container"), contentForFunction, ), Footer(Class("footer"), Div(Class("footer-menu"), Aria("label", "Footer Menu"), getFooterMenu(req, metadata), ), P(Class("footer-disclaimer"), Text(getTexts().disclaimer.From(req))), P(Text(getTexts().getCopyright(req.GetLanguage()))), ), }, }) req.Render(page) } func addLanguageSelectScript(metadata PageWebsiteMetaData) Node { script := InlineTemplate(` (function() { const langs = { de: "$.DeUrl$", en: "$.EnUrl$", }; const currentLang = "$.CurrentLang$"; const defaultLang = "$.DefaultLang$"; selectWebsiteLanguage(currentLang, langs, defaultLang); })();`, struct { CurrentLang string DeUrl string EnUrl string DefaultLang string }{ CurrentLang: string(metadata.Lang), DeUrl: DeIndexUrl, EnUrl: EnIndexUrl, DefaultLang: string(DefaultLanguage), }) return Script(Type("text/javascript"), Raw(script)) } func getNav(c HtmxContext, metadata PageWebsiteMetaData) Node { return Nav(Class("nav"), Aria("label", "Main Menu"), Map(metadata.NavItems, func(path ActivePath) Node { return createNavItem(c, path) }), ) } func createNavItem(c HtmxContext, activePath ActivePath) Node { isActive := activePath.IsActive(c) return A( Href(activePath.GetPath(c.GetLanguage())), Text(activePath.From(c)), If(isActive, Attr("aria-current", "page")), If(isActive, Class("selected")), ) } func getLanguageSwitcher(c HtmxContext, metadata PageWebsiteMetaData) Node { currentLang := c.GetLanguage() var currentRoute HtmxRoute for _, route := range c.GetAllRoutes() { if route.IsCurrentRoute(c) { currentRoute = route break } } return Div(Class("language-switcher"), createLanguageButton(En, currentLang, currentRoute, c), createLanguageButton(De, currentLang, currentRoute, c), ) } func getFooterMenu(c HtmxContext, metadata PageWebsiteMetaData) Node { lang := c.GetLanguage() return Div( Map(metadata.FooterNavItems, func(path ActivePath) Node { return Span( A(Href(path.GetPath(lang)), Class("footer-link"), Text(path.From(c))), ) }), ) } func createLanguageButton(lang Language, currentLang Language, route HtmxRoute, c HtmxContext) Node { isActive := lang == currentLang var href string if route != nil { href = route.ToUrlFromContext(c, lang) } else { // Fallback to index page if no active path found if lang == En { href = EnIndexUrl } else { href = DeIndexUrl } } var langText string if lang == En { langText = "EN" } else { langText = "DE" } // Combine classes properly var classes string if isActive { classes = "language-button active" } else { classes = "language-button inactive" } return A( Href(href), Text(langText), Class(classes), ) } type Texts struct { disclaimer I18nText copyright I18nText } func NewTexts() *Texts { return &Texts{ disclaimer: NewI18nText(map[Language]string{ De: "Dies ist eine White-Label-Vorlage. Passen Sie den Inhalt an Ihre Bedürfnisse an.", En: "This is a white label template. Customize the content to fit your needs.", }), copyright: NewI18nText(map[Language]string{ De: "© 2020 - $Year$ White Label App. Alle Rechte vorbehalten.", En: "© 2020 - $Year$ White Label App. All rights reserved.", }), } } func (t *Texts) getCopyright(lang Language) string { currentYear := fmt.Sprint(time.Now().Year()) text := t.copyright.FromLang(lang) return InlineTemplate(text, struct { Year string }{ Year: currentYear, }) } func getTexts() *Texts { if _texts != nil { return _texts } _texts = NewTexts() return _texts }