package utils import ( "math" "github.com/gofiber/fiber/v2" "gorm.io/gorm" ) const ( // DefaultPageSize bounds a list request that doesn't ask for a specific // window. It is deliberately high: these endpoints previously returned // whole tables, so a small default would silently truncate results for // consoles that don't paginate yet. It exists to stop a growing table // from being loaded into memory wholesale, not to enforce a page size. DefaultPageSize = 500 // MaxPageSize is the ceiling a caller can request, so a client can't opt // back into an unbounded scan by sending pagesize=999999. MaxPageSize = 1000 ) // Page is a validated pagination window. Build one with ParsePage rather than // constructing it directly. type Page struct { No int // 1-based page number Size int Offset int } // ParsePage reads ?pageno and ?pagesize off the request, matching the naming // GetAdminBookings already established. Both are clamped into a safe range; // absent or malformed values fall back to page 1 at DefaultPageSize rather // than erroring, so a bad query string degrades instead of failing the call. func ParsePage(c *fiber.Ctx) Page { no := c.QueryInt("pageno", 1) if no < 1 { no = 1 } size := c.QueryInt("pagesize", DefaultPageSize) if size < 1 { size = DefaultPageSize } if size > MaxPageSize { size = MaxPageSize } return Page{No: no, Size: size, Offset: (no - 1) * size} } // Apply scopes a query to this page's window. func (p Page) Apply(q *gorm.DB) *gorm.DB { return q.Offset(p.Offset).Limit(p.Size) } // Paginated writes one page of a larger result set, using the same response // keys GetAdminBookings already returns. It keeps the {success, data, total} // shape utils.List emits and only adds keys, so clients that ignore the new // fields are unaffected. total is the count of all matching rows, not the // length of data. func Paginated(c *fiber.Ctx, data interface{}, total int64, p Page) error { return c.JSON(fiber.Map{ "success": true, "data": data, "total": total, "pageno": p.No, "pagesize": p.Size, "pages": int(math.Ceil(float64(total) / float64(p.Size))), }) }