Skip to content

Commit

Permalink
feat: add isLastPage to paginated view
Browse files Browse the repository at this point in the history
  • Loading branch information
litsynp committed Feb 3, 2024
1 parent c5dc5dd commit 15c19bc
Show file tree
Hide file tree
Showing 20 changed files with 330 additions and 226 deletions.
27 changes: 20 additions & 7 deletions api/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,28 @@ func NewItemListView[T interface{}](items []T) *ItemListView[T] {
}

type PaginatedView[T interface{}] struct {
Page int `json:"page"`
Size int `json:"size"`
Items []T `json:"items"`
Page int `json:"page"`
Size int `json:"size"`
IsLastPage bool `json:"is_last_page"`
Items []T `json:"items"`
}

func NewPaginatedView[T interface{}](page int, size int, items []T) *PaginatedView[T] {
func NewPaginatedView[T interface{}](page int, size int, isLastPage bool, items []T) *PaginatedView[T] {
return &PaginatedView[T]{
Page: page,
Size: size,
Items: items,
Page: page,
Size: size,
IsLastPage: isLastPage,
Items: items,
}
}

// CalcLastPage는 현재 페이지가 마지막 페이지인지를 items의 개수를 통해 계산한다.
// 마지막 페이지가 아니라면 items를 size만큼 잘라서 마지막 페이지로 만든다.
func (l *PaginatedView[T]) CalcLastPage() {
if len(l.Items) > l.Size {
l.IsLastPage = false
l.Items = l.Items[:l.Size]
} else {
l.IsLastPage = true
}
}
4 changes: 2 additions & 2 deletions cmd/server/handler/breed_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func NewBreedHandler(breedService pet.BreedService) *BreedHandler {
// @Param page query int false "페이지 번호" default(1)
// @Param size query int false "페이지 사이즈" default(20)
// @Param pet_type query string false "펫 종류" Enums(dog, cat)
// @Success 200 {object} pnd.PaginatedView[pet.BreedView]
// @Success 200 {object} pet.BreedListView
// @Router /breeds [get]
func (h *BreedHandler) FindBreeds(w http.ResponseWriter, r *http.Request) {
petType := pnd.ParseOptionalStringQuery(r, "pet_type")
Expand All @@ -41,5 +41,5 @@ func (h *BreedHandler) FindBreeds(w http.ResponseWriter, r *http.Request) {
return
}

render.JSON(w, r, pnd.NewPaginatedView(page, size, res))
render.JSON(w, r, res)
}
7 changes: 3 additions & 4 deletions cmd/server/handler/sos_post_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (h *SosPostHandler) WriteSosPost(w http.ResponseWriter, r *http.Request) {
// @Param page query int false "페이지 번호" default(1)
// @Param size query int false "페이지 사이즈" default(20)
// @Param sort_by query string false "정렬 기준" Enums(newest, deadline)
// @Success 200 {object} pnd.PaginatedView[sos_post.FindSosPostView]
// @Success 200 {object} sos_post.FindSosPostListView
// @Router /posts/sos [get]
func (h *SosPostHandler) FindSosPosts(w http.ResponseWriter, r *http.Request) {
authorID, err := pnd.ParseOptionalIntQuery(r, "author_id")
Expand All @@ -85,8 +85,7 @@ func (h *SosPostHandler) FindSosPosts(w http.ResponseWriter, r *http.Request) {
return
}

var res []sos_post.FindSosPostView

var res *sos_post.FindSosPostListView
if authorID != nil {
res, err = h.sosPostService.FindSosPostsByAuthorID(*authorID, page, size)
if err != nil {
Expand All @@ -101,7 +100,7 @@ func (h *SosPostHandler) FindSosPosts(w http.ResponseWriter, r *http.Request) {
}
}

render.JSON(w, r, pnd.NewPaginatedView(page, size, res))
render.JSON(w, r, res)
}

// FindSosPostByID godoc
Expand Down
7 changes: 3 additions & 4 deletions cmd/server/handler/user_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (h *UserHandler) FindUserStatusByEmail(w http.ResponseWriter, r *http.Reque
// @Param page query int false "페이지 번호" default(1)
// @Param size query int false "페이지 사이즈" default(10)
// @Param nickname query string false "닉네임 (완전 일치)"
// @Success 200 {object} pnd.PaginatedView[user.UserWithoutPrivateInfo]
// @Success 200 {object} user.UserWithoutPrivateInfoList
// @Router /users [get]
func (h *UserHandler) FindUsers(w http.ResponseWriter, r *http.Request) {
_, err := h.authService.VerifyAuthAndGetUser(r.Context(), r)
Expand All @@ -131,15 +131,14 @@ func (h *UserHandler) FindUsers(w http.ResponseWriter, r *http.Request) {
return
}

var res []*user.UserWithoutPrivateInfo

var res *user.UserWithoutPrivateInfoList
res, err = h.userService.FindUsers(page, size, nickname)
if err != nil {
render.Render(w, r, err)
return
}

render.JSON(w, r, pnd.NewPaginatedView(page, size, res))
render.JSON(w, r, res)
}

// FindMyProfile godoc
Expand Down
12 changes: 11 additions & 1 deletion internal/domain/pet/breed.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,18 @@ type Breed struct {
DeletedAt string `field:"deleted_at"`
}

type BreedList struct {
*pnd.PaginatedView[Breed]
}

func NewBreedList(page int, size int) *BreedList {
return &BreedList{PaginatedView: pnd.NewPaginatedView(
page, size, false, make([]Breed, 0),
)}
}

type BreedStore interface {
FindBreeds(page int, size int, petType *string) ([]*Breed, *pnd.AppError)
FindBreeds(page int, size int, petType *string) (*BreedList, *pnd.AppError)
FindBreedByPetTypeAndName(petType PetType, name string) (*Breed, *pnd.AppError)
CreateBreed(breed *Breed) (*Breed, *pnd.AppError)
}
13 changes: 2 additions & 11 deletions internal/domain/pet/breed_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,13 @@ func NewBreedService(breedStore BreedStore) *BreedService {
}
}

func (service *BreedService) FindBreeds(page int, size int, petType *string) ([]*BreedView, *pnd.AppError) {
func (service *BreedService) FindBreeds(page int, size int, petType *string) (*BreedListView, *pnd.AppError) {
breeds, err := service.breedStore.FindBreeds(page, size, petType)
if err != nil {
return nil, err
}

breedViews := make([]*BreedView, 0)
for _, breed := range breeds {
breedViews = append(breedViews, &BreedView{
ID: breed.ID,
PetType: breed.PetType,
Name: breed.Name,
})
}

return breedViews, nil
return FromBreedList(breeds), nil
}

func (service *BreedService) FindBreedByPetTypeAndName(petType PetType, name string) (*BreedView, *pnd.AppError) {
Expand Down
23 changes: 23 additions & 0 deletions internal/domain/pet/view.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package pet

import pnd "github.com/pet-sitter/pets-next-door-api/api"

type AddPetsToOwnerRequest struct {
Pets []AddPetRequest `json:"pets" validate:"required"`
}
Expand Down Expand Up @@ -34,3 +36,24 @@ type BreedView struct {
PetType PetType `json:"pet_type"`
Name string `json:"name"`
}

type BreedListView struct {
*pnd.PaginatedView[*BreedView]
}

func FromBreedList(breeds *BreedList) *BreedListView {
breedViews := make([]*BreedView, 0)
for _, breed := range breeds.Items {
breedViews = append(breedViews, &BreedView{
ID: breed.ID,
PetType: breed.PetType,
Name: breed.Name,
})
}

return &BreedListView{
PaginatedView: pnd.NewPaginatedView(
breeds.Page, breeds.Size, breeds.IsLastPage, breedViews,
),
}
}
16 changes: 8 additions & 8 deletions internal/domain/sos_post/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,15 @@ func (service *SosPostService) WriteSosPost(fbUid string, request *WriteSosPostR
}, nil
}

func (service *SosPostService) FindSosPosts(page int, size int, sortBy string) ([]FindSosPostView, *pnd.AppError) {
func (service *SosPostService) FindSosPosts(page int, size int, sortBy string) (*FindSosPostListView, *pnd.AppError) {
sosPosts, err := service.sosPostStore.FindSosPosts(page, size, sortBy)
if err != nil {
return nil, err
}

var findSosPostViews []FindSosPostView
findSosPostViews := FromEmptySosPostList(sosPosts)

for _, sosPost := range sosPosts {
for _, sosPost := range sosPosts.Items {
mediaData, err := service.resourceMediaStore.FindResourceMediaByResourceID(sosPost.ID, string(media.SosResourceType))
if err != nil {
return nil, err
Expand Down Expand Up @@ -193,21 +193,21 @@ func (service *SosPostService) FindSosPosts(page int, size int, sortBy string) (
UpdatedAt: sosPost.UpdatedAt,
}

findSosPostViews = append(findSosPostViews, *findByAuthorSosPostView)
findSosPostViews.Items = append(findSosPostViews.Items, *findByAuthorSosPostView)
}

return findSosPostViews, nil
}

func (service *SosPostService) FindSosPostsByAuthorID(authorID int, page int, size int) ([]FindSosPostView, *pnd.AppError) {
func (service *SosPostService) FindSosPostsByAuthorID(authorID int, page int, size int) (*FindSosPostListView, *pnd.AppError) {
sosPosts, err := service.sosPostStore.FindSosPostsByAuthorID(authorID, page, size)
if err != nil {
return nil, err
}

var findSosPostViews []FindSosPostView
findSosPostViews := FromEmptySosPostList(sosPosts)

for _, sosPost := range sosPosts {
for _, sosPost := range sosPosts.Items {
mediaData, err := service.resourceMediaStore.FindResourceMediaByResourceID(sosPost.ID, string(media.SosResourceType))
if err != nil {
return nil, err
Expand Down Expand Up @@ -281,7 +281,7 @@ func (service *SosPostService) FindSosPostsByAuthorID(authorID int, page int, si
UpdatedAt: sosPost.UpdatedAt,
}

findSosPostViews = append(findSosPostViews, *findByAuthorSosPostView)
findSosPostViews.Items = append(findSosPostViews.Items, *findByAuthorSosPostView)
}

return findSosPostViews, nil
Expand Down
14 changes: 12 additions & 2 deletions internal/domain/sos_post/sos_post.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,20 @@ type SosPost struct {
DeletedAt time.Time `field:"deleted_at"`
}

type SosPostList struct {
*pnd.PaginatedView[SosPost]
}

func NewSosPostList(page int, size int) *SosPostList {
return &SosPostList{PaginatedView: pnd.NewPaginatedView(
page, size, false, make([]SosPost, 0),
)}
}

type SosPostStore interface {
WriteSosPost(authorID int, utcDateStart string, utcDateEnd string, request *WriteSosPostRequest) (*SosPost, *pnd.AppError)
FindSosPosts(page int, size int, sortBy string) ([]SosPost, *pnd.AppError)
FindSosPostsByAuthorID(authorID int, page int, size int) ([]SosPost, *pnd.AppError)
FindSosPosts(page int, size int, sortBy string) (*SosPostList, *pnd.AppError)
FindSosPostsByAuthorID(authorID int, page int, size int) (*SosPostList, *pnd.AppError)
FindSosPostByID(id int) (*SosPost, *pnd.AppError)
UpdateSosPost(request *UpdateSosPostRequest) (*SosPost, *pnd.AppError)
FindConditionByID(id int) ([]Condition, *pnd.AppError)
Expand Down
11 changes: 5 additions & 6 deletions internal/domain/sos_post/tests/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,13 @@ func TestSosPostService(t *testing.T) {
sosPosts = append(sosPosts, *sosPost)
}

findSosPosts, err := sosPostService.FindSosPosts(1, 3, "newest")
for i, sosPost := range findSosPosts {
sosPostList, err := sosPostService.FindSosPosts(1, 3, "newest")
for i, sosPost := range sosPostList.Items {
assertConditionEquals(t, sosPost.Conditions, conditionIDs)
assertPetEquals(t, sosPost.Pets[0], addPets[0])
assertMediaEquals(t, sosPost.Media, sosPostMedia)

idx := len(findSosPosts) - i - 1
idx := len(sosPostList.Items) - i - 1

if err != nil {
t.Errorf("got %v want %v", err, nil)
Expand Down Expand Up @@ -414,9 +414,8 @@ func TestSosPostService(t *testing.T) {
sosPosts = append(sosPosts, *sosPost)
}

findSosPostByAuthorID, err := sosPostService.FindSosPostsByAuthorID(owner.ID, 1, 3)

for i, sosPost := range findSosPostByAuthorID {
sosPostListByAuthorID, err := sosPostService.FindSosPostsByAuthorID(owner.ID, 1, 3)
for i, sosPost := range sosPostListByAuthorID.Items {
assertConditionEquals(t, sosPost.Conditions, conditionIDs)
assertPetEquals(t, sosPost.Pets[0], addPets[0])
assertMediaEquals(t, sosPost.Media, sosPostMedia)
Expand Down
13 changes: 13 additions & 0 deletions internal/domain/sos_post/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package sos_post
import (
"time"

pnd "github.com/pet-sitter/pets-next-door-api/api"
"github.com/pet-sitter/pets-next-door-api/internal/domain/media"
"github.com/pet-sitter/pets-next-door-api/internal/domain/pet"
)
Expand Down Expand Up @@ -65,6 +66,18 @@ type FindSosPostView struct {
UpdatedAt time.Time `json:"updated_at"`
}

type FindSosPostListView struct {
*pnd.PaginatedView[FindSosPostView]
}

func FromEmptySosPostList(sosPosts *SosPostList) *FindSosPostListView {
return &FindSosPostListView{
PaginatedView: pnd.NewPaginatedView(
sosPosts.Page, sosPosts.Size, sosPosts.IsLastPage, make([]FindSosPostView, 0),
),
}
}

type UpdateSosPostRequest struct {
ID int `json:"id" validate:"required"`
Title string `json:"title" validate:"required"`
Expand Down
6 changes: 3 additions & 3 deletions internal/domain/user/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ func (service *UserService) RegisterUser(registerUserRequest *RegisterUserReques
}, nil
}

func (service *UserService) FindUsers(page int, size int, nickname *string) ([]*UserWithoutPrivateInfo, *pnd.AppError) {
usersData, err := service.userStore.FindUsers(page, size, nickname)
func (service *UserService) FindUsers(page int, size int, nickname *string) (*UserWithoutPrivateInfoList, *pnd.AppError) {
userList, err := service.userStore.FindUsers(page, size, nickname)
if err != nil {
return nil, err
}

return usersData, nil
return userList, nil
}

func (service *UserService) FindUserByEmail(email string) (*UserWithProfileImage, *pnd.AppError) {
Expand Down
5 changes: 2 additions & 3 deletions internal/domain/user/tests/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,8 @@ func TestUserService(t *testing.T) {
}

found, _ := service.FindUsers(1, 20, &targetNickname)

if len(found) != 1 {
t.Errorf("got %v want %v", len(found), 1)
if len(found.Items) != 1 {
t.Errorf("got %v want %v", len(found.Items), 1)
}
})
})
Expand Down
12 changes: 11 additions & 1 deletion internal/domain/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,23 @@ type UserWithoutPrivateInfo struct {
ProfileImageURL *string `field:"profile_image_url" json:"profileImageUrl"`
}

type UserWithoutPrivateInfoList struct {
*pnd.PaginatedView[UserWithoutPrivateInfo]
}

func NewUserWithoutPrivateInfoList(page int, size int) *UserWithoutPrivateInfoList {
return &UserWithoutPrivateInfoList{PaginatedView: pnd.NewPaginatedView(
page, size, false, make([]UserWithoutPrivateInfo, 0),
)}
}

type UserStatus struct {
FirebaseProviderType FirebaseProviderType `field:"fb_provider_type"`
}

type UserStore interface {
CreateUser(request *RegisterUserRequest) (*User, *pnd.AppError)
FindUsers(page int, size int, nickname *string) ([]*UserWithoutPrivateInfo, *pnd.AppError)
FindUsers(page int, size int, nickname *string) (*UserWithoutPrivateInfoList, *pnd.AppError)
FindUserByEmail(email string) (*UserWithProfileImage, *pnd.AppError)
FindUserByUID(uid string) (*UserWithProfileImage, *pnd.AppError)
FindUserIDByFbUID(fbUid string) (int, *pnd.AppError)
Expand Down
Loading

0 comments on commit 15c19bc

Please sign in to comment.