package admin import ( "quyun/app/models" "quyun/app/requests" "quyun/database/fields" "quyun/database/schemas/public/model" "github.com/gofiber/fiber/v3" "github.com/samber/lo" ) type ListQuery struct { Keyword *string `query:"keyword"` } // @provider type posts struct{} // List posts // @Router /v1/admin/posts [get] // @Bind pagination query // @Bind query query func (ctl *posts) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery) (*requests.Pager, error) { cond := models.Posts.BuildConditionWithKey(query.Keyword) pager, err := models.Posts.List(ctx.Context(), pagination, cond) if err != nil { return nil, err } postIds := lo.Map(pager.Items.([]model.Posts), func(item model.Posts, _ int) int64 { return item.ID }) if len(postIds) > 0 { postCntMap, err := models.Posts.BoughtStatistics(ctx.Context(), postIds) if err != nil { return pager, err } items := lo.Map(pager.Items.([]model.Posts), func(item model.Posts, _ int) PostItem { cnt := int64(0) if v, ok := postCntMap[item.ID]; ok { cnt = v } return PostItem{Posts: &item, BoughtCount: cnt} }) pager.Items = items } return pager, err } type PostForm struct { Title string `json:"title"` HeadImages []int64 `json:"head_images"` Price int64 `json:"price"` Discount int16 `json:"discount"` Introduction string `json:"introduction"` Medias []int64 `json:"medias"` Status fields.PostStatus `json:"status"` Content string `json:"content"` } // Create // @Router /v1/admin/posts [post] // @Bind form body func (ctl *posts) Create(ctx fiber.Ctx, form *PostForm) error { post := model.Posts{ Title: form.Title, HeadImages: fields.ToJson(form.HeadImages), Price: form.Price, Discount: form.Discount, Description: form.Introduction, Status: form.Status, Content: form.Content, Tags: fields.Json[[]string]{}, Assets: fields.Json[[]fields.MediaAsset]{}, } if form.Medias != nil { medias, err := models.Medias.GetByIds(ctx.Context(), form.Medias) if err != nil { return err } assets := lo.Map(medias, func(media *model.Medias, _ int) fields.MediaAsset { return fields.MediaAsset{ Type: media.MimeType, Media: media.ID, Mark: nil, } }) post.Assets = fields.ToJson(assets) } if err := models.Posts.Create(ctx.Context(), &post); err != nil { return err } return nil } // Update posts // @Router /v1/admin/posts/:id [put] // @Bind id path // @Bind form body func (ctl *posts) Update(ctx fiber.Ctx, id int64, form *PostForm) error { oldPost, err := models.Posts.GetByID(ctx.Context(), id) if err != nil { return err } post := &model.Posts{ Title: form.Title, HeadImages: fields.ToJson(form.HeadImages), Price: form.Price, Discount: form.Discount, Description: form.Introduction, Status: form.Status, Content: form.Content, Tags: fields.Json[[]string]{}, Assets: fields.Json[[]fields.MediaAsset]{}, CreatedAt: oldPost.CreatedAt, UpdatedAt: oldPost.UpdatedAt, DeletedAt: oldPost.DeletedAt, Views: oldPost.Views, Likes: oldPost.Likes, } if form.Medias != nil { medias, err := models.Medias.GetByIds(ctx.Context(), form.Medias) if err != nil { return err } assets := lo.Map(medias, func(media *model.Medias, _ int) fields.MediaAsset { return fields.MediaAsset{ Type: media.MimeType, Media: media.ID, Mark: nil, } }) post.Assets = fields.ToJson(assets) } if err := models.Posts.Update(ctx.Context(), id, post); err != nil { return err } return nil } // Delete posts // @Router /v1/admin/posts/:id [delete] // @Bind id path func (ctl *posts) Delete(ctx fiber.Ctx, id int64) error { post, err := models.Posts.GetByID(ctx.Context(), id) if err != nil { return err } if post == nil { return fiber.ErrNotFound } if err := models.Posts.DeleteByID(ctx.Context(), id); err != nil { return err } return nil } type PostItem struct { *model.Posts Medias []*model.Medias `json:"medias"` BoughtCount int64 `json:"bought_count"` } // Show posts by id // @Router /v1/admin/posts/:id [get] // @Bind id path func (ctl *posts) Show(ctx fiber.Ctx, id int64) (*PostItem, error) { post, err := models.Posts.GetByID(ctx.Context(), id) if err != nil { return nil, err } medias, err := models.Medias.GetByIds(ctx.Context(), lo.Map(post.Assets.Data, func(asset fields.MediaAsset, _ int) int64 { return asset.Media })) if err != nil { return nil, err } return &PostItem{ Posts: post, Medias: medias, }, nil } // SendTo // @Router /v1/admin/posts/:id/send-to/:userId [post] // @Bind id path // @Bind userId path func (ctl *posts) SendTo(ctx fiber.Ctx, id, userId int64) error { if _, err := models.Posts.GetByID(ctx.Context(), id); err != nil { return err } if _, err := models.Users.GetByID(ctx.Context(), userId); err != nil { return err } if err := models.Posts.SendTo(ctx.Context(), id, userId); err != nil { return err } return nil }