mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-02 12:49:02 -05:00
shopping line item dialog WIP
This commit is contained in:
94
vue3/src/components/dialogs/ShoppingLineItemDialog.vue
Normal file
94
vue3/src/components/dialogs/ShoppingLineItemDialog.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<v-dialog 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-label>{{ $t('Choose_Category') }}</v-label>
|
||||
<ModelSelect model="SupermarketCategory"></ModelSelect>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-btn height="80px" color="info" 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>
|
||||
<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>
|
||||
<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>
|
||||
<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-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 #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>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {PropType} from "vue";
|
||||
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 {DateTime} from "luxon";
|
||||
|
||||
const showDialog = defineModel<Boolean>()
|
||||
|
||||
const props = defineProps({
|
||||
shoppingListFood: {type: {} as PropType<IShoppingListFood>, required: true},
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<v-list-item class="swipe-container" :id="itemContainerId" @touchend="handleSwipe()"
|
||||
<v-list-item class="swipe-container" :id="itemContainerId" @touchend="handleSwipe()" @click="emit('clicked', entries)"
|
||||
v-if="(useUserPreferenceStore().deviceSettings.shopping_show_checked_entries || !isChecked) && (useUserPreferenceStore().deviceSettings.shopping_show_delayed_entries || !isDelayed)"
|
||||
@click="detail_modal_visible = true"
|
||||
>
|
||||
<!-- <div class="swipe-action" :class="{'bg-success': !isChecked , 'bg-warning': isChecked }">-->
|
||||
<!-- <i class="swipe-icon fa-fw fas" :class="{'fa-check': !isChecked , 'fa-cart-plus': isChecked }"></i>-->
|
||||
@@ -16,13 +15,14 @@
|
||||
<div class="flex-grow-1 p-2">
|
||||
<div class="d-flex">
|
||||
<div class="d-flex flex-column pr-2">
|
||||
<span v-for="[i, a] in amounts" v-bind:key="a">
|
||||
<span v-for="[i, a] in amounts" v-bind:key="a.key">
|
||||
|
||||
<span>
|
||||
<i class="fas fa-check" v-if="a.checked && !isChecked"></i>
|
||||
<i class="fas fa-hourglass-half" v-if="a.delayed && !a.checked"></i> <b>
|
||||
{{ a.amount }}
|
||||
{{ a.unit.name }} </b>
|
||||
<span v-if="a.unit">{{ a.unit.name }}</span>
|
||||
</b>
|
||||
</span>
|
||||
<br/>
|
||||
</span>
|
||||
@@ -60,14 +60,12 @@ import {ApiApi, Food, ShoppingListEntry} from '@/openapi'
|
||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
||||
import {ShoppingLineAmount} from "@/types/Shopping";
|
||||
|
||||
const emit = defineEmits(['clicked'])
|
||||
|
||||
const props = defineProps({
|
||||
entries: {type: [] as PropType<ShoppingListEntry[]>, required: true},
|
||||
entries: {type: Array as PropType<Array<ShoppingListEntry>>, required: true},
|
||||
})
|
||||
|
||||
const detail_modal_visible = ref(false)
|
||||
const editing_food = ref({} as Food)
|
||||
|
||||
|
||||
const itemContainerId = computed(() => {
|
||||
let id = 'id_sli_'
|
||||
for (let i in props.entries) {
|
||||
@@ -125,6 +123,7 @@ const amounts = computed((): Map<number, ShoppingLineAmount> => {
|
||||
unitAmounts.get(unit)!.amount += e.amount
|
||||
} else {
|
||||
unitAmounts.set(unit, {
|
||||
key: e.food?.id!,
|
||||
amount: e.amount,
|
||||
unit: e.unit,
|
||||
checked: e.checked,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<v-tabs v-model="currentTab" density="compact">
|
||||
<v-tabs v-model="currentTab" >
|
||||
<v-tab value="shopping"><i class="fas fa-shopping-cart fa-fw"></i> <span class="d-none d-md-block ms-1">{{ $t('Shopping_list') }}</span></v-tab>
|
||||
<v-tab value="recipes"><i class="fas fa-book fa-fw"></i> <span class="d-none d-md-block ms-1">{{ $t('Recipes') }}</span></v-tab>
|
||||
</v-tabs>
|
||||
@@ -30,8 +30,8 @@
|
||||
<v-list-subheader v-else>{{ category.name }}</v-list-subheader>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<template v-for="[i, value] in category.foods" :key="i">
|
||||
<shopping-line-item :entries="Array.from(value.entries.values())"></shopping-line-item>
|
||||
<template v-for="[i, value] in category.foods" :key="value.food.id">
|
||||
<shopping-line-item :entries="Array.from(value.entries.values())" @clicked="args => {shoppingLineItemDialog = true; shoppingLineItemDialogFood = value;}"></shopping-line-item>
|
||||
</template>
|
||||
|
||||
</template>
|
||||
@@ -46,18 +46,22 @@
|
||||
<v-card-title>{{ $t('Recipes') }}</v-card-title>
|
||||
<v-card-text>
|
||||
|
||||
<v-label >{{$t('Add_to_Shopping')}}</v-label>
|
||||
<v-label>{{ $t('Add_to_Shopping') }}</v-label>
|
||||
<ModelSelect model="Recipe"></ModelSelect>
|
||||
|
||||
<v-label>{{$t('Recipes')}}</v-label>
|
||||
<v-label>{{ $t('Recipes') }}</v-label>
|
||||
<v-list>
|
||||
|
||||
<v-list-item v-for="r in useShoppingStore().getAssociatedRecipes()">
|
||||
{{r}}
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-window-item>
|
||||
</v-window>
|
||||
|
||||
<shopping-line-item-dialog v-model="shoppingLineItemDialog" :shopping-list-food="shoppingLineItemDialogFood"></shopping-line-item-dialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -69,12 +73,17 @@ import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
||||
import ShoppingLineItem from "@/components/display/ShoppingLineItem.vue";
|
||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
import ShoppingLineItemDialog from "@/components/dialogs/ShoppingLineItemDialog.vue";
|
||||
import {IShoppingListFood} from "@/types/Shopping";
|
||||
|
||||
const currentTab = ref("shopping")
|
||||
|
||||
const ingredientInput = ref('')
|
||||
const ingredientInputIcon = ref('fa-solid fa-plus')
|
||||
|
||||
const shoppingLineItemDialog = ref(false)
|
||||
const shoppingLineItemDialogFood = ref({} as IShoppingListFood)
|
||||
|
||||
onMounted(() => {
|
||||
useShoppingStore().refreshFromAPI()
|
||||
})
|
||||
@@ -87,7 +96,7 @@ function addIngredient() {
|
||||
|
||||
api.apiIngredientFromStringCreate({ingredientString: {text: ingredientInput.value} as IngredientString}).then(r => {
|
||||
useShoppingStore().createObject({
|
||||
amount: r.amount,
|
||||
amount: Math.max(r.amount, 1),
|
||||
unit: (r.unit != null) ? {name: r.unit} as Unit : null,
|
||||
food: {name: r.food} as Food,
|
||||
} as ShoppingListEntry)
|
||||
|
||||
Reference in New Issue
Block a user