From 82feccf64aab94a2c85b7459aa40028d20e8a8fd Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Sun, 22 Mar 2026 14:33:31 +1100 Subject: [PATCH] feat: add pagination to admin post list handler and service Co-Authored-By: Claude Opus 4.6 --- handlers/posts.go | 30 ++++++++++++++++++++++++++---- services/posts/list.go | 25 ++++++++++++++++--------- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/handlers/posts.go b/handlers/posts.go index a133758..3326533 100644 --- a/handlers/posts.go +++ b/handlers/posts.go @@ -6,6 +6,7 @@ import ( "github.com/gofiber/fiber/v3" "lmika.dev/lmika/weiro/models" + "lmika.dev/lmika/weiro/providers/db" "lmika.dev/lmika/weiro/services/categories" "lmika.dev/lmika/weiro/services/posts" ) @@ -18,22 +19,43 @@ type PostsHandler struct { func (ph PostsHandler) Index(c fiber.Ctx) error { var req struct { Filter string `query:"filter"` + Page int `query:"page"` } if err := c.Bind().Query(&req); err != nil { return fiber.ErrBadRequest } - posts, err := ph.PostService.ListPosts(c.Context(), req.Filter == "deleted") + const perPage = 25 + if req.Page < 1 { + req.Page = 1 + } + + result, err := ph.PostService.ListPosts(c.Context(), req.Filter == "deleted", db.PagingParams{ + Offset: int64((req.Page - 1) * perPage), + Limit: perPage, + }) if err != nil { return err } + totalPages := int(result.TotalCount+int64(perPage)-1) / perPage + if totalPages < 1 { + totalPages = 1 + } + + pageInfo := models.PageInfo{ + CurrentPage: req.Page, + TotalPages: totalPages, + PostsPerPage: perPage, + } + return accepts(c, json(func() any { - return posts + return result.Posts }), html(func(c fiber.Ctx) error { return c.Render("posts/index", fiber.Map{ - "req": req, - "posts": posts, + "req": req, + "posts": result.Posts, + "pageInfo": pageInfo, }) })) } diff --git a/services/posts/list.go b/services/posts/list.go index 15e14d3..dd25bae 100644 --- a/services/posts/list.go +++ b/services/posts/list.go @@ -12,29 +12,36 @@ type PostWithCategories struct { Categories []*models.Category } -func (s *Service) ListPosts(ctx context.Context, showDeleted bool) ([]*PostWithCategories, error) { +type ListPostsResult struct { + Posts []*PostWithCategories + TotalCount int64 +} + +func (s *Service) ListPosts(ctx context.Context, showDeleted bool, paging db.PagingParams) (ListPostsResult, error) { site, ok := models.GetSite(ctx) if !ok { - return nil, models.SiteRequiredError + return ListPostsResult{}, models.SiteRequiredError } - posts, err := s.db.SelectPostsOfSite(ctx, site.ID, showDeleted, db.PagingParams{ - Offset: 0, - Limit: 25, - }) + posts, err := s.db.SelectPostsOfSite(ctx, site.ID, showDeleted, paging) if err != nil { - return nil, err + return ListPostsResult{}, err + } + + count, err := s.db.CountPostsOfSite(ctx, site.ID, showDeleted) + if err != nil { + return ListPostsResult{}, err } result := make([]*PostWithCategories, len(posts)) for i, post := range posts { cats, err := s.db.SelectCategoriesOfPost(ctx, post.ID) if err != nil { - return nil, err + return ListPostsResult{}, err } result[i] = &PostWithCategories{Post: post, Categories: cats} } - return result, nil + return ListPostsResult{Posts: result, TotalCount: count}, nil } func (s *Service) GetPost(ctx context.Context, pid int64) (*models.Post, error) {