85 lines
2.8 KiB
Rust
85 lines
2.8 KiB
Rust
|
|
use uuid::Uuid;
|
||
|
|
use yew::{prelude::*, suspense::use_future};
|
||
|
|
use yew_router::prelude::*;
|
||
|
|
|
||
|
|
use crate::{api, RegaladeGlobalState, Route};
|
||
|
|
|
||
|
|
async fn get_all_recipes(
|
||
|
|
token: String,
|
||
|
|
household: Uuid,
|
||
|
|
) -> anyhow::Result<api::ListRecipesResponse> {
|
||
|
|
let rsp = gloo_net::http::Request::get(api!("household/{household}/recipe"))
|
||
|
|
.header("Authorization", &format!("Bearer {token}"))
|
||
|
|
.send()
|
||
|
|
.await?;
|
||
|
|
|
||
|
|
if !rsp.ok() {
|
||
|
|
let body = rsp.text().await.unwrap_or_default();
|
||
|
|
anyhow::bail!("Could not get recipes (code={}): {body}", rsp.status());
|
||
|
|
}
|
||
|
|
|
||
|
|
Ok(rsp.json().await?)
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Debug, Clone, PartialEq, Eq, Properties)]
|
||
|
|
struct RecipeListProps {
|
||
|
|
token: String,
|
||
|
|
household: Uuid,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[function_component]
|
||
|
|
fn RecipeListInner(props: &RecipeListProps) -> HtmlResult {
|
||
|
|
let state = use_future(|| get_all_recipes(props.token.clone(), props.household))?;
|
||
|
|
|
||
|
|
Ok(match &*state {
|
||
|
|
Ok(l) => html! {
|
||
|
|
<div class="container text-center">
|
||
|
|
<div class="row row-cols-2 row-cols-sm-2 row-cols-md-4 g-2 mb-1">
|
||
|
|
{for l.recipes.iter().map(|(id, name)| html!{
|
||
|
|
<div class="col" key={*id}>
|
||
|
|
<div class="p-3 border rounded border-light-subtle h-100">
|
||
|
|
<Link<Route>
|
||
|
|
classes={classes!(
|
||
|
|
"link-light",
|
||
|
|
"link-offset-2",
|
||
|
|
"link-underline-opacity-25",
|
||
|
|
"link-underline-opacity-100-hover",
|
||
|
|
)}
|
||
|
|
to={Route::Recipe { id: *id }}
|
||
|
|
>
|
||
|
|
{name}
|
||
|
|
</Link<Route>>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
},
|
||
|
|
Err(e) => html! {
|
||
|
|
<div class={classes!("alert", "alert-danger")} role="alert">
|
||
|
|
{format!("Error fetching recipes: {e}")}
|
||
|
|
</div>
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
#[function_component]
|
||
|
|
pub fn RecipeList() -> Html {
|
||
|
|
let fallback = html! {"Loading ..."};
|
||
|
|
let global_state = use_state(RegaladeGlobalState::get);
|
||
|
|
|
||
|
|
html! {
|
||
|
|
<div class="d-flex align-items-center justify-content-center w-100">
|
||
|
|
<div class={classes!("container", "text-center", "rounded", "border", "pt-2", "m-2")}>
|
||
|
|
<h2>{"Recipes"}</h2>
|
||
|
|
<Suspense {fallback}>
|
||
|
|
<RecipeListInner
|
||
|
|
token={global_state.token.token.clone()}
|
||
|
|
household={global_state.household.id}
|
||
|
|
/>
|
||
|
|
</Suspense>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
}
|