add ready ui

This commit is contained in:
2023-08-29 21:34:00 +02:00
parent 199e4abc97
commit ce7c67d599
2 changed files with 224 additions and 14 deletions

View File

@@ -210,6 +210,14 @@ async fn main() -> Result<(), StartError> {
"/:id/packagelist/item/:id/unpack", "/:id/packagelist/item/:id/unpack",
post(trip_item_packagelist_set_unpack_htmx), post(trip_item_packagelist_set_unpack_htmx),
) )
.route(
"/:id/packagelist/item/:id/ready",
post(trip_item_packagelist_set_ready_htmx),
)
.route(
"/:id/packagelist/item/:id/unready",
post(trip_item_packagelist_set_unready_htmx),
)
.route("/:id/state/:id", post(trip_state_set)) .route("/:id/state/:id", post(trip_state_set))
.route("/:id/total_weight", get(trip_total_weight_htmx)) .route("/:id/total_weight", get(trip_total_weight_htmx))
.route("/:id/type/:id/add", get(trip_type_add)) .route("/:id/type/:id/add", get(trip_type_add))
@@ -1194,7 +1202,7 @@ async fn trip_item_packagelist_set_pack_htmx(
message: format!("an item with id {item_id} does not exist"), message: format!("an item with id {item_id} does not exist"),
}))?; }))?;
Ok(view::trip::packagelist::TripPackageListRow::build( Ok(view::trip::packagelist::TripPackageListRowReady::build(
trip_id, &item, trip_id, &item,
)) ))
} }
@@ -1220,7 +1228,57 @@ async fn trip_item_packagelist_set_unpack_htmx(
message: format!("an item with id {item_id} does not exist"), message: format!("an item with id {item_id} does not exist"),
}))?; }))?;
Ok(view::trip::packagelist::TripPackageListRow::build( Ok(view::trip::packagelist::TripPackageListRowReady::build(
trip_id, &item,
))
}
async fn trip_item_packagelist_set_ready_htmx(
State(state): State<AppState>,
Path((trip_id, item_id)): Path<(Uuid, Uuid)>,
) -> Result<impl IntoResponse, Error> {
trip_item_set_state(
&state,
trip_id,
item_id,
models::trips::TripItemStateKey::Ready,
true,
)
.await?;
let item = models::trips::TripItem::find(&state.database_pool, trip_id, item_id)
.await?
.ok_or(Error::Request(RequestError::NotFound {
message: format!("an item with id {item_id} does not exist"),
}))?;
Ok(view::trip::packagelist::TripPackageListRowUnready::build(
trip_id, &item,
))
}
async fn trip_item_packagelist_set_unready_htmx(
State(state): State<AppState>,
Path((trip_id, item_id)): Path<(Uuid, Uuid)>,
) -> Result<impl IntoResponse, Error> {
trip_item_set_state(
&state,
trip_id,
item_id,
models::trips::TripItemStateKey::Ready,
false,
)
.await?;
// note that this cannot fail due to a missing item, as trip_item_set_state would already
// return 404. but error handling cannot hurt ;)
let item = models::trips::TripItem::find(&state.database_pool, trip_id, item_id)
.await?
.ok_or(Error::Request(RequestError::NotFound {
message: format!("an item with id {item_id} does not exist"),
}))?;
Ok(view::trip::packagelist::TripPackageListRowUnready::build(
trip_id, &item, trip_id, &item,
)) ))
} }

View File

@@ -3,9 +3,9 @@ use uuid::Uuid;
use crate::models; use crate::models;
pub struct TripPackageListRow; pub struct TripPackageListRowReady;
impl TripPackageListRow { impl TripPackageListRowReady {
pub fn build(trip_id: Uuid, item: &models::trips::TripItem) -> Markup { pub fn build(trip_id: Uuid, item: &models::trips::TripItem) -> Markup {
html!( html!(
li li
@@ -79,9 +79,85 @@ impl TripPackageListRow {
} }
} }
pub struct TripPackageListCategoryBlock; pub struct TripPackageListRowUnready;
impl TripPackageListCategoryBlock { impl TripPackageListRowUnready {
pub fn build(trip_id: Uuid, item: &models::trips::TripItem) -> Markup {
html!(
li
."flex"
."flex-row"
."justify-between"
."items-stretch"
."bg-green-50"[item.ready]
."bg-red-50"[!item.ready]
."hover:bg-white"[!item.ready]
."h-full"
{
span
."p-2"
{
(item.item.name)
}
@if item.ready {
a
href={
"/trips/" (trip_id)
"/items/" (item.item.id)
"/unready"
}
hx-post={
"/trips/" (trip_id)
"/packagelist/item/"
(item.item.id) "/unready"
}
hx-target="closest li"
hx-swap="outerHTML"
."flex"
."flex-row"
."aspect-square"
{
span
."mdi"
."m-auto"
."text-xl"
."mdi-check"
{}
}
} @else {
a
href={
"/trips/" (trip_id)
"/items/" (item.item.id)
"/ready"
}
hx-post={
"/trips/" (trip_id)
"/packagelist/item/"
(item.item.id) "/ready"
}
hx-target="closest li"
hx-swap="outerHTML"
."flex"
."flex-row"
."aspect-square"
{
span
."mdi"
."m-auto"
."text-xl"
."mdi-checkbox-blank-outline"
{}
}
}
}
)
}
}
pub struct TripPackageListCategoryBlockReady;
impl TripPackageListCategoryBlockReady {
pub fn build(trip: &models::trips::Trip, category: &models::trips::TripCategory) -> Markup { pub fn build(trip: &models::trips::Trip, category: &models::trips::TripCategory) -> Markup {
let empty = !category let empty = !category
.items .items
@@ -125,8 +201,8 @@ impl TripPackageListCategoryBlock {
."flex" ."flex"
."flex-col" ."flex-col"
{ {
@for item in category.items.as_ref().unwrap() { @for item in category.items.as_ref().unwrap().iter().filter(|item| item.picked) {
(TripPackageListRow::build(trip.id, item)) (TripPackageListRowReady::build(trip.id, item))
} }
} }
} }
@@ -135,6 +211,61 @@ impl TripPackageListCategoryBlock {
} }
} }
pub struct TripPackageListCategoryBlockUnready;
impl TripPackageListCategoryBlockUnready {
pub fn build(trip: &models::trips::Trip, category: &models::trips::TripCategory) -> Markup {
let empty = !category
.items
.as_ref()
.unwrap()
.iter()
.any(|item| item.picked);
html!(
div
."inline-block"
."w-full"
."mb-5"
."border"
."border-2"
."border-gray-300"
."opacity-30"[empty]
{
div
."bg-gray-100"
."border-b-2"
."border-gray-300"
."p-3"
{
h3 { (category.category.name) }
}
@if empty {
div
."flex"
."p-1"
{
span
."text-sm"
."m-auto"
{
"no items picked"
}
}
} @else {
ul
."flex"
."flex-col"
{
@for item in category.items.as_ref().unwrap().iter().filter(|item| item.picked) {
(TripPackageListRowUnready::build(trip.id, item))
}
}
}
}
)
}
}
pub struct TripPackageList; pub struct TripPackageList;
impl TripPackageList { impl TripPackageList {
@@ -147,6 +278,14 @@ impl TripPackageList {
// .iter() // .iter()
// .all(|item| !item.picked || item.packed) // .all(|item| !item.picked || item.packed)
// }); // });
let has_unready_items: bool = trip.categories.as_ref().unwrap().iter().any(|category| {
category
.items
.as_ref()
.unwrap()
.iter()
.any(|item| item.picked && !item.ready)
});
html!( html!(
div div
."p-8" ."p-8"
@@ -183,12 +322,25 @@ impl TripPackageList {
"Finish packing" "Finish packing"
} }
} }
div @if has_unready_items {
."columns-3" p { "There are items that are not yet ready, get them!"}
."gap-5" div
{ ."columns-3"
@for category in trip.categories() { ."gap-5"
(TripPackageListCategoryBlock::build(trip, category)) {
@for category in trip.categories() {
(TripPackageListCategoryBlockUnready::build(trip, category))
}
}
} @else {
p { "All items are ready, pack the following things:" }
div
."columns-3"
."gap-5"
{
@for category in trip.categories() {
(TripPackageListCategoryBlockReady::build(trip, category))
}
} }
} }
} }