diff --git a/vue3/src/components/dialogs/ShoppingLineItemDialog.vue b/vue3/src/components/dialogs/ShoppingLineItemDialog.vue
index f1d6ddd7c..e3102eed5 100644
--- a/vue3/src/components/dialogs/ShoppingLineItemDialog.vue
+++ b/vue3/src/components/dialogs/ShoppingLineItemDialog.vue
@@ -66,11 +66,11 @@
{{ $t('PostponedUntil') }} {{ DateTime.fromJSDate(e.delayUntil).toLocaleString(DateTime.DATETIME_SHORT) }}
-
-
-
-
-
+
+
+
+
+
@@ -126,6 +126,10 @@ const isShoppingLineDelayed = computed(() => {
return isShoppingListFoodDelayed(shoppingListFood.value)
})
+/**
+ * change category of food and update via API
+ * @param category
+ */
function categoryUpdate(category: SupermarketCategory) {
const api = new ApiApi()
shoppingListFood.value.food.supermarketCategory = category
diff --git a/vue3/src/components/display/ShoppingLineItem.vue b/vue3/src/components/display/ShoppingLineItem.vue
index d432f1712..0151aef0b 100644
--- a/vue3/src/components/display/ShoppingLineItem.vue
+++ b/vue3/src/components/display/ShoppingLineItem.vue
@@ -15,23 +15,25 @@
- {{ a.amount }}
+
+ {{ a.amount }}
+
{{ a.unit.name }}
-
- {{ food.name }}
-
{{ info_row }}
+
+ {{ shoppingListFood.food.name }}
+ {{ infoRow }}
-
+
@@ -63,6 +65,9 @@ const props = defineProps({
shoppingListFood: {type: {} as PropType, required: true},
})
+/**
+ * ID of outer container, used by swipe system
+ */
const itemContainerId = computed(() => {
let id = 'id_sli_'
for (let i in props.entries) {
@@ -71,6 +76,10 @@ const itemContainerId = computed(() => {
return id
})
+
+/**
+ * tests if all entries of the given food are checked
+ */
const isChecked = computed(() => {
for (let i in props.entries) {
if (!props.entries[i].checked) {
@@ -80,15 +89,24 @@ const isChecked = computed(() => {
return true
})
+/**
+ * determine if any entry in a given IShoppingListFood is delayed, if so return true
+ */
const isShoppingLineDelayed = computed(() => {
return isShoppingListFoodDelayed(props.shoppingListFood)
})
-
-const food = computed(() => {
- return props.entries[Object.keys(props.entries)[0]]['food']
+/**
+ * style action button depending on if all items are checked or not
+ */
+const actionButtonIcon = computed(() => {
+ if (isChecked.value){
+ return 'fa-solid fa-plus'
+ }
+ return 'fa-solid fa-check'
})
+
/**
* calculate the amounts for the given line
* can combine 1 to n entries with the same unit
@@ -128,7 +146,7 @@ const amounts = computed((): Map => {
return unitAmounts
})
-const info_row = computed(() => {
+const infoRow = computed(() => {
let info_row = []
let authors = []
@@ -170,25 +188,6 @@ const info_row = computed(() => {
return info_row.join(' - ')
})
-// TODO implement
-/**
- * update the food after the category was changed
- * handle changing category to category ID as a workaround
- * @param food
- */
-function updateFoodCategory(food: Food) {
- // if (typeof food.supermarketCategory === "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]
- // }
- //
- // let apiClient = new ApiApiFactory()
- // apiClient.updateFood(food.id, food).then(r => {
- //
- // }).catch((err) => {
- // StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
- // })
-}
-
/**
* set food on_hand status to true and check all associated entries
* @param food
diff --git a/vue3/src/components/display/ShoppingListView.vue b/vue3/src/components/display/ShoppingListView.vue
index 1453a2bf9..1cfd01280 100644
--- a/vue3/src/components/display/ShoppingListView.vue
+++ b/vue3/src/components/display/ShoppingListView.vue
@@ -92,6 +92,28 @@
+
+
+ Sync Queue Debug
+
+ Length: {{ useShoppingStore().itemCheckSyncQueue.length }}
+ Has Failed Items: {{ useShoppingStore().hasFailedItems()}}
+
+ {{ i }}
+
+
+
+
+
+
+ Undo Debug
+
+
+ {{ i.type }} {{ i.entries.flatMap(e => e.food.name)}}
+
+
+
+
diff --git a/vue3/src/stores/ShoppingStore.ts b/vue3/src/stores/ShoppingStore.ts
index 33eec1c8f..f6cc59dc9 100644
--- a/vue3/src/stores/ShoppingStore.ts
+++ b/vue3/src/stores/ShoppingStore.ts
@@ -1,5 +1,5 @@
import {acceptHMRUpdate, defineStore} from "pinia"
-import {ApiApi, Food, ShoppingListEntry, Supermarket, SupermarketCategory} from "@/openapi";
+import {ApiApi, Food, ShoppingListEntry, ShoppingListEntryBulk, Supermarket, SupermarketCategory} from "@/openapi";
import {computed, ref} from "vue";
import {
IShoppingExportEntry,
@@ -346,7 +346,6 @@ export const useShoppingStore = defineStore(_STORE_ID, () => {
let entryIdList: number[] = []
entries.forEach(entry => {
entry.checked = checked
- // TODO used to set updatedAt but does not make sense on client, rethink solution (as above)
entryIdList.push(entry.id!)
})
@@ -367,34 +366,30 @@ export const useShoppingStore = defineStore(_STORE_ID, () => {
function _replaySyncQueue() {
if (navigator.onLine || document.location.href.includes('localhost')) {
let api = new ApiApi()
- let promises = []
+ let promises: Promise[] = []
- for (let i in itemCheckSyncQueue.value) {
- let entry = itemCheckSyncQueue.value[i]
+ itemCheckSyncQueue.value.forEach((entry, index) => {
entry['status'] = ((entry['status'] === 'waiting') ? 'syncing' : 'syncing_failed_before')
- itemCheckSyncQueue.value[i] = entry
- // TODO set timeout for request (previously was 15000ms) or check that default timeout is similar
- let p = api.apiShoppingListEntryBulkCreate({shoppingListEntryBulk: entry}, {}).then((r) => {
+ let p = api.apiShoppingListEntryBulkCreate({shoppingListEntryBulk: entry}, {}).then((r) => {
entry.ids.forEach(id => {
let e = entries.value.get(id)
e.updatedAt = r.timestamp
entries.value.set(id, e)
})
- delete itemCheckSyncQueue.value[i]
+ itemCheckSyncQueue.value.splice(index,1)
}).catch((err) => {
if (err.code === "ERR_NETWORK" || err.code === "ECONNABORTED") {
entry['status'] = 'waiting_failed_before'
- itemCheckSyncQueue.value[i] = entry
} else {
- delete itemCheckSyncQueue.value[i]
+ itemCheckSyncQueue.value.splice(index,1)
console.error('Failed API call for entry ', entry)
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
}
})
promises.push(p)
- }
-
+ })
+ // TODO verify this all settled works
Promise.allSettled(promises).finally(() => {
runSyncQueue(500)
})
@@ -542,6 +537,8 @@ export const useShoppingStore = defineStore(_STORE_ID, () => {
currentlyUpdating,
getFlatEntries,
hasFailedItems,
+ itemCheckSyncQueue,
+ undoStack,
refreshFromAPI,
autoSync,
createObject,