diff --git a/vue/src/components/ShoppingLineItem.vue b/vue/src/components/ShoppingLineItem.vue index f6f080062..a5560f6a9 100644 --- a/vue/src/components/ShoppingLineItem.vue +++ b/vue/src/components/ShoppingLineItem.vue @@ -1,7 +1,12 @@ @@ -186,7 +207,7 @@ export default { if (e.recipe_mealplan !== null) { let recipe_name = e.recipe_mealplan.recipe_name if (recipes.indexOf(recipe_name) === -1) { - recipes.push(recipe_name) + recipes.push(recipe_name.substring(0, 14) + (recipe_name.length > 14 ? '..' : '')) } if ('mealplan_from_date' in e.recipe_mealplan) { @@ -196,14 +217,6 @@ export default { } } } - - if (recipes.length > 1) { - let short_recipes = [] - recipes.forEach(r => { - short_recipes.push(r.substring(0, 14) + (r.length > 14 ? '..' : '')) - }) - recipes = short_recipes - } } if (useUserPreferenceStore().device_settings.shopping_item_info_created_by && authors.length > 0) { @@ -236,9 +249,12 @@ export default { dateStyle: "short", }).format(Date.parse(datetime)) }, - + /** + * update the food after the category was changed + * handle changing category to category ID as a workaround + * @param food + */ updateFoodCategory: function (food) { - if (typeof food.supermarket_category === "number") { // not the best solution, but as long as generic multiselect does not support caching, I don't want to use a proper model food.supermarket_category = this.useShoppingListStore().supermarket_categories.filter(sc => sc.id === food.supermarket_category)[0] } @@ -249,14 +265,66 @@ export default { }).catch((err) => { StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) }) + }, + /** + * function triggered by touchend event of swipe container + * check if min distance is reached and execute desired action + */ + handleSwipe: function () { + const minDistance = 80; + const container = document.querySelector('.swipe-container'); + // get the distance the user swiped + const swipeDistance = container.scrollLeft - container.clientWidth; + if (swipeDistance < minDistance * -1) { + useShoppingListStore().setEntriesCheckedState(this.entries, !this.is_checked) + } else if (swipeDistance > minDistance) { + useShoppingListStore().delayEntries(this.entries, !this.is_delayed, true) + } } - - }, } diff --git a/vue/src/stores/ShoppingListStore.js b/vue/src/stores/ShoppingListStore.js index 488b40ee8..f13076a6a 100644 --- a/vue/src/stores/ShoppingListStore.js +++ b/vue/src/stores/ShoppingListStore.js @@ -291,27 +291,34 @@ export const useShoppingListStore = defineStore(_STORE_ID, { * function to handle user checking or unchecking a set of entries * @param {{}} entries set of entries * @param checked boolean to set checked state of entry to + * @param undo if the user should be able to undo the change or not */ - setEntriesCheckedState(entries, checked) { - this.registerChange((checked ? 'CHECKED' : 'UNCHECKED'), entries) + setEntriesCheckedState(entries, checked, undo) { + if (undo) { + this.registerChange((checked ? 'CHECKED' : 'UNCHECKED'), entries) + } + for (let i in entries) { this.entries[i].checked = checked this.updateObject(this.entries[i]) } }, /** - * function to handle user "delaying" shopping entries + * function to handle user "delaying" and "undelaying" shopping entries * @param {{}} entries set of entries + * @param delay if entries should be delayed or if delay should be removed + * @param undo if the user should be able to undo the change or not */ - delayEntries(entries) { - let delay = 4 //TODO get delay from settings in an offline friendly way - let delay_date = new Date(Date.now() + delay * (60 * 60 * 1000)) + delayEntries(entries, delay, undo) { + let delay_hours = 4 //TODO get delay from settings in an offline friendly way + let delay_date = new Date(Date.now() + delay_hours * (60 * 60 * 1000)) - this.registerChange('DELAY', entries) + if (undo) { + this.registerChange((delay ? 'DELAY' : 'UNDELAY'), entries) + } for (let i in entries) { - console.log('DELAYING ', i, ' until ', delay_date) - this.entries[i].delay_until = delay_date + this.entries[i].delay_until = (delay ? delay_date : null) this.updateObject(this.entries[i]) } }, @@ -332,7 +339,7 @@ export const useShoppingListStore = defineStore(_STORE_ID, { * @param {{}} entries set of entries */ registerChange(type, entries) { - if (!['CREATED', 'CHECKED', 'UNCHECKED', 'DELAY'].includes(type)) { + if (!['CREATED', 'CHECKED', 'UNCHECKED', 'DELAY', 'UNDELAY'].includes(type)) { throw Error('Tried to register unknown change type') } this.undo_stack.push({'type': type, 'entries': entries}) @@ -346,18 +353,15 @@ export const useShoppingListStore = defineStore(_STORE_ID, { let type = last_item['type'] let entries = last_item['entries'] - for (let i in entries) { - let e = entries[i] - if (type === 'CREATED') { + if (type === 'CHECKED' || type === 'UNCHECKED') { + this.setEntriesCheckedState(entries, (type === 'UNCHECKED'), false) + } else if (type === 'DELAY' || type === 'UNDELAY') { + this.delayEntries(entries, (type === 'UNDELAY'), false) + } else if (type === 'CREATED') { + for (let i in entries) { + let e = entries[i] this.deleteObject(e) - } else if (type === 'CHECKED' || type === 'UNCHECKED') { - e.checked = (type === 'UNCHECKED') - this.updateObject(e) - } else if (type === 'DELAY') { - e.delay_until = null - this.updateObject(e) } - } } else { // can use localization in store