package handlers import ( "net/http" "github.com/go-chi/chi/v5" "github.com/google/uuid" "git.threesix.ai/jordan/slack-auth-1770277167/pkg/app" "git.threesix.ai/jordan/slack-auth-1770277167/pkg/httperror" "git.threesix.ai/jordan/slack-auth-1770277167/pkg/httpresponse" "git.threesix.ai/jordan/slack-auth-1770277167/pkg/logging" ) // Example demonstrates the Wrap pattern for error-returning handlers. type Example struct { logger *logging.Logger } // NewExample creates a new Example handler. func NewExample(logger *logging.Logger) *Example { return &Example{logger: logger} } // CreateRequest is the request body for creating an example. type CreateRequest struct { Name string `json:"name" validate:"required,min=1,max=100"` Description string `json:"description" validate:"max=500"` } // UpdateRequest is the request body for updating an example. type UpdateRequest struct { Name string `json:"name" validate:"omitempty,min=1,max=100"` Description string `json:"description" validate:"max=500"` } // ExampleResponse is the response for an example resource. type ExampleResponse struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` } // List returns a paginated list of examples. // Demonstrates pagination query params and list responses. func (h *Example) List(w http.ResponseWriter, r *http.Request) error { // Example: Parse pagination query params // page := r.URL.Query().Get("page") // perPage := r.URL.Query().Get("per_page") // Example: Fetch from database // items, total, err := h.repo.List(r.Context(), page, perPage) // if err != nil { // return err // } // Placeholder response items := []ExampleResponse{ { ID: "550e8400-e29b-41d4-a716-446655440000", Name: "Example Item 1", Description: "First example item", CreatedAt: "2024-01-15T10:30:00Z", UpdatedAt: "2024-01-15T10:30:00Z", }, { ID: "550e8400-e29b-41d4-a716-446655440001", Name: "Example Item 2", Description: "Second example item", CreatedAt: "2024-01-16T12:00:00Z", UpdatedAt: "2024-01-16T12:00:00Z", }, } httpresponse.OK(w, r, items) return nil } // Get returns an example by ID. // Demonstrates returning HTTPErrors for common error cases. func (h *Example) Get(w http.ResponseWriter, r *http.Request) error { id := chi.URLParam(r, "id") // Validate UUID format if _, err := uuid.Parse(id); err != nil { return httperror.BadRequest("invalid id format") } // Example: Fetch from database // item, err := h.repo.Get(r.Context(), id) // if err != nil { // if errors.Is(err, ErrNotFound) { // return httperror.NotFoundf("example %s not found", id) // } // return err // } // Placeholder response httpresponse.OK(w, r, ExampleResponse{ ID: id, Name: "Example Item", Description: "This is an example item", CreatedAt: "2024-01-15T10:30:00Z", UpdatedAt: "2024-01-15T10:30:00Z", }) return nil } // Create creates a new example. // Demonstrates using BindAndValidate for request parsing and validation. func (h *Example) Create(w http.ResponseWriter, r *http.Request) error { var req CreateRequest // Bind and validate request body if err := app.BindAndValidate(r, &req); err != nil { return err } // Example: Check for duplicates // if exists, _ := h.repo.GetByName(r.Context(), req.Name); exists != nil { // return httperror.Conflict("example with this name already exists") // } // Example: Create in database // item, err := h.repo.Create(r.Context(), req) // if err != nil { // return err // } // Example: Access authenticated user // user := auth.GetUser(r.Context()) // h.logger.Info("example created", "by", user.ID, "name", req.Name) id := uuid.New().String() httpresponse.Created(w, r, ExampleResponse{ ID: id, Name: req.Name, Description: req.Description, CreatedAt: "2024-01-15T10:30:00Z", UpdatedAt: "2024-01-15T10:30:00Z", }) return nil } // Update updates an existing example. // Demonstrates partial updates with BindAndValidate. func (h *Example) Update(w http.ResponseWriter, r *http.Request) error { id := chi.URLParam(r, "id") if _, err := uuid.Parse(id); err != nil { return httperror.BadRequest("invalid id format") } var req UpdateRequest if err := app.BindAndValidate(r, &req); err != nil { return err } // Example: Fetch existing, apply updates, save // item, err := h.repo.Get(r.Context(), id) // if err != nil { // if errors.Is(err, ErrNotFound) { // return httperror.NotFoundf("example %s not found", id) // } // return err // } // if err := h.repo.Update(r.Context(), id, req); err != nil { // return err // } httpresponse.OK(w, r, ExampleResponse{ ID: id, Name: req.Name, Description: req.Description, CreatedAt: "2024-01-15T10:30:00Z", UpdatedAt: "2024-01-16T14:00:00Z", }) return nil } // Delete deletes an example by ID. // Demonstrates no-content response. func (h *Example) Delete(w http.ResponseWriter, r *http.Request) error { id := chi.URLParam(r, "id") if _, err := uuid.Parse(id); err != nil { return httperror.BadRequest("invalid id format") } // Example: Delete from database // if err := h.repo.Delete(r.Context(), id); err != nil { // if errors.Is(err, ErrNotFound) { // return httperror.NotFoundf("example %s not found", id) // } // return err // } httpresponse.NoContent(w) return nil }