chore: slight simplifications to bags
This commit is contained in:
parent
ec8dbea7ea
commit
7eab263071
4 changed files with 50 additions and 84 deletions
|
|
@ -22,16 +22,19 @@ use crate::presentation::web::views::{BagView, ListNavigator, Paginated, Roaster
|
||||||
const BAG_PAGE_PATH: &str = "/bags";
|
const BAG_PAGE_PATH: &str = "/bags";
|
||||||
const BAG_FRAGMENT_PATH: &str = "/bags#bag-list";
|
const BAG_FRAGMENT_PATH: &str = "/bags#bag-list";
|
||||||
|
|
||||||
|
struct BagPageData {
|
||||||
|
open_bags: Vec<BagView>,
|
||||||
|
bags: Paginated<BagView>,
|
||||||
|
navigator: ListNavigator<BagSortKey>,
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(state))]
|
#[tracing::instrument(skip(state))]
|
||||||
async fn load_bag_page(
|
async fn load_bag_page(
|
||||||
state: &AppState,
|
state: &AppState,
|
||||||
request: ListRequest<BagSortKey>,
|
request: ListRequest<BagSortKey>,
|
||||||
) -> Result<(Vec<BagView>, Paginated<BagView>, ListNavigator<BagSortKey>), AppError> {
|
) -> Result<BagPageData, AppError> {
|
||||||
let open_bags = state.bag_repo.list_open().await.map_err(AppError::from)?;
|
let open_bags = state.bag_repo.list_open().await.map_err(AppError::from)?;
|
||||||
let open_bags_view = open_bags
|
let open_bags_view = open_bags.into_iter().map(BagView::from_domain).collect();
|
||||||
.into_iter()
|
|
||||||
.map(BagView::from_with_roast)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let page = state
|
let page = state
|
||||||
.bag_repo
|
.bag_repo
|
||||||
|
|
@ -42,12 +45,16 @@ async fn load_bag_page(
|
||||||
let (bags, navigator) = crate::application::routes::support::build_page_view(
|
let (bags, navigator) = crate::application::routes::support::build_page_view(
|
||||||
page,
|
page,
|
||||||
request,
|
request,
|
||||||
BagView::from_with_roast,
|
BagView::from_domain,
|
||||||
BAG_PAGE_PATH,
|
BAG_PAGE_PATH,
|
||||||
BAG_FRAGMENT_PATH,
|
BAG_FRAGMENT_PATH,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok((open_bags_view, bags, navigator))
|
Ok(BagPageData {
|
||||||
|
open_bags: open_bags_view,
|
||||||
|
bags,
|
||||||
|
navigator,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(state, cookies, headers, query))]
|
#[tracing::instrument(skip(state, cookies, headers, query))]
|
||||||
|
|
@ -75,7 +82,11 @@ pub(crate) async fn bags_page(
|
||||||
|
|
||||||
let roaster_options = roasters.into_iter().map(RoasterOptionView::from).collect();
|
let roaster_options = roasters.into_iter().map(RoasterOptionView::from).collect();
|
||||||
|
|
||||||
let (open_bags, bags, navigator) = load_bag_page(&state, request)
|
let BagPageData {
|
||||||
|
open_bags,
|
||||||
|
bags,
|
||||||
|
navigator,
|
||||||
|
} = load_bag_page(&state, request)
|
||||||
.await
|
.await
|
||||||
.map_err(map_app_error)?;
|
.map_err(map_app_error)?;
|
||||||
|
|
||||||
|
|
@ -352,7 +363,11 @@ async fn render_bag_list_fragment(
|
||||||
request: ListRequest<BagSortKey>,
|
request: ListRequest<BagSortKey>,
|
||||||
is_authenticated: bool,
|
is_authenticated: bool,
|
||||||
) -> Result<Response, AppError> {
|
) -> Result<Response, AppError> {
|
||||||
let (open_bags, bags, navigator) = load_bag_page(&state, request).await?;
|
let BagPageData {
|
||||||
|
open_bags,
|
||||||
|
bags,
|
||||||
|
navigator,
|
||||||
|
} = load_bag_page(&state, request).await?;
|
||||||
|
|
||||||
let template = BagListTemplate {
|
let template = BagListTemplate {
|
||||||
is_authenticated,
|
is_authenticated,
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ pub(crate) async fn roast_page(
|
||||||
|
|
||||||
let bag_views = bags
|
let bag_views = bags
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(crate::presentation::web::views::BagView::from_with_roast)
|
.map(crate::presentation::web::views::BagView::from_domain)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let is_authenticated =
|
let is_authenticated =
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,16 @@ use crate::domain::listing::{ListRequest, Page, SortDirection};
|
||||||
use crate::domain::repositories::BagRepository;
|
use crate::domain::repositories::BagRepository;
|
||||||
use crate::infrastructure::database::DatabasePool;
|
use crate::infrastructure::database::DatabasePool;
|
||||||
|
|
||||||
|
const BASE_SELECT: &str = r#"
|
||||||
|
SELECT
|
||||||
|
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
|
||||||
|
r.name as roast_name, r.slug as roast_slug,
|
||||||
|
rr.name as roaster_name, rr.slug as roaster_slug
|
||||||
|
FROM bags b
|
||||||
|
JOIN roasts r ON b.roast_id = r.id
|
||||||
|
JOIN roasters rr ON r.roaster_id = rr.id
|
||||||
|
"#;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SqlBagRepository {
|
pub struct SqlBagRepository {
|
||||||
pool: DatabasePool,
|
pool: DatabasePool,
|
||||||
|
|
@ -111,22 +121,12 @@ impl BagRepository for SqlBagRepository {
|
||||||
|
|
||||||
let order_clause = format!("{} {}", sort_column, direction);
|
let order_clause = format!("{} {}", sort_column, direction);
|
||||||
|
|
||||||
let base_query = r#"
|
|
||||||
SELECT
|
|
||||||
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
|
|
||||||
r.name as roast_name, r.slug as roast_slug,
|
|
||||||
rr.name as roaster_name, rr.slug as roaster_slug
|
|
||||||
FROM bags b
|
|
||||||
JOIN roasts r ON b.roast_id = r.id
|
|
||||||
JOIN roasters rr ON r.roaster_id = rr.id
|
|
||||||
"#;
|
|
||||||
|
|
||||||
let count_query = "SELECT COUNT(*) FROM bags";
|
let count_query = "SELECT COUNT(*) FROM bags";
|
||||||
|
|
||||||
crate::infrastructure::repositories::pagination::paginate(
|
crate::infrastructure::repositories::pagination::paginate(
|
||||||
&self.pool,
|
&self.pool,
|
||||||
request,
|
request,
|
||||||
base_query,
|
BASE_SELECT,
|
||||||
count_query,
|
count_query,
|
||||||
&order_clause,
|
&order_clause,
|
||||||
|record| Ok(Self::to_domain_with_roast(record)),
|
|record| Ok(Self::to_domain_with_roast(record)),
|
||||||
|
|
@ -135,19 +135,12 @@ impl BagRepository for SqlBagRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_by_roast(&self, roast_id: RoastId) -> Result<Vec<BagWithRoast>, RepositoryError> {
|
async fn list_by_roast(&self, roast_id: RoastId) -> Result<Vec<BagWithRoast>, RepositoryError> {
|
||||||
let query = r#"
|
let query = format!(
|
||||||
SELECT
|
"{} WHERE b.roast_id = ? ORDER BY b.roast_date DESC",
|
||||||
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
|
BASE_SELECT
|
||||||
r.name as roast_name, r.slug as roast_slug,
|
);
|
||||||
rr.name as roaster_name, rr.slug as roaster_slug
|
|
||||||
FROM bags b
|
|
||||||
JOIN roasts r ON b.roast_id = r.id
|
|
||||||
JOIN roasters rr ON r.roaster_id = rr.id
|
|
||||||
WHERE b.roast_id = ?
|
|
||||||
ORDER BY b.roast_date DESC
|
|
||||||
"#;
|
|
||||||
|
|
||||||
let records = query_as::<_, BagWithRoastRecord>(query)
|
let records = query_as::<_, BagWithRoastRecord>(&query)
|
||||||
.bind(roast_id.into_inner())
|
.bind(roast_id.into_inner())
|
||||||
.fetch_all(&self.pool)
|
.fetch_all(&self.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -226,19 +219,12 @@ impl BagRepository for SqlBagRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_open(&self) -> Result<Vec<BagWithRoast>, RepositoryError> {
|
async fn list_open(&self) -> Result<Vec<BagWithRoast>, RepositoryError> {
|
||||||
let query = r#"
|
let query = format!(
|
||||||
SELECT
|
"{} WHERE b.closed = FALSE ORDER BY b.roast_date DESC",
|
||||||
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
|
BASE_SELECT
|
||||||
r.name as roast_name, r.slug as roast_slug,
|
);
|
||||||
rr.name as roaster_name, rr.slug as roaster_slug
|
|
||||||
FROM bags b
|
|
||||||
JOIN roasts r ON b.roast_id = r.id
|
|
||||||
JOIN roasters rr ON r.roaster_id = rr.id
|
|
||||||
WHERE b.closed = FALSE
|
|
||||||
ORDER BY b.roast_date DESC
|
|
||||||
"#;
|
|
||||||
|
|
||||||
let records = query_as::<_, BagWithRoastRecord>(query)
|
let records = query_as::<_, BagWithRoastRecord>(&query)
|
||||||
.fetch_all(&self.pool)
|
.fetch_all(&self.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| RepositoryError::unexpected(err.to_string()))?;
|
.map_err(|err| RepositoryError::unexpected(err.to_string()))?;
|
||||||
|
|
@ -268,23 +254,14 @@ impl BagRepository for SqlBagRepository {
|
||||||
|
|
||||||
let order_clause = format!("{} {}", sort_column, direction);
|
let order_clause = format!("{} {}", sort_column, direction);
|
||||||
|
|
||||||
let base_query = r#"
|
let base_query = format!("{} WHERE b.closed = TRUE", BASE_SELECT);
|
||||||
SELECT
|
|
||||||
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
|
|
||||||
r.name as roast_name, r.slug as roast_slug,
|
|
||||||
rr.name as roaster_name, rr.slug as roaster_slug
|
|
||||||
FROM bags b
|
|
||||||
JOIN roasts r ON b.roast_id = r.id
|
|
||||||
JOIN roasters rr ON r.roaster_id = rr.id
|
|
||||||
WHERE b.closed = TRUE
|
|
||||||
"#;
|
|
||||||
|
|
||||||
let count_query = "SELECT COUNT(*) FROM bags WHERE closed = TRUE";
|
let count_query = "SELECT COUNT(*) FROM bags WHERE closed = TRUE";
|
||||||
|
|
||||||
crate::infrastructure::repositories::pagination::paginate(
|
crate::infrastructure::repositories::pagination::paginate(
|
||||||
&self.pool,
|
&self.pool,
|
||||||
request,
|
request,
|
||||||
base_query,
|
&base_query,
|
||||||
count_query,
|
count_query,
|
||||||
&order_clause,
|
&order_clause,
|
||||||
|record| Ok(Self::to_domain_with_roast(record)),
|
|record| Ok(Self::to_domain_with_roast(record)),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::domain::bags::{Bag, BagWithRoast};
|
use crate::domain::bags::BagWithRoast;
|
||||||
use crate::domain::listing::{DEFAULT_PAGE_SIZE, ListRequest, Page, PageSize, SortKey};
|
use crate::domain::listing::{DEFAULT_PAGE_SIZE, ListRequest, Page, PageSize, SortKey};
|
||||||
use crate::domain::roasters::Roaster;
|
use crate::domain::roasters::Roaster;
|
||||||
use crate::domain::roasts::{Roast, RoastWithRoaster};
|
use crate::domain::roasts::{Roast, RoastWithRoaster};
|
||||||
|
|
@ -537,33 +537,7 @@ pub struct BagView {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BagView {
|
impl BagView {
|
||||||
pub fn from_domain(
|
pub fn from_domain(bag: BagWithRoast) -> Self {
|
||||||
bag: Bag,
|
|
||||||
roast_name: &str,
|
|
||||||
roaster_name: &str,
|
|
||||||
roast_slug: &str,
|
|
||||||
roaster_slug: &str,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
id: bag.id.to_string(),
|
|
||||||
roast_id: bag.roast_id.to_string(),
|
|
||||||
roast_date: bag.roast_date.map(|d| d.to_string()),
|
|
||||||
amount: format!("{:.1}", bag.amount),
|
|
||||||
remaining: format!("{:.1}", bag.remaining),
|
|
||||||
closed: bag.closed,
|
|
||||||
finished_at: bag
|
|
||||||
.finished_at
|
|
||||||
.map(|d| d.to_string())
|
|
||||||
.unwrap_or_else(|| "—".to_string()),
|
|
||||||
created_at: bag.created_at.format("%Y-%m-%d").to_string(),
|
|
||||||
roast_name: roast_name.to_string(),
|
|
||||||
roaster_name: roaster_name.to_string(),
|
|
||||||
roast_slug: roast_slug.to_string(),
|
|
||||||
roaster_slug: roaster_slug.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_with_roast(bag: BagWithRoast) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
id: bag.bag.id.to_string(),
|
id: bag.bag.id.to_string(),
|
||||||
roast_id: bag.bag.roast_id.to_string(),
|
roast_id: bag.bag.roast_id.to_string(),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue