initial commit
This commit is contained in:
363
internal/delivery/http/platform/asset.go
Normal file
363
internal/delivery/http/platform/asset.go
Normal file
@@ -0,0 +1,363 @@
|
||||
package platform
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
||||
appAsset "base/internal/application/asset"
|
||||
"base/internal/dto"
|
||||
)
|
||||
|
||||
// ListAssetCategories godoc
|
||||
// @Summary list asset categories
|
||||
// @Description returns all asset categories
|
||||
// @Tags Asset
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} dto.ListCategoriesResponse "list of categories"
|
||||
// @Failure 500 {object} dto.ErrorResponse "internal server error"
|
||||
// @Router /api/v1/assets/categories [get]
|
||||
func (ctl *Controller) ListAssetCategories(c *gin.Context) {
|
||||
lg := ctl.logger.With().
|
||||
Str("module", "platform").
|
||||
Str("router", "asset").
|
||||
Str("handler", "ListAssetCategories").
|
||||
Logger()
|
||||
|
||||
resp, err := ctl.assetService.ListCategories(c.Request.Context())
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("failed to list asset categories")
|
||||
r := dto.InternalServerError()
|
||||
c.JSON(r.Status, r)
|
||||
return
|
||||
}
|
||||
|
||||
r := dto.OK().WithData(resp)
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
|
||||
// ListCategoriesWithPreview returns categories with up to 8 assets per category.
|
||||
// @Summary list categories with preview assets
|
||||
// @Description returns asset categories, each with up to N sample assets (default 8). Use for carousels and landing previews.
|
||||
// @Tags Asset
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body dto.CategoriesPreviewRequest true "filter options"
|
||||
// @Success 200 {object} dto.CategoriesPreviewResponse "categories with preview assets"
|
||||
// @Failure 400 {object} dto.ErrorResponse "invalid request"
|
||||
// @Failure 500 {object} dto.ErrorResponse "internal server error"
|
||||
// @Router /api/v1/assets/categories/preview [post]
|
||||
func (ctl *Controller) ListCategoriesWithPreview(c *gin.Context) {
|
||||
lg := ctl.logger.With().
|
||||
Str("module", "platform").
|
||||
Str("router", "asset").
|
||||
Str("handler", "ListCategoriesWithPreview").
|
||||
Logger()
|
||||
|
||||
var req dto.CategoriesPreviewRequest
|
||||
if !ctl.validateRequest(c, &req) {
|
||||
return
|
||||
}
|
||||
if req.AssetsPerCategory == 0 {
|
||||
req.AssetsPerCategory = 8
|
||||
}
|
||||
|
||||
resp, err := ctl.assetService.GetCategoriesWithPreview(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("failed to list categories with preview")
|
||||
r := dto.InternalServerError()
|
||||
c.JSON(r.Status, r)
|
||||
return
|
||||
}
|
||||
|
||||
r := dto.OK().WithData(resp).WithMessage("Asset categories with sample assets")
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
|
||||
// ListAssetsByCategoryID returns paginated assets for a single category (Phase 2 of two-phase loading).
|
||||
// @Summary list assets by category ID
|
||||
// @Description returns paginated assets for the given category. Use after fetching categories from GET /assets/categories.
|
||||
// @Tags Asset
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "category UUID"
|
||||
// @Param limit query int false "max items per page (default 10)"
|
||||
// @Param page query int false "page number (default 1)"
|
||||
// @Success 200 {object} dto.ListAssetsByCategoryIDResponse "paginated assets for category"
|
||||
// @Failure 400 {object} dto.ErrorResponse "invalid category ID"
|
||||
// @Failure 404 {object} dto.ErrorResponse "category not found"
|
||||
// @Failure 500 {object} dto.ErrorResponse "internal server error"
|
||||
// @Router /api/v1/assets/categories/{id}/assets [get]
|
||||
func (ctl *Controller) ListAssetsByCategoryID(c *gin.Context) {
|
||||
lg := ctl.logger.With().
|
||||
Str("module", "platform").
|
||||
Str("router", "asset").
|
||||
Str("handler", "ListAssetsByCategoryID").
|
||||
Logger()
|
||||
|
||||
categoryID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
r := dto.BadRequest().WithMessage("invalid category ID")
|
||||
c.JSON(r.Status, r)
|
||||
return
|
||||
}
|
||||
|
||||
limit, page := 10, 1
|
||||
if v := c.Query("limit"); v != "" {
|
||||
if n, err := strconv.Atoi(v); err == nil && n > 0 {
|
||||
limit = n
|
||||
}
|
||||
}
|
||||
if v := c.Query("page"); v != "" {
|
||||
if n, err := strconv.Atoi(v); err == nil && n > 0 {
|
||||
page = n
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := ctl.assetService.ListByCategoryID(c.Request.Context(), categoryID, limit, page)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("failed to list assets by category")
|
||||
switch {
|
||||
case errors.Is(err, appAsset.ErrCategoryNotFound):
|
||||
r := dto.NotFound().WithMessage("category not found")
|
||||
c.JSON(r.Status, r)
|
||||
default:
|
||||
r := dto.InternalServerError()
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
r := dto.OK().WithData(resp)
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
|
||||
// CreateAsset godoc
|
||||
// @Summary create asset
|
||||
// @Description create a new asset
|
||||
// @Tags Asset
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body dto.CreateAssetRequest true "create asset request"
|
||||
// @Success 201 {object} dto.AssetResponse "asset response"
|
||||
// @Failure 400 {object} dto.ErrorResponse "invalid request"
|
||||
// @Failure 404 {object} dto.ErrorResponse "category not found"
|
||||
// @Failure 500 {object} dto.ErrorResponse "internal server error"
|
||||
// @Router /api/v1/assets [post]
|
||||
func (ctl *Controller) CreateAsset(c *gin.Context) {
|
||||
lg := ctl.logger.With().
|
||||
Str("module", "platform").
|
||||
Str("router", "asset").
|
||||
Str("handler", "CreateAsset").
|
||||
Logger()
|
||||
|
||||
var req dto.CreateAssetRequest
|
||||
if !ctl.validateRequest(c, &req) {
|
||||
return
|
||||
}
|
||||
|
||||
asset, err := ctl.assetService.Create(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("failed to create asset")
|
||||
switch {
|
||||
case errors.Is(err, appAsset.ErrCategoryNotFound):
|
||||
r := dto.NotFound().WithMessage("asset category not found")
|
||||
c.JSON(r.Status, r)
|
||||
default:
|
||||
r := dto.InternalServerError().WithMessage("failed to create asset")
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
r := dto.Created(asset)
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
|
||||
// GetAsset godoc
|
||||
// @Summary get asset by ID
|
||||
// @Description get asset by ID
|
||||
// @Tags Asset
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "asset ID"
|
||||
// @Success 200 {object} dto.AssetResponse "asset response"
|
||||
// @Failure 400 {object} dto.ErrorResponse "invalid request"
|
||||
// @Failure 404 {object} dto.ErrorResponse "asset not found"
|
||||
// @Failure 500 {object} dto.ErrorResponse "internal server error"
|
||||
// @Router /api/v1/assets/{id} [get]
|
||||
func (ctl *Controller) GetAsset(c *gin.Context) {
|
||||
lg := ctl.logger.With().
|
||||
Str("module", "platform").
|
||||
Str("router", "asset").
|
||||
Str("handler", "GetAsset").
|
||||
Logger()
|
||||
|
||||
var req dto.GetAssetRequest
|
||||
if !ctl.validateRequest(c, &req) {
|
||||
return
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(req.ID)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("invalid asset ID")
|
||||
r := dto.BadRequest().WithMessage("invalid asset ID")
|
||||
c.JSON(r.Status, r)
|
||||
return
|
||||
}
|
||||
|
||||
asset, err := ctl.assetService.GetByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("failed to get asset")
|
||||
switch {
|
||||
case errors.Is(err, appAsset.ErrAssetNotFound):
|
||||
r := dto.NotFound().WithMessage("asset not found")
|
||||
c.JSON(r.Status, r)
|
||||
default:
|
||||
r := dto.InternalServerError()
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
r := dto.OK().WithData(asset)
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
|
||||
// UpdateAsset godoc
|
||||
// @Summary update asset
|
||||
// @Description update an existing asset
|
||||
// @Tags Asset
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "asset ID"
|
||||
// @Param request body dto.UpdateAssetRequest true "update asset request"
|
||||
// @Success 200 {object} dto.AssetResponse "asset response"
|
||||
// @Failure 400 {object} dto.ErrorResponse "invalid request"
|
||||
// @Failure 404 {object} dto.ErrorResponse "asset not found"
|
||||
// @Failure 500 {object} dto.ErrorResponse "internal server error"
|
||||
// @Router /api/v1/assets/{id} [put]
|
||||
func (ctl *Controller) UpdateAsset(c *gin.Context) {
|
||||
lg := ctl.logger.With().
|
||||
Str("module", "platform").
|
||||
Str("router", "asset").
|
||||
Str("handler", "UpdateAsset").
|
||||
Logger()
|
||||
|
||||
var req dto.UpdateAssetRequest
|
||||
if !ctl.validateRequest(c, &req) {
|
||||
return
|
||||
}
|
||||
|
||||
asset, err := ctl.assetService.Update(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("failed to update asset")
|
||||
switch {
|
||||
case errors.Is(err, appAsset.ErrAssetNotFound):
|
||||
r := dto.NotFound().WithMessage("asset not found")
|
||||
c.JSON(r.Status, r)
|
||||
default:
|
||||
r := dto.InternalServerError()
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
r := dto.OK().WithData(asset)
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
|
||||
// ListAssetsByProfile godoc
|
||||
// @Summary list assets by profile ID
|
||||
// @Description list all assets for a profile
|
||||
// @Tags Asset
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "profile ID"
|
||||
// @Success 200 {object} dto.ListAssetsResponse "list assets response"
|
||||
// @Failure 400 {object} dto.ErrorResponse "invalid request"
|
||||
// @Failure 500 {object} dto.ErrorResponse "internal server error"
|
||||
// @Router /api/v1/profiles/{id}/assets [get]
|
||||
func (ctl *Controller) ListAssetsByProfile(c *gin.Context) {
|
||||
lg := ctl.logger.With().
|
||||
Str("module", "platform").
|
||||
Str("router", "asset").
|
||||
Str("handler", "ListAssetsByProfile").
|
||||
Logger()
|
||||
|
||||
var req dto.ListAssetsByProfileRequest
|
||||
if !ctl.validateRequest(c, &req) {
|
||||
return
|
||||
}
|
||||
|
||||
profileID, err := uuid.Parse(req.ProfileID)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("invalid profile ID")
|
||||
r := dto.BadRequest().WithMessage("invalid profile ID")
|
||||
c.JSON(r.Status, r)
|
||||
return
|
||||
}
|
||||
|
||||
assets, err := ctl.assetService.FindByProfileID(c.Request.Context(), profileID)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("failed to list assets")
|
||||
r := dto.InternalServerError()
|
||||
c.JSON(r.Status, r)
|
||||
return
|
||||
}
|
||||
|
||||
r := dto.OK().WithData(assets)
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
|
||||
// DeleteAsset godoc
|
||||
// @Summary delete asset
|
||||
// @Description delete an asset
|
||||
// @Tags Asset
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "asset ID"
|
||||
// @Success 200 {object} dto.SuccessResponse "success response"
|
||||
// @Failure 400 {object} dto.ErrorResponse "invalid request"
|
||||
// @Failure 404 {object} dto.ErrorResponse "asset not found"
|
||||
// @Failure 500 {object} dto.ErrorResponse "internal server error"
|
||||
// @Router /api/v1/assets/{id} [delete]
|
||||
func (ctl *Controller) DeleteAsset(c *gin.Context) {
|
||||
lg := ctl.logger.With().
|
||||
Str("module", "platform").
|
||||
Str("router", "asset").
|
||||
Str("handler", "DeleteAsset").
|
||||
Logger()
|
||||
|
||||
var req dto.DeleteAssetRequest
|
||||
if !ctl.validateRequest(c, &req) {
|
||||
return
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(req.ID)
|
||||
if err != nil {
|
||||
lg.Error().Err(err).Msg("invalid asset ID")
|
||||
r := dto.BadRequest().WithMessage("invalid asset ID")
|
||||
c.JSON(r.Status, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err := ctl.assetService.Delete(c.Request.Context(), id); err != nil {
|
||||
lg.Error().Err(err).Msg("failed to delete asset")
|
||||
switch {
|
||||
case errors.Is(err, appAsset.ErrAssetNotFound):
|
||||
r := dto.NotFound().WithMessage("asset not found")
|
||||
c.JSON(r.Status, r)
|
||||
default:
|
||||
r := dto.InternalServerError()
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
r := dto.OK().WithMessage("asset deleted successfully")
|
||||
c.JSON(r.Status, r)
|
||||
}
|
||||
Reference in New Issue
Block a user