meal plan and recipe editor improvements

This commit is contained in:
vabene1111
2024-12-28 12:55:20 +01:00
parent ea1e47e579
commit cde632241b
42 changed files with 358 additions and 70 deletions

View File

@@ -1104,7 +1104,7 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
servings = CustomDecimalField()
shared = UserSerializer(many=True, required=False, allow_null=True)
shopping = serializers.SerializerMethodField('in_shopping')
addshopping = serializers.BooleanField(write_only=True)
addshopping = serializers.BooleanField(write_only=True, required=False)
to_date = serializers.DateTimeField(required=False)

View File

@@ -0,0 +1,59 @@
<template>
<v-alert :title="props.title" closable @click:close="closeAlert()" v-if="showAlert">
<template #prepend>
<v-icon icon="$help"></v-icon>
</template>
<p>
{{ props.text}}
<v-btn color="success" class="float-right" v-if="props.actionText != ''" @click="emit('click')">{{ actionText}}</v-btn>
</p>
</v-alert>
</template>
<script setup lang="ts">
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import {MessageType, useMessageStore} from "@/stores/MessageStore";
import {computed} from "vue";
// emit click if action is clicked, actual effect must come from parent component
const emit = defineEmits(['click'])
const props = defineProps({
title: {type: String, required: false,},
text: {type: String, required: true},
// show an action button if any text is given and emit click event if button is pressed
actionText: {type: String, required: false,},
})
/**
* somewhat unique hash of the given text to save which alerts have already been closed
*/
const alertHash = computed(() => {
return props.text.split('').reduce((prevHash, currVal) => (((prevHash << 5) - prevHash) + currVal.charCodeAt(0))|0, 0).toString()
})
/**
* only show the alert if it hasn't been closed on that device before
*/
const showAlert = computed(() => {
return !useUserPreferenceStore().deviceSettings.general_closedHelpAlerts.includes(alertHash.value)
})
/**
* called when alert is closed to save this alert into the list of closed alerts
*/
function closeAlert() {
if (!useUserPreferenceStore().deviceSettings.general_closedHelpAlerts.includes(alertHash.value)) {
useUserPreferenceStore().deviceSettings.general_closedHelpAlerts.push(alertHash.value)
} else {
useMessageStore().addMessage(MessageType.ERROR, 'Trying to close already closed alert', 0, props.text)
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,22 @@
<template>
<span v-if="ingredient.amount && !Number.isNaN(ingredient.amount)">{{$n(ingredient.amount)}}</span>
<span class="ms-1" v-if="ingredient.unit">{{ ingredient.unit.name}}</span>
<span class="ms-1" v-if="ingredient.food">{{ ingredient.food.name}}</span>
</template>
<script setup lang="ts">
import {Ingredient} from "@/openapi";
import {PropType} from "vue";
const props = defineProps({
ingredient: {type: {} as PropType<Ingredient>, required: true}
})
</script>
<style scoped>
</style>

View File

@@ -1,7 +1,9 @@
<template>
<v-row class="h-100">
<v-col>
<v-col class="pb-0">
<v-card class="h-100" :loading="useMealPlanStore().loading">
<!-- TODO add hint about CTRL key while drag/drop -->
<!-- TODO multi selection? date range selection ? -->
<calendar-view
:show-date="calendarDate"
:items="planItems"
@@ -29,6 +31,8 @@
></meal-plan-calendar-item>
</template>
</calendar-view>
</v-card>
<model-edit-dialog model="MealPlan" v-model="newPlanDialog" :itemDefaults="newPlanDialogDefaultItem"
@create="(arg: any) => useMealPlanStore().plans.set(arg.id, arg)"></model-edit-dialog>
@@ -44,8 +48,8 @@ import "vue-simple-calendar/dist/css/default.css"
import MealPlanCalendarItem from "@/components/display/MealPlanCalendarItem.vue";
import {IMealPlanCalendarItem, IMealPlanNormalizedCalendarItem} from "@/types/MealPlan";
import {computed, onMounted, ref} from "vue";
import {DateTime} from "luxon";
import {computed, onMounted, ref, watch} from "vue";
import {DateTime, Duration} from "luxon";
import {useDisplay} from "vuetify";
import {useMealPlanStore} from "@/stores/MealPlanStore";
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
@@ -89,22 +93,47 @@ const calendarItemHeight = computed(() => {
}
})
onMounted(() => {
useMealPlanStore().refreshFromAPI() //TODO filter to visible date
/**
* watch calendar date and load entries accordingly
*/
watch(calendarDate, () => {
let daysInPeriod = 7
if (useUserPreferenceStore().deviceSettings.mealplan_displayPeriod == 'month') {
daysInPeriod = 31
} else if (useUserPreferenceStore().deviceSettings.mealplan_displayPeriod == 'year') {
daysInPeriod = 365
}
let days = useUserPreferenceStore().deviceSettings.mealplan_displayPeriodCount * daysInPeriod
useMealPlanStore().refreshFromAPI(calendarDate.value, DateTime.now().plus({days: days}).toJSDate())
})
onMounted(() => {
// initial load for next 30 days
useMealPlanStore().refreshFromAPI(calendarDate.value, DateTime.now().plus({days: 30}).toJSDate())
})
/**
* handle drop event for calendar items on fields
* @param undefinedItem
* @param targetDate
* @param event
*/
function dropCalendarItemOnDate(undefinedItem: IMealPlanNormalizedCalendarItem, targetDate: Date, event: DragEvent) {
//The item argument (first) is undefined because our custom calendar item cannot manipulate the calendar state so the item is unknown to the calendar (probably fixable by somehow binding state to the item)
if (currentlyDraggedMealplan.value.originalItem.mealPlan.id != undefined) {
let mealPlan = useMealPlanStore().plans.get(currentlyDraggedMealplan.value.originalItem.mealPlan.id)
if (mealPlan != undefined) {
let fromToDiff = DateTime.fromJSDate(mealPlan.toDate).diff(DateTime.fromJSDate(mealPlan.fromDate), 'days')
let fromToDiff = {days: 1}
if (mealPlan.toDate) {
fromToDiff = DateTime.fromJSDate(mealPlan.toDate).diff(DateTime.fromJSDate(mealPlan.fromDate), 'days')
}
// create copy of item if control is pressed
if (event.ctrlKey) {
let new_entry = Object.assign({}, mealPlan)
new_entry.fromDate = targetDate
new_entry.toDate = DateTime.fromJSDate(targetDate).plus(fromToDiff).toJSDate()
useMealPlanStore().createObject(new_entry)
} else {
mealPlan.fromDate = targetDate
mealPlan.toDate = DateTime.fromJSDate(targetDate).plus(fromToDiff).toJSDate()

View File

@@ -4,7 +4,6 @@
<v-input :hint="props.hint" persistent-hint :label="props.label" class="" >
<!-- TODO resolve-on-load false for now, race condition with model class, make prop once better solution is found -->
<Multiselect
:ref="`ref_${props.id}`"

View File

@@ -14,11 +14,15 @@
<v-icon icon="fas fa-sliders-h"></v-icon>
<v-menu activator="parent">
<v-list>
<v-list-item prepend-icon="fas fa-plus-circle" @click="showName = true" v-if="!showName && (step.name == null || step.name == '')">{{
$t('Name')
}}
</v-list-item>
<v-list-item prepend-icon="fas fa-plus-circle" @click="showTime = true" v-if="!showTime && step.time == 0">{{ $t('Time') }}</v-list-item>
<v-list-item prepend-icon="fas fa-plus-circle" @click="showFile = true" v-if="!showFile && step.file == null">{{ $t('File') }}</v-list-item>
<v-list-item prepend-icon="fas fa-plus-circle" @click="showRecipe = true" v-if="!showRecipe && step.stepRecipe == null">{{ $t('Recipe') }}</v-list-item>
<v-list-item prepend-icon="$delete">{{ $t('Delete') }}</v-list-item>
<v-list-item prepend-icon="$delete" @click="emit('delete')">{{ $t('Delete') }}</v-list-item>
</v-list>
</v-menu>
</v-btn>
@@ -27,7 +31,8 @@
<v-card-text>
<v-text-field
v-model="step.name"
label="Step Name"
:label="$t('Name')"
v-if="showName || (step.name != null && step.name != '')"
></v-text-field>
<v-row>
@@ -46,20 +51,21 @@
<v-col cols="12">
<v-label>{{ $t('Ingredients') }}</v-label>
<vue-draggable v-model="step.ingredients" handle=".drag-handle" :on-sort="sortIngredients">
<vue-draggable v-model="step.ingredients" handle=".drag-handle" :on-sort="sortIngredients" v-if="!mobile">
<v-row v-for="(ingredient, index) in step.ingredients" dense>
<v-col cols="2">
<v-number-input :id="`id_input_amount_${step.id}_${index}`" :label="$t('Amount')" v-model="ingredient.amount" inset control-variant="stacked"
hide-details
:min="0"></v-number-input>
</v-col>
<v-col cols="3">
<model-select model="Unit" v-model="ingredient.unit"></model-select>
<model-select model="Unit" v-model="ingredient.unit" hide-details></model-select>
</v-col>
<v-col cols="3">
<model-select model="Food" v-model="ingredient.food"></model-select>
<model-select model="Food" v-model="ingredient.food" hide-details></model-select>
</v-col>
<v-col cols="3" @keydown.tab="event => handleIngredientNoteTab(event, index)">
<v-text-field :label="$t('Note')" v-model="ingredient.note"></v-text-field>
<v-text-field :label="$t('Note')" v-model="ingredient.note" hide-details></v-text-field>
</v-col>
<v-col cols="1">
<v-btn variant="plain" icon>
@@ -74,15 +80,36 @@
</v-col>
</v-row>
</vue-draggable>
<v-btn-group density="compact">
<v-list v-if="mobile">
<vue-draggable v-model="step.ingredients" handle=".drag-handle" :on-sort="sortIngredients">
<v-list-item v-for="(ingredient, index) in step.ingredients" border @click="editingIngredientIndex = index; dialogIngredientEditor = true">
<ingredient-string :ingredient="ingredient"></ingredient-string>
<template #append>
<v-icon icon="$dragHandle" class="drag-handle"></v-icon>
</template>
</v-list-item>
</vue-draggable>
</v-list>
<v-btn-group density="compact" class="mt-1">
<v-btn color="success" @click="insertAndFocusIngredient()" prepend-icon="$add">{{ $t('Add') }}</v-btn>
<v-btn color="warning" @click="dialogIngredientParser = true"><v-icon icon="$add"></v-icon> <v-icon icon="$add"></v-icon></v-btn>
<v-btn color="warning" @click="dialogIngredientParser = true">
<v-icon icon="$add"></v-icon>
<v-icon icon="$add"></v-icon>
</v-btn>
</v-btn-group>
</v-col>
<v-col cols="12">
<v-label>{{ $t('Instructions') }}</v-label>
<v-alert @click="dialogMarkdownEdit = true" class="mt-2 cursor-text" min-height="52px">
<v-alert @click="dialogMarkdownEditor = true" class="mt-2 cursor-pointer" min-height="52px">
<template v-if="step.instruction != '' && step.instruction != null">
{{ step.instruction }}
</template>
<template v-else>
<i> {{ $t('InstructionsEditHelp') }} </i>
</template>
</v-alert>
</v-col>
</v-row>
@@ -92,12 +119,15 @@
</v-card>
<v-dialog
v-model="dialogMarkdownEdit"
v-model="dialogMarkdownEditor"
:max-width="(mobile) ? '100vw': '75vw'"
:fullscreen="mobile">
<v-card>
<v-closable-card-title :title="$t('Instructions')" v-model="dialogMarkdownEdit"></v-closable-card-title>
<v-closable-card-title :title="$t('Instructions')" v-model="dialogMarkdownEditor"></v-closable-card-title>
<step-markdown-editor class="h-100" v-model="step"></step-markdown-editor>
<v-card-actions v-if="!mobile">
<v-btn @click="dialogMarkdownEditor = false">{{ $t('Close') }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
@@ -115,34 +145,59 @@
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog
v-model="dialogIngredientEditor"
:max-width="(mobile) ? '100vw': '75vw'"
:fullscreen="mobile">
<v-card>
<v-closable-card-title :title="$t('Ingredient Editor')" v-model="dialogIngredientEditor"></v-closable-card-title>
<v-card-text>
<v-form>
<v-number-input v-model="step.ingredients[editingIngredientIndex].amount" inset control-variant="stacked" :label="$t('Amount')"
:min="0"></v-number-input>
<model-select model="Unit" v-model="step.ingredients[editingIngredientIndex].unit" :label="$t('Unit')"></model-select>
<model-select model="Food" v-model="step.ingredients[editingIngredientIndex].food" :label="$t('Food')"></model-select>
<v-text-field :label="$t('Note')" v-model="step.ingredients[editingIngredientIndex].note" ></v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn @click="dialogIngredientEditor = false">{{ $t('Close') }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
import {nextTick, ref} from 'vue'
import {ApiApi, Food, Ingredient, ParsedIngredient, Step} from "@/openapi";
import {ApiApi, Ingredient, ParsedIngredient, Step} from "@/openapi";
import StepMarkdownEditor from "@/components/inputs/StepMarkdownEditor.vue";
import {VNumberInput} from 'vuetify/labs/VNumberInput' //TODO remove once component is out of labs
import IngredientsTableRow from "@/components/display/IngredientsTableRow.vue";
import {VNumberInput} from 'vuetify/labs/VNumberInput'
import ModelSelect from "@/components/inputs/ModelSelect.vue";
import {useDisplay} from "vuetify";
import {VueDraggable} from "vue-draggable-plus";
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
import IngredientString from "@/components/display/IngredientString.vue";
const emit = defineEmits(['delete'])
const step = defineModel<Step>({required: true})
const props = defineProps({
stepIndex: {type: Number, required: true},
})
const {mobile} = useDisplay()
const showName = ref(false)
const showTime = ref(false)
const showRecipe = ref(false)
const showFile = ref(false)
const dialogMarkdownEdit = ref(false)
const dialogMarkdownEditor = ref(false)
const dialogIngredientEditor = ref(false)
const dialogIngredientParser = ref(false)
const editingIngredientIndex = ref({} as Ingredient)
const ingredientTextInput = ref("")
/**

View File

@@ -57,6 +57,7 @@
</v-col>
</v-row>
<closable-help-alert :text="$t('RecipeStepsHelp')" :action-text="$t('Steps')" @click="tab='steps'"></closable-help-alert>
</v-form>
</v-tabs-window-item>
@@ -64,13 +65,13 @@
<v-form :disabled="loading || fileApiLoading">
<v-row v-for="(s,i ) in editingObj.steps" :key="s.id">
<v-col>
<step-editor v-model="editingObj.steps[i]" :step-index="i"></step-editor>
<step-editor v-model="editingObj.steps[i]" :step-index="i" @delete="deleteStepAtIndex(i)"></step-editor>
</v-col>
</v-row>
<v-row>
<v-col class="text-center">
<v-btn-group density="compact">
<v-btn color="success" prepend-icon="fa-solid fa-plus">{{ $t('Add_Step') }}</v-btn>
<v-btn color="success" prepend-icon="fa-solid fa-plus" @click="addStep()">{{ $t('Add_Step') }}</v-btn>
<v-btn color="warning" @click="dialogStepManager = true">
<v-icon icon="fa-solid fa-arrow-down-1-9"></v-icon>
</v-btn>
@@ -124,7 +125,7 @@
<script setup lang="ts">
import {onMounted, PropType, ref, shallowRef} from "vue";
import {Recipe, Step} from "@/openapi";
import {Ingredient, Recipe, Step} from "@/openapi";
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
import {useI18n} from "vue-i18n";
@@ -134,6 +135,7 @@ import {VueDraggable} from "vue-draggable-plus";
import PropertiesEditor from "@/components/inputs/PropertiesEditor.vue";
import {useFileApi} from "@/composables/useFileApi";
import {VFileUpload} from 'vuetify/labs/VFileUpload'
import ClosableHelpAlert from "@/components/display/ClosableHelpAlert.vue";
const props = defineProps({
@@ -183,6 +185,16 @@ function deleteImage() {
})
}
/**
* add a new step to the recipe
*/
function addStep(){
editingObj.value.steps.push({
ingredients: [] as Ingredient[],
time: 0,
} as Step)
}
/**
* called by draggable in step manager dialog when steps are sorted
*/
@@ -192,6 +204,14 @@ function sortSteps() {
})
}
/**
* delete a step at the given index of the steps array of the editingObject
* @param index index to delete at
*/
function deleteStepAtIndex(index: number){
editingObj.value.steps.splice(index, 1)
}
</script>
<style scoped>

View File

@@ -21,9 +21,10 @@
<br/>
<p class="text-h6 mt-3">{{ $t('DeviceSettings') }}</p>
<p class="text-disabled">{{$t('DeviceSettingsHelp')}}</p>
<p class="text-disabled">{{ $t('DeviceSettingsHelp') }}</p>
<v-btn @click="useUserPreferenceStore().resetDeviceSettings()">{{$t('Reset')}}</v-btn>
<v-btn @click="useUserPreferenceStore().resetDeviceSettings()" color="warning">{{ $t('Reset') }}</v-btn> <br/>
<v-btn @click="useUserPreferenceStore().deviceSettings.general_closedHelpAlerts = []" color="warning" class="mt-1">{{ $t('ResetHelp') }}</v-btn>
</v-form>
</template>
@@ -51,7 +52,7 @@ onMounted(() => {
})
})
function save(){
function save() {
let api = new ApiApi()
api.apiUserPartialUpdate({id: user.value.id!, patchedUser: user.value}).then(r => {
user.value = r

View File

@@ -147,6 +147,7 @@
"InheritFields_help": "",
"InheritWarning": "",
"Instructions": "",
"InstructionsEditHelp": "",
"Internal": "",
"Invite_Link": "",
"Invites": "",
@@ -246,6 +247,7 @@
"Ratings": "",
"Recently_Viewed": "",
"Recipe": "",
"RecipeStepsHelp": "",
"Recipe_Book": "",
"Recipe_Image": "",
"Recipes": "",
@@ -255,6 +257,7 @@
"RemoveFoodFromShopping": "",
"Remove_nutrition_recipe": "",
"Reset": "",
"ResetHelp": "",
"Reset_Search": "",
"Reusable": "",
"Role": "",

View File

@@ -143,6 +143,7 @@
"InheritFields_help": "Стойностите на тези полета ще бъдат наследени от родител (Изключение: празни категории за пазаруване не се наследяват)",
"InheritWarning": "{food} е настроен да наследява, промените може да не продължат.",
"Instructions": "Инструкции",
"InstructionsEditHelp": "",
"Internal": "Вътрешен",
"Invite_Link": "",
"Key_Ctrl": "Контрол",
@@ -239,6 +240,7 @@
"Ratings": "Рейтинги",
"Recently_Viewed": "Наскоро разгледани",
"Recipe": "Рецепта",
"RecipeStepsHelp": "",
"Recipe_Book": "Книга с рецепти",
"Recipe_Image": "Изображение на рецептата",
"Recipes": "Рецепти",
@@ -248,6 +250,7 @@
"RemoveFoodFromShopping": "Премахнете {food} от списъка си за пазаруване",
"Remove_nutrition_recipe": "Изтрийте хранителните стойности от рецептата",
"Reset": "Нулиране",
"ResetHelp": "",
"Reset_Search": "Нулиране на търсенето",
"Reusable": "",
"Role": "",

View File

@@ -192,6 +192,7 @@
"Input": "",
"Instruction_Replace": "Substituïu instrucció",
"Instructions": "",
"InstructionsEditHelp": "",
"Internal": "",
"Invite_Link": "",
"Invites": "",
@@ -316,6 +317,7 @@
"Ratings": "",
"Recently_Viewed": "Vistos recentment",
"Recipe": "",
"RecipeStepsHelp": "",
"Recipe_Book": "",
"Recipe_Image": "Imatge de la recepta",
"Recipes": "",
@@ -325,6 +327,7 @@
"RemoveFoodFromShopping": "",
"Remove_nutrition_recipe": "Esborreu nutrició de la recepta",
"Reset": "",
"ResetHelp": "",
"Reset_Search": "Reinicieu la cerca",
"Reusable": "",
"Role": "",

View File

@@ -191,6 +191,7 @@
"InheritWarning": "{food} se propisuje, změny nemusí setrvat.",
"Instruction_Replace": "Nahraď instrukce",
"Instructions": "Instrukce",
"InstructionsEditHelp": "",
"Internal": "Interní",
"Invite_Link": "",
"Invites": "Pozvánky",
@@ -314,6 +315,7 @@
"Ratings": "Hodnocení",
"Recently_Viewed": "Naposledy prohlížené",
"Recipe": "Recept",
"RecipeStepsHelp": "",
"Recipe_Book": "Kuchařka",
"Recipe_Image": "Obrázek k receptu",
"Recipes": "Recepty",
@@ -323,6 +325,7 @@
"RemoveFoodFromShopping": "Odstranit {food} z nákupního seznamu",
"Remove_nutrition_recipe": "Smazat nutriční hodnoty",
"Reset": "Resetovat",
"ResetHelp": "",
"Reset_Search": "Zrušit filtry vyhledávání",
"Reusable": "",
"Role": "",

View File

@@ -179,6 +179,7 @@
"InheritWarning": "{food} er sat til at nedarve, ændringer bliver måske ikke gemt.",
"Instruction_Replace": "Erstat instruktion",
"Instructions": "Instruktioner",
"InstructionsEditHelp": "",
"Internal": "Interne",
"Invite_Link": "",
"Invites": "Invitationer",
@@ -296,6 +297,7 @@
"Ratings": "Bedømmelser",
"Recently_Viewed": "Vist for nylig",
"Recipe": "Opskrift",
"RecipeStepsHelp": "",
"Recipe_Book": "Opskriftsbog",
"Recipe_Image": "Opskriftsbillede",
"Recipes": "Opskrifter",
@@ -305,6 +307,7 @@
"RemoveFoodFromShopping": "Fjern {food} fra indkøbsliste",
"Remove_nutrition_recipe": "Fjern næringsindhold fra opskrift",
"Reset": "Nulstil",
"ResetHelp": "",
"Reset_Search": "Nulstil søgning",
"Reusable": "",
"Role": "",

View File

@@ -194,6 +194,7 @@
"Input": "Eingabe",
"Instruction_Replace": "Anleitung ersetzen",
"Instructions": "Anleitung",
"InstructionsEditHelp": "Hier klicken um eine Anleitung hinzuzufügen.",
"Internal": "Intern",
"Invite_Link": "Einladungs Link",
"Invites": "Einladungen",
@@ -319,6 +320,7 @@
"Ratings": "Bewertungen",
"Recently_Viewed": "Kürzlich angesehen",
"Recipe": "Rezept",
"RecipeStepsHelp": "Zutaten, Anleitungen und mehr können unter dem Tab Schritte hinzugefügt werden.",
"Recipe_Book": "Kochbuch",
"Recipe_Image": "Rezeptbild",
"Recipes": "Rezepte",
@@ -328,6 +330,7 @@
"RemoveFoodFromShopping": "{food} von der Einkaufsliste löschen",
"Remove_nutrition_recipe": "Nährwerte aus Rezept löschen",
"Reset": "Zurücksetzen",
"ResetHelp": "Hilfe Zurücksetzen",
"Reset_Search": "Suche zurücksetzen",
"Reusable": "Wiederverwendbar",
"Role": "Rolle",

View File

@@ -174,6 +174,7 @@
"InheritWarning": "To φαγητό {food} έχει ρυθμιστεί να κληρονομεί, οι αλλαγές μπορεί να μην διατηρηθούν.",
"Instruction_Replace": "Αλλαγή οδηγίας",
"Instructions": "Οδηγίες",
"InstructionsEditHelp": "",
"Internal": "Εσωτερική",
"Invite_Link": "",
"Invites": "Προσκλήσεις",
@@ -288,6 +289,7 @@
"Ratings": "Βαθμολογίες",
"Recently_Viewed": "Προβλήθηκαν πρόσφατα",
"Recipe": "Συνταγή",
"RecipeStepsHelp": "",
"Recipe_Book": "Βιβλίο συνταγών",
"Recipe_Image": "Εικόνα συνταγής",
"Recipes": "Συνταγές",
@@ -297,6 +299,7 @@
"RemoveFoodFromShopping": "Αφαίρεση του φαγητού {food} από τη λίστα αγορών σας",
"Remove_nutrition_recipe": "Αφαίρεση διατροφικής αξίας από τη συνταγή",
"Reset": "Επαναφορά",
"ResetHelp": "",
"Reset_Search": "Επαναφορά αναζήτησης",
"Reusable": "",
"Role": "",

View File

@@ -193,6 +193,7 @@
"Input": "Input",
"Instruction_Replace": "Instruction Replace",
"Instructions": "Instructions",
"InstructionsEditHelp": "Click here to add instructions. ",
"Internal": "Internal",
"Invite_Link": "Invite Link",
"Invites": "Invites",
@@ -318,6 +319,7 @@
"Ratings": "Ratings",
"Recently_Viewed": "Recently Viewed",
"Recipe": "Recipe",
"RecipeStepsHelp": "Ingredients, Instructions and more can be edited in the tab Steps.",
"Recipe_Book": "Recipe Book",
"Recipe_Image": "Recipe Image",
"Recipes": "Recipes",
@@ -327,6 +329,7 @@
"RemoveFoodFromShopping": "Remove {food} from your shopping list",
"Remove_nutrition_recipe": "Delete nutrition from recipe",
"Reset": "Reset",
"ResetHelp": "Reset Help",
"Reset_Search": "Reset Search",
"Reusable": "Reusable",
"Role": "Role",

View File

@@ -193,6 +193,7 @@
"Input": "Entrada",
"Instruction_Replace": "Reemplazar Instrucción",
"Instructions": "Instrucciones",
"InstructionsEditHelp": "",
"Internal": "Interno",
"Invite_Link": "",
"Invites": "Invitaciones",
@@ -315,6 +316,7 @@
"Ratings": "Calificaciones",
"Recently_Viewed": "Visto recientemente",
"Recipe": "Receta",
"RecipeStepsHelp": "",
"Recipe_Book": "Libro de recetas",
"Recipe_Image": "Imagen de la receta",
"Recipes": "Recetas",
@@ -324,6 +326,7 @@
"RemoveFoodFromShopping": "Eliminar {food} de la lista de la compra",
"Remove_nutrition_recipe": "Borrar nutrición de la canasta",
"Reset": "Restablecer",
"ResetHelp": "",
"Reset_Search": "Resetear busqueda",
"Reusable": "",
"Role": "",

View File

@@ -100,6 +100,7 @@
"Information": "Tiedot",
"Ingredients": "Ainesosat",
"Instructions": "Ohjeet",
"InstructionsEditHelp": "",
"Invite_Link": "",
"Key_Ctrl": "Ctrl",
"Key_Shift": "Shift",
@@ -176,12 +177,14 @@
"Rating": "Luokitus",
"Recently_Viewed": "Äskettäin katsotut",
"Recipe": "Resepti",
"RecipeStepsHelp": "",
"Recipe_Book": "Keittokirja",
"Recipe_Image": "Reseptin Kuva",
"Recipes": "Reseptit",
"Recipes_per_page": "Reseptejä sivulla",
"Remove": "",
"Remove_nutrition_recipe": "Poista ravintoaine reseptistä",
"ResetHelp": "",
"Reset_Search": "Nollaa haku",
"Reusable": "",
"Role": "",

View File

@@ -192,6 +192,7 @@
"Input": "Entrée",
"Instruction_Replace": "Instruction Remplacer",
"Instructions": "Instructions",
"InstructionsEditHelp": "",
"Internal": "Interne",
"Invite_Link": "",
"Invites": "Invitations",
@@ -316,6 +317,7 @@
"Ratings": "Notes",
"Recently_Viewed": "Vu récemment",
"Recipe": "Recette",
"RecipeStepsHelp": "",
"Recipe_Book": "Livre de recettes",
"Recipe_Image": "Image de la recette",
"Recipes": "Recettes",
@@ -325,6 +327,7 @@
"RemoveFoodFromShopping": "Supprimer laliment {food} de votre liste de courses",
"Remove_nutrition_recipe": "Supprimer les valeurs nutritionelles de la recette",
"Reset": "Réinitialiser",
"ResetHelp": "",
"Reset_Search": "Réinitialiser la recherche",
"Reusable": "",
"Role": "",

View File

@@ -193,6 +193,7 @@
"Input": "קלט",
"Instruction_Replace": "החלפת הוראות",
"Instructions": "הוראות",
"InstructionsEditHelp": "",
"Internal": "פנימי",
"Invite_Link": "",
"Invites": "הזמנות",
@@ -317,6 +318,7 @@
"Ratings": "דירוג",
"Recently_Viewed": "נצפו לאחרונה",
"Recipe": "מתכון",
"RecipeStepsHelp": "",
"Recipe_Book": "ספר מתכון",
"Recipe_Image": "תמונת מתכון",
"Recipes": "מתכונים",
@@ -326,6 +328,7 @@
"RemoveFoodFromShopping": "הסר {מזון} מרשימת הקניות",
"Remove_nutrition_recipe": "מחר ערכים תזונתיים מהמתכון",
"Reset": "אפס",
"ResetHelp": "",
"Reset_Search": "אפס חיפוש",
"Reusable": "",
"Role": "",

View File

@@ -175,6 +175,7 @@
"InheritWarning": "",
"Instruction_Replace": "Elkészítési leírás cseréje",
"Instructions": "Elkészítés",
"InstructionsEditHelp": "",
"Internal": "Belső",
"Invite_Link": "",
"Invites": "Meghívók",
@@ -290,6 +291,7 @@
"Ratings": "Értékelések",
"Recently_Viewed": "Nemrég megtekintett",
"Recipe": "Recept",
"RecipeStepsHelp": "",
"Recipe_Book": "Szakácskönyv",
"Recipe_Image": "Receptkép",
"Recipes": "Receptek",
@@ -299,6 +301,7 @@
"RemoveFoodFromShopping": "{food} eltávolítása bevásárlólistáról",
"Remove_nutrition_recipe": "Tápértékadatok törlése a receptből",
"Reset": "Visszaállítás",
"ResetHelp": "",
"Reset_Search": "Keresés alaphelyzetbe állítása",
"Reusable": "",
"Role": "",

View File

@@ -74,6 +74,7 @@
"Import_finished": "Ներմուծումն ավարտված է",
"Information": "Տեղեկություն",
"Ingredients": "",
"InstructionsEditHelp": "",
"Invite_Link": "",
"Keywords": "",
"Link": "",
@@ -122,12 +123,14 @@
"Rating": "",
"Recently_Viewed": "Վերջերս դիտած",
"Recipe": "Բաղադրատոմս",
"RecipeStepsHelp": "",
"Recipe_Book": "Բաղադրատոմսերի գիրք",
"Recipe_Image": "Բաղադրատոմսի նկար",
"Recipes": "Բաղադրատոմսեր",
"Recipes_per_page": "Բաղադրատոմս էջում",
"Remove": "",
"Remove_nutrition_recipe": "Հեռացնել բաղադրատոմսի սննդայնությունը",
"ResetHelp": "",
"Reset_Search": "Զրոյացնել որոնումը",
"Reusable": "",
"Role": "",

View File

@@ -161,6 +161,7 @@
"InheritFields_help": "",
"InheritWarning": "",
"Instructions": "",
"InstructionsEditHelp": "",
"Internal": "",
"Invite_Link": "",
"Invites": "",
@@ -266,6 +267,7 @@
"Ratings": "",
"Recently_Viewed": "baru saja dilihat",
"Recipe": "",
"RecipeStepsHelp": "",
"Recipe_Book": "",
"Recipe_Image": "Gambar Resep",
"Recipes": "Resep",
@@ -275,6 +277,7 @@
"RemoveFoodFromShopping": "",
"Remove_nutrition_recipe": "Hapus nutrisi dari resep",
"Reset": "",
"ResetHelp": "",
"Reset_Search": "Setel Ulang Pencarian",
"Reusable": "",
"Role": "",

View File

@@ -192,6 +192,7 @@
"Input": "",
"Instruction_Replace": "",
"Instructions": "",
"InstructionsEditHelp": "",
"Internal": "",
"Invite_Link": "",
"Invites": "",
@@ -316,6 +317,7 @@
"Ratings": "",
"Recently_Viewed": "",
"Recipe": "",
"RecipeStepsHelp": "",
"Recipe_Book": "",
"Recipe_Image": "",
"Recipes": "",
@@ -325,6 +327,7 @@
"RemoveFoodFromShopping": "",
"Remove_nutrition_recipe": "",
"Reset": "",
"ResetHelp": "",
"Reset_Search": "",
"Reusable": "",
"Role": "",

View File

@@ -166,6 +166,7 @@
"InheritWarning": "{food} è impostato per ereditare, i cambiamenti potrebbero non essere applicati.",
"Instruction_Replace": "Sostituisci istruzioni",
"Instructions": "Istruzioni",
"InstructionsEditHelp": "",
"Internal": "Interno",
"Invite_Link": "",
"Invites": "Inviti",
@@ -274,6 +275,7 @@
"Ratings": "Valutazioni",
"Recently_Viewed": "Visualizzato di recente",
"Recipe": "Ricetta",
"RecipeStepsHelp": "",
"Recipe_Book": "Libro di Ricette",
"Recipe_Image": "Immagine ricetta",
"Recipes": "Ricette",
@@ -283,6 +285,7 @@
"RemoveFoodFromShopping": "Rimuovi {food} dalla tua lista della spesa",
"Remove_nutrition_recipe": "Elimina nutrienti dalla ricetta",
"Reset": "Azzera",
"ResetHelp": "",
"Reset_Search": "Ripristina Ricerca",
"Reusable": "",
"Role": "",

View File

@@ -177,6 +177,7 @@
"InheritWarning": "",
"Instruction_Replace": "",
"Instructions": "",
"InstructionsEditHelp": "",
"Internal": "",
"Invite_Link": "",
"Invites": "",
@@ -294,6 +295,7 @@
"Ratings": "",
"Recently_Viewed": "Neseniai Žiūrėta",
"Recipe": "",
"RecipeStepsHelp": "",
"Recipe_Book": "",
"Recipe_Image": "Recepto nuotrauka",
"Recipes": "",
@@ -303,6 +305,7 @@
"RemoveFoodFromShopping": "",
"Remove_nutrition_recipe": "Ištrinti mitybos informaciją iš recepto",
"Reset": "",
"ResetHelp": "",
"Reset_Search": "Iš naujo nustatyti paiešką",
"Reusable": "",
"Role": "",

View File

@@ -172,6 +172,7 @@
"InheritWarning": "",
"Instruction_Replace": "Erstatt instruksjoner",
"Instructions": "Instruksjoner",
"InstructionsEditHelp": "",
"Internal": "",
"Invite_Link": "",
"Invites": "Invitasjoner",
@@ -286,6 +287,7 @@
"Ratings": "",
"Recently_Viewed": "Nylig vist",
"Recipe": "Oppskrift",
"RecipeStepsHelp": "",
"Recipe_Book": "Oppskriftsbok",
"Recipe_Image": "Oppskriftsbilde",
"Recipes": "Oppskrift",
@@ -295,6 +297,7 @@
"RemoveFoodFromShopping": "Fjern {food} fra handelisten din",
"Remove_nutrition_recipe": "Fjern næringsinnhold fra oppskrift",
"Reset": "",
"ResetHelp": "",
"Reset_Search": "Nullstill søk",
"Reusable": "",
"Role": "",

View File

@@ -176,6 +176,7 @@
"InheritWarning": "{food} erft informatie, wijzigingen zijn mogelijk niet blijvend.",
"Instruction_Replace": "Vervang instructie",
"Instructions": "Instructies",
"InstructionsEditHelp": "",
"Internal": "Interne",
"Invite_Link": "",
"Invites": "Uitnodigingen",
@@ -290,6 +291,7 @@
"Ratings": "Waardering",
"Recently_Viewed": "Recent bekeken",
"Recipe": "Recept",
"RecipeStepsHelp": "",
"Recipe_Book": "Kookboek",
"Recipe_Image": "Afbeelding Recept",
"Recipes": "Recepten",
@@ -299,6 +301,7 @@
"RemoveFoodFromShopping": "Verwijder {food} van je boodschappenlijst",
"Remove_nutrition_recipe": "Verwijder voedingswaarde van recept",
"Reset": "Herstel",
"ResetHelp": "",
"Reset_Search": "Zoeken resetten",
"Reusable": "",
"Role": "",

View File

@@ -194,6 +194,7 @@
"Input": "Wprowadź",
"Instruction_Replace": "Zmień instrukcję",
"Instructions": "Instrukcje",
"InstructionsEditHelp": "",
"Internal": "Wewnętrzne",
"Invite_Link": "",
"Invites": "Zaprasza",
@@ -318,6 +319,7 @@
"Ratings": "Oceny",
"Recently_Viewed": "Ostatnio oglądane",
"Recipe": "Przepis",
"RecipeStepsHelp": "",
"Recipe_Book": "Książka z przepisami",
"Recipe_Image": "Obrazek dla przepisu",
"Recipes": "Przepisy",
@@ -327,6 +329,7 @@
"RemoveFoodFromShopping": "Usuń {food} z listy zakupów",
"Remove_nutrition_recipe": "Usuń wartości odżywcze z przepisu",
"Reset": "Resetowanie",
"ResetHelp": "",
"Reset_Search": "Resetuj wyszukiwanie",
"Reusable": "",
"Role": "",

View File

@@ -139,6 +139,7 @@
"InheritWarning": "{food} esta definida para herdar, alterações podem não persistir.",
"Instruction_Replace": "Substituir Instrução",
"Instructions": "Instruções",
"InstructionsEditHelp": "",
"Internal": "Interno",
"Invite_Link": "",
"Key_Ctrl": "Ctrl",
@@ -236,6 +237,7 @@
"Ratings": "Avaliações",
"Recently_Viewed": "Vistos Recentemente",
"Recipe": "Receita",
"RecipeStepsHelp": "",
"Recipe_Book": "Livro de Receitas",
"Recipe_Image": "Imagem da Receita",
"Recipes": "Receitas",
@@ -244,6 +246,7 @@
"RemoveFoodFromShopping": "Remover {food} da sua lista de compras",
"Remove_nutrition_recipe": "Remover valor nutricional da receita",
"Reset": "Reiniciar",
"ResetHelp": "",
"Reset_Search": "Repor Pesquisa",
"Reusable": "",
"Role": "",

View File

@@ -187,6 +187,7 @@
"Input": "Entrada",
"Instruction_Replace": "Substituir Instrução",
"Instructions": "Instruções",
"InstructionsEditHelp": "",
"Internal": "Interno",
"Invite_Link": "",
"Invites": "Convites",
@@ -305,6 +306,7 @@
"Ratings": "Classificações",
"Recently_Viewed": "Visto recentemente",
"Recipe": "Receita",
"RecipeStepsHelp": "",
"Recipe_Book": "Livro de Receitas",
"Recipe_Image": "Imagem da receita",
"Recipes": "Receitas",
@@ -314,6 +316,7 @@
"RemoveFoodFromShopping": "Remover {food} da sua lista de compras",
"Remove_nutrition_recipe": "Deletar dados nutricionais da receita",
"Reset": "Reiniciar",
"ResetHelp": "",
"Reset_Search": "Resetar Busca",
"Reusable": "",
"Role": "",

View File

@@ -170,6 +170,7 @@
"InheritWarning": "{food} este setat să moștenească, este posibil ca modificările să nu persiste.",
"Instruction_Replace": "Înlocuire instrucții",
"Instructions": "Instrucțiuni",
"InstructionsEditHelp": "",
"Internal": "Intern",
"Invite_Link": "",
"Invites": "Invită",
@@ -278,6 +279,7 @@
"Ratings": "Evaluări",
"Recently_Viewed": "Vizualizate recent",
"Recipe": "Rețetă",
"RecipeStepsHelp": "",
"Recipe_Book": "Carte de rețete",
"Recipe_Image": "Imagine a rețetei",
"Recipes": "Rețete",
@@ -287,6 +289,7 @@
"RemoveFoodFromShopping": "Șterge {food} din lista de cumpărături",
"Remove_nutrition_recipe": "Ștergere a nutriției din rețetă",
"Reset": "Resetare",
"ResetHelp": "",
"Reset_Search": "Resetarea căutării",
"Reusable": "",
"Role": "",

View File

@@ -129,6 +129,7 @@
"InheritFields": "Наследование значений полей",
"InheritWarning": "{food} примет предыдущие настройки, изменения не будут приняты.",
"Instructions": "Инструкции",
"InstructionsEditHelp": "",
"Internal": "Внутренний",
"Invite_Link": "",
"Key_Ctrl": "Ctrl",
@@ -221,6 +222,7 @@
"Ratings": "Рейтинги",
"Recently_Viewed": "Недавно просмотренные",
"Recipe": "Рецепт",
"RecipeStepsHelp": "",
"Recipe_Book": "Книга рецептов",
"Recipe_Image": "Изображение рецепта",
"Recipes": "Рецепты",
@@ -229,6 +231,7 @@
"RemoveFoodFromShopping": "Удалить {food} из вашего списка покупок",
"Remove_nutrition_recipe": "Уберите питательные вещества из рецепта",
"Reset": "Сбросить",
"ResetHelp": "",
"Reset_Search": "Очистить строку поиска",
"Reusable": "",
"Role": "",

View File

@@ -126,6 +126,7 @@
"InheritWarning": "{food} je nastavljena na dedovanje, spremembe morda ne bodo trajale.",
"Instruction_Replace": "Zamenjaj Navodila",
"Instructions": "Navodila",
"InstructionsEditHelp": "",
"Invite_Link": "",
"Key_Ctrl": "Ctrl",
"Key_Shift": "Shift",
@@ -213,6 +214,7 @@
"Rating": "Ocena",
"Recently_Viewed": "Nazadnje videno",
"Recipe": "Recept",
"RecipeStepsHelp": "",
"Recipe_Book": "Knjiga receptov",
"Recipe_Image": "Slika recepta",
"Recipes": "Recepti",
@@ -220,6 +222,7 @@
"Remove": "",
"RemoveFoodFromShopping": "Odstrani {food} iz nakupovalnega listka",
"Remove_nutrition_recipe": "Receptu izbriši hranilno vrednost",
"ResetHelp": "",
"Reset_Search": "Ponastavi iskalnik",
"Reusable": "",
"Role": "",

View File

@@ -194,6 +194,7 @@
"Input": "Inmatning",
"Instruction_Replace": "Ersätt instruktion",
"Instructions": "Instruktioner",
"InstructionsEditHelp": "",
"Internal": "Intern",
"Invite_Link": "",
"Invites": "Inbjudningar",
@@ -318,6 +319,7 @@
"Ratings": "Betyg",
"Recently_Viewed": "Nyligen visade",
"Recipe": "Recept",
"RecipeStepsHelp": "",
"Recipe_Book": "Receptbok",
"Recipe_Image": "Receptbild",
"Recipes": "Recept",
@@ -327,6 +329,7 @@
"RemoveFoodFromShopping": "Ta bort {mat} från din inköpslista",
"Remove_nutrition_recipe": "Ta bort näring från receptet",
"Reset": "Återställ",
"ResetHelp": "",
"Reset_Search": "Rensa sök",
"Reusable": "",
"Role": "",

View File

@@ -193,6 +193,7 @@
"Input": "Giriş",
"Instruction_Replace": "Talimat Değiştir",
"Instructions": "Talimatlar",
"InstructionsEditHelp": "",
"Internal": "Dahili",
"Invite_Link": "",
"Invites": "Davetler",
@@ -317,6 +318,7 @@
"Ratings": "Derecelendirmeler",
"Recently_Viewed": "Son Görüntülenen",
"Recipe": "Tarif",
"RecipeStepsHelp": "",
"Recipe_Book": "Yemek Tarifi Kitabı",
"Recipe_Image": "Tarif Resmi",
"Recipes": "Tarifler",
@@ -326,6 +328,7 @@
"RemoveFoodFromShopping": "{food}'ı alışveriş listenizden çıkarın",
"Remove_nutrition_recipe": "Tariften besin değeri sil",
"Reset": "Sıfırla",
"ResetHelp": "",
"Reset_Search": "Aramayı Sıfırla",
"Reusable": "",
"Role": "",

View File

@@ -153,6 +153,7 @@
"InheritWarning": "",
"Instruction_Replace": "Замінити Інструкцію",
"Instructions": "Інструкції",
"InstructionsEditHelp": "",
"Internal": "",
"Invite_Link": "",
"Key_Ctrl": "Ctrl",
@@ -254,6 +255,7 @@
"Ratings": "",
"Recently_Viewed": "Нещодавно переглянуті",
"Recipe": "Рецепт",
"RecipeStepsHelp": "",
"Recipe_Book": "Книга Рецептів",
"Recipe_Image": "Зображення Рецепту",
"Recipes": "Рецепти",
@@ -263,6 +265,7 @@
"RemoveFoodFromShopping": "Видалити {food} з вашого списку покупок",
"Remove_nutrition_recipe": "Видалити харчову цінність з рецепта",
"Reset": "",
"ResetHelp": "",
"Reset_Search": "Скинути Пошук",
"Reusable": "",
"Role": "",

View File

@@ -189,6 +189,7 @@
"Input": "输入",
"Instruction_Replace": "替换指令",
"Instructions": "说明",
"InstructionsEditHelp": "",
"Internal": "内部",
"Invite_Link": "",
"Invites": "邀请",
@@ -312,6 +313,7 @@
"Ratings": "等级",
"Recently_Viewed": "最近浏览",
"Recipe": "食谱",
"RecipeStepsHelp": "",
"Recipe_Book": "食谱书",
"Recipe_Image": "食谱图像",
"Recipes": "食谱",
@@ -321,6 +323,7 @@
"RemoveFoodFromShopping": "从购物清单中移除 {food}",
"Remove_nutrition_recipe": "从食谱中删除营养信息",
"Reset": "重置",
"ResetHelp": "",
"Reset_Search": "重置搜索",
"Reusable": "",
"Role": "",

View File

@@ -59,6 +59,7 @@
"Import_finished": "匯入完成",
"Information": "",
"Ingredients": "",
"InstructionsEditHelp": "",
"Invite_Link": "",
"Keywords": "",
"Link": "",
@@ -96,10 +97,12 @@
"Proteins": "",
"Rating": "",
"Recently_Viewed": "",
"RecipeStepsHelp": "",
"Recipe_Image": "食譜圖片",
"Recipes_per_page": "每頁食譜",
"Remove": "",
"Remove_nutrition_recipe": "從食譜中刪除營養資訊",
"ResetHelp": "",
"Reset_Search": "",
"Reusable": "",
"Role": "",

View File

@@ -1,5 +1,5 @@
<template>
<v-container class="h-100 pt-0 pl-0 pn-0" fluid>
<v-container class="h-100 pt-0 pl-0 pb-0" fluid>
<meal-plan-view></meal-plan-view>
</v-container>

View File

@@ -13,6 +13,7 @@ export const useMealPlanStore = defineStore(_STORE_ID, () => {
let plans = ref(new Map<number, MealPlan>)
let currently_updating = ref([new Date(0), new Date(0)])
const loading = ref(false)
let settings = ref({})
const planList = computed(() => {
@@ -52,15 +53,17 @@ export const useMealPlanStore = defineStore(_STORE_ID, () => {
function refreshFromAPI(from_date: Date, to_date: Date) {
if (currently_updating.value[0] !== from_date || currently_updating.value[1] !== to_date) {
currently_updating.value = [from_date, to_date] // certainly no perfect check but better than nothing
loading.value = true
const api = new ApiApi()
return api.apiMealPlanList({fromDate: DateTime.fromJSDate(from_date).toISODate() as string, toDate: DateTime.fromJSDate(to_date).toISODate() as string}).then(r => {
return api.apiMealPlanList({fromDate: DateTime.fromJSDate(from_date).toISODate() as string, toDate: DateTime.fromJSDate(to_date).toISODate() as string, pageSize: 100}).then(r => {
r.results.forEach((p) => {
plans.value.set(p.id, p)
})
currently_updating.value = [new Date(0), new Date(0)]
}).catch((err) => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
}).finally(() => {
loading.value = false
})
}
return new Promise(() => {
@@ -77,20 +80,23 @@ export const useMealPlanStore = defineStore(_STORE_ID, () => {
function createObject(object: MealPlan) {
const api = new ApiApi()
loading.value = true
return api.apiMealPlanCreate({mealPlan: object}).then((r) => {
useMessageStore().addMessage(MessageType.SUCCESS, 'Created successfully', 7000, object)
plans.value.set(r.id, r)
plans.value.set(r.id!, r)
return r
}).catch((err) => {
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
}).finally(() => {
loading.value = false
})
}
function updateObject(object: MealPlan) {
const api = new ApiApi()
return api.apiMealPlanUpdate({id: object.id, mealPlan: object}).then((r) => {
return api.apiMealPlanUpdate({id: object.id!, mealPlan: object}).then((r) => {
useMessageStore().addMessage(MessageType.SUCCESS, 'Updated successfully', 7000, object)
plans.value.set(r.id, r)
plans.value.set(r.id!, r)
}).catch((err) => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
@@ -98,11 +104,14 @@ export const useMealPlanStore = defineStore(_STORE_ID, () => {
function deleteObject(object: MealPlan) {
const api = new ApiApi()
return api.apiMealPlanDestroy({id: object.id}).then((r) => {
loading.value = true
return api.apiMealPlanDestroy({id: object.id!}).then((r) => {
useMessageStore().addMessage(MessageType.INFO, 'Deleted successfully', 7000, object)
plans.value.delete(object.id)
plans.value.delete(object.id!)
}).catch((err) => {
useMessageStore().addError(ErrorMessageType.DELETE_ERROR, err)
}).finally(() => {
loading.value = false
})
}
@@ -124,7 +133,7 @@ export const useMealPlanStore = defineStore(_STORE_ID, () => {
// return JSON.parse(s)
// }
// }
return {plans, currently_updating, planList, refreshFromAPI, createObject, updateObject, deleteObject, createOrUpdate}
return {plans, currently_updating, planList, loading, refreshFromAPI, createObject, updateObject, deleteObject, createOrUpdate}
})
// enable hot reload for store

View File

@@ -26,6 +26,7 @@ class DeviceSettings {
mealplan_displayWeekNumbers = true
general_tableItemsPerPage = 10
general_closedHelpAlerts: String[] = []
}
export const useUserPreferenceStore = defineStore('user_preference_store', () => {