use arcature_db::Db;
use arcature_db::sea_orm;
use arcature_db::sea_orm::PaginatorTrait;
use crate::error::{DataError, PaginationError};
#[derive(Debug, Clone)]
pub struct Page<T> {
pub rows: Vec<T>,
pub page: u64,
pub per_page: u64,
pub total: u64,
pub num_pages: u64,
}
impl<T> Page<T> {
#[must_use]
pub fn is_empty(&self) -> bool {
self.rows.is_empty()
}
}
pub struct Paginated<'db, E>
where
E: sea_orm::EntityTrait,
{
db: &'db Db,
select: sea_orm::Select<E>,
per_page: u64,
page: u64,
}
impl<'db, E> Paginated<'db, E>
where
E: sea_orm::EntityTrait,
{
pub(crate) fn new(db: &'db Db, select: sea_orm::Select<E>, per_page: u64) -> Self {
Self {
db,
select,
per_page,
page: 1,
}
}
#[must_use]
pub fn page(mut self, page: u64) -> Self {
self.page = page;
self
}
pub async fn fetch(self) -> Result<Page<E::Model>, DataError>
where
E::Model: sea_orm::FromQueryResult + Send + Sync,
{
if self.per_page == 0 {
return Err(PaginationError::PerPageMustBePositive.into());
}
if self.page == 0 {
return Err(PaginationError::PageMustBePositive.into());
}
let paginator = self.select.paginate(self.db.orm(), self.per_page);
let total = paginator.num_items().await.map_err(DataError::from)?;
let num_pages = total.div_ceil(self.per_page);
let rows = paginator
.fetch_page(self.page - 1)
.await
.map_err(DataError::from)?;
Ok(Page {
rows,
page: self.page,
per_page: self.per_page,
total,
num_pages,
})
}
}