Navigate to recipe view from plan page

This commit is contained in:
Jeremy Wall 2022-07-21 16:33:55 -04:00
parent 35f48298dd
commit 71a4e093b9
5 changed files with 44 additions and 15 deletions

View File

@ -49,13 +49,16 @@ fn steps(steps: ReadSignal<Vec<recipes::Step>>) -> View<G> {
#[component(Recipe<G>)]
pub fn recipe(idx: ReadSignal<usize>) -> View<G> {
let app_service = use_context::<AppService>();
let recipe = app_service.get_recipes().get()[*idx.get()].1.clone();
let view = Signal::new(View::empty());
create_effect(cloned!((app_service, view) => move || {
if let Some((_, recipe)) = app_service.get_recipes().get().get(*idx.get()) {
let recipe = recipe.clone();
let title = create_memo(cloned!((recipe) => move || recipe.get().title.clone()));
let desc = create_memo(
cloned!((recipe) => move || recipe.clone().get().desc.clone().unwrap_or_else(|| String::new())),
);
let steps = create_memo(cloned!((recipe) => move || recipe.get().steps.clone()));
view! {
view.set(view! {
div(class="recipe") {
h1(class="recipe_title") { (title.get()) }
div(class="recipe_description") {
@ -63,5 +66,10 @@ pub fn recipe(idx: ReadSignal<usize>) -> View<G> {
}
Steps(steps)
}
});
}
}));
view! {
(view.get().as_ref())
}
}

View File

@ -38,7 +38,7 @@ pub fn recipe_selection(props: RecipeCheckBoxProps) -> View<G> {
let count = Signal::new(format!("{}", app_service.get_recipe_count_by_index(i)));
view! {
div() {
label(for=id_cloned_2) { (props.title.get()) }
label(for=id_cloned_2) { a(href=format!("#recipe/{}", i)) { (props.title.get()) } }
input(type="number", class="item-count-sel", min="0", bind:value=count.clone(), name=format!("recipe_id:{}", i), value=id_as_str.clone(), on:change=move |_| {
let mut app_service = app_service.clone();
debug!(idx=%i, count=%(*count.get()), "setting recipe count");

View File

@ -14,11 +14,14 @@
use crate::components::{recipe::Recipe, tabs::*};
use sycamore::prelude::*;
use tracing::instrument;
#[derive(Debug)]
pub struct RecipePageProps {
pub recipe: Signal<usize>,
}
#[instrument]
#[component(RecipePage<G>)]
pub fn recipe_page(props: RecipePageProps) -> View<G> {
view! {

View File

@ -37,6 +37,16 @@ impl BrowserIntegration {
)))
}
#[instrument(skip(self, f))]
pub fn register_post_state_handler(&self, f: Box<dyn FnMut()>) {
let closure = Closure::wrap(f);
web_sys::window()
.unwrap_throw()
.add_event_listener_with_callback("popstate", closure.as_ref().unchecked_ref())
.unwrap_throw();
closure.forget();
}
#[instrument(skip(self))]
pub fn click_handler(&self) -> Box<dyn Fn(web_sys::Event)> {
let route_signal = self.0.clone();
@ -130,6 +140,12 @@ where
}),
);
let path_signal = integration.0.clone();
integration.register_post_state_handler(Box::new(cloned!((path_signal) => move || {
let location = web_sys::window().unwrap_throw().location();
path_signal.set((location.origin().unwrap_throw(), location.pathname().unwrap_throw(), location.hash().unwrap_throw()));
})));
// NOTE(jwall): This needs to be a dynamic node so Sycamore knows to rerender it
// based on the results of the effect above.
view! {

View File

@ -13,7 +13,7 @@
// limitations under the License.
use crate::pages::*;
use crate::{app_state::*, components::*, router_integration::*, service::AppService};
use tracing::{error, info, instrument};
use tracing::{debug, error, info, instrument};
use sycamore::{
context::{ContextProvider, ContextProviderProps},
@ -21,6 +21,7 @@ use sycamore::{
prelude::*,
};
#[instrument]
fn route_switch<G: Html>(route: ReadSignal<AppRoutes>) -> View<G> {
// NOTE(jwall): This needs to not be a dynamic node. The rules around
// this are somewhat unclear and underdocumented for Sycamore. But basically
@ -66,6 +67,7 @@ pub fn ui() -> View<G> {
spawn_local_in_scope({
let mut app_service = app_service.clone();
async move {
debug!("fetching recipes");
match AppService::fetch_recipes_from_storage() {
Ok((_, Some(recipes))) => {
app_service.set_recipes(recipes);