mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-04 21:58:54 -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>
|
||||
Reference in New Issue
Block a user