From 52698e43b0168fafb00295edb3bd12159aef37a9 Mon Sep 17 00:00:00 2001 From: Kurt Riddlesperger Date: Fri, 24 Jan 2020 00:56:59 -0600 Subject: [PATCH] Products allowed in meal plan --- controllers/RecipesController.php | 36 +++++++++--- migrations/0096.sql | 1 + public/viewjs/mealplan.js | 92 ++++++++++++++++++++++++++++++- views/mealplan.blade.php | 10 +++- 4 files changed, 127 insertions(+), 12 deletions(-) diff --git a/controllers/RecipesController.php b/controllers/RecipesController.php index ed0d8005..9d6e3654 100644 --- a/controllers/RecipesController.php +++ b/controllers/RecipesController.php @@ -132,6 +132,7 @@ class RecipesController extends BaseController public function MealPlan(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args) { $recipes = $this->Database->recipes()->where('type', RecipesService::RECIPE_TYPE_NORMAL)->fetchAll(); + $products = $this->Database->products()->orderBy('name'); $events = array(); foreach($this->Database->meal_plan() as $mealPlanEntry) @@ -141,22 +142,39 @@ class RecipesController extends BaseController if ($recipe !== null) { $title = $recipe->name; + + $events[] = array( + 'id' => $mealPlanEntry['id'], + 'title' => $title, + 'start' => $mealPlanEntry['day'], + 'date_format' => 'date', + 'recipe' => json_encode($recipe), + 'mealPlanEntry' => json_encode($mealPlanEntry), + 'type' => $mealPlanEntry['type'] + ); } - $events[] = array( - 'id' => $mealPlanEntry['id'], - 'title' => $title, - 'start' => $mealPlanEntry['day'], - 'date_format' => 'date', - 'recipe' => json_encode($recipe), - 'mealPlanEntry' => json_encode($mealPlanEntry), - 'type' => $mealPlanEntry['type'] - ); + $product = FindObjectInArrayByPropertyValue($products, 'id', $mealPlanEntry['product_id']); + if ($product !== null) + { + $title = $product->name; + + $events[] = array( + 'id' => $mealPlanEntry['id'], + 'title' => $title, + 'start' => $mealPlanEntry['day'], + 'date_format' => 'date', + 'product' => json_encode($product), + 'mealPlanEntry' => json_encode($mealPlanEntry), + 'type' => $mealPlanEntry['type'] + ); + } } return $this->AppContainer->view->render($response, 'mealplan', [ 'fullcalendarEventSources' => $events, 'recipes' => $recipes, + 'products' => $products, 'internalRecipes' => $this->Database->recipes()->whereNot('type', RecipesService::RECIPE_TYPE_NORMAL)->fetchAll(), 'recipesResolved' => $this->RecipesService->GetRecipesResolved() ]); diff --git a/migrations/0096.sql b/migrations/0096.sql index a3e66a30..3ace6fc0 100644 --- a/migrations/0096.sql +++ b/migrations/0096.sql @@ -6,6 +6,7 @@ CREATE TABLE meal_plan ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, day DATE NOT NULL, type TEXT DEFAULT 'recipe', + product_id INTEGER, recipe_id INTEGER, recipe_servings INTEGER DEFAULT 1, note TEXT, diff --git a/public/viewjs/mealplan.js b/public/viewjs/mealplan.js index 956f8383..fc73eadd 100644 --- a/public/viewjs/mealplan.js +++ b/public/viewjs/mealplan.js @@ -157,6 +157,33 @@ var calendar = $("#calendar").fullCalendar({ } } } + if (event.type == "product") + { + var product = JSON.parse(event.product); + if (product === null || product === undefined) + { + return false; + } + + + element.attr("data-product", event.product); + + var productConsumeButtonDisabledClasses = ""; + element.html('\ +
\ +
' + product.name + '
\ +
' + __n(mealPlanEntry.recipe_servings, "%s serving", "%s servings") + '
\ +
\ + \ + \ +
\ +
'); + + if (product.picture_file_name && !product.picture_file_name.isEmpty()) + { + element.html(element.html() + '
') + } + } else if (event.type == "note") { element.html('\ @@ -254,7 +281,18 @@ $('#save-add-recipe-button').on('click', function(e) return false; } - Grocy.Api.Post('objects/meal_plan', $('#add-recipe-form').serializeJSON(), + var jsonData = $('#add-recipe-form').serializeJSON(); + + if (Grocy.Components.RecipePicker.GetValue() != "") + { + jsonData.type = "recipe"; + } + else if (Grocy.Components.ProductPicker.GetValue() != "") + { + jsonData.type = "product"; + } + + Grocy.Api.Post('objects/meal_plan', jsonData, function(result) { window.location.reload(); @@ -376,6 +414,45 @@ $(document).on('click', '.recipe-order-missing-button', function(e) }); }); +$(document).on('click', '.product-consume-button', function(e) +{ + e.preventDefault(); + + // Remove the focus from the current button + // to prevent that the tooltip stays until clicked anywhere else + document.activeElement.blur(); + + Grocy.FrontendHelpers.BeginUiBusy(); + + var productId = $(e.currentTarget).attr('data-product-id'); + var consumeAmount = $(e.currentTarget).attr('data-servings-amount'); + + Grocy.Api.Post('stock/products/' + productId + '/consume', { 'amount': consumeAmount, 'spoiled': false }, + function(bookingResponse) + { + Grocy.Api.Get('stock/products/' + productId, + function(result) + { + var toastMessage = __t('Removed %1$s of %2$s from stock', consumeAmount.toString() + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural), result.product.name) + '
' + __t("Undo") + ''; + + Grocy.FrontendHelpers.EndUiBusy(); + toastr.success(toastMessage); + }, + function(xhr) + { + Grocy.FrontendHelpers.EndUiBusy(); + console.error(xhr); + } + ); + }, + function(xhr) + { + Grocy.FrontendHelpers.EndUiBusy(); + console.error(xhr); + } + ); +}); + $(document).on('click', '.recipe-consume-button', function(e) { // Remove the focus from the current button @@ -461,3 +538,16 @@ $(window).on("resize", function() calendar.fullCalendar("changeView", "basicWeek"); } }); +function UndoStockTransaction(transactionId) +{ + Grocy.Api.Post('stock/transactions/' + transactionId.toString() + '/undo', { }, + function (result) + { + toastr.success(__t("Transaction successfully undone")); + }, + function (xhr) + { + console.error(xhr); + } + ); +}; diff --git a/views/mealplan.blade.php b/views/mealplan.blade.php index e4759cad..79351d90 100644 --- a/views/mealplan.blade.php +++ b/views/mealplan.blade.php @@ -45,7 +45,14 @@ @include('components.recipepicker', array( 'recipes' => $recipes, - 'isRequired' => true, + 'isRequired' => false, + 'nextInputSelector' => '#recipe_servings' + )) + + @include('components.productpicker', array( + 'products' => $products, + 'isRequired' => false, + 'disallowAllProductWorkflows' => true, 'nextInputSelector' => '#recipe_servings' )) @@ -58,7 +65,6 @@ )) -