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>
|
<template>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
<button v-if="editing" @click="$emit('on-add')">Add Ingredient</button>
|
||||||
|
<button @click="toggleEditing">{{ editing ? 'Finished Editing' : 'Edit' }}</button>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="ingredient in ingredients" :key="ingredient.id">
|
<li v-for="ingredient in ingredients" :key="ingredient.id">
|
||||||
<div v-if="editing">
|
<div v-if="editing">
|
||||||
|
|
@ -19,8 +21,6 @@
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<button v-if="editing" @click="$emit('on-add')">Add Ingredient</button>
|
|
||||||
<button @click="editing = !editing">{{ editing ? 'Done' : 'Edit' }}</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -81,6 +81,12 @@ export default {
|
||||||
const newIngredients = await data.parseIngredients([line]);
|
const newIngredients = await data.parseIngredients([line]);
|
||||||
this.$emit('on-update-ingredient', ingredient, newIngredients[0]);
|
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>
|
||||||
<div class="ingredients">
|
<div class="ingredients">
|
||||||
<h2>Sides & Additional Ingredients</h2>
|
<h2>Sides & Additional Ingredients</h2>
|
||||||
<ul v-if="meal.extra_ingredients && meal.extra_ingredients.length">
|
<editable-ingredients-panel :ingredients="meal.extra_ingredients" @on-add="addIngredient" @on-delete="deleteIngredient" @on-update-ingredient="updateIngredient" />
|
||||||
<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" />
|
|
||||||
</div>
|
</div>
|
||||||
<button @click="saveMeal">Save</button>
|
<button @click="saveMeal">Save</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -50,14 +39,13 @@
|
||||||
import data from '@/data.js'
|
import data from '@/data.js'
|
||||||
import RecipeSearchBox from '@/components/recipes/RecipeSearchBox.vue';
|
import RecipeSearchBox from '@/components/recipes/RecipeSearchBox.vue';
|
||||||
import RecipeCard from '@/components/recipes/RecipeCard.vue';
|
import RecipeCard from '@/components/recipes/RecipeCard.vue';
|
||||||
import CompactParsedIngredient from '@/components/ingredients/CompactParsedIngredient.vue';
|
|
||||||
import DatePicker from './DatePicker.vue';
|
import DatePicker from './DatePicker.vue';
|
||||||
import IngredientAddBox from '@/components/ingredients/IngredientAddBox.vue';
|
import EditableIngredientsPanel from '../ingredients/EditableIngredientsPanel.vue';
|
||||||
import PersonList from './PersonList.vue';
|
import PersonList from './PersonList.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['id'],
|
props: ['id'],
|
||||||
components: { RecipeSearchBox, DatePicker, RecipeCard, IngredientAddBox, CompactParsedIngredient, PersonList },
|
components: { RecipeSearchBox, DatePicker, RecipeCard, EditableIngredientsPanel, PersonList },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
meal: {
|
meal: {
|
||||||
|
|
@ -98,12 +86,15 @@ export default {
|
||||||
removeRecipe(recipe) {
|
removeRecipe(recipe) {
|
||||||
this.meal.recipes = this.meal.recipes.filter(r => r.id !== recipe.id);
|
this.meal.recipes = this.meal.recipes.filter(r => r.id !== recipe.id);
|
||||||
},
|
},
|
||||||
addIngredient(ingredient) {
|
addIngredient() {
|
||||||
this.meal.extra_ingredients.push(ingredient);
|
this.meal.extra_ingredients = [{ line: '', product: null }, ...this.meal.extra_ingredients];
|
||||||
},
|
},
|
||||||
deleteIngredient(ingredient) {
|
deleteIngredient(ingredient) {
|
||||||
this.meal.extra_ingredients = this.meal.extra_ingredients.filter(i => i != 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) {
|
removePerson(list, person) {
|
||||||
this.meal[list] = this.meal[list].filter(p => p.id !== person.id);
|
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>
|
<h1><input class="recipe-name" type="text" v-model="recipe.name" /></h1>
|
||||||
<h3 class="recipe-link"><a :href="recipe.link">View Recipe</a></h3>
|
<h3 class="recipe-link"><a :href="recipe.link">View Recipe</a></h3>
|
||||||
<h2>Ingredients</h2>
|
<h2>Ingredients</h2>
|
||||||
<ul>
|
<editable-ingredients-panel
|
||||||
<li v-for="ingredient in recipe.ingredients" :key="ingredient.line">
|
:ingredients="recipe.ingredients"
|
||||||
<p class="ingredient-line">
|
:edit-only="true"
|
||||||
<ingredient-line
|
@on-add="addIngredient" @on-delete="deleteIngredient" @on-update-ingredient="updateIngredient"
|
||||||
:ingredient="ingredient"
|
/>
|
||||||
@update-ingredient="updateIngredient"
|
|
||||||
@update-product-link="updateProduct" />
|
|
||||||
</p>
|
|
||||||
<button @click="deleteIngredient(ingredient)">Delete</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<button @click="addIngredient">Add Ingredient</button>
|
|
||||||
<div>
|
<div>
|
||||||
<button v-if="recipe.id" class="delete-btn" @click="deleteRecipe">Delete</button>
|
<button v-if="recipe.id" class="delete-btn" @click="deleteRecipe">Delete</button>
|
||||||
<button class="submit-btn" @click="saveRecipe">{{ recipe.id ? "Save" : "Create" }}</button>
|
<button class="submit-btn" @click="saveRecipe">{{ recipe.id ? "Save" : "Create" }}</button>
|
||||||
|
|
@ -65,40 +58,18 @@ input.recipe-name {
|
||||||
text-decoration: none;
|
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>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import data from '@/data.js'
|
import data from '@/data.js'
|
||||||
import IngredientLine from '@/components/ingredients/IngredientLine.vue'
|
import EditableIngredientsPanel from '@/components/ingredients/EditableIngredientsPanel.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
id: { type: Number, optional: true }
|
id: { type: Number, optional: true }
|
||||||
},
|
},
|
||||||
components: {
|
components: { EditableIngredientsPanel },
|
||||||
IngredientLine
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
link: this.$route.query.url ?? "",
|
link: this.$route.query.url ?? "",
|
||||||
|
|
@ -139,17 +110,7 @@ export default {
|
||||||
this.recipe = null;
|
this.recipe = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async updateProduct(ingredient, product_link) {
|
async updateIngredient(ingredient, newIngredient) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.recipe.ingredients = this.recipe.ingredients.map(i => i == ingredient ? newIngredient : i);
|
this.recipe.ingredients = this.recipe.ingredients.map(i => i == ingredient ? newIngredient : i);
|
||||||
},
|
},
|
||||||
deleteIngredient(ingredient) {
|
deleteIngredient(ingredient) {
|
||||||
|
|
@ -174,7 +135,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addIngredient() {
|
addIngredient() {
|
||||||
this.recipe.ingredients.push({ line: '', product: null });
|
this.recipe.ingredients = [{ line: '', product: null }, ...this.recipe.ingredients];
|
||||||
},
|
},
|
||||||
async deleteRecipe() {
|
async deleteRecipe() {
|
||||||
if (confirm('Are you sure you want to delete this recipe?')) {
|
if (confirm('Are you sure you want to delete this recipe?')) {
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ export default {
|
||||||
const person = await data.currentUser();
|
const person = await data.currentUser();
|
||||||
if (!person) return;
|
if (!person) return;
|
||||||
|
|
||||||
this.sources = this.sources.concat([{ ingredient: { id: 0 }, person }]);
|
this.sources = [{ ingredient: { id: 0 }, person }, ...this.sources];
|
||||||
},
|
},
|
||||||
async deleteIngredient(ingredient) {
|
async deleteIngredient(ingredient) {
|
||||||
const person = await data.currentUser();
|
const person = await data.currentUser();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue