diff --git a/static/style.css b/static/style.css index 98a1c03..a077651 100644 --- a/static/style.css +++ b/static/style.css @@ -1,17 +1,135 @@ - body { - display: flex; - flex-direction: column; - background-color: #222; - color: #AFA; - align-content: center; - justify-content: center; - align-items: center; - text-align: center; - max-width: 70vw; - margin: 0 auto; - width: 70vw; - font-family: sans-serif; - } + body { + display: flex; + flex-direction: column; + background-color: #222; + color: #AFA; + align-content: center; + justify-content: center; + align-items: center; + text-align: center; + max-width: 70vw; + margin: 0 auto; + width: 70vw; + font-family: sans-serif; + padding-top: 80px; + } + + /* Hamburger Menu Button - left side */ + .menu-button { + position: fixed; + top: 20px; + left: 20px; + width: 40px; + height: 40px; + cursor: pointer; + z-index: 1000; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 5px; + } + + .menu-button span { + display: block; + width: 28px; + height: 3px; + background-color: #AFA; + border-radius: 2px; + transition: all 0.3s ease; + } + + .menu-button.active span:nth-child(1) { + transform: rotate(45deg) translate(5px, 6px); + } + + .menu-button.active span:nth-child(2) { + opacity: 0; + } + + .menu-button.active span:nth-child(3) { + transform: rotate(-45deg) translate(5px, -6px); + } + + /* Slide-out Menu */ + .side-menu { + position: fixed; + top: 0; + left: -280px; + width: 280px; + height: 100vh; + background-color: #1a1a1a; + z-index: 999; + transition: left 0.3s ease; + display: flex; + flex-direction: column; + padding-top: 60px; + } + + .side-menu.active { + left: 0; + } + + .menu-header { + padding: 20px; + border-bottom: 1px solid #333; + } + + .menu-header h3 { + margin: 0; + color: #AFA; + font-size: 24px; + } + + .menu-nav { + display: flex; + flex-direction: column; + padding: 10px 0; + } + + .menu-item { + display: flex; + align-items: center; + gap: 15px; + padding: 15px 20px; + color: #EEE; + text-decoration: none; + transition: background-color 0.2s; + } + + .menu-item:hover { + background-color: #333; + } + + .menu-item .menu-icon { + color: #FFF; + } + + .menu-icon { + width: 24px; + height: 24px; + flex-shrink: 0; + filter: invert(1) brightness(1.5); + } + + /* Menu Overlay */ + .menu-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 998; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease, visibility 0.3s ease; + } + + .menu-overlay.active { + opacity: 1; + visibility: visible; + } .page_buttons { display: flex; @@ -146,6 +264,43 @@ background: #444; } +/* Settings Tab Navigation */ +.settings-tabs { + display: flex; + flex-direction: row; + border-bottom: 1px solid #333; + margin-bottom: 20px; +} + +.tab-button { + padding: 12px 24px; + background: none; + border: none; + color: #888; + font-size: 16px; + cursor: pointer; + position: relative; + transition: color 0.2s; +} + +.tab-button:hover { + color: #AFA; +} + +.tab-button.active { + color: #AFA; +} + +.tab-button.active::after { + content: ''; + position: absolute; + bottom: -1px; + left: 0; + width: 100%; + height: 2px; + background-color: #AFA; +} + .progress-container { margin-top: 15px; padding: 15px; diff --git a/templates/profile.gohtml b/templates/profile.gohtml index eb8e00c..f259ec5 100644 --- a/templates/profile.gohtml +++ b/templates/profile.gohtml @@ -1,52 +1,40 @@ - - - - - - muzi | {{.Username}}'s Profile - - - -
- {{.Username}}'s avatar -
-

{{.Username}}

-

{{.Bio}}

-
-
-
-
-

{{formatInt .ScrobbleCount}}

Listens

-

{{formatInt .ArtistCount}}

Artists

-

+{{define "profile"}} +
+ {{.Username}}'s avatar +
+

{{.Username}}

+

{{.Bio}}

-
- Import Data +
-
-

Listening History

- - - - - - - {{$artists := .Artists}} - {{$times := .Times}} - {{range $index, $title := .Titles}} - - - - - - {{end}} -
ArtistTitleTimestamp
{{index $artists $index}}{{$title}}{{index $times $index}}
-
-
- {{if gt .Page 1 }} - Prev Page +
+

{{formatInt .ScrobbleCount}}

Listens

+

{{formatInt .ArtistCount}}

Artists

+

+
+
+

Listening History

+ + + + + + + {{$artists := .Artists}} + {{$times := .Times}} + {{range $index, $title := .Titles}} + + + + + {{end}} - Next Page - - - +
ArtistTitleTimestamp
{{index $artists $index}}{{$title}}{{formatTimestamp (index $times $index)}}
+
+
+ {{if gt .Page 1 }} + Prev Page + {{end}} + Next Page +
+{{end}} diff --git a/web/profile.go b/web/profile.go index 6759952..f4363ab 100644 --- a/web/profile.go +++ b/web/profile.go @@ -25,6 +25,9 @@ type ProfileData struct { Titles []string Times []string Page int + Title string + LoggedInUsername string + TemplateName string } // Render a page of the profile in the URL @@ -57,6 +60,9 @@ func profilePageHandler() http.HandlerFunc { var profileData ProfileData profileData.Username = username profileData.Page = pageInt + profileData.Title = username + "'s Profile" + profileData.LoggedInUsername = getLoggedInUsername(r) + profileData.TemplateName = "profile" err = db.Pool.QueryRow( r.Context(), @@ -100,7 +106,7 @@ func profilePageHandler() http.HandlerFunc { profileData.Times = append(profileData.Times, time.Time.String()) } - err = templates.ExecuteTemplate(w, "profile.gohtml", profileData) + err = templates.ExecuteTemplate(w, "base", profileData) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } diff --git a/web/web.go b/web/web.go index 78d4172..f61657b 100644 --- a/web/web.go +++ b/web/web.go @@ -80,6 +80,7 @@ func Start() { r.Post("/import/spotify", importSpotifyHandler) r.Get("/import/lastfm/progress", importLastFMProgressHandler) r.Get("/import/spotify/progress", importSpotifyProgressHandler) + r.Get("/settings", settingsPageHandler()) fmt.Printf("WebUI starting on %s\n", addr) prot := http.NewCrossOriginProtection() http.ListenAndServe(addr, prot.Handler(r))