diff --git a/src/models/book.rs b/src/models/book.rs index e8a5898..f52ce8c 100644 --- a/src/models/book.rs +++ b/src/models/book.rs @@ -70,7 +70,7 @@ impl BookOperator { /// Lists all books matching the optional query filters. /// /// Results are ordered by ID in descending order (newest first). - pub async fn list(&self) -> Result, BookError> { + pub async fn all(&self) -> Result, BookError> { Entity::find() .order_by_desc(Column::Id) .all(&self.state.db) diff --git a/src/models/user.rs b/src/models/user.rs index bdf2624..0ce96eb 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,9 +1,11 @@ use crate::models::book; use crate::routes::book::BookForm; +use crate::routes::user::IndexQuery; use crate::routes::user::UserForm; use crate::state::AppState; use crate::state::error::UserSnafu; use sea_orm::ActiveValue::Set; +use sea_orm::Condition; use sea_orm::DeleteResult; use sea_orm::entity::prelude::*; use snafu::ResultExt; @@ -53,10 +55,23 @@ impl UserOperator { Self { state } } - pub async fn list(&self) -> Result, UserError> { + pub async fn all(&self) -> Result, UserError> { Entity::find().all(&self.state.db).await.context(DBSnafu) } + pub async fn all_filtered(&self, query: IndexQuery) -> Result, UserError> { + let mut conditions = Condition::all(); + if let Some(name) = query.name { + conditions = conditions.add(Column::Name.contains(name)) + } + + Entity::find() + .filter(conditions) + .all(&self.state.db) + .await + .context(DBSnafu) + } + pub async fn find_by_id(&self, id: i32) -> Result { let user: Option = Entity::find_by_id(id) .one(&self.state.db) diff --git a/src/routes/book.rs b/src/routes/book.rs index 26545fb..faaaac4 100644 --- a/src/routes/book.rs +++ b/src/routes/book.rs @@ -66,7 +66,7 @@ pub async fn index( // Get all Users let users = UserOperator::new(state.clone()) - .list() + .all() .await .context(UserSnafu)?; @@ -203,7 +203,7 @@ struct NewBookTemplate { pub async fn new( State(state): State, ) -> Result { - let users = UserOperator::new(state).list().await.context(UserSnafu)?; + let users = UserOperator::new(state).all().await.context(UserSnafu)?; Ok(NewBookTemplate { users }) } @@ -220,7 +220,7 @@ pub async fn edit( Path(id): Path, ) -> Result { let users = UserOperator::new(state.clone()) - .list() + .all() .await .context(UserSnafu)?; let book = BookOperator::new(state) diff --git a/src/routes/user.rs b/src/routes/user.rs index b245d42..3c81570 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -4,10 +4,11 @@ use askama::Template; use askama_web::WebTemplate; use axum::{ Form, - extract::{Path, State}, + extract::{Path, Query, State}, response::Redirect, }; use serde::Deserialize; +use serde_with::{NoneAsEmptyString, serde_as}; use snafu::prelude::*; use crate::{ @@ -25,6 +26,7 @@ use crate::{ #[template(path = "users/index.html")] struct UsersIndexTemplate { user_with_books_number: Vec, + query: IndexQuery, } pub struct UserWithBookNumber { @@ -36,16 +38,25 @@ pub struct UserWithBookNumber { pub borrowed_book_number: usize, } +#[serde_as] +#[derive(Deserialize, Clone)] +pub struct IndexQuery { + #[serde(default)] + #[serde_as(as = "NoneAsEmptyString")] + pub name: Option, +} + pub async fn index( State(state): State, + Query(query): Query, ) -> Result { let users = UserOperator::new(state.clone()) - .list() + .all_filtered(query.clone()) .await .context(UserSnafu)?; let books = BookOperator::new(state.clone()) - .list() + .all() .await .context(BookSnafu)?; @@ -74,6 +85,7 @@ pub async fn index( Ok(UsersIndexTemplate { user_with_books_number: result, + query, }) } diff --git a/templates/users/index.html b/templates/users/index.html index 04aedae..0f4d131 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -9,6 +9,30 @@ Add User {% endcall %} + {% call cards::card() %} +
+
+
+ + {% match query.name %} + {% when Some with (value) %} + + {% when None %} + + {% endmatch %} +
+ +
+ +
+ +
+ Reset +
+
+
+ {% endcall %} + {% call cards::card() %}