Basic editing of users ingredients

This commit is contained in:
jableader 2024-05-12 16:32:28 +10:00
parent a4a4497dc4
commit 6a7dfbe460
3 changed files with 105 additions and 13 deletions

View file

@ -0,0 +1,56 @@
<template>
<div>
<ul>
<li v-for="ingredient in ingredients" :key="ingredient.id">
<div v-if="editing">
<ingredient-line :ingredient="ingredient" @update="updateIngredient" @update-ingredient="updateIngredient" @update-product-link="updateProduct" />
<button @click="$emit('on-delete', ingredient)">
<img class="icon" :src="require('@/assets/trash.svg')" />
</button>
</div>
<div v-else>
<compact-parsed-ingredient :ingredient="ingredient" />
</div>
</li>
</ul>
<button v-if="editing" @click="$emit('on-add')">Add Ingredient</button>
<button @click="editing = !editing">{{ editing ? 'Done' : 'Edit' }}</button>
</div>
</template>
<style>
.icon {
width: 1em;
height: 1em;
}
</style>
<script>
import data from '@/data.js'
import IngredientLine from './IngredientLine.vue'
import CompactParsedIngredient from './CompactParsedIngredient.vue'
export default {
name: 'EditableIngredientsPanel',
components: { IngredientLine, CompactParsedIngredient },
props: ['ingredients', 'editOnly'],
data() {
return {
editing: this.editOnly ?? false
}
},
methods: {
async updateProduct(ingredient, product_link) {
const product = await data.parseProduct(ingredient, product_link);
this.$emit('on-update-ingredient', ingredient, { ...ingredient, product });
},
async updateIngredient(ingredient, line) {
const newIngredients = await data.parseIngredients([line]);
this.$emit('on-update-ingredient', ingredient, newIngredients[0]);
},
}
}
</script>

View file

@ -3,7 +3,11 @@
<h1>Shopping List</h1>
<h4>Included Meals</h4>
<meal-selection-list @meal-selected="mealSelected" @meal-unselected="mealUnselected" />
<ul>
<h4>My Requests</h4>
<editable-ingredients-panel @on-add="addIngredient" @on-delete="deleteIngredient" @on-update-ingredient="updateIngredient" :ingredients="mySources" />
<h4>Full shopping list</h4>
<ul class="full-shopping-list">
<li v-for="item in shoppingList" :key="item.id">
<shopping-list-item :product="item.product" :sources="item.sources" />
</li>
@ -38,7 +42,7 @@
<style scoped>
li {
.full-shopping-list li {
list-style-type: none;
border: 1px solid #ccc;
@ -46,28 +50,33 @@ li {
margin-bottom: 1em;
}
ul {
.full-shopping-list {
padding: 0;
}
</style>
<script>
import data from '@/data.js'
import EditableIngredientsPanel from '@/components/ingredients/EditableIngredientsPanel.vue'
import ShoppingListItem from './ShoppingListItem.vue'
import MealSelectionList from './MealSelectionList.vue'
import { mealToShoppingListSources, removeMealFromShoppingListSources, groupByProduct } from './shopping.js'
export default {
name: 'ShoppingPage',
components: {
ShoppingListItem, MealSelectionList
},
components: { ShoppingListItem, MealSelectionList, EditableIngredientsPanel },
data() {
return { shoppingList: [], sources: [] }
return { shoppingList: [], sources: [], mySources: [] }
},
watch: {
sources() {
async sources() {
this.shoppingList = groupByProduct(this.sources);
const person = await data.currentUser();
this.mySources = this.sources.filter(source => source.person?.id === person?.id).map(source => source.ingredient);
}
},
methods: {
@ -76,6 +85,25 @@ export default {
},
mealUnselected(meal) {
this.sources = removeMealFromShoppingListSources(this.sources, meal);
},
async addIngredient() {
const person = await data.currentUser();
if (!person) return;
this.sources = this.sources.concat([{ ingredient: { id: 0 }, person }]);
},
async deleteIngredient(ingredient) {
const person = await data.currentUser();
if (!person) return;
const isMatch = source => source.ingredient === ingredient && source.person?.id === person.id;
this.sources = this.sources.filter(source => !isMatch(source));
},
async updateIngredient(oldIngredient, newIngredient) {
const person = await data.currentUser();
if (!person) return;
this.sources = this.sources.map(source => source.ingredient === oldIngredient ? { ingredient: newIngredient, person } : source);
}
}
}

View file

@ -14,20 +14,28 @@ export function mealToShoppingListSources(meal) {
}
export function removeMealFromShoppingListSources(sources, meal) {
return sources.filter(source => source.meal.id !== meal.id);
return sources.filter(source => source.meal?.id !== meal.id);
}
export function groupByProduct(sources) {
const noProductKey = "no-product";
const noProduct = { name: "No product", };
const grouped = {};
for (const source of sources) {
if (!grouped[source.ingredient.product.id]) {
grouped[source.ingredient.product.id] = {
product: source.ingredient.product,
const key = source.ingredient?.product?.id ?? noProductKey;
if (!key) {
continue;
}
if (!grouped[key]) {
grouped[key] = {
product: source.ingredient.product ?? noProduct,
sources: [],
};
}
grouped[source.ingredient.product.id].sources.push(source);
grouped[key].sources.push(source);
}
return Object.values(grouped);