Files
pocket-id-pocket-id-2/backend/internal/utils/paging_util.go

100 lines
2.4 KiB
Go
Raw Normal View History

2024-08-12 11:00:25 +02:00
package utils
import (
2025-01-11 20:14:12 +01:00
"reflect"
"strconv"
"strings"
"gorm.io/gorm"
"gorm.io/gorm/clause"
2024-08-12 11:00:25 +02:00
)
type PaginationResponse struct {
2024-10-02 08:43:44 +02:00
TotalPages int64 `json:"totalPages"`
TotalItems int64 `json:"totalItems"`
CurrentPage int `json:"currentPage"`
ItemsPerPage int `json:"itemsPerPage"`
2024-08-12 11:00:25 +02:00
}
2025-01-11 20:14:12 +01:00
type SortedPaginationRequest struct {
Pagination struct {
Page int `form:"pagination[page]"`
Limit int `form:"pagination[limit]"`
} `form:"pagination"`
Sort struct {
Column string `form:"sort[column]"`
Direction string `form:"sort[direction]"`
} `form:"sort"`
}
func PaginateAndSort(sortedPaginationRequest SortedPaginationRequest, query *gorm.DB, result interface{}) (PaginationResponse, error) {
pagination := sortedPaginationRequest.Pagination
sort := sortedPaginationRequest.Sort
capitalizedSortColumn := CapitalizeFirstLetter(sort.Column)
sortField, sortFieldFound := reflect.TypeOf(result).Elem().Elem().FieldByName(capitalizedSortColumn)
isSortable, _ := strconv.ParseBool(sortField.Tag.Get("sortable"))
2025-01-11 20:14:12 +01:00
sort.Direction = NormalizeSortDirection(sort.Direction)
2025-06-08 16:04:58 +02:00
if sortFieldFound && isSortable {
columnName := CamelCaseToSnakeCase(sort.Column)
query = query.Clauses(clause.OrderBy{
Columns: []clause.OrderByColumn{
{Column: clause.Column{Name: columnName}, Desc: sort.Direction == "desc"},
},
})
2025-01-11 20:14:12 +01:00
}
return Paginate(pagination.Page, pagination.Limit, query, result)
}
func Paginate(page int, pageSize int, query *gorm.DB, result interface{}) (PaginationResponse, error) {
2024-08-12 11:00:25 +02:00
if page < 1 {
page = 1
}
if pageSize < 1 {
pageSize = 20
2024-08-12 11:00:25 +02:00
} else if pageSize > 100 {
pageSize = 100
}
offset := (page - 1) * pageSize
var totalItems int64
2025-01-11 20:14:12 +01:00
if err := query.Count(&totalItems).Error; err != nil {
2024-08-12 11:00:25 +02:00
return PaginationResponse{}, err
}
2025-01-11 20:14:12 +01:00
if err := query.Offset(offset).Limit(pageSize).Find(result).Error; err != nil {
2024-08-12 11:00:25 +02:00
return PaginationResponse{}, err
}
totalPages := (totalItems + int64(pageSize) - 1) / int64(pageSize)
if totalItems == 0 {
totalPages = 1
}
2024-08-12 11:00:25 +02:00
return PaginationResponse{
TotalPages: totalPages,
2024-10-02 08:43:44 +02:00
TotalItems: totalItems,
CurrentPage: page,
ItemsPerPage: pageSize,
2024-08-12 11:00:25 +02:00
}, nil
}
func NormalizeSortDirection(direction string) string {
d := strings.ToLower(strings.TrimSpace(direction))
if d != "asc" && d != "desc" {
return "asc"
}
return d
}
func IsValidSortDirection(direction string) bool {
d := strings.ToLower(strings.TrimSpace(direction))
return d == "asc" || d == "desc"
}