package web import ( "net/http" "donniemarko/internal/service" "donniemarko/internal/render" ) type Handler struct { notesService *service.NotesService templates *render.TemplateManager } func NewHandler(ns *service.NotesService, tm *render.TemplateManager) *Handler { return &Handler{ notesService: ns, templates: tm, } } // ViewState is built per-request, not shared type ViewState struct { Notes []*note.Note CurrentNote *note.Note SortBy string SearchTerm string ActiveHash string } func (h *Handler) handleRoot(w http.ResponseWriter, r *http.Request) { // Build view state from query params state, err := h.buildViewState(r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Render with state h.templates.Render(w, "index", state) } func (h *Handler) buildViewState(r *http.Request) (*ViewState, error) { query := r.URL.Query() // Extract params sortBy := query.Get("sort") if sortBy == "" { sortBy = "recent" } searchTerm := query.Get("search") // Get notes from service var notes []*note.Note if searchTerm != "" { notes = h.notesService.Search(searchTerm) } else { notes = h.notesService.GetNotes() } // Apply sorting switch sortBy { case "recent": service.SortByDate(notes) case "alpha": service.SortByTitle(notes) } return &ViewState{ Notes: notes, SortBy: sortBy, SearchTerm: searchTerm, }, nil } func (h *Handler) handleNotes(w http.ResponseWriter, r *http.Request) { // Build base state state, err := h.buildViewState(r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Extract hash from URL hash := extractHash(r.URL.Path) // Get specific note note, err := h.notesService.GetNoteByHash(hash) if err != nil { http.Error(w, "Note not found", http.StatusNotFound) return } // Add to state state.CurrentNote = note state.ActiveHash = hash h.templates.Render(w, "note", state) }