This commit is contained in:
vabene1111 2023-12-27 21:15:24 +01:00
parent 0dacdcc72f
commit 0ce4d45eeb
4 changed files with 88 additions and 57 deletions

View File

@ -52,20 +52,19 @@
</b-row> </b-row>
<!-- shopping list table --> <!-- shopping list table -->
<b-row v-for="c in shopping_list_store.get_entries_by_group" v-bind:key="c.id" class="pr-1 pl-1"> <b-row v-for="c in shopping_list_store.get_entries_by_group" v-bind:key="c.id" class="pr-1 pl-1">
<b-col cols="12"> <b-col cols="12">
<b-button-group class="w-100 mt-1"> <b-button-group class="w-100 mt-1">
<b-button variant="light" block class="btn btn-block text-left"> <b-button variant="light" block class="btn btn-block text-left">
<span v-if="c.name === -1">{{ $t('Undefined') }}</span> <span v-if="c.name === shopping_list_store.UNDEFINED_CATEGORY">{{ $t('Undefined') }}</span>
<span v-else>{{ c.name }}</span> <span v-else>{{ c.name }}</span>
</b-button> </b-button>
<b-button variant="success"><i class="fas fa-check"></i></b-button> <!-- todo implement --> <b-button variant="success"><i class="fas fa-check"></i></b-button> <!-- todo implement -->
</b-button-group> </b-button-group>
<span v-for="f in c.foods" v-bind:key="f.id"> <span v-for="f in c.foods" v-bind:key="f.id">
<shopping-line-item :entries="f['entries']" class="mt-1"/> <shopping-line-item :entries="f['entries']" class="mt-1"/>
</span> </span>
</b-col> </b-col>
</b-row> </b-row>
@ -371,8 +370,9 @@
<b-form-select v-model="group_by" :options="group_by_choices" size="sm"></b-form-select> <b-form-select v-model="group_by" :options="group_by_choices" size="sm"></b-form-select>
</b-form-group> </b-form-group>
<b-form-group v-bind:label="$t('Supermarket')" label-for="popover-input-2" label-cols="6" class="mb-1"> <b-form-group v-bind:label="$t('Supermarket')" label-for="popover-input-2" label-cols="6" class="mb-1">
<b-form-select v-model="ui.selected_supermarket" :options="supermarkets" text-field="name" <generic-multiselect :model="Models.SUPERMARKET" @change="shopping_list_store.selected_supermarket = $event.val" :multiple="false"></generic-multiselect>
value-field="id" size="sm"></b-form-select> <!-- <b-form-select v-model="shopping_list_store.selected_supermarket" :options="shopping_list_store.supermarkets" text-field="name"-->
<!-- value-field="id" size="sm"></b-form-select>-->
</b-form-group> </b-form-group>
<!-- TODO: shade filters red when they are actually filtering content --> <!-- TODO: shade filters red when they are actually filtering content -->
<b-form-group v-bind:label="$t('ShowDelayed')" label-for="popover-input-3" content-cols="1" <b-form-group v-bind:label="$t('ShowDelayed')" label-for="popover-input-3" content-cols="1"
@ -814,8 +814,7 @@ export default {
}) })
this.$i18n.locale = window.CUSTOM_LOCALE this.$i18n.locale = window.CUSTOM_LOCALE
let store = useShoppingListStore() this.shopping_list_store.refreshFromAPI()
store.refreshFromAPI()
}, },
methods: { methods: {
useShoppingListStore, useShoppingListStore,
@ -951,32 +950,32 @@ export default {
} else { } else {
this.loading = true this.loading = true
} }
this.genericAPI(this.Models.SHOPPING_LIST, this.Actions.LIST, params).then((results) => { // this.genericAPI(this.Models.SHOPPING_LIST, this.Actions.LIST, params).then((results) => {
if (!autosync) { // if (!autosync) {
if (results.data?.length) { // if (results.data?.length) {
this.items = results.data // this.items = results.data
} else { // } else {
console.log("no data returned") // console.log("no data returned")
} // }
this.loading = false // this.loading = false
} else { // } else {
if (!this.auto_sync_blocked) { // if (!this.auto_sync_blocked) {
this.getSyncQueueLength().then((r) => { // this.getSyncQueueLength().then((r) => {
if (r === 0) { // if (r === 0) {
this.mergeShoppingList(results.data) // this.mergeShoppingList(results.data)
} else { // } else {
this.auto_sync_running = false // this.auto_sync_running = false
this.replaySyncQueue() // this.replaySyncQueue()
} // }
}) // })
} // }
} // }
}) // })
.catch((err) => { // .catch((err) => {
if (!autosync) { // if (!autosync) {
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err) // StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
} // }
}) // })
}, },
getSupermarkets: function () { getSupermarkets: function () {
let api = new ApiApiFactory() let api = new ApiApiFactory()

View File

@ -31,7 +31,8 @@
</template> </template>
<template #default> <template #default>
<h6 class="mt-2">{{ $t('Quick actions') }}</h6> <h5 class="mt-2">{{ $t('Quick actions') }}</h5>
{{ $t('Category')}}
<b-form-select <b-form-select
class="form-control mb-2" class="form-control mb-2"
:options="useShoppingListStore().supermarket_categories" :options="useShoppingListStore().supermarket_categories"
@ -41,9 +42,10 @@
@change="detail_modal_visible = false; updateFoodCategory(food)" @change="detail_modal_visible = false; updateFoodCategory(food)"
></b-form-select> ></b-form-select>
<b-button variant="success" block @click="detail_modal_visible = false;"> {{ $t("Edit_Food") }}</b-button> <!-- TODO implement --> <!-- TODO implement -->
<!-- <b-button variant="success" block @click="detail_modal_visible = false;"> {{ $t("Edit_Food") }}</b-button> -->
<b-button variant="info" block @click="detail_modal_visible = false;useShoppingListStore().delayEntries(entries)">{{ $t('Delay') }}</b-button> <b-button variant="info" block @click="detail_modal_visible = false;useShoppingListStore().delayEntries(entries)">{{ $t('Shop_later') }}</b-button>
<h6 class="mt-2">{{ $t('Entries') }}</h6> <h6 class="mt-2">{{ $t('Entries') }}</h6>

View File

@ -67,6 +67,7 @@
"Step_Type": "Step Type", "Step_Type": "Step Type",
"Make_Header": "Make Header", "Make_Header": "Make Header",
"Make_Ingredient": "Make Ingredient", "Make_Ingredient": "Make Ingredient",
"Shop_later": "Shop later",
"Amount": "Amount", "Amount": "Amount",
"Enable_Amount": "Enable Amount", "Enable_Amount": "Enable Amount",
"Disable_Amount": "Disable Amount", "Disable_Amount": "Disable Amount",

View File

@ -12,32 +12,66 @@ const _LOCAL_STORAGE_KEY = "SHOPPING_LIST_CLIENT_SETTINGS"
* */ * */
export const useShoppingListStore = defineStore(_STORE_ID, { export const useShoppingListStore = defineStore(_STORE_ID, {
state: () => ({ state: () => ({
// shopping data
entries: {}, entries: {},
category_food_entries: {},
supermarket_categories: [], supermarket_categories: [],
supermarkets: [],
//settings
show_checked_entries: false, // TODO move to settings show_checked_entries: false, // TODO move to settings
show_delayed_entries: false,
show_selected_supermarket_only: false,
selected_supermarket: null,
selected_group: 'food.supermarket_category.name',
// internal
currently_updating: false, currently_updating: false,
settings: null, settings: null,
// constants
GROUP_CATEGORY: 'food.supermarket_category.name', GROUP_CATEGORY: 'food.supermarket_category.name',
GROUP_CREATED_BY: 'created_by.display_name', GROUP_CREATED_BY: 'created_by.display_name',
GROUP_RECIPE: 'recipe_mealplan.recipe_name', GROUP_RECIPE: 'recipe_mealplan.recipe_name',
GROUP_MEALPLAN: 'recipe_mealplan.mealplan', //TODO give this some name from the API GROUP_MEALPLAN: 'recipe_mealplan.mealplan', //TODO give this some name from the API
UNDEFINED_CATEGORY: 'shopping_undefined_category'
selected_group: 'food.supermarket_category.name',
}), }),
getters: { getters: {
/**
* build a multi-level data structure ready for display from shopping list entries
* group by selected grouping key
* @return {{}}
*/
get_entries_by_group: function () { get_entries_by_group: function () {
let structure = {} let structure = {}
let ordered_structure = []
for (let i in this.entries) { for (let i in this.entries) {
structure = this.updateEntryInStructure(structure, this.entries[i], this.selected_group) structure = this.updateEntryInStructure(structure, this.entries[i], this.selected_group)
} }
return structure
if (this.selected_group === this.GROUP_CATEGORY && this.selected_supermarket !== null) {
if (this.UNDEFINED_CATEGORY in structure) {
ordered_structure.push(structure[this.UNDEFINED_CATEGORY])
Vue.delete(structure, this.UNDEFINED_CATEGORY)
}
for (let c of this.selected_supermarket.category_to_supermarket) {
if (c.category.name in structure) {
ordered_structure.push(structure[c.category.name])
Vue.delete(structure, c.category.name)
}
}
if (!this.show_selected_supermarket_only) {
for (let i in structure) {
ordered_structure.push(structure[i])
}
}
} else {
for (let i in structure) {
ordered_structure.push(structure[i])
}
}
return ordered_structure
}, },
client_settings: function () { client_settings: function () {
@ -52,8 +86,6 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
/** /**
* Retrieves all shopping list entries from the API and parses them into a structured object category > food > entry * Retrieves all shopping list entries from the API and parses them into a structured object category > food > entry
*/ */
this.category_food_entries = {}
Vue.set(this.category_food_entries, -1, {'id': -1, 'name': '', foods: {}})
if (!this.currently_updating) { if (!this.currently_updating) {
this.currently_updating = true this.currently_updating = true
@ -72,6 +104,12 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
}).catch((err) => { }).catch((err) => {
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err) StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
}) })
apiClient.listSupermarkets().then(r => {
this.supermarkets = r.data
}).catch((err) => {
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
})
} }
}, },
createObject(object) { createObject(object) {
@ -120,15 +158,6 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
}, },
// concenience methods // concenience methods
getFoodCategory(food) {
/**
* Get category id from food or return -1 if food has no category
*/
if (food.supermarket_category !== null) {
return food.supermarket_category.id
}
return -1
},
/** /**
* function to set entry to its proper place in the data structure to perform grouping * function to set entry to its proper place in the data structure to perform grouping
* @param {{}} structure datastructure * @param {{}} structure datastructure
@ -137,10 +166,10 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
* @returns updated datastructure including entry * @returns updated datastructure including entry
*/ */
updateEntryInStructure(structure, entry, group) { updateEntryInStructure(structure, entry, group) {
let grouping_key = _.get(entry, group, -1) let grouping_key = _.get(entry, group, this.UNDEFINED_CATEGORY)
// todo handele parent // todo handele parent
if (grouping_key === undefined || grouping_key === null) { if (grouping_key === undefined || grouping_key === null) {
grouping_key = -1 grouping_key = this.UNDEFINED_CATEGORY
} }
if (!(grouping_key in structure)) { if (!(grouping_key in structure)) {