From ddf9ef11a0ad7d35273cea0bc902784ec29e99c2 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 22 Dec 2023 13:12:28 +0100 Subject: [PATCH] basic working shopping list store --- .../ShoppingListView/ShoppingListView.vue | 4 + vue/src/stores/ShoppingListStore.js | 123 ++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 vue/src/stores/ShoppingListStore.js diff --git a/vue/src/apps/ShoppingListView/ShoppingListView.vue b/vue/src/apps/ShoppingListView/ShoppingListView.vue index b0f8742c..c48bc217 100644 --- a/vue/src/apps/ShoppingListView/ShoppingListView.vue +++ b/vue/src/apps/ShoppingListView/ShoppingListView.vue @@ -631,6 +631,7 @@ Vue.use(VueCookies) let SETTINGS_COOKIE_NAME = "shopping_settings" import {Workbox} from 'workbox-window'; import BottomNavigationBar from "@/components/BottomNavigationBar.vue"; +import {useShoppingListStore} from "@/stores/ShoppingListStore"; export default { name: "ShoppingListView", @@ -920,6 +921,9 @@ export default { } }) this.$i18n.locale = window.CUSTOM_LOCALE + + let store = useShoppingListStore() + store.refreshFromAPI() }, methods: { /** diff --git a/vue/src/stores/ShoppingListStore.js b/vue/src/stores/ShoppingListStore.js new file mode 100644 index 00000000..22e3b19b --- /dev/null +++ b/vue/src/stores/ShoppingListStore.js @@ -0,0 +1,123 @@ +import {ApiApiFactory} from "@/utils/openapi/api" +import {StandardToasts} from "@/utils/utils" +import {defineStore} from "pinia" +import Vue from "vue" + +const _STORE_ID = "shopping_list_store" +const _LOCAL_STORAGE_KEY = "SHOPPING_LIST_CLIENT_SETTINGS" +/* + * test store to play around with pinia and see if it can work for my usecases + * dont trust that all shopping list entries are in store as there is no cache validation logic, its just a shared data holder + * */ +export const useShoppingListStore = defineStore(_STORE_ID, { + state: () => ({ + category_food_entries: {}, + + currently_updating: false, + settings: null, + }), + getters: { + + client_settings: function () { + if (this.settings === null) { + this.settings = this.loadClientSettings() + } + return this.settings + }, + }, + actions: { + refreshFromAPI() { + /** + * 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: {}}) //TODO use localization to get name for undefined category + + if (!this.currently_updating) { + this.currently_updating = true + let apiClient = new ApiApiFactory() + apiClient.listShoppingListEntrys().then((r) => { + r.data.forEach((e) => { + let category = this.getFoodCategory(e.food) + if (!(category in this.category_food_entries)) { + Vue.set(this.category_food_entries, category, {'id': category, 'name': e.food.supermarket_category.name, foods: {}}) + } + if (!(e.food.id in this.category_food_entries[category]['foods'])) { + Vue.set(this.category_food_entries[category]['foods'], e.food.id, {'id': e.food.id, 'name': e.food.name, 'entries': {}}) + } + Vue.set(this.category_food_entries[category]['foods'][e.food.id]['entries'], e.id, e) + }) + this.currently_updating = false + }) + } + }, + createObject(object) { + let apiClient = new ApiApiFactory() + + // TODO shared handled in backend? + + return apiClient.createShoppingListEntry(object).then((r) => { + Vue.set(this.category_food_entries[this.getFoodCategory(r.food)]['foods'][r.food.id][r.id], r.id, r) + }).catch((err) => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) + }) + }, + updateObject(object) { + let apiClient = new ApiApiFactory() + return apiClient.updateShoppingListEntry(object.id, object).then((r) => { + Vue.set(this.category_food_entries[this.getFoodCategory(r.food)]['foods'][r.food.id][r.id], r.id, r) + }).catch((err) => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) + }) + }, + deleteObject(object) { + let apiClient = new ApiApiFactory() + return apiClient.destroyShoppingListEntry(object.id).then((r) => { + Vue.delete(this.category_food_entries[this.getFoodCategory(object.food)]['foods'][object.food.id], object.id) + }).catch((err) => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_DELETE, err) + }) + }, + updateClientSettings(settings) { + // this.settings = settings + // localStorage.setItem(_LOCAL_STORAGE_KEY, JSON.stringify(this.settings)) + }, + loadClientSettings() { + // let s = localStorage.getItem(_LOCAL_STORAGE_KEY) + // if (s === null || s === {}) { + // return { + // displayPeriodUom: "week", + // displayPeriodCount: 3, + // startingDayOfWeek: 1, + // displayWeekNumbers: true, + // } + // } else { + // return JSON.parse(s) + // } + }, + + // 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 + }, + delayFood(food) { + /** + * function to handle user "delaying" shopping entry + * takes a food object as an argument and delays all entries associated with the food + */ + let delay = 4 //TODO get delay from settings + let delay_date = new Date(Date.now() + delay * (60 * 60 * 1000)) + + this.category_food_entries[this.getFoodCategory(food)]['foods'][food.id]['entries'].forEach(e => { + e.delayed_until = delay_date + this.updateObject(e) + }) + }, + }, +})