using Microsoft.AspNetCore.WebUtilities; using System.Reflection; namespace SharedKernel.Helpers { public class Pagination { public int Page { get; set; } = 1; // 현재 페이지 public int TotalRows { get; set; } = 0; // 전체 항목 수 public int TotalPage { get; set; } = 0; // 전체 페이지 수 public int PerPage = 10; public int StartPage = 0; // 현재 페이지의 시작 번호 public int EndPage = 0; // 현재 페이지의 마지막 번호 public int PageGroupSize = 10; // 한번에 보여줄 페이지 번호 개수 public int CurrentPageGroup = 0; // 현재 페이지가 속한 페이지 그룹의 시작번호 public int GroupStartPage = 0; // 페이지 그룹의 시작 페이지 번호 public int GroupEndPage = 0; // 페이지 그룹의 마지막 페이지 번호 public int PrevGroupPage = 0; // 이전 페이지 그룹의 페이지 번호 public int NextGroupPage = 0; // 다음 페이지 그룹 페이지 번호 private Dictionary QueryStringParams; public Pagination(long totalRows, int page, int perPage, object? queryParams) : this((int)totalRows, page, perPage, queryParams) { } public Pagination(int totalRows, int page, int perPage, object? queryParams = null) { Page = page; PerPage = perPage; TotalRows = Math.Max(totalRows, 0); TotalPage = (int)Math.Ceiling((double)TotalRows / perPage); CurrentPageGroup = (Page - 1) / PageGroupSize + 1; StartPage = (CurrentPageGroup - 1) * PageGroupSize + 1; EndPage = Math.Min(StartPage + PageGroupSize - 1, TotalPage); GroupStartPage = StartPage; GroupEndPage = EndPage; PrevGroupPage = Math.Max(StartPage - PageGroupSize, 1); // 이전 페이지 그룹의 첫 페이지 계산 NextGroupPage = Math.Min(EndPage + 1, TotalPage); // 다음 페이지 그룹의 첫 페이지 계산 // 객체를 쿼리스트링으로 변환 QueryStringParams = ToDictionary(queryParams); } // 이전 페이지 여부 public bool HasPreviousPage => Page > 1; // 다음 페이지 여부 public bool HasNextPage => Page < TotalPage; // 객체를 Dictionary로 변환하는 메서드 private static Dictionary ToDictionary(object? obj) { var dictionary = new Dictionary(); if (obj is null) { return dictionary; } // 문자열이면 직접 분리 if (obj is string str) { var parsed = QueryHelpers.ParseQuery(str); foreach (var row in parsed) { dictionary[row.Key] = row.Value.ToString(); } return dictionary; } // 일반 객체는 reflection을 사용하여 속성들을 가져옴 var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { var value = prop.GetValue(obj)?.ToString(); if (!string.IsNullOrEmpty(value)) { dictionary[prop.Name] = value; } } return dictionary; } // 최종 쿼리스트링을 반환하는 메서드 public string BuildQueryString() { if (QueryStringParams == null || QueryStringParams.Count == 0) { return ""; } var queryString = QueryHelpers.AddQueryString("", QueryStringParams); // ?key=value&key2=value2 if (string.IsNullOrEmpty(queryString)) { return ""; } return "&" + queryString.TrimStart('?'); } } }