package query import ( "strconv" "github.com/gin-gonic/gin" "gorm.io/gorm" ) type Params struct { Page int PageSize int SortBy string SortDir string Filters map[string]string } func ParseParams(c *gin.Context) Params { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) if page < 1 { page = 1 } if pageSize < 1 { pageSize = 20 } if pageSize > 100 { pageSize = 100 } sortBy := c.Query("sort_by") sortDir := c.DefaultQuery("sort_dir", "asc") if sortDir != "asc" && sortDir != "desc" { sortDir = "asc" } filters := make(map[string]string) for key, values := range c.Request.URL.Query() { if key != "page" && key != "page_size" && key != "sort_by" && key != "sort_dir" { filters[key] = values[0] } } return Params{ Page: page, PageSize: pageSize, SortBy: sortBy, SortDir: sortDir, Filters: filters, } } func Paginate(p Params) func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB { offset := (p.Page - 1) * p.PageSize return db.Offset(offset).Limit(p.PageSize) } } func Sort(p Params) func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB { if p.SortBy == "" { return db } return db.Order(p.SortBy + " " + p.SortDir) } } func Filter(p Params, allowed map[string]string) func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB { for key, value := range p.Filters { if col, ok := allowed[key]; ok && value != "" { db = db.Where(col+" = ?", value) } } return db } } type PageResult[T any] struct { Items []T `json:"items"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` }