User filtered

This commit is contained in:
gabatxo1312 2026-01-30 14:24:00 +01:00
parent 3b9a5800a5
commit a4c5e8185b
No known key found for this signature in database
5 changed files with 59 additions and 8 deletions

View File

@ -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<Vec<Model>, BookError> {
pub async fn all(&self) -> Result<Vec<Model>, BookError> {
Entity::find()
.order_by_desc(Column::Id)
.all(&self.state.db)

View File

@ -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<Vec<Model>, UserError> {
pub async fn all(&self) -> Result<Vec<Model>, UserError> {
Entity::find().all(&self.state.db).await.context(DBSnafu)
}
pub async fn all_filtered(&self, query: IndexQuery) -> Result<Vec<Model>, 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<Model, UserError> {
let user: Option<Model> = Entity::find_by_id(id)
.one(&self.state.db)

View File

@ -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<AppState>,
) -> Result<impl axum::response::IntoResponse, AppStateError> {
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<i32>,
) -> Result<impl axum::response::IntoResponse, AppStateError> {
let users = UserOperator::new(state.clone())
.list()
.all()
.await
.context(UserSnafu)?;
let book = BookOperator::new(state)

View File

@ -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<UserWithBookNumber>,
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<String>,
}
pub async fn index(
State(state): State<AppState>,
Query(query): Query<IndexQuery>,
) -> Result<impl axum::response::IntoResponse, AppStateError> {
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,
})
}

View File

@ -9,6 +9,30 @@
<a class="btn-success btn" href="/users/new">Add User</a>
{% endcall %}
{% call cards::card() %}
<form method="get">
<div class="row">
<div class="col-md-3">
<label for="name" class="form-label">Name</label>
{% match query.name %}
{% when Some with (value) %}
<input type="text" name="name" value="{{ value }}" class="form-control" placeholder="Ex: Koprotkine">
{% when None %}
<input type="text" name="name" class="form-control" placeholder="Ex: Koprotkine">
{% endmatch %}
</div>
<div class="col-md-1 d-flex align-items-end">
<input type="submit" value="Search" class="btn btn-info w-100">
</div>
<div class="col-md-1 d-flex align-items-end">
<a href="/users" class="btn btn-light">Reset</a>
</div>
</div>
</form>
{% endcall %}
{% call cards::card() %}
<table class="table table-hover">
<thead>