364 lines
10 KiB
Go
364 lines
10 KiB
Go
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)
|
|
}
|