package main import ( "errors" "net/http" "strconv" "github.com/FernandoVideira/LK_API_Temp/internal/store" "github.com/go-chi/chi/v5" ) type postKey string const postCtx postKey = "post" type CreatePostPayload struct { Title string `json:"title" validate:"required,max=100"` Content string `json:"content" validate:"required,max=1000"` Tags []string `json:"tags"` } // CreatePost godoc // // @Summary Creates a new Post // @Description Creates a new Post // @Tags posts // @Accept json // @Produce json // @Param in body CreatePostPayload true "Post Payload" // @Success 200 {object} store.Post // @Failure 400 {object} error // @Failure 404 {object} error // @Failure 500 {object} error // @Security ApiKeyAuth // @Router /posts [post] func (api *api) createPostHandler(w http.ResponseWriter, r *http.Request) { var payload CreatePostPayload if err := readJSON(w, r, &payload); err != nil { api.badRequestError(w, r, err) return } if err := Validate.Struct(payload); err != nil { api.badRequestError(w, r, err) return } user := getUserFromContext(r) post := &store.Post{ UserID: user.ID, Title: payload.Title, Content: payload.Content, Tags: payload.Tags, } ctx := r.Context() if err := api.store.Posts.Create(ctx, post); err != nil { api.internalServerError(w, r, err) return } if err := api.jsonResponse(w, http.StatusCreated, post); err != nil { api.internalServerError(w, r, err) return } } // GetPost godoc // // @Summary Fetches a Post // @Description Fetches a Post by ID // @Tags posts // @Accept json // @Produce json // @Param id path int true "Post ID" // @Success 200 {object} store.Post // @Failure 400 {object} error // @Failure 404 {object} error // @Failure 500 {object} error // @Security ApiKeyAuth // @Router /posts/{id} [get] func (api *api) getPostHandler(w http.ResponseWriter, r *http.Request) { post := getPostFromContext(r) comments, err := api.store.Comments.GetByPostID(r.Context(), post.ID) if err != nil { api.internalServerError(w, r, err) return } post.Comments = comments if err := api.jsonResponse(w, http.StatusOK, post); err != nil { api.internalServerError(w, r, err) return } } type UpdatePostPayload struct { Title *string `json:"title" validate:"omitempty,max=100"` Content *string `json:"content" validate:"omitempty,max=1000"` } // UpdatePost godoc // // @Summary Update a Post // @Description Update a Post by ID // @Tags posts // @Accept json // @Produce json // @Param id path int true "Post ID" // @Param in body UpdatePostPayload true "Post Payload" // @Success 200 {object} store.Post // @Failure 400 {object} error // @Failure 404 {object} error // @Failure 500 {object} error // @Security ApiKeyAuth // @Router /posts/{id} [patch] func (api *api) updatePostHandler(w http.ResponseWriter, r *http.Request) { post := getPostFromContext(r) var payload UpdatePostPayload if err := readJSON(w, r, &payload); err != nil { api.badRequestError(w, r, err) return } if err := Validate.Struct(payload); err != nil { api.badRequestError(w, r, err) return } if payload.Content != nil { post.Content = *payload.Content } if payload.Title != nil { post.Title = *payload.Title } if err := api.store.Posts.Update(r.Context(), post); err != nil { switch { case errors.Is(err, store.ErrNotFound): api.conflictError(w, r, err) default: api.internalServerError(w, r, err) } return } if err := api.jsonResponse(w, http.StatusOK, post); err != nil { api.internalServerError(w, r, err) return } } // DeletePost godoc // // @Summary Deletes a Post // @Description Deletse a Post by ID // @Tags posts // @Accept json // @Produce json // @Param id path int true "Post ID" // @Success 204 {object} string // @Failure 404 {object} error // @Failure 500 {object} error // @Security ApiKeyAuth // @Router /posts/{id} [delete] func (api *api) deletePostHandler(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") id, err := strconv.ParseInt(idParam, 10, 64) if err != nil { api.badRequestError(w, r, err) return } ctx := r.Context() if err := api.store.Posts.Delete(ctx, id); err != nil { switch { case errors.Is(err, store.ErrNotFound): api.notFoundError(w, r, err) default: api.internalServerError(w, r, err) } return } w.WriteHeader(http.StatusNoContent) } func getPostFromContext(r *http.Request) *store.Post { post, _ := r.Context().Value(postCtx).(*store.Post) return post }