package handlers // Page handlers for the Custom Views shell (t-paliad-144 Phase A2). // // Three URLs: // GET /views — landing; redirects to most-recently-used // saved view, or shows the empty/onboarding // card. // GET /views/{slug} — render a saved or system view. // GET /views/new — view editor (blank slate). // GET /views/{slug}/edit — view editor (edit existing). // // Each route serves the static dist HTML; the client bundle (views.ts / // views-editor.ts) hydrates via /api/* on load. import ( "net/http" ) // GET /views — landing. // // Behaviour matches design Q10 most-recently-used: // - If the caller has a saved view with last_used_at set → 302 to it. // - Otherwise serve the onboarding shell (the views.html dist file // handles the empty state in JS). func handleViewsLandingPage(w http.ResponseWriter, r *http.Request) { if !requireDB(w) { return } uid, ok := requireUser(w, r) if !ok { return } if dbSvc.userView != nil { mr, err := dbSvc.userView.MostRecent(r.Context(), uid) if err == nil && mr != nil { http.Redirect(w, r, "/views/"+mr.Slug, http.StatusFound) return } } http.ServeFile(w, r, "dist/views.html") } // GET /views/{slug} — saved or system view shell. // // The handler doesn't validate the slug here — the client bundle calls // POST /api/views/{slug}/run and lets the API surface the 404 with a // proper empty-state. This keeps the page surface trivially cacheable. func handleViewsShellPage(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "dist/views.html") } // GET /views/new — editor with a blank slate. func handleViewsNewPage(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "dist/views-editor.html") } // GET /views/{slug}/edit — editor for an existing saved view. func handleViewsEditPage(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "dist/views-editor.html") }