mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-05 06:08:46 -05:00
various improvements for shopping line item dialog
This commit is contained in:
@@ -1,73 +1,85 @@
|
||||
<template>
|
||||
<v-dialog v-model="showDialog" max-width="500px">
|
||||
<v-dialog :fullscreen="mobile" v-model="showDialog" max-width="500px">
|
||||
<v-card>
|
||||
<v-closable-card-title :title="props.shoppingListFood.food.name" v-model="showDialog"></v-closable-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-card-text class="pt-0 pr-4 pl-4">
|
||||
|
||||
<v-label>{{ $t('Choose_Category') }}</v-label>
|
||||
<ModelSelect model="SupermarketCategory"></ModelSelect>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-btn height="80px" color="info" block stacked>
|
||||
<v-col class="pr-0">
|
||||
<v-btn height="80px" color="info" density="compact" size="small" block stacked>
|
||||
<i class="fa-solid fa-clock-rotate-left fa-2x mb-2"></i>
|
||||
{{ $t('Postpone') }}
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-btn height="80px" color="secondary" block stacked>
|
||||
<v-btn height="80px" color="secondary" density="compact" size="small" block stacked>
|
||||
<i class="fa-solid fa-eye-slash fa-2x mb-2"></i>
|
||||
{{ $t('Ignore_Shopping') }}
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-btn height="80px" color="primary" block stacked>
|
||||
<v-col class="pr-0 pt-0">
|
||||
<v-btn height="80px" color="primary" density="compact" size="small" block stacked>
|
||||
<i class="fa-solid fa-pencil fa-2x mb-2"></i>
|
||||
{{ $t('Edit_Food') }}
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-btn height="80px" color="success" block stacked>
|
||||
<v-col class="pt-0">
|
||||
<v-btn height="80px" color="success" density="compact" size="small" block stacked>
|
||||
<i class="fa-solid fa-plus fa-2x mb-2"></i>
|
||||
{{ $t('Add') }}
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-label class="mt-2">{{ $t('Entries') }}</v-label>
|
||||
<v-label class="mt-3">{{ $t('Entries') }}</v-label>
|
||||
<v-list density="compact">
|
||||
<v-list-item variant="tonal" class="mt-1" v-for="[i, e] in props.shoppingListFood.entries" :key="e.id">
|
||||
<v-list-item-title>
|
||||
<b>
|
||||
{{ e.amount }}
|
||||
<span v-if="e.unit">{{ e.unit.name }}</span>
|
||||
</b>
|
||||
{{ e.food.name }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle v-if="e.recipeMealplan && e.recipeMealplan.recipeName !== ''">
|
||||
<v-icon icon="$recipes" size="x-small"></v-icon> {{ e.recipeMealplan.servings }} {{ $t('Servings') }}
|
||||
<router-link :to="{name: 'view_recipe', params: {id: e.recipeMealplan.id}}" target="_blank"><b>
|
||||
{{ e.recipeMealplan.recipeName }} </b>
|
||||
</router-link>
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-subtitle v-if="e.recipeMealplan && e.recipeMealplan.mealplanType !== undefined">
|
||||
<v-icon icon="$mealplan" size="x-small"></v-icon> {{ e.recipeMealplan.mealplanType }} {{ DateTime.fromJSDate(e.recipeMealplan.mealplanFromDate).toLocaleString(DateTime.DATE_SHORT) }}
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-subtitle>
|
||||
<v-icon icon="fa-solid fa-user" size="x-small"></v-icon> {{ e.createdBy.displayName }} - {{ DateTime.fromJSDate(e.createdAt).toLocaleString(DateTime.DATETIME_SHORT) }}
|
||||
</v-list-item-subtitle>
|
||||
<template v-for="[i, e] in props.shoppingListFood.entries" :key="e.id">
|
||||
<v-list-item border class="mt-1" :class="{'cursor-pointer': !e.recipeMealplan}">
|
||||
<v-list-item-title>
|
||||
<b>
|
||||
{{ e.amount }}
|
||||
<span v-if="e.unit">{{ e.unit.name }}</span>
|
||||
</b>
|
||||
{{ e.food.name }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle v-if="e.recipeMealplan && e.recipeMealplan.recipeName !== ''">
|
||||
{{ e.recipeMealplan.servings }} x
|
||||
<router-link :to="{name: 'view_recipe', params: {id: e.recipeMealplan.id}}" target="_blank" class="text-decoration-none"><b>
|
||||
{{ e.recipeMealplan.recipeName }} </b>
|
||||
</router-link>
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-subtitle v-if="e.recipeMealplan && e.recipeMealplan.mealplanType !== undefined">
|
||||
{{ e.recipeMealplan.mealplanType }} {{ DateTime.fromJSDate(e.recipeMealplan.mealplanFromDate).toLocaleString(DateTime.DATE_SHORT) }}
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-subtitle>
|
||||
{{ e.createdBy.displayName }} - {{ DateTime.fromJSDate(e.createdAt).toLocaleString(DateTime.DATETIME_SHORT) }}
|
||||
</v-list-item-subtitle>
|
||||
|
||||
<template #append>
|
||||
<v-btn size="small" color="delete" icon="$delete" v-if="!e.recipeMealplan">
|
||||
<v-icon icon="$delete"></v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<!-- TODO make properly reactive or delete from the food instance in this component as well-->
|
||||
<model-edit-dialog model="ShoppingListEntry" :item="e" @delete="useShoppingStore().entries.delete(e.id!);" v-if="!e.recipeMealplan"></model-edit-dialog>
|
||||
</v-list-item>
|
||||
</template>
|
||||
|
||||
|
||||
<template #append>
|
||||
<v-btn size="small" color="edit"> <v-icon icon="$edit"></v-icon></v-btn>
|
||||
<v-btn size="small" color="delete"> <v-icon icon="$delete"></v-icon></v-btn>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
|
||||
</v-card-text>
|
||||
<v-card-actions v-if="mobile">
|
||||
<v-btn @click="showDialog = false">{{ $t('Close') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
@@ -79,7 +91,13 @@ import {ShoppingListEntry} from "@/openapi";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
import {IShoppingList, IShoppingListFood} from "@/types/Shopping";
|
||||
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
|
||||
import {VNumberInput} from "vuetify/labs/VNumberInput";
|
||||
import {DateTime} from "luxon";
|
||||
import {useDisplay} from "vuetify";
|
||||
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
|
||||
import {useShoppingStore} from "@/stores/ShoppingStore";
|
||||
|
||||
const {mobile} = useDisplay()
|
||||
|
||||
const showDialog = defineModel<Boolean>()
|
||||
|
||||
@@ -91,4 +109,5 @@ const props = defineProps({
|
||||
|
||||
<style scoped>
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<v-card-title >
|
||||
<v-row align="center">
|
||||
<v-card-title class="pb-0">
|
||||
<v-row align="center" >
|
||||
<v-col cols="11" class="text-truncate">
|
||||
<i :class="props.icon" v-if="props.icon != ''"></i>
|
||||
{{ props.title }}
|
||||
<v-card-subtitle class="pa-0" v-if="props.subTitle != ''">{{ props.subTitle}}</v-card-subtitle>
|
||||
</v-col>
|
||||
<v-col cols="1" v-if="!props.hideClose">
|
||||
<v-btn class="float-right" icon="$close" variant="plain" @click="model = false; emit('close')"></v-btn>
|
||||
<v-btn class="float-right pr-2" icon="$close" variant="plain" @click="model = false; emit('close')"></v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-title>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<model-editor-base
|
||||
:loading="loading"
|
||||
:dialog="dialog"
|
||||
@save="saveObject"
|
||||
@delete="deleteObject"
|
||||
@close="emit('close')"
|
||||
:is-update="isUpdate()"
|
||||
:model-class="modelClass"
|
||||
:object-name="editingObjName()">
|
||||
<v-card-text>
|
||||
<v-form :disabled="loading">
|
||||
<v-number-input v-model="editingObj.amount" control-variant="split">
|
||||
<template #prepend>
|
||||
<v-btn icon="" @click="editingObj.amount = editingObj.amount / 2">
|
||||
<v-icon icon="fa-solid fa-divide"></v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<template #append>
|
||||
<v-btn icon="" @click="editingObj.amount = editingObj.amount * 2">
|
||||
<v-icon icon="fa-solid fa-times"></v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-number-input>
|
||||
<model-select model="Unit" v-model="editingObj.unit"></model-select>
|
||||
<model-select model="Food" v-model="editingObj.food"></model-select>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
</model-editor-base>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {onMounted, PropType} from "vue";
|
||||
import {ShoppingListEntry} from "@/openapi";
|
||||
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
|
||||
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {VNumberInput} from "vuetify/labs/VNumberInput";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
|
||||
const props = defineProps({
|
||||
item: {type: {} as PropType<ShoppingListEntry>, required: false, default: null},
|
||||
itemId: {type: [Number, String], required: false, default: undefined},
|
||||
dialog: {type: Boolean, default: false}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['create', 'save', 'delete', 'close'])
|
||||
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<ShoppingListEntry>('ShoppingListEntry', emit)
|
||||
|
||||
// object specific data (for selects/display)
|
||||
|
||||
onMounted(() => {
|
||||
setupState(props.item, props.itemId)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -3,6 +3,7 @@ import {onBeforeMount, ref} from "vue";
|
||||
import {EditorSupportedModels, GenericModel, getGenericModelFromString} from "@/types/Models";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {ResponseError} from "@/openapi";
|
||||
import {getNestedProperty} from "@/utils/utils";
|
||||
|
||||
// TODO type emit parameter (https://mokkapps.de/vue-tips/emit-event-from-composable)
|
||||
// TODO alternatively there seems to be a getContext method to get the calling context (good practice?)
|
||||
@@ -120,7 +121,8 @@ export function useModelEditorFunctions<T>(modelName: EditorSupportedModels, emi
|
||||
let name = ''
|
||||
if (editingObj.value.id) {
|
||||
modelClass.value.model.toStringKeys.forEach(key => {
|
||||
name += ' ' + key.split('.').reduce((a, b) => a[b], editingObj.value);
|
||||
let value = getNestedProperty(editingObj.value, key)
|
||||
name += ' ' + ((value != null) ? value : '')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -260,6 +260,7 @@
|
||||
"Servings": "",
|
||||
"Settings": "",
|
||||
"Share": "",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "",
|
||||
"Shopping_Category": "",
|
||||
"Shopping_List_Empty": "",
|
||||
|
||||
@@ -253,6 +253,7 @@
|
||||
"Servings": "Порции",
|
||||
"Settings": "Настройки",
|
||||
"Share": "Споделяне",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Категории за пазаруване",
|
||||
"Shopping_Category": "Категория за пазаруване",
|
||||
"Shopping_List_Empty": "Вашият списък за пазаруване в момента е празен, можете да добавяте артикули чрез контекстното меню на запис на план за хранене (щракнете с десния бутон върху картата или щракнете с левия бутон върху иконата на менюто)",
|
||||
|
||||
@@ -333,6 +333,7 @@
|
||||
"Settings": "",
|
||||
"Share": "",
|
||||
"ShoppingBackgroundSyncWarning": "",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "",
|
||||
"Shopping_Category": "",
|
||||
"Shopping_List_Empty": "",
|
||||
|
||||
@@ -330,6 +330,7 @@
|
||||
"Servings": "Porce",
|
||||
"Settings": "Nastavení",
|
||||
"Share": "Sdílet",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Kategorie nákupního seznamu",
|
||||
"Shopping_Category": "Kategorie nákupního seznamu",
|
||||
"Shopping_List_Empty": "Váš nákupní seznam je momentálně prázdný, můžete přidat položky pomocí kontextového menu záznamu v jídelníčku (pravým kliknutím na kartu nebo levým kliknutím na ikonu menu)",
|
||||
|
||||
@@ -312,6 +312,7 @@
|
||||
"Servings": "Serveringer",
|
||||
"Settings": "Indstillinger",
|
||||
"Share": "Del",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Indkøbskategorier",
|
||||
"Shopping_Category": "Indkøbskategori",
|
||||
"Shopping_List_Empty": "Din indkøbsliste er i øjeblikket tom, du kan tilføje varer via menuen for et madplanspunkt (højreklik på punktet eller venstreklik på menu ikonet)",
|
||||
|
||||
@@ -336,6 +336,7 @@
|
||||
"Settings": "Einstellungen",
|
||||
"Share": "Teilen",
|
||||
"ShoppingBackgroundSyncWarning": "Schlechte Netzwerkverbindung, Warten auf Synchronisation ...",
|
||||
"ShoppingListEntry": "Einkaufslisten Eintrag",
|
||||
"Shopping_Categories": "Einkaufskategorien",
|
||||
"Shopping_Category": "Einkaufskategorie",
|
||||
"Shopping_List_Empty": "Deine Einkaufsliste ist aktuell leer. Einträge können über das Kontextmenü hinzugefügt werden (Rechtsklick auf einen Eintrag oder Klick auf das Menü-Icon)",
|
||||
|
||||
@@ -304,6 +304,7 @@
|
||||
"Servings": "Μερίδες",
|
||||
"Settings": "Ρυθμίσεις",
|
||||
"Share": "Κοινοποίηση",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Κατηγορίες αγορών",
|
||||
"Shopping_Category": "Κατηγορία αγορών",
|
||||
"Shopping_List_Empty": "Η λίστα αγορών σας είναι κενή, μπορείτε να προσθέσετε αντικείμενα από το μενού μιας εγγραφής στο πρόγραμμα γευμάτων (δεξί κλικ στην κάρτα ή αριστερό κλικ στο εικονίδιο του μενού)",
|
||||
|
||||
@@ -335,6 +335,7 @@
|
||||
"Settings": "Settings",
|
||||
"Share": "Share",
|
||||
"ShoppingBackgroundSyncWarning": "Bad network, waiting to sync ...",
|
||||
"ShoppingListEntry": "Shoppinglist Entry",
|
||||
"Shopping_Categories": "Shopping Categories",
|
||||
"Shopping_Category": "Shopping Category",
|
||||
"Shopping_List_Empty": "Your shopping list is currently empty, you can add items via the context menu of a meal plan entry (right click on the card or left click the menu icon)",
|
||||
|
||||
@@ -332,6 +332,7 @@
|
||||
"Settings": "Opciones",
|
||||
"Share": "Compartir",
|
||||
"ShoppingBackgroundSyncWarning": "Red defectuosa, esperando para sincronizar ...",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Categorías Compras",
|
||||
"Shopping_Category": "Categoría Compras",
|
||||
"Shopping_List_Empty": "Tu lista de la compra esta actualmente vacía, puedes añadir nuevos elementos mediante el menú de un régimen de comidas (click derecho en la tarjeta o click sobre el menú de la misma)",
|
||||
|
||||
@@ -185,6 +185,7 @@
|
||||
"Servings": "Annokset",
|
||||
"Settings": "Asetukset",
|
||||
"Share": "Jaa",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Ostoskategoriat",
|
||||
"Shopping_Category": "Ostosluokka",
|
||||
"Shopping_List_Empty": "Ostoslistasi on tällä hetkellä tyhjä, voit lisätä tuotteita ateriasuunnitelmamerkinnän valikon kautta(klikkaa korttia hiiren kaksoispainikkeella tai valikkokuvaketta)",
|
||||
|
||||
@@ -333,6 +333,7 @@
|
||||
"Settings": "Paramètres",
|
||||
"Share": "Partager",
|
||||
"ShoppingBackgroundSyncWarning": "Mauvais réseau, en attente de synchronisation ...",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Catégories de courses",
|
||||
"Shopping_Category": "Catégorie de courses",
|
||||
"Shopping_List_Empty": "Votre liste de courses est actuellement vide, vous pouvez ajouter des articles via le menu contextuel d’une entrée de menu de la semaine (clic droit sur la carte ou clic gauche sur l’icône du menu)",
|
||||
|
||||
@@ -334,6 +334,7 @@
|
||||
"Settings": "הגדרות",
|
||||
"Share": "שיתוף",
|
||||
"ShoppingBackgroundSyncWarning": "בעיית תקשורת, מחכה לסנכון...",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "קטגוריות קניות",
|
||||
"Shopping_Category": "קטגוריית קניות",
|
||||
"Shopping_List_Empty": "רשימת הקניות שלך ריקה כרגע. ניתן להוסיף פריטים דרך תפריט תוכנית אוכל (מקש ימני על הכרטיס או מקש שמאלי על האייקון בתפריט)",
|
||||
|
||||
@@ -306,6 +306,7 @@
|
||||
"Servings": "Adag",
|
||||
"Settings": "Beállítások",
|
||||
"Share": "Megosztás",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Vásárlási kategóriák",
|
||||
"Shopping_Category": "Vásárlási kategória",
|
||||
"Shopping_List_Empty": "A bevásárlólista jelenleg üres. A tételeket a menüterv menüjében (jobb klikk a kártyára vagy bal klikk a menü ikonjára) adhatja hozzá.",
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
"Servings": "",
|
||||
"Settings": "Կարգավորումներ",
|
||||
"Share": "",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Category": "Գնումների կատեգորիա",
|
||||
"Shopping_list": "Գնումների ցուցակ",
|
||||
"Show_as_header": "Ցույց տալ որպես խորագիր",
|
||||
|
||||
@@ -282,6 +282,7 @@
|
||||
"Servings": "Porsi",
|
||||
"Settings": "Pengaturan",
|
||||
"Share": "Bagikan",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Kategori Belanja",
|
||||
"Shopping_Category": "Kategori Belanja",
|
||||
"Shopping_List_Empty": "",
|
||||
|
||||
@@ -333,6 +333,7 @@
|
||||
"Settings": "",
|
||||
"Share": "",
|
||||
"ShoppingBackgroundSyncWarning": "",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "",
|
||||
"Shopping_Category": "",
|
||||
"Shopping_List_Empty": "",
|
||||
|
||||
@@ -290,6 +290,7 @@
|
||||
"Servings": "Porzioni",
|
||||
"Settings": "Impostazioni",
|
||||
"Share": "Condividi",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Categorie di spesa",
|
||||
"Shopping_Category": "Categoria Spesa",
|
||||
"Shopping_List_Empty": "La tua lista della spesa è vuota, puoi aggiungere elementi dal menù contestuale di una voce nel piano alimentare (clicca con il tasto destro sulla scheda o clicca con il tasto sinistro sull'icona del menù)",
|
||||
|
||||
@@ -310,6 +310,7 @@
|
||||
"Servings": "",
|
||||
"Settings": "",
|
||||
"Share": "",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "",
|
||||
"Shopping_Category": "",
|
||||
"Shopping_List_Empty": "",
|
||||
|
||||
@@ -302,6 +302,7 @@
|
||||
"Servings": "Porsjoner",
|
||||
"Settings": "Innstillinger",
|
||||
"Share": "Del",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Butikk Kategorier",
|
||||
"Shopping_Category": "Butikk Kategori",
|
||||
"Shopping_List_Empty": "",
|
||||
|
||||
@@ -306,6 +306,7 @@
|
||||
"Servings": "Porties",
|
||||
"Settings": "Instellingen",
|
||||
"Share": "Deel",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Boodschappen categorieën",
|
||||
"Shopping_Category": "Boodschappencategorie",
|
||||
"Shopping_List_Empty": "Je boodschappenlijst is op dit moment leeg, je kan artikelen via het context menu of een maaltijdplan (rechtermuisknop op de kaart of linkermuisknop op het menu icoon) toevoegen",
|
||||
|
||||
@@ -335,6 +335,7 @@
|
||||
"Settings": "Ustawienia",
|
||||
"Share": "Udostępnij",
|
||||
"ShoppingBackgroundSyncWarning": "Słaba sieć, oczekiwanie na synchronizację...",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Kategorie zakupów",
|
||||
"Shopping_Category": "Kategoria zakupów",
|
||||
"Shopping_List_Empty": "Twoja lista zakupów jest obecnie pusta, możesz dodawać pozycje za pomocą menu kontekstowego wpisu planu posiłków (kliknij prawym przyciskiem myszy na karcie lub lewym przyciskiem myszy ikonę menu)",
|
||||
|
||||
@@ -248,6 +248,7 @@
|
||||
"Servings": "Doses",
|
||||
"Settings": "Definições",
|
||||
"Share": "Partilhar",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Categorias de Compras",
|
||||
"Shopping_Category": "Categoria de Compras",
|
||||
"Shopping_List_Empty": "A sua lista de compras encontra-se vazia, pode adicionar itens através do menu de contexto de um plano de refeições (carregar com o botão direito no cartão ou carregar com o botão esquerdo no ícone do menu)",
|
||||
|
||||
@@ -322,6 +322,7 @@
|
||||
"Settings": "Configurações",
|
||||
"Share": "Compartilhar",
|
||||
"ShoppingBackgroundSyncWarning": "Rede ruim, aguardando sincronização...",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Categorias de Mercado",
|
||||
"Shopping_Category": "Categoria de Mercado",
|
||||
"Shopping_List_Empty": "Sua lista de compras está vazia. Você pode incluir itens pelo menu Plano de Refeição (click direiro no cartão ou click esquerdo no ícone do menu)",
|
||||
|
||||
@@ -294,6 +294,7 @@
|
||||
"Servings": "Porții",
|
||||
"Settings": "Setări",
|
||||
"Share": "Împărtășire",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Categorii de cumpărături",
|
||||
"Shopping_Category": "Categorie de cumpărături",
|
||||
"Shopping_List_Empty": "Lista de cumpărături este în prezent goală, puteți adăuga articole prin meniul contextual al unei intrări în planul de alimentație (faceți click dreapta pe card sau faceți click stânga pe iconița meniului)",
|
||||
|
||||
@@ -233,6 +233,7 @@
|
||||
"Servings": "Порции",
|
||||
"Settings": "Настройки",
|
||||
"Share": "Поделиться",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Категории покупок",
|
||||
"Shopping_Category": "Категория покупок",
|
||||
"Shopping_List_Empty": "В настоящее время ваш список покупок пуст, вы можете добавить пункты через контекстное меню записи плана питания (щелкните правой кнопкой мыши на карточке или щелкните левой кнопкой мыши на значке меню)",
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
"Servings": "Porcije",
|
||||
"Settings": "Nastavitve",
|
||||
"Share": "Deli",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Kategorije nakupa",
|
||||
"Shopping_Category": "Kategorija nakupa",
|
||||
"Shopping_List_Empty": "Tvoj nakupovalni listek je trenutno prazen. Stvari lahko dodaš preko menija za načrt obroka (desni klik na kartico ali levi klik na ikono za meni)",
|
||||
|
||||
@@ -335,6 +335,7 @@
|
||||
"Settings": "Inställningar",
|
||||
"Share": "Dela",
|
||||
"ShoppingBackgroundSyncWarning": "Dålig uppkoppling, inväntar synkronisering...",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Shopping kategorier",
|
||||
"Shopping_Category": "Shopping kategori",
|
||||
"Shopping_List_Empty": "Din inköpslista är för närvarande tom, du kan lägga till varor via snabbmenyn för en måltidsplan (högerklicka på kortet eller vänsterklicka på menyikonen)",
|
||||
|
||||
@@ -334,6 +334,7 @@
|
||||
"Settings": "Ayarlar",
|
||||
"Share": "Paylaş",
|
||||
"ShoppingBackgroundSyncWarning": "Kötü bağlantı, senkronizasyon bekleniyor...",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Alışveriş Kategorileri",
|
||||
"Shopping_Category": "Alışveriş Kategorisi",
|
||||
"Shopping_List_Empty": "Alışveriş listeniz şu anda boş, yemek planı girişinin içerik menüsü aracılığıyla öğeler ekleyebilirsiniz (karta sağ tıklayın veya menü simgesine sol tıklayın)",
|
||||
|
||||
@@ -268,6 +268,7 @@
|
||||
"Servings": "Порції",
|
||||
"Settings": "Налаштування",
|
||||
"Share": "Поділитися",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "Категорії Покупок",
|
||||
"Shopping_Category": "Категорія Покупок",
|
||||
"Shopping_List_Empty": "Ваш список покупок зараз пустий, ви можете додати товари за допомогою контекстного меню плану харчування (права кнопка мишки на картку або на ліву кнопку на іконку меню)",
|
||||
|
||||
@@ -329,6 +329,7 @@
|
||||
"Settings": "设置",
|
||||
"Share": "分享",
|
||||
"ShoppingBackgroundSyncWarning": "网络状况不佳,正在等待进行同步……",
|
||||
"ShoppingListEntry": "",
|
||||
"Shopping_Categories": "购物类别",
|
||||
"Shopping_Category": "购物类别",
|
||||
"Shopping_List_Empty": "您的购物列表当前为空,您可以通过用餐计划条目的上下文菜单添加项目(右键单击卡片或左键单击菜单图标)",
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
"Servings": "",
|
||||
"Settings": "",
|
||||
"Share": "",
|
||||
"ShoppingListEntry": "",
|
||||
"Show_as_header": "顯示為標題",
|
||||
"Size": "",
|
||||
"Sort_by_new": "按最新排序",
|
||||
|
||||
@@ -70,7 +70,7 @@ export type Model = {
|
||||
}
|
||||
export let SUPPORTED_MODELS = new Map<string, Model>()
|
||||
|
||||
export type EditorSupportedModels = 'UnitConversion' | 'AccessToken' | 'InviteLink' | 'UserSpace' | 'MealType' | 'MealPlan' | 'Property' | 'Food' | 'Supermarket' | 'SupermarketCategory' | 'PropertyType' | 'Automation' | 'Keyword' | 'UserFile'
|
||||
export type EditorSupportedModels = 'UnitConversion' | 'AccessToken' | 'InviteLink' | 'UserSpace' | 'MealType' | 'MealPlan' | 'Property' | 'Food' | 'Supermarket' | 'SupermarketCategory' | 'PropertyType' | 'Automation' | 'Keyword' | 'UserFile' | 'ShoppingListEntry'
|
||||
|
||||
export const TFood = {
|
||||
name: 'Food',
|
||||
@@ -215,6 +215,23 @@ export const TSupermarketCategory = {
|
||||
} as Model
|
||||
registerModel(TSupermarketCategory)
|
||||
|
||||
export const TShoppingListEntry = {
|
||||
name: 'ShoppingListEntry',
|
||||
localizationKey: 'ShoppingListEntry',
|
||||
icon: 'fa-solid fa-list-check',
|
||||
|
||||
isPaginated: true,
|
||||
toStringKeys: ['amount', 'unit.name', 'food.name'],
|
||||
|
||||
tableHeaders: [
|
||||
{title: 'Amount', key: 'amount'},
|
||||
{title: 'Unit', key: 'unit.name'},
|
||||
{title: 'Food', key: 'food.name'},
|
||||
{title: 'Actions', key: 'action', align: 'end'},
|
||||
]
|
||||
} as Model
|
||||
registerModel(TShoppingListEntry)
|
||||
|
||||
export const TPropertyType = {
|
||||
name: 'PropertyType',
|
||||
localizationKey: 'Property',
|
||||
@@ -236,7 +253,7 @@ export const TProperty = {
|
||||
icon: 'fa-solid fa-database',
|
||||
|
||||
isPaginated: true,
|
||||
toStringKeys: ['propertyType'], // TODO improve
|
||||
toStringKeys: ['propertyAmount','propertyType.name'],
|
||||
|
||||
tableHeaders: [
|
||||
{title: 'Amount', key: 'propertyAmount'},
|
||||
@@ -252,7 +269,7 @@ export const TUnitConversion = {
|
||||
icon: 'fa-solid fa-exchange-alt',
|
||||
|
||||
isPaginated: true,
|
||||
toStringKeys: ['food'], // TODO improve
|
||||
toStringKeys: ['food.name','baseUnit.name','convertedUnit.name'],
|
||||
|
||||
tableHeaders: [
|
||||
{title: 'Food', key: 'food.name'},
|
||||
@@ -350,7 +367,7 @@ export const TUserSpace = {
|
||||
icon: 'fa-solid fa-users',
|
||||
|
||||
isPaginated: true,
|
||||
toStringKeys: ['user'], // TODO improve
|
||||
toStringKeys: ['user.displayName'],
|
||||
|
||||
disableCreate: true,
|
||||
|
||||
|
||||
18
vue3/src/utils/utils.ts
Normal file
18
vue3/src/utils/utils.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Gets a nested property of an object given a dot-notation path.
|
||||
*
|
||||
* @param object The object to access the property from.
|
||||
* @param path The dot-notation path to the property.
|
||||
* @returns The value of the nested property, or `undefined` if not found.
|
||||
*/
|
||||
export function getNestedProperty(object: any, path: string): any {
|
||||
const pathParts = path.split('.');
|
||||
|
||||
return pathParts.reduce((obj, key) => {
|
||||
if (obj && typeof obj === 'object') {
|
||||
return obj[key]
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}, object);
|
||||
}
|
||||
Reference in New Issue
Block a user