diff --git a/vue3/src/apps/tandoor/Tandoor.vue b/vue3/src/apps/tandoor/Tandoor.vue
index 7da3996df..17438e476 100644
--- a/vue3/src/apps/tandoor/Tandoor.vue
+++ b/vue3/src/apps/tandoor/Tandoor.vue
@@ -90,9 +90,12 @@ import GlobalSearchDialog from "@/components/inputs/GlobalSearchDialog.vue"
import {useDisplay} from "vuetify"
import VSnackbarQueued from "@/components/display/VSnackbarQueued.vue";
import MessageListDialog from "@/components/dialogs/MessageListDialog.vue";
+import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
const {lgAndUp} = useDisplay()
+useUserPreferenceStore()
+
diff --git a/vue3/src/components/dialogs/MealPlanDialog.vue b/vue3/src/components/dialogs/MealPlanDialog.vue
index ddf5caaed..3de970846 100644
--- a/vue3/src/components/dialogs/MealPlanDialog.vue
+++ b/vue3/src/components/dialogs/MealPlanDialog.vue
@@ -70,6 +70,7 @@ import {VDateInput} from 'vuetify/labs/VDateInput' //TODO remove once component
import ModelSelect from "@/components/inputs/ModelSelect.vue";
import {useMessageStore} from "@/stores/MessageStore";
import {adjustDateRangeLength, shiftDateRange} from "@/utils/date_utils";
+import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
const props = defineProps(
{
@@ -133,11 +134,12 @@ function saveMealPlan() {
* create new meal plan on current date
*/
function newMealPlan() {
- // TODO load default meal type and shared users
+ // TODO load default meal type
return {
fromDate: DateTime.now().toJSDate(),
toDate: DateTime.now().toJSDate(),
servings: 1,
+ shared: useUserPreferenceStore().userSettings.planShare
} as MealPlan
}
diff --git a/vue3/src/stores/UserPreferenceStore.js b/vue3/src/stores/UserPreferenceStore.js
deleted file mode 100644
index b457cfa57..000000000
--- a/vue3/src/stores/UserPreferenceStore.js
+++ /dev/null
@@ -1,205 +0,0 @@
-import {defineStore} from 'pinia'
-
-
-import {ApiApiFactory, UserPreference} from "@/utils/openapi/api";
-import Vue from "vue";
-import {StandardToasts} from "@/utils/utils";
-
-const _STALE_TIME_IN_MS = 1000 * 30
-const _STORE_ID = 'user_preference_store'
-
-const _LS_DEVICE_SETTINGS = 'TANDOOR_LOCAL_SETTINGS'
-const _LS_USER_SETTINGS = 'TANDOOR_USER_SETTINGS'
-const _USER_ID = localStorage.getItem('USER_ID')
-
-export const useUserPreferenceStore = defineStore(_STORE_ID, {
- state: () => ({
- data: null,
- updated_at: null,
- currently_updating: false,
-
- user_settings_loaded_at: new Date(0),
- user_settings: {
- image: null,
- theme: "TANDOOR",
- nav_bg_color: "#ddbf86",
- nav_text_color: "DARK",
- nav_show_logo: true,
- default_unit: "g",
- default_page: "SEARCH",
- use_fractions: false,
- use_kj: false,
- plan_share: [],
- nav_sticky: true,
- ingredient_decimals: 2,
- comments: true,
- shopping_auto_sync: 5,
- mealplan_autoadd_shopping: false,
- food_inherit_default: [],
- default_delay: "4.0000",
- mealplan_autoinclude_related: true,
- mealplan_autoexclude_onhand: true,
- shopping_share: [],
- shopping_recent_days: 7,
- csv_delim: ",",
- csv_prefix: "",
- filter_to_supermarket: false,
- shopping_add_onhand: false,
- left_handed: false,
- show_step_ingredients: true,
- food_children_exist: false,
- locally_updated_at: new Date(0),
- },
-
- device_settings_initialized: false,
- device_settings_loaded_at: new Date(0),
- device_settings: {
- // shopping
- shopping_show_checked_entries: false,
- shopping_show_delayed_entries: false,
- shopping_show_selected_supermarket_only: false,
- shopping_selected_grouping: 'food.supermarket_category.name',
- shopping_selected_supermarket: null,
- shopping_item_info_created_by: false,
- shopping_item_info_mealplan: false,
- shopping_item_info_recipe: true,
- },
- }),
- getters: {},
- actions: {
- // Device settings (on device settings stored in local storage)
- /**
- * Load device settings from local storage and update state device_settings
- */
- loadDeviceSettings() {
- let s = localStorage.getItem(_LS_DEVICE_SETTINGS)
- if (s !== null) {
- let settings = JSON.parse(s)
- for (s in settings) {
- Vue.set(this.device_settings, s, settings[s])
- }
- }
- this.device_settings_initialized = true
- },
- /**
- * persist changes to device settings into local storage
- */
- updateDeviceSettings: function () {
- localStorage.setItem(_LS_DEVICE_SETTINGS, JSON.stringify(this.device_settings))
- },
- // ---------------- new methods for user settings
- loadUserSettings: function (allow_cached_results) {
- let s = localStorage.getItem(_LS_USER_SETTINGS)
- if (s !== null) {
- let settings = JSON.parse(s)
- for (s in settings) {
- Vue.set(this.user_settings, s, settings[s])
- }
- console.log(`loaded local user settings age ${((new Date().getTime()) - this.user_settings.locally_updated_at) / 1000} `)
- }
- if (((new Date().getTime()) - this.user_settings.locally_updated_at) > _STALE_TIME_IN_MS || !allow_cached_results) {
- console.log('refreshing user settings from API')
- let apiClient = new ApiApiFactory()
- apiClient.retrieveUserPreference(localStorage.getItem('USER_ID')).then(r => {
- for (s in r.data) {
- if (!(s in this.user_settings) && s !== 'user') {
- // dont load new keys if no default exists (to prevent forgetting to add defaults)
- console.error(`API returned UserPreference key "${s}" which has no default in UserPreferenceStore.user_settings.`)
- } else {
- Vue.set(this.user_settings, s, r.data[s])
- }
- }
- Vue.set(this.user_settings, 'locally_updated_at', new Date().getTime())
- localStorage.setItem(_LS_USER_SETTINGS, JSON.stringify(this.user_settings))
- }).catch(err => {
- this.currently_updating = false
- })
- }
-
- },
- updateUserSettings: function () {
- let apiClient = new ApiApiFactory()
- apiClient.partialUpdateUserPreference(_USER_ID, this.user_settings).then(r => {
- this.user_settings = r.data
- Vue.set(this.user_settings, 'locally_updated_at', new Date().getTime())
- localStorage.setItem(_LS_USER_SETTINGS, JSON.stringify(this.user_settings))
- StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE)
- }).catch(err => {
- this.currently_updating = false
- StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
- })
- },
- // ----------------
- // User Preferences (database settings stored in user preference model)
- /**
- * gets data from the store either directly or refreshes from API if data is considered stale
- * @returns {UserPreference|*|Promise>}
- */
- getData: function () {
- if (this.isStaleOrEmpty) {
- return this.refreshFromAPI()
- } else {
- return this.data
- }
- },
- /**
- * get data from store. Does not use API, if store is not initialized returns null.
- * @returns {null|UserPreference|*}
- */
- getStaleData: function () {
- return this.data
- },
- /**
- * checks if update timestamp is older than configured stale time interval
- * @returns {boolean} true if data is considered stale and should be updated
- */
- isStale() {
- return this.updated_at === null || ((new Date()) - this.updated_at) > _STALE_TIME_IN_MS;
- },
- /**
- * checks if data of store is empty/not initialized
- * @returns {boolean} true if store is empty
- */
- isEmpty() {
- return this.data === null
- },
- /**
- * checks if store is empty or data is considered stale, see isStale() and isEmpty()
- * @returns {boolean}
- */
- isStaleOrEmpty() {
- return this.isStale() || this.isEmpty()
- },
- /**
- * refreshes store data if isStaleOrEmpty() is true
- * @returns {Promise>} returns promise with data
- */
- updateIfStaleOrEmpty() {
- if (this.isStaleOrEmpty) {
- return this.refreshFromAPI()
- }
- },
- /**
- * refreshes store data from API
- * @returns {Promise>} returns promise with data
- */
- refreshFromAPI() {
- let apiClient = new ApiApiFactory()
- if (!this.currently_updating) {
- this.currently_updating = true
- return apiClient.retrieveUserPreference(localStorage.getItem('USER_ID')).then(r => {
- this.data = r.data
- this.updated_at = new Date()
- this.currently_updating = false
-
- this.user_settings = r.data
- this.user_settings_loaded_at = new Date()
-
- return this.data
- }).catch(err => {
- this.currently_updating = false
- })
- }
- },
- },
-})
\ No newline at end of file
diff --git a/vue3/src/stores/UserPreferenceStore.ts b/vue3/src/stores/UserPreferenceStore.ts
new file mode 100644
index 000000000..c5aec1857
--- /dev/null
+++ b/vue3/src/stores/UserPreferenceStore.ts
@@ -0,0 +1,48 @@
+import {acceptHMRUpdate, defineStore} from 'pinia'
+import {useStorage} from "@vueuse/core";
+import {ErrorMessageType, Message, useMessageStore} from "@/stores/MessageStore";
+import {ApiApi, UserPreference} from "@/openapi";
+import {ref} from "vue";
+
+const DEVICE_SETTINGS_KEY = 'TANDOOR_DEVICE_SETTINGS'
+
+class DeviceSettings {
+
+ shopping_show_checked_entries = false
+ shopping_show_delayed_entries = false
+ shopping_show_selected_supermarket_only = false
+ shopping_selected_grouping = 'food.supermarket_category.name'
+ shopping_selected_supermarket = null
+ shopping_item_info_created_by = false
+ shopping_item_info_mealplan = false
+ shopping_item_info_recipe = true
+
+}
+
+export const useUserPreferenceStore = defineStore('user_preference_store', () => {
+ let deviceSettings = useStorage(DEVICE_SETTINGS_KEY, {} as DeviceSettings)
+ let userSettings = ref({} as UserPreference)
+
+ function loadUserSettings() {
+ console.log('loading user settings from DB')
+ let api = new ApiApi()
+ api.apiUserPreferenceList().then(r => {
+ if (r.length == 1) {
+ userSettings.value = r[0]
+ } else {
+ useMessageStore().addError(ErrorMessageType.FETCH_ERROR, r)
+ }
+ }).catch(err => {
+ useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
+ })
+ }
+
+ loadUserSettings()
+
+ return {deviceSettings, userSettings}
+})
+
+// enable hot reload for store
+if (import.meta.hot) {
+ import.meta.hot.accept(acceptHMRUpdate(useUserPreferenceStore, import.meta.hot))
+}
\ No newline at end of file