mirror of
https://github.com/zaphar/kitchen.git
synced 2025-07-22 19:40:14 -04:00
Save plans for date via api
This commit is contained in:
parent
0a68c3d51c
commit
7549decc71
@ -258,6 +258,23 @@ async fn api_all_plans(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn api_save_plan_for_date(
|
||||||
|
Extension(app_store): Extension<Arc<storage::SqliteStore>>,
|
||||||
|
session: storage::UserIdFromSession,
|
||||||
|
Path(date): Path<chrono::NaiveDate>,
|
||||||
|
Json(meal_plan): Json<Vec<(String, i32)>>,
|
||||||
|
) -> api::EmptyResponse {
|
||||||
|
use storage::{UserId, UserIdFromSession::FoundUserId};
|
||||||
|
if let FoundUserId(UserId(id)) = session {
|
||||||
|
app_store
|
||||||
|
.save_meal_plan(id.as_str(), &meal_plan, date)
|
||||||
|
.await
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
api::EmptyResponse::Unauthorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn api_save_plan(
|
async fn api_save_plan(
|
||||||
Extension(app_store): Extension<Arc<storage::SqliteStore>>,
|
Extension(app_store): Extension<Arc<storage::SqliteStore>>,
|
||||||
session: storage::UserIdFromSession,
|
session: storage::UserIdFromSession,
|
||||||
@ -484,7 +501,10 @@ fn mk_v2_routes() -> Router {
|
|||||||
// mealplan api path routes
|
// mealplan api path routes
|
||||||
.route("/plan", get(api_plan).post(api_save_plan))
|
.route("/plan", get(api_plan).post(api_save_plan))
|
||||||
.route("/plan/since/:date", get(api_plan_since))
|
.route("/plan/since/:date", get(api_plan_since))
|
||||||
.route("/plan/at/:date", get(api_plan_for_date))
|
.route(
|
||||||
|
"/plan/at/:date",
|
||||||
|
get(api_plan_for_date).post(api_save_plan_for_date),
|
||||||
|
)
|
||||||
.route("/plan/all", get(api_all_plans))
|
.route("/plan/all", get(api_all_plans))
|
||||||
.route(
|
.route(
|
||||||
"/inventory",
|
"/inventory",
|
||||||
|
@ -75,7 +75,7 @@ pub enum Message {
|
|||||||
SaveState(Option<Box<dyn FnOnce()>>),
|
SaveState(Option<Box<dyn FnOnce()>>),
|
||||||
LoadState(Option<Box<dyn FnOnce()>>),
|
LoadState(Option<Box<dyn FnOnce()>>),
|
||||||
UpdateStaples(String, Option<Box<dyn FnOnce()>>),
|
UpdateStaples(String, Option<Box<dyn FnOnce()>>),
|
||||||
SelectPlanDate(NaiveDate),
|
SelectPlanDate(NaiveDate, Option<Box<dyn FnOnce()>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Message {
|
impl Debug for Message {
|
||||||
@ -116,7 +116,7 @@ impl Debug for Message {
|
|||||||
Self::SaveState(_) => write!(f, "SaveState"),
|
Self::SaveState(_) => write!(f, "SaveState"),
|
||||||
Self::LoadState(_) => write!(f, "LoadState"),
|
Self::LoadState(_) => write!(f, "LoadState"),
|
||||||
Self::UpdateStaples(arg, _) => f.debug_tuple("UpdateStaples").field(arg).finish(),
|
Self::UpdateStaples(arg, _) => f.debug_tuple("UpdateStaples").field(arg).finish(),
|
||||||
Self::SelectPlanDate(arg) => f.debug_tuple("SelectPlanDate").field(arg).finish(),
|
Self::SelectPlanDate(arg, _) => f.debug_tuple("SelectPlanDate").field(arg).finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,7 +452,7 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Message::SelectPlanDate(date) => {
|
Message::SelectPlanDate(date, callback) => {
|
||||||
let store = self.store.clone();
|
let store = self.store.clone();
|
||||||
let local_store = self.local_store.clone();
|
let local_store = self.local_store.clone();
|
||||||
spawn_local_scoped(cx, async move {
|
spawn_local_scoped(cx, async move {
|
||||||
@ -476,6 +476,8 @@ impl MessageMapper<Message, AppState> for StateMachine {
|
|||||||
local_store.set_plan_date(&date);
|
local_store.set_plan_date(&date);
|
||||||
|
|
||||||
original.set(original_copy);
|
original.set(original_copy);
|
||||||
|
|
||||||
|
callback.map(|f| f());
|
||||||
});
|
});
|
||||||
// NOTE(jwall): Because we do our signal set above in the async block
|
// NOTE(jwall): Because we do our signal set above in the async block
|
||||||
// we have to return here to avoid lifetime issues and double setting
|
// we have to return here to avoid lifetime issues and double setting
|
||||||
|
@ -26,7 +26,7 @@ pub fn Header<'ctx, G: Html>(cx: Scope<'ctx>, h: StateHandler<'ctx>) -> View<G>
|
|||||||
nav(class="no-print") {
|
nav(class="no-print") {
|
||||||
h1(class="title") { "Kitchen" }
|
h1(class="title") { "Kitchen" }
|
||||||
ul {
|
ul {
|
||||||
li { a(href="/ui/planning/plan") { "MealPlan" } }
|
li { a(href="/ui/planning/select") { "MealPlan" } }
|
||||||
li { a(href="/ui/manage/ingredients") { "Manage" } }
|
li { a(href="/ui/manage/ingredients") { "Manage" } }
|
||||||
li { a(href="/ui/login") { (login.get()) } }
|
li { a(href="/ui/login") { (login.get()) } }
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,24 @@ pub struct PlanListProps<'ctx> {
|
|||||||
pub fn PlanList<'ctx, G: Html>(cx: Scope<'ctx>, props: PlanListProps<'ctx>) -> View<G> {
|
pub fn PlanList<'ctx, G: Html>(cx: Scope<'ctx>, props: PlanListProps<'ctx>) -> View<G> {
|
||||||
let PlanListProps { sh, list } = props;
|
let PlanListProps { sh, list } = props;
|
||||||
view! {cx,
|
view! {cx,
|
||||||
Indexed(
|
div() {
|
||||||
iterable=list,
|
table() {
|
||||||
view=move |cx, date| {
|
Indexed(
|
||||||
let date_display = format!("{}", date);
|
iterable=list,
|
||||||
view!{cx,
|
view=move |cx, date| {
|
||||||
button(on:click=move |_| {
|
let date_display = format!("{}", date);
|
||||||
sh.dispatch(cx, Message::SelectPlanDate(date))
|
view!{cx,
|
||||||
}) { (date_display) }
|
tr() {
|
||||||
}
|
td() {
|
||||||
},
|
span(role="button", class="outline", on:click=move |_| {
|
||||||
)
|
sh.dispatch(cx, Message::SelectPlanDate(date, None))
|
||||||
|
}) { (date_display) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
use super::PlanningPage;
|
use super::PlanningPage;
|
||||||
use crate::{app_state::StateHandler, components::PlanList};
|
use crate::{
|
||||||
|
app_state::{Message, StateHandler},
|
||||||
|
components::PlanList,
|
||||||
|
};
|
||||||
|
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
@ -30,6 +33,15 @@ pub fn SelectPage<'ctx, G: Html>(cx: Scope<'ctx>, sh: StateHandler<'ctx>) -> Vie
|
|||||||
view! {cx,
|
view! {cx,
|
||||||
PlanningPage(
|
PlanningPage(
|
||||||
selected=Some("Select".to_owned()),
|
selected=Some("Select".to_owned()),
|
||||||
) { PlanList(sh=sh, list=plan_dates) }
|
) {
|
||||||
|
PlanList(sh=sh, list=plan_dates)
|
||||||
|
span(role="button", on:click=move |_| {
|
||||||
|
sh.dispatch(cx, Message::SelectPlanDate(chrono::offset::Local::now().naive_local().date(), Some(Box::new(|| {
|
||||||
|
sycamore_router::navigate("/ui/planning/plan");
|
||||||
|
}))))
|
||||||
|
}) {
|
||||||
|
"Start Plan for Today"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user