Add CMS Management Functionality
- Introduced a new CMS management feature, including the ability to create, retrieve, update, search, and delete CMS entries. - Implemented the CMS entity, repository, service, and handler layers following Clean Architecture principles. - Added API endpoints for CMS operations in Swagger documentation, ensuring comprehensive API specifications. - Enhanced error handling and validation for CMS data, improving robustness and user experience. - Updated the main application to initialize the CMS repository and service, integrating them into the existing system.
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
package cms
|
||||
|
||||
import (
|
||||
"tm/pkg/response"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// Handler handles HTTP requests for CMS operations
|
||||
type Handler struct {
|
||||
service Service
|
||||
}
|
||||
|
||||
// NewHandler creates a new CMS handler
|
||||
func NewHandler(service Service) *Handler {
|
||||
return &Handler{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// GetByKey handles retrieving CMS content by key (public API)
|
||||
// @Summary Get CMS content by key
|
||||
// @Description Retrieve CMS content for public display by its key
|
||||
// @Tags CMS
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param key path string true "CMS key"
|
||||
// @Success 200 {object} response.APIResponse{data=CMSResponse}
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/cms/{key} [get]
|
||||
func (h *Handler) GetByKey(c echo.Context) error {
|
||||
key := c.Param("key")
|
||||
|
||||
cms, err := h.service.GetByKey(c.Request().Context(), key)
|
||||
if err != nil {
|
||||
return response.NotFound(c, "CMS content not found")
|
||||
}
|
||||
|
||||
return response.Success(c, cms, "CMS content retrieved successfully")
|
||||
}
|
||||
|
||||
// Create handles creating a new CMS entry (admin only)
|
||||
// @Summary Create a new CMS entry
|
||||
// @Description Create a new CMS entry for content management (admin only)
|
||||
// @Tags Admin-CMS
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param cms body CMSForm true "CMS information"
|
||||
// @Success 201 {object} response.APIResponse{data=CMSResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 409 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin/v1/cms [post]
|
||||
func (h *Handler) Create(c echo.Context) error {
|
||||
form, err := response.Parse[CMSForm](c)
|
||||
if err != nil {
|
||||
return response.ValidationError(c, "Invalid request data", err.Error())
|
||||
}
|
||||
|
||||
// Create CMS
|
||||
cms, err := h.service.Create(c.Request().Context(), form)
|
||||
if err != nil {
|
||||
if err == ErrCMSKeyExists {
|
||||
return response.Conflict(c, "CMS with this key already exists")
|
||||
}
|
||||
return response.InternalServerError(c, "Failed to create CMS")
|
||||
}
|
||||
|
||||
return response.Created(c, cms, "CMS entry created successfully")
|
||||
}
|
||||
|
||||
// GetByID handles retrieving a CMS entry by ID (admin only)
|
||||
// @Summary Get CMS by ID
|
||||
// @Description Retrieve a CMS entry by its ID for editing (admin only)
|
||||
// @Tags Admin-CMS
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "CMS ID"
|
||||
// @Success 200 {object} response.APIResponse{data=CMSResponse}
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin/v1/cms/{id} [get]
|
||||
func (h *Handler) GetByID(c echo.Context) error {
|
||||
id := c.Param("id")
|
||||
|
||||
cms, err := h.service.GetByID(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
if err.Error() == "cms not found" {
|
||||
return response.NotFound(c, "CMS entry not found")
|
||||
}
|
||||
return response.InternalServerError(c, "Failed to get CMS entry")
|
||||
}
|
||||
|
||||
return response.Success(c, cms, "CMS entry retrieved successfully")
|
||||
}
|
||||
|
||||
// Update handles updating a CMS entry (admin only)
|
||||
// @Summary Update CMS entry
|
||||
// @Description Update an existing CMS entry by its ID (admin only)
|
||||
// @Tags Admin-CMS
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "CMS ID"
|
||||
// @Param cms body CMSForm true "Updated CMS information"
|
||||
// @Success 200 {object} response.APIResponse{data=CMSResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 409 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin/v1/cms/{id} [put]
|
||||
func (h *Handler) Update(c echo.Context) error {
|
||||
id := c.Param("id")
|
||||
|
||||
form, err := response.Parse[CMSForm](c)
|
||||
if err != nil {
|
||||
return response.ValidationError(c, "Invalid request data", err.Error())
|
||||
}
|
||||
|
||||
// Update CMS
|
||||
cms, err := h.service.Update(c.Request().Context(), id, form)
|
||||
if err != nil {
|
||||
if err == ErrCMSKeyExists {
|
||||
return response.Conflict(c, "CMS with this key already exists")
|
||||
}
|
||||
if err.Error() == "cms not found" {
|
||||
return response.NotFound(c, "CMS entry not found")
|
||||
}
|
||||
return response.InternalServerError(c, "Failed to update CMS entry")
|
||||
}
|
||||
|
||||
return response.Success(c, cms, "CMS entry updated successfully")
|
||||
}
|
||||
|
||||
// Delete handles deleting a CMS entry (admin only)
|
||||
// @Summary Delete CMS entry
|
||||
// @Description Delete a CMS entry by its ID (admin only)
|
||||
// @Tags Admin-CMS
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "CMS ID"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin/v1/cms/{id} [delete]
|
||||
func (h *Handler) Delete(c echo.Context) error {
|
||||
id := c.Param("id")
|
||||
|
||||
err := h.service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
if err.Error() == "cms not found" {
|
||||
return response.NotFound(c, "CMS entry not found")
|
||||
}
|
||||
return response.InternalServerError(c, "Failed to delete CMS entry")
|
||||
}
|
||||
|
||||
return response.Success(c, nil, "CMS entry deleted successfully")
|
||||
}
|
||||
|
||||
// Search handles searching CMS entries (admin only)
|
||||
// @Summary Search CMS entries
|
||||
// @Description Search CMS entries with filters and pagination (admin only)
|
||||
// @Tags Admin-CMS
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param q query string false "Search query"
|
||||
// @Param key query string false "CMS key filter"
|
||||
// @Param limit query integer false "Number of CMS entries per page (1-100)" minimum(1) maximum(100) default(20)
|
||||
// @Param offset query integer false "Number of CMS entries to skip for pagination" minimum(0) default(0)
|
||||
// @Param sort_by query string false "Field to sort by" Enums(key, created_at, updated_at) default(created_at)
|
||||
// @Param sort_order query string false "Sort order" Enums(asc, desc) default(desc)
|
||||
// @Success 200 {object} response.APIResponse{data=CMSListResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin/v1/cms [get]
|
||||
func (h *Handler) Search(c echo.Context) error {
|
||||
form, err := response.Parse[SearchCMSForm](c)
|
||||
if err != nil {
|
||||
return response.ValidationError(c, "Invalid request data", err.Error())
|
||||
}
|
||||
|
||||
pagination := response.NewPagination(c)
|
||||
|
||||
result, err := h.service.Search(c.Request().Context(), form, pagination)
|
||||
if err != nil {
|
||||
return response.InternalServerError(c, "Failed to search CMS entries")
|
||||
}
|
||||
|
||||
return response.SuccessWithMeta(c, result, result.Meta, "CMS entries retrieved successfully")
|
||||
}
|
||||
Reference in New Issue
Block a user