Generalised ingredients editor
This commit is contained in:
parent
6b3a87ebc8
commit
1663f3788d
5 changed files with 26 additions and 157 deletions
|
|
@ -1,6 +1,8 @@
|
|||
<template>
|
||||
|
||||
<div>
|
||||
<button v-if="editing" @click="$emit('on-add')">Add Ingredient</button>
|
||||
<button @click="toggleEditing">{{ editing ? 'Finished Editing' : 'Edit' }}</button>
|
||||
<ul>
|
||||
<li v-for="ingredient in ingredients" :key="ingredient.id">
|
||||
<div v-if="editing">
|
||||
|
|
@ -19,8 +21,6 @@
|
|||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<button v-if="editing" @click="$emit('on-add')">Add Ingredient</button>
|
||||
<button @click="editing = !editing">{{ editing ? 'Done' : 'Edit' }}</button>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
|
@ -81,6 +81,12 @@ export default {
|
|||
const newIngredients = await data.parseIngredients([line]);
|
||||
this.$emit('on-update-ingredient', ingredient, newIngredients[0]);
|
||||
},
|
||||
toggleEditing() {
|
||||
this.editing = !this.editing;
|
||||
if (this.editing && !this.ingredients.length) {
|
||||
this.$emit('on-add');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
<template>
|
||||
<div class="ingredient-add-box" :class="{ 'adding-ingredient': showIngredientLine}">
|
||||
<p class="ingredient-line" v-if="showIngredientLine">
|
||||
<ingredient-line ref="line" :ingredient="ingredient"
|
||||
@update-ingredient="updateIngredient"
|
||||
@update-product-link="updateProduct" />
|
||||
</p>
|
||||
<p>
|
||||
<button v-if="showIngredientLine" @click="addIngredient(ingredient)">
|
||||
<img :src="require('@/assets/chevron-up.svg')" /> <br>
|
||||
Add ingredient
|
||||
</button>
|
||||
<button v-if="showIngredientLine" @click="showIngredientLine = false">
|
||||
<img :src="require('@/assets/close.svg')" /> <br>
|
||||
Cancel
|
||||
</button>
|
||||
<button v-else @click="showIngredientLine = true">
|
||||
<img :src="require('@/assets/create.svg')" /> <br>
|
||||
Add ingredient
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import IngredientLine from './IngredientLine.vue';
|
||||
import data from '@/data.js'
|
||||
|
||||
export default {
|
||||
name: 'IngredientAddBox',
|
||||
components: { IngredientLine },
|
||||
data() {
|
||||
return {
|
||||
ingredient: {},
|
||||
showIngredientLine: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addIngredient() {
|
||||
this.$emit('add-ingredient', this.ingredient);
|
||||
this.ingredient = {};
|
||||
this.showIngredientLine = false;
|
||||
},
|
||||
async updateProduct(ingredient, product_link) {
|
||||
this.ingredient.product = await data.parseProduct(ingredient, product_link);
|
||||
},
|
||||
async updateIngredient(ingredient, line) {
|
||||
const newIngredients = await data.parseIngredients([line]);
|
||||
this.ingredient = newIngredients[0];
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.ingredient-add-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 1ex 2em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.adding-ingredient {
|
||||
border: solid 1px #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.ingredient-line {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
button {
|
||||
border: 0;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
padding: 2ex 1em;
|
||||
}
|
||||
|
||||
button img {
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -29,18 +29,7 @@
|
|||
</div>
|
||||
<div class="ingredients">
|
||||
<h2>Sides & Additional Ingredients</h2>
|
||||
<ul v-if="meal.extra_ingredients && meal.extra_ingredients.length">
|
||||
<li v-for="ingredient in meal.extra_ingredients" :key="ingredient" class="saved-ingredient">
|
||||
<compact-parsed-ingredient :ingredient="ingredient" />
|
||||
<button @click="deleteIngredient(ingredient)">
|
||||
<img class="icon" :src="require('@/assets/trash.svg')" />
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-else>
|
||||
<p>Add some ingredients using the search box</p>
|
||||
</div>
|
||||
<ingredient-add-box @add-ingredient="addIngredient" />
|
||||
<editable-ingredients-panel :ingredients="meal.extra_ingredients" @on-add="addIngredient" @on-delete="deleteIngredient" @on-update-ingredient="updateIngredient" />
|
||||
</div>
|
||||
<button @click="saveMeal">Save</button>
|
||||
</div>
|
||||
|
|
@ -50,14 +39,13 @@
|
|||
import data from '@/data.js'
|
||||
import RecipeSearchBox from '@/components/recipes/RecipeSearchBox.vue';
|
||||
import RecipeCard from '@/components/recipes/RecipeCard.vue';
|
||||
import CompactParsedIngredient from '@/components/ingredients/CompactParsedIngredient.vue';
|
||||
import DatePicker from './DatePicker.vue';
|
||||
import IngredientAddBox from '@/components/ingredients/IngredientAddBox.vue';
|
||||
import EditableIngredientsPanel from '../ingredients/EditableIngredientsPanel.vue';
|
||||
import PersonList from './PersonList.vue';
|
||||
|
||||
export default {
|
||||
props: ['id'],
|
||||
components: { RecipeSearchBox, DatePicker, RecipeCard, IngredientAddBox, CompactParsedIngredient, PersonList },
|
||||
components: { RecipeSearchBox, DatePicker, RecipeCard, EditableIngredientsPanel, PersonList },
|
||||
data() {
|
||||
return {
|
||||
meal: {
|
||||
|
|
@ -98,12 +86,15 @@ export default {
|
|||
removeRecipe(recipe) {
|
||||
this.meal.recipes = this.meal.recipes.filter(r => r.id !== recipe.id);
|
||||
},
|
||||
addIngredient(ingredient) {
|
||||
this.meal.extra_ingredients.push(ingredient);
|
||||
addIngredient() {
|
||||
this.meal.extra_ingredients = [{ line: '', product: null }, ...this.meal.extra_ingredients];
|
||||
},
|
||||
deleteIngredient(ingredient) {
|
||||
this.meal.extra_ingredients = this.meal.extra_ingredients.filter(i => i != ingredient);
|
||||
},
|
||||
updateIngredient(ingredient, newIngredient) {
|
||||
this.meal.extra_ingredients = this.meal.extra_ingredients.map(i => i == ingredient ? newIngredient : i);
|
||||
},
|
||||
removePerson(list, person) {
|
||||
this.meal[list] = this.meal[list].filter(p => p.id !== person.id);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,19 +15,12 @@
|
|||
<h1><input class="recipe-name" type="text" v-model="recipe.name" /></h1>
|
||||
<h3 class="recipe-link"><a :href="recipe.link">View Recipe</a></h3>
|
||||
<h2>Ingredients</h2>
|
||||
<ul>
|
||||
<li v-for="ingredient in recipe.ingredients" :key="ingredient.line">
|
||||
<p class="ingredient-line">
|
||||
<ingredient-line
|
||||
:ingredient="ingredient"
|
||||
@update-ingredient="updateIngredient"
|
||||
@update-product-link="updateProduct" />
|
||||
</p>
|
||||
<button @click="deleteIngredient(ingredient)">Delete</button>
|
||||
</li>
|
||||
</ul>
|
||||
<editable-ingredients-panel
|
||||
:ingredients="recipe.ingredients"
|
||||
:edit-only="true"
|
||||
@on-add="addIngredient" @on-delete="deleteIngredient" @on-update-ingredient="updateIngredient"
|
||||
/>
|
||||
|
||||
<button @click="addIngredient">Add Ingredient</button>
|
||||
<div>
|
||||
<button v-if="recipe.id" class="delete-btn" @click="deleteRecipe">Delete</button>
|
||||
<button class="submit-btn" @click="saveRecipe">{{ recipe.id ? "Save" : "Create" }}</button>
|
||||
|
|
@ -65,40 +58,18 @@ input.recipe-name {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.ingredient-line {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
import data from '@/data.js'
|
||||
import IngredientLine from '@/components/ingredients/IngredientLine.vue'
|
||||
import EditableIngredientsPanel from '@/components/ingredients/EditableIngredientsPanel.vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
id: { type: Number, optional: true }
|
||||
},
|
||||
components: {
|
||||
IngredientLine
|
||||
},
|
||||
components: { EditableIngredientsPanel },
|
||||
data() {
|
||||
return {
|
||||
link: this.$route.query.url ?? "",
|
||||
|
|
@ -139,17 +110,7 @@ export default {
|
|||
this.recipe = null;
|
||||
}
|
||||
},
|
||||
async updateProduct(ingredient, product_link) {
|
||||
const product = await data.parseProduct(ingredient, product_link);
|
||||
this.recipe.ingredients = this.recipe.ingredients.map(i => i.name == ingredient.name ? { ...i, product, product_id: product.id } : i);
|
||||
},
|
||||
async updateIngredient(ingredient, line) {
|
||||
const newIngredients = await data.parseIngredients([line]);
|
||||
const newIngredient = newIngredients[0];
|
||||
if (!newIngredient?.product) {
|
||||
newIngredient.product = ingredient.product;
|
||||
}
|
||||
|
||||
async updateIngredient(ingredient, newIngredient) {
|
||||
this.recipe.ingredients = this.recipe.ingredients.map(i => i == ingredient ? newIngredient : i);
|
||||
},
|
||||
deleteIngredient(ingredient) {
|
||||
|
|
@ -174,7 +135,7 @@ export default {
|
|||
}
|
||||
},
|
||||
addIngredient() {
|
||||
this.recipe.ingredients.push({ line: '', product: null });
|
||||
this.recipe.ingredients = [{ line: '', product: null }, ...this.recipe.ingredients];
|
||||
},
|
||||
async deleteRecipe() {
|
||||
if (confirm('Are you sure you want to delete this recipe?')) {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export default {
|
|||
const person = await data.currentUser();
|
||||
if (!person) return;
|
||||
|
||||
this.sources = this.sources.concat([{ ingredient: { id: 0 }, person }]);
|
||||
this.sources = [{ ingredient: { id: 0 }, person }, ...this.sources];
|
||||
},
|
||||
async deleteIngredient(ingredient) {
|
||||
const person = await data.currentUser();
|
||||
|
|
|
|||
Loading…
Reference in a new issue