From 87f53b56e8c898080a6e81919e5711a4199e6650 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sun, 1 Mar 2026 21:00:00 -0500 Subject: [PATCH] feat(router): add collection modal routes for HTMX Add three new frontend routes to support HTMX-powered modal dialogs: 1. GET /collections/create-modal - Renders empty collection creation modal - Uses CollectionModal template with empty CollectionData 2. GET /collections/:id/edit-modal - Fetches collection by ID from database - Pre-populates modal with existing collection data - Returns 400 for invalid UUID, 404 if collection not found 3. GET /collections/restore-modal - Renders system collection restoration modal - Allows users to restore deleted system collections Route registration order: - /collections/:id/edit-modal must be registered before /collections/:id to avoid path conflicts in Echo's router These routes enable the collections page to load modals dynamically via HTMX (hx-get) instead of embedding modal HTML in the base page. --- internal/router/frontend.go | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/internal/router/frontend.go b/internal/router/frontend.go index d55c911..cbcb871 100644 --- a/internal/router/frontend.go +++ b/internal/router/frontend.go @@ -238,6 +238,63 @@ func registerFrontendRoutes(cfg *Config) { return c.HTML(http.StatusOK, buf.String()) }) + // Collection create modal + frontendProtected.GET("/collections/create-modal", func(c echo.Context) error { + var buf bytes.Buffer + err := templates.CollectionModal(templates.CollectionData{}).Render(c.Request().Context(), &buf) + if err != nil { + return err + } + return c.HTML(http.StatusOK, buf.String()) + }) + + // Collection edit modal + frontendProtected.GET("/collections/:id/edit-modal", func(c echo.Context) error { + // Parse collection ID + collectionID := c.Param("id") + collUUID, err := uuid.Parse(collectionID) + if err != nil { + return c.HTML(http.StatusBadRequest, "
Invalid collection ID
") + } + + // Fetch collection data + collection, err := cfg.Queries.GetCollection(c.Request().Context(), pgtype.UUID{Bytes: collUUID, Valid: true}) + if err != nil { + return c.HTML(http.StatusNotFound, "
Collection not found
") + } + + // Convert to template type + colData := templates.CollectionData{ + ID: uuid.UUID(collection.ID.Bytes).String(), + Name: collection.Name, + Description: getText(collection.Description), + Color: getText(collection.Color), + Icon: getText(collection.Icon), + } + + // Ensure default color if empty + if colData.Color == "" { + colData.Color = "blue" + } + + var buf bytes.Buffer + err = templates.CollectionModal(colData).Render(c.Request().Context(), &buf) + if err != nil { + return err + } + return c.HTML(http.StatusOK, buf.String()) + }) + + // Restore system collection modal + frontendProtected.GET("/collections/restore-modal", func(c echo.Context) error { + var buf bytes.Buffer + err := templates.RestoreSystemCollectionModal().Render(c.Request().Context(), &buf) + if err != nil { + return err + } + return c.HTML(http.StatusOK, buf.String()) + }) + // Collection detail page (works for both system and user collections) frontendProtected.GET("/collections/:id", func(c echo.Context) error { user, err := getTemplateUserWithTheme(c, cfg)