@@ -197,3 +197,65 @@ func PaginatedAPIResponseWithIncludes[T any](
197197
198198 return NewPaginatedResponse (200 , message , data , paginationResponse )
199199}
200+
201+ // PaginatedQueryWithQueryLayer provides pagination using query layer pattern
202+ // This function separates the database logic from the handler
203+ func PaginatedQueryWithQueryLayer [T any ](
204+ filter IncludableQueryBuilder ,
205+ queryFunc func (IncludableQueryBuilder ) ([]T , int64 , error ),
206+ ) ([]T , int64 , error ) {
207+ // Validate includes before processing
208+ if validator , ok := filter .(interface { Validate () }); ok {
209+ validator .Validate ()
210+ }
211+
212+ // Execute query through query layer
213+ return queryFunc (filter )
214+ }
215+
216+ // PaginatedAPIResponseWithQueryLayer creates a complete API response using query layer pattern
217+ func PaginatedAPIResponseWithQueryLayer [T any ](
218+ ctx * gin.Context ,
219+ filter IncludableQueryBuilder ,
220+ message string ,
221+ queryFunc func (IncludableQueryBuilder ) ([]T , int64 , error ),
222+ ) PaginatedResponse {
223+ // Bind pagination from context
224+ if baseFilter , ok := filter .(interface { BindPagination (* gin.Context ) }); ok {
225+ baseFilter .BindPagination (ctx )
226+ }
227+
228+ // Bind custom filter parameters
229+ if err := ctx .ShouldBindQuery (filter ); err != nil {
230+ return NewPaginatedResponse (400 , "Invalid query parameters: " + err .Error (), nil , PaginationResponse {})
231+ }
232+
233+ // Execute query through query layer
234+ data , total , err := PaginatedQueryWithQueryLayer (filter , queryFunc )
235+ if err != nil {
236+ return NewPaginatedResponse (500 , "Internal Server Error: " + err .Error (), nil , PaginationResponse {})
237+ }
238+
239+ paginationResponse := CalculatePagination (filter .GetPagination (), total )
240+ return NewPaginatedResponse (200 , message , data , paginationResponse )
241+ }
242+
243+ // BindAndValidateFilter binds pagination and query parameters, then validates the filter
244+ func BindAndValidateFilter (ctx * gin.Context , filter IncludableQueryBuilder ) error {
245+ // Bind pagination from context
246+ if baseFilter , ok := filter .(interface { BindPagination (* gin.Context ) }); ok {
247+ baseFilter .BindPagination (ctx )
248+ }
249+
250+ // Bind custom filter parameters
251+ if err := ctx .ShouldBindQuery (filter ); err != nil {
252+ return err
253+ }
254+
255+ // Validate includes
256+ if validator , ok := filter .(interface { Validate () }); ok {
257+ validator .Validate ()
258+ }
259+
260+ return nil
261+ }
0 commit comments