From 8cae1c5b5939441b9660b242b8e72d2bba240c6c Mon Sep 17 00:00:00 2001 From: Ryan Yeske Date: Sat, 2 Aug 2025 15:06:12 -0700 Subject: [PATCH 1/4] Remove quizzes.gohtml --- handlers/admin/quizzes/page.go | 35 +++++++++++++++++++----------- handlers/admin/quizzes/page.gohtml | 11 ---------- internal/link/link.go | 5 +++++ 3 files changed, 27 insertions(+), 24 deletions(-) delete mode 100644 handlers/admin/quizzes/page.gohtml diff --git a/handlers/admin/quizzes/page.go b/handlers/admin/quizzes/page.go index c486ac60..abe4eb64 100644 --- a/handlers/admin/quizzes/page.go +++ b/handlers/admin/quizzes/page.go @@ -7,9 +7,12 @@ import ( "oj/api" "oj/handlers/layout" "oj/handlers/render" + "oj/internal/link" "github.com/go-chi/chi/v5" "github.com/jackc/pgx/v5" + g "maragu.dev/gomponents" + h "maragu.dev/gomponents/html" ) type service struct { @@ -24,12 +27,6 @@ func (s *service) Router(r chi.Router) { r.Get("/", s.page) } -var ( - //go:embed page.gohtml - pageContent string - pageTemplate = layout.MustParse(pageContent, pageContent) -) - func (s *service) page(w http.ResponseWriter, r *http.Request) { ctx := r.Context() l := layout.FromContext(ctx) @@ -40,11 +37,23 @@ func (s *service) page(w http.ResponseWriter, r *http.Request) { return } - render.Execute(w, pageTemplate, struct { - Layout layout.Data - Quizzes []api.Quiz - }{ - Layout: l, - Quizzes: allQuizzes, - }) + layout.Layout(l, "quizzes", + h.Div( + h.Div( + h.Style("display:flex; justify-content:space-between; align-items:center"), + h.H1( + g.Text("quizzes"), + ), + ), + g.Map(allQuizzes, func(q api.Quiz) g.Node { + return h.Div( + h.Class("nes-container ghost"), + h.A( + h.Href(link.Quiz(q)), + g.Text(q.Name), + ), + ) + }), + ), + ).Render(w) } diff --git a/handlers/admin/quizzes/page.gohtml b/handlers/admin/quizzes/page.gohtml deleted file mode 100644 index 178a020f..00000000 --- a/handlers/admin/quizzes/page.gohtml +++ /dev/null @@ -1,11 +0,0 @@ -{{define "main"}} -
-

quizzes

- create quiz -
- {{range .Quizzes}} -
- {{.Name}} -
- {{end}} -{{end}} diff --git a/internal/link/link.go b/internal/link/link.go index 94fdaead..fd1e2b3a 100644 --- a/internal/link/link.go +++ b/internal/link/link.go @@ -2,6 +2,7 @@ package link import ( "fmt" + "oj/api" "strings" ) @@ -20,3 +21,7 @@ func ChessMatch(id int64, rest ...string) string { func ConnectFriend(id int64) string { return Link("connectkids/friend", id) } + +func Quiz(quiz api.Quiz, rest ...string) string { + return fmt.Sprintf("/u/%d/quizzes/%d", quiz.UserID, quiz.ID) +} From 2053d231f499f88ef3a55f31c8a0d84cb818d978 Mon Sep 17 00:00:00 2001 From: Ryan Yeske Date: Sat, 2 Aug 2025 15:15:47 -0700 Subject: [PATCH 2/4] Remove /admin gohtml page --- handlers/admin/page.go | 37 ++++++++++++++++++++++++------------- handlers/admin/page.gohtml | 12 ------------ 2 files changed, 24 insertions(+), 25 deletions(-) delete mode 100644 handlers/admin/page.gohtml diff --git a/handlers/admin/page.go b/handlers/admin/page.go index 79cd34b1..7bc50a4f 100644 --- a/handlers/admin/page.go +++ b/handlers/admin/page.go @@ -12,9 +12,12 @@ import ( "oj/handlers/admin/quizzes" "oj/handlers/layout" "oj/handlers/render" + "oj/internal/link" "github.com/go-chi/chi/v5" "github.com/jackc/pgx/v5/pgxpool" + g "maragu.dev/gomponents" + h "maragu.dev/gomponents/html" ) type service struct { @@ -37,12 +40,6 @@ func (s *service) Routes() chi.Router { return r } -var ( - //go:embed page.gohtml - pageContent string - pageTemplate = layout.MustParse(pageContent, pageContent) -) - func (s *service) page(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -54,11 +51,25 @@ func (s *service) page(w http.ResponseWriter, r *http.Request) { return } - render.Execute(w, pageTemplate, struct { - Layout layout.Data - Users []api.User - }{ - Layout: l, - Users: allUsers, - }) + layout.Layout(l, "admin", g.Group{ + h.Div(h.Style("display:flex; gap:1em"), + h.A( + h.Href("/admin/quizzes"), + g.Text("quizzes"), + ), + h.A( + h.Href("/admin/messages"), + g.Text("messages"), + ), + ), + h.Hr(), + g.Map(allUsers, func(user api.User) g.Node { + return h.Div( + h.A( + h.Href(link.User(user.ID)), + g.Text(user.Username), + ), + ) + }), + }).Render(w) } diff --git a/handlers/admin/page.gohtml b/handlers/admin/page.gohtml deleted file mode 100644 index 6cbb9214..00000000 --- a/handlers/admin/page.gohtml +++ /dev/null @@ -1,12 +0,0 @@ -{{define "main"}} - quizzes - messages - -
- - {{range .Users}} -
- {{.Username}} -
- {{end}} -{{end}} From 6f2cd7f949be4c594700209c981e71706de89bcb Mon Sep 17 00:00:00 2001 From: Ryan Yeske Date: Sat, 2 Aug 2025 15:33:46 -0700 Subject: [PATCH 3/4] Remove deliveries gohtml --- handlers/deliveries/page.go | 45 ++++++++++++++++++++++----------- handlers/deliveries/page.gohtml | 13 ---------- 2 files changed, 30 insertions(+), 28 deletions(-) delete mode 100644 handlers/deliveries/page.gohtml diff --git a/handlers/deliveries/page.go b/handlers/deliveries/page.go index a70cd444..ebe75233 100644 --- a/handlers/deliveries/page.go +++ b/handlers/deliveries/page.go @@ -12,6 +12,8 @@ import ( "github.com/go-chi/chi/v5" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" + g "maragu.dev/gomponents" + h "maragu.dev/gomponents/html" ) type service struct { @@ -23,12 +25,6 @@ func NewService(q *api.Queries, conn *pgxpool.Pool) *service { return &service{Queries: q, Conn: conn} } -var ( - //go:embed "page.gohtml" - pageContent string - pageTemplate = layout.MustParse(pageContent) -) - func (s *service) Page(w http.ResponseWriter, r *http.Request) { ctx := r.Context() l := layout.FromContext(r.Context()) @@ -50,15 +46,34 @@ func (s *service) Page(w http.ResponseWriter, r *http.Request) { return } - render.Execute(w, pageTemplate, struct { - Layout layout.Data - LogoutActionURL string - Delivery api.Delivery - }{ - Layout: l, - LogoutActionURL: fmt.Sprintf("%d/logout", delivery.ID), - Delivery: delivery, - }) + logoutActionURL := fmt.Sprintf("%d/logout", delivery.ID) + + layout.Layout(l, "Delivery", + h.Dialog( + g.Attr("open"), + h.Class("nes-dialog"), + h.Form( + h.Method("post"), + h.Action(logoutActionURL), + h.P( + g.Text(fmt.Sprintf("You are currently logged in as %s.", l.User.Username)), + ), + h.P( + g.Text("This content is for a different user!"), + ), + h.Div( + h.Style("display:flex; justify-content: space-between"), + h.Button( + h.Class("nes-btn is-primary"), + g.Text("Switch User"), + ), + h.A( + h.Href("/"), + h.Class("nes-btn"), + g.Text("Cancel"), + ), + ), + ))).Render(w) } // Logout and redirect back to delivery page to recheck current user diff --git a/handlers/deliveries/page.gohtml b/handlers/deliveries/page.gohtml deleted file mode 100644 index 552fdb2c..00000000 --- a/handlers/deliveries/page.gohtml +++ /dev/null @@ -1,13 +0,0 @@ -{{define "main"}} - -
-

You are currently logged in as {{.Layout.User.Username}}.

-

This content is for a different user!

-
- - Cancel -
-
-
- -{{end}} From eb0f82b60a7faf90515c9edb36c4c47582d4cfbc Mon Sep 17 00:00:00 2001 From: Ryan Yeske Date: Sun, 10 Aug 2025 08:58:14 -0700 Subject: [PATCH 4/4] Remove parent.gohtml --- internal/link/link.go | 4 + internal/resources/parent/parent.go | 106 +++++++++++++++++++----- internal/resources/parent/parent.gohtml | 69 --------------- 3 files changed, 90 insertions(+), 89 deletions(-) delete mode 100644 internal/resources/parent/parent.gohtml diff --git a/internal/link/link.go b/internal/link/link.go index fd1e2b3a..ddcab7c3 100644 --- a/internal/link/link.go +++ b/internal/link/link.go @@ -25,3 +25,7 @@ func ConnectFriend(id int64) string { func Quiz(quiz api.Quiz, rest ...string) string { return fmt.Sprintf("/u/%d/quizzes/%d", quiz.UserID, quiz.ID) } + +func ParentKid(id int64, rest ...string) string { + return Link("parent/kids", id, rest...) +} diff --git a/internal/resources/parent/parent.go b/internal/resources/parent/parent.go index fa36aab6..f8eef90f 100644 --- a/internal/resources/parent/parent.go +++ b/internal/resources/parent/parent.go @@ -9,12 +9,16 @@ import ( "oj/api" "oj/handlers/layout" "oj/handlers/render" + "oj/internal/link" "oj/internal/middleware/auth" "oj/services/family" + "time" "github.com/go-chi/chi/v5" "github.com/jackc/pgx/v5" "github.com/jmoiron/sqlx" + g "maragu.dev/gomponents" + h "maragu.dev/gomponents/html" ) type Resource struct { @@ -31,16 +35,9 @@ func (rs Resource) Routes() chi.Router { return r } -var ( - //go:embed parent.gohtml - pageContent string - - t = layout.MustParse(pageContent) -) - func (rs Resource) index(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - l := layout.FromContext(r.Context()) + l := layout.FromContext(ctx) kids, err := rs.Queries.KidsByParentID(ctx, l.User.ID) if err != nil { @@ -48,18 +45,87 @@ func (rs Resource) index(w http.ResponseWriter, r *http.Request) { return } - err = t.Execute(w, struct { - Layout layout.Data - User api.User - Kids []api.User - }{ - Layout: l, - User: l.User, - Kids: kids, - }) - if err != nil { - render.Error(w, fmt.Errorf("Execute: %w", err), 500) - } + layout.Layout(l, "parent", + h.Div( + h.Style("display:flex; flex-direction: column; gap:1em; margin-bottom: 50%"), + h.Div( + h.Class("nes-container is-dark"), + h.Style("display:flex; flex-direction:column; gap:1em"), + h.H1( + g.Text("Hello parent!"), + h.Small( + g.Text(l.User.Email.String), + ), + ), + h.P( + g.Text("Here you can add managed accounts for your kids."), + ), + h.P( + g.Text("You are the manager for these accounts. You can remove them and\n all associated data at any time."), + ), + h.P( + g.Text("Choose a unique username for your child. It can contain their name, but doesn't have to. They will be able to change it to whatever they want when they login."), + ), + h.Div( + h.Class("nes-container is-dark"), + h.Form( + h.Action("/parent/kids"), + h.Method("post"), + h.Label( + g.Text("Child's Username"), + h.Input( + h.Class("nes-input"), + h.Type("text"), + h.Name("username"), + ), + ), + h.Button( + h.Class("nes-btn is-primary"), + g.Text("Add Kid"), + ), + ), + ), + h.P( + g.Text(fmt.Sprintf("Kids login with their username and a one time code that will be emailed to %s.", + l.User.Email)), + ), + ), + g.Map(kids, func(kid api.User) g.Node { + return h.Div( + h.Class("nes-container ghost kid"), + h.Div( + h.Style("display:flex; justify-content:space-between"), + h.A( + h.Href(link.User(l.User.ID)), + h.Style("display: flex; gap:1em"), + h.Img( + h.Width("100"), + h.Src(kid.Avatar.URL()), + ), + h.Div( + h.Style("display:flex; flex-direction: column"), + h.H2( + g.Text(fmt.Sprintf("username: %s", kid.Username)), + ), + h.Div( + g.Text(fmt.Sprintf("Joined %s", kid.CreatedAt.Time.Format(time.DateOnly))), + ), + ), + ), + h.Div( + h.Button( + h.Class("nes-btn is-error"), + g.Attr("hx-delete", link.ParentKid(kid.ID)), + g.Attr("hx-confirm", fmt.Sprintf("Permanently delete %s and all associated data?", kid.Username)), + g.Attr("hx-target", "closest .kid"), + g.Attr("hx-swap", "outerHTML"), + g.Text("delete"), + ), + ), + ), + ) + }), + )).Render(w) } func (rs Resource) createKid(w http.ResponseWriter, r *http.Request) { diff --git a/internal/resources/parent/parent.gohtml b/internal/resources/parent/parent.gohtml deleted file mode 100644 index f470ef34..00000000 --- a/internal/resources/parent/parent.gohtml +++ /dev/null @@ -1,69 +0,0 @@ -{{define "main"}} -
-
-

Hello parent! {{.User.Email.String}}

- -

- Here you can add managed accounts for your kids. -

- -

- You are the manager for these accounts. You can remove them and - all associated data at any time. -

- -

- Choose a unique username for your child. It can contain their - name, but doesn't have to. They will be able to - change it to whatever they want when they login. -

- -
-
- - -
-
- -

- Kids login with their username and a one time code that will - be emailed to {{.User.Email}}. -

-
- - {{range .Kids}} - {{template "kid" .}} - {{end}} -
-{{end}} - -{{define "kid"}} - -{{end}}