Squashed commit of the following:

commit c5461420e7f1022019b79517d853a26301add9e9
Author: jableader <jacobdunk@gmail.com>
Date:   Sat Sep 28 14:55:18 2024 +1000

    meal scaling improvements

commit 37a444ff1fb5cbd1942161a8097a44fa7483b14c
Author: jableader <jacobdunk@gmail.com>
Date:   Sat Sep 28 13:13:06 2024 +1000

    Implementation
This commit is contained in:
jableader 2024-09-28 14:57:32 +10:00
parent e59d4aa0ed
commit 531e4f057f
5 changed files with 85 additions and 21 deletions

View file

@ -1,5 +1,5 @@
{
"name": "doof-front",
"name": "doof",
"version": "0.1.0",
"private": true,
"scripts": {

View file

@ -11,11 +11,17 @@
<div class="recipes">
<h2>Recipes</h2>
<ul v-if="meal.recipes && meal.recipes.length">
<li v-for="recipe in meal.recipes" :key="recipe.id" class="saved-recipe">
<li v-for="meal_recipe in meal.recipes" :key="meal_recipe.recipe.id" class="saved-recipe">
<p class="recipe-card">
<recipe-card :recipe="recipe" />
<recipe-card :recipe="meal_recipe.recipe" />
</p>
<button @click="removeRecipe(recipe)">
<p class="servings">
<input type="number" v-model="meal_recipe.servings" min="1" />
<small><em>servings</em></small>
</p>
<button class="delete-button" @click="removeRecipe(meal_recipe)">
<img class="icon" :src="require('@/assets/trash.svg')" />
</button>
</li>
@ -31,7 +37,10 @@
<h2>Sides & Additional Ingredients</h2>
<editable-ingredients-panel :ingredients="meal.extra_ingredients" @on-add="addIngredient" @on-delete="deleteIngredient" @on-update-ingredient="updateIngredient" @on-editing="onEditAdditionalIngredients" />
</div>
<button @click="saveMeal" v-if="!meal.purchase_date">Save</button>
<button @click="saveMeal">Save</button>
<p v-if="meal.purchase_date"><em>Purchased {{ formatDate(meal.purchase_date) }}</em></p>
</div>
</template>
@ -90,13 +99,36 @@ export default {
}
}
this.meal.recipes.push(recipe);
this.meal.recipes.push({ recipe, recipe_id: recipe.id, meal_id: this.meal.id, servings: recipe.serves });
},
selectDate(date) {
this.meal.suggested_date = date;
},
removeRecipe(recipe) {
this.meal.recipes = this.meal.recipes.filter(r => r.id !== recipe.id);
formatDate(date) {
// If it's today, show 'x hours ago'
// If it's within the last week, show 'x days ago'
// If it's within the last month weeks, show 'x weeks ago'
// Otherwise, show the date as dd/mm
const now = new Date();
const diff = now - date;
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
if (days === 0) {
const hours = Math.floor(diff / (1000 * 60 * 60));
return `${hours} hour${hours === 1 ? '' : 's'} ago`;
}
if (days < 7) {
return `${days} day${days === 1 ? '' : 's'} ago`;
}
if (days < 30) {
return `${Math.floor(days / 7)} week${days === 7 ? '' : 's'} ago`;
}
return date.toLocaleDateString('en-au', { day: 'numeric', month: 'numeric' });
},
removeRecipe(mealRecipe) {
this.meal.recipes = this.meal.recipes.filter(r => r != mealRecipe);
},
addIngredient() {
this.meal.extra_ingredients = [{ line: '', product: null }, ...this.meal.extra_ingredients];
@ -198,4 +230,35 @@ li {
margin: 0;
}
.recipe-card {
flex: 1;
}
.servings {
display: inline-block;
margin-right: 1em;
}
.servings input {
width: 3em;
border: none;
border-bottom: 1px solid #000;
text-align: center;
font-size: large;
font-style: italic;
}
.delete-button {
background: none;
border: none;
cursor: pointer;
border-radius: 1em;
padding: 0.5em;
}
.delete-button:hover {
/* Invert the colors of the trash icon */
filter: invert(1);
}
</style>

View file

@ -3,8 +3,8 @@
<h3>{{ dayOfWeek }} <small>{{ date }}</small></h3>
<p v-if="meal.recipes.length && meal.extra_ingredients.length">
<span v-for="(recipe, index) in meal.recipes" :key="recipe.id">
{{ recipe.name }}{{ seperator(index, meal.recipes) }}
<span v-for="(meal_recipe, index) in meal.recipes" :key="meal_recipe.recipe.id">
{{ meal_recipe.recipe.name }}{{ seperator(index, meal.recipes) }}
</span>
with
<span v-for="(ingredient, index) in meal.extra_ingredients" :key="ingredient.id">
@ -12,8 +12,8 @@
</span>
</p>
<p v-else-if="meal.recipes.length">
<span v-for="(recipe, index) in meal.recipes" :key="recipe.id">
{{ recipe.name }}{{ seperator(index, meal.recipes) }}
<span v-for="(meal_recipe, index) in meal.recipes" :key="meal_recipe.recipe.id">
{{ meal_recipe.recipe.name }}{{ seperator(index, meal.recipes) }}
</span>
</p>
<p v-else-if="meal.extra_ingredients.length">

View file

@ -93,7 +93,8 @@ const formatDate = (date) => {
const getUrl = (meal) => {
// First non empty value in meal.recipe/image_urls
for (const recipe of meal.recipes) {
for (const mr of meal.recipes) {
const recipe = mr.recipe;
if (recipe.image_urls.length && recipe.image_urls[0]) {
return recipe.image_urls[0];
}

View file

@ -1,19 +1,19 @@
import units from '@/units.js';
function scaleFactor(meal, recipe) {
const numYield = recipe.serves;
const numConsumers = meal.consumers.length;
function scaleFactor(mealRecipe) {
const numRecipe = mealRecipe.recipe.serves;
const numRequested = mealRecipe.servings;
return numConsumers / numYield;
return numRequested / numRecipe;
}
export function mealToShoppingListSources(meal) {
const sources = [];
for (const recipe of meal.recipes) {
const scale = scaleFactor(meal, recipe);
for (const ingredient of recipe.ingredients) {
for (const mealRecipe of meal.recipes) {
const scale = scaleFactor(mealRecipe);
for (const ingredient of mealRecipe.recipe.ingredients) {
const quantity = ingredient.quantity * scale;
sources.push({ meal, recipe, ingredient: { ...ingredient, quantity, }, });
sources.push({ meal, mealRecipe, recipe: mealRecipe.recipe, ingredient: { ...ingredient, quantity, }, });
}
}