package handlers import ( "encoding/json" "html/template" "log" "net/http" "path/filepath" "custom-start-page/internal/middleware" "custom-start-page/internal/services" ) // PageHandler handles page-related HTTP requests type PageHandler struct { pageService services.PageServiceInterface templates *template.Template } // NewPageHandler creates a new page handler func NewPageHandler(pageService services.PageServiceInterface) *PageHandler { // Parse templates templates := template.Must(template.ParseGlob(filepath.Join("templates", "*.html"))) template.Must(templates.ParseGlob(filepath.Join("templates", "layouts", "*.html"))) template.Must(templates.ParseGlob(filepath.Join("templates", "partials", "*.html"))) return &PageHandler{ pageService: pageService, templates: templates, } } // HandleGetPage returns the widget grid HTML fragment for a specific page // GET /pages/:id func (h *PageHandler) HandleGetPage(w http.ResponseWriter, r *http.Request) { // Get user ID from context userID, ok := middleware.GetUserIDFromContext(r.Context()) if !ok { http.Error(w, "User ID not found in context", http.StatusInternalServerError) return } // Get page ID from URL path pageID := r.PathValue("id") if pageID == "" { http.Error(w, "Page ID is required", http.StatusBadRequest) return } // TODO: Fetch widgets for this page // For now, return empty widget grid data := map[string]interface{}{ "PageID": pageID, "UserID": userID, "Widgets": []interface{}{}, } if err := h.templates.ExecuteTemplate(w, "widget-grid.html", data); err != nil { log.Printf("Failed to render widget grid template: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) } } // HandleCreatePage creates a new page and returns updated page tabs HTML // POST /pages func (h *PageHandler) HandleCreatePage(w http.ResponseWriter, r *http.Request) { // Get user ID from context userID, ok := middleware.GetUserIDFromContext(r.Context()) if !ok { http.Error(w, "User ID not found in context", http.StatusInternalServerError) return } // Parse form data if err := r.ParseForm(); err != nil { http.Error(w, "Failed to parse form data", http.StatusBadRequest) return } pageName := r.FormValue("name") if pageName == "" { http.Error(w, "Page name is required", http.StatusBadRequest) return } // Validate page name length if len(pageName) < 1 || len(pageName) > 50 { http.Error(w, "Page name must be between 1 and 50 characters", http.StatusBadRequest) return } // Create the page _, err := h.pageService.CreatePage(r.Context(), userID, pageName) if err != nil { log.Printf("Failed to create page: %v", err) http.Error(w, "Failed to create page", http.StatusInternalServerError) return } // Get all pages to render updated tabs pages, err := h.pageService.GetPages(r.Context(), userID) if err != nil { log.Printf("Failed to get pages: %v", err) http.Error(w, "Failed to get pages", http.StatusInternalServerError) return } // Render page tabs partial data := map[string]interface{}{ "Pages": pages, } if err := h.templates.ExecuteTemplate(w, "page-tabs.html", data); err != nil { log.Printf("Failed to render page tabs template: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) } } // HandleUpdatePage updates a page and returns updated page tab HTML // PUT /pages/:id func (h *PageHandler) HandleUpdatePage(w http.ResponseWriter, r *http.Request) { // Get user ID from context userID, ok := middleware.GetUserIDFromContext(r.Context()) if !ok { http.Error(w, "User ID not found in context", http.StatusInternalServerError) return } // Get page ID from URL path pageID := r.PathValue("id") if pageID == "" { http.Error(w, "Page ID is required", http.StatusBadRequest) return } // Parse form data if err := r.ParseForm(); err != nil { http.Error(w, "Failed to parse form data", http.StatusBadRequest) return } pageName := r.FormValue("name") if pageName == "" { http.Error(w, "Page name is required", http.StatusBadRequest) return } // Validate page name length if len(pageName) < 1 || len(pageName) > 50 { http.Error(w, "Page name must be between 1 and 50 characters", http.StatusBadRequest) return } // Update the page page, err := h.pageService.UpdatePage(r.Context(), userID, pageID, pageName) if err != nil { log.Printf("Failed to update page: %v", err) http.Error(w, "Failed to update page", http.StatusInternalServerError) return } // Render single page tab partial data := map[string]interface{}{ "Page": page, } if err := h.templates.ExecuteTemplate(w, "page-tab.html", data); err != nil { log.Printf("Failed to render page tab template: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) } } // HandleDeletePage deletes a page and returns updated page tabs HTML // DELETE /pages/:id func (h *PageHandler) HandleDeletePage(w http.ResponseWriter, r *http.Request) { // Get user ID from context userID, ok := middleware.GetUserIDFromContext(r.Context()) if !ok { http.Error(w, "User ID not found in context", http.StatusInternalServerError) return } // Get page ID from URL path pageID := r.PathValue("id") if pageID == "" { http.Error(w, "Page ID is required", http.StatusBadRequest) return } // Delete the page err := h.pageService.DeletePage(r.Context(), userID, pageID) if err != nil { if err.Error() == "cannot delete the last page" { http.Error(w, "Cannot delete the last page. You must have at least one page.", http.StatusBadRequest) return } log.Printf("Failed to delete page: %v", err) http.Error(w, "Failed to delete page", http.StatusInternalServerError) return } // Get all pages to render updated tabs pages, err := h.pageService.GetPages(r.Context(), userID) if err != nil { log.Printf("Failed to get pages: %v", err) http.Error(w, "Failed to get pages", http.StatusInternalServerError) return } // Render page tabs partial data := map[string]interface{}{ "Pages": pages, } if err := h.templates.ExecuteTemplate(w, "page-tabs.html", data); err != nil { log.Printf("Failed to render page tabs template: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) } } // HandleReorderPages reorders pages and returns updated page tabs HTML // POST /pages/reorder func (h *PageHandler) HandleReorderPages(w http.ResponseWriter, r *http.Request) { // Get user ID from context userID, ok := middleware.GetUserIDFromContext(r.Context()) if !ok { http.Error(w, "User ID not found in context", http.StatusInternalServerError) return } // Parse form data if err := r.ParseForm(); err != nil { http.Error(w, "Failed to parse form data", http.StatusBadRequest) return } // Get page order from form orderJSON := r.FormValue("order") if orderJSON == "" { http.Error(w, "Page order is required", http.StatusBadRequest) return } var pageOrder []string if err := json.Unmarshal([]byte(orderJSON), &pageOrder); err != nil { http.Error(w, "Invalid page order format", http.StatusBadRequest) return } // Reorder pages err := h.pageService.ReorderPages(r.Context(), userID, pageOrder) if err != nil { log.Printf("Failed to reorder pages: %v", err) http.Error(w, "Failed to reorder pages", http.StatusInternalServerError) return } // Get all pages to render updated tabs pages, err := h.pageService.GetPages(r.Context(), userID) if err != nil { log.Printf("Failed to get pages: %v", err) http.Error(w, "Failed to get pages", http.StatusInternalServerError) return } // Render page tabs partial data := map[string]interface{}{ "Pages": pages, } if err := h.templates.ExecuteTemplate(w, "page-tabs.html", data); err != nil { log.Printf("Failed to render page tabs template: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) } }