Add paginate

This commit is contained in:
gabatxo1312 2026-01-28 23:26:37 +01:00
parent e0ef3229ab
commit 46c9b89ccc
No known key found for this signature in database
3 changed files with 68 additions and 4 deletions

View File

@ -51,6 +51,13 @@ pub struct BookOperator {
pub state: AppState, pub state: AppState,
} }
#[derive(Debug, Clone)]
pub struct BooksPaginate {
pub books: Vec<Model>,
pub current_page: u64,
pub total_page: u64,
}
impl BookOperator { impl BookOperator {
pub fn new(state: AppState) -> Self { pub fn new(state: AppState) -> Self {
Self { state } Self { state }
@ -64,6 +71,24 @@ impl BookOperator {
.context(DBSnafu) .context(DBSnafu)
} }
pub async fn list_paginate(&self, page: u64) -> Result<BooksPaginate, BookError> {
let page = if page > 0 { page - 1 } else { 0 };
let book_pages = Entity::find()
.order_by_desc(Column::Id)
.paginate(&self.state.db, 1);
let books = book_pages.fetch_page(page).await.context(DBSnafu)?;
let current_page = book_pages.cur_page();
let total_page = book_pages.num_pages().await.context(DBSnafu)?;
Ok(BooksPaginate {
books,
current_page,
total_page,
})
}
pub async fn find_by_id(&self, id: i32) -> Result<Model, BookError> { pub async fn find_by_id(&self, id: i32) -> Result<Model, BookError> {
let book_by_id = Entity::find_by_id(id) let book_by_id = Entity::find_by_id(id)
.one(&self.state.db) .one(&self.state.db)

View File

@ -4,7 +4,7 @@ use askama::Template;
use askama_web::WebTemplate; use askama_web::WebTemplate;
use axum::{ use axum::{
Form, Form,
extract::{Path, State}, extract::{Path, Query, State},
response::{IntoResponse, Redirect}, response::{IntoResponse, Redirect},
}; };
use serde::Deserialize; use serde::Deserialize;
@ -26,6 +26,8 @@ use crate::{
#[template(path = "index.html")] #[template(path = "index.html")]
struct BookIndexTemplate { struct BookIndexTemplate {
books_with_user: Vec<BookWithUser>, books_with_user: Vec<BookWithUser>,
current_page: u64,
total_page: u64,
} }
// Book list with the owner and the current holder inside // Book list with the owner and the current holder inside
@ -35,21 +37,36 @@ struct BookWithUser {
pub current_holder: Option<UserModel>, pub current_holder: Option<UserModel>,
} }
#[derive(Deserialize)]
pub struct Pagination {
pub page: Option<usize>,
}
pub async fn index( pub async fn index(
State(state): State<AppState>, State(state): State<AppState>,
Query(pagination): Query<Pagination>,
) -> Result<impl axum::response::IntoResponse, AppStateError> { ) -> Result<impl axum::response::IntoResponse, AppStateError> {
let page: u64 = if let Some(page) = pagination.page {
page.try_into().unwrap()
} else {
1
};
let users = UserOperator::new(state.clone()) let users = UserOperator::new(state.clone())
.list() .list()
.await .await
.context(UserSnafu)?; .context(UserSnafu)?;
let books = BookOperator::new(state).list().await.context(BookSnafu)?; let books_paginate = BookOperator::new(state)
.list_paginate(page)
.await
.context(BookSnafu)?;
let user_by_id: HashMap<i32, UserModel> = let user_by_id: HashMap<i32, UserModel> =
users.into_iter().map(|user| (user.id, user)).collect(); users.into_iter().map(|user| (user.id, user)).collect();
let mut result: Vec<BookWithUser> = Vec::with_capacity(books.len()); let mut result: Vec<BookWithUser> = Vec::with_capacity(books_paginate.books.len());
for book in books { for book in books_paginate.books {
let owner = user_by_id.get(&book.owner_id).cloned().unwrap(); let owner = user_by_id.get(&book.owner_id).cloned().unwrap();
let current_holder = if let Some(current_holder_id) = book.current_holder_id { let current_holder = if let Some(current_holder_id) = book.current_holder_id {
user_by_id.get(&current_holder_id).cloned() user_by_id.get(&current_holder_id).cloned()
@ -66,6 +83,8 @@ pub async fn index(
Ok(BookIndexTemplate { Ok(BookIndexTemplate {
books_with_user: result, books_with_user: result,
current_page: books_paginate.current_page,
total_page: books_paginate.total_page,
}) })
} }

View File

@ -40,5 +40,25 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<nav aria-label="Page navigation">
<ul class="pagination">
<li class="page-item {% if current_page == 1 %}disabled{% endif %}">
<a class="page-link" href="/?page={{ current_page - 1 }}">Prev</a>
</li>
{% for page in (current_page - 1)..(current_page + 1) %}
{% if page >= 1 && page <= total_page %}
<li class="page-item {% if page == current_page %}active{% endif %}">
<a class="page-link" href="/?page={{ page }}">{{ page }}</a>
</li>
{% endif %}
{% endfor %}
<li class="page-item {% if current_page == total_page %}disabled{% endif %}">
<a class="page-link" href="/?page={{ current_page + 1 }}">Next</a>
</li>
</ul>
</nav>
{% endcall %} {% endcall %}
{% endblock %} {% endblock %}