This commit is contained in:
vabene1111
2024-10-27 14:40:33 +01:00
parent 77748a951b
commit ba401877e8
5 changed files with 109 additions and 29 deletions

View File

@@ -10,13 +10,13 @@
<v-row>
<v-col class="pr-0">
<v-btn height="80px" color="info" density="compact" size="small" block stacked>
<v-btn height="80px" color="info" density="compact" size="small" block stacked @click="useShoppingStore().delayEntries(entriesList, !isDelayed, true); ">
<i class="fa-solid fa-clock-rotate-left fa-2x mb-2"></i>
{{ $t('Postpone') }}
{{ $t('Postpone') }} {{isDelayed}}
</v-btn>
</v-col>
<v-col>
<v-btn height="80px" color="secondary" density="compact" size="small" block stacked>
<v-btn height="80px" color="secondary" density="compact" size="small" block stacked @click="useShoppingStore().setFoodIgnoredState(entriesList,true, true); showDialog = false">
<i class="fa-solid fa-eye-slash fa-2x mb-2"></i>
{{ $t('Ignore_Shopping') }}
</v-btn>
@@ -24,7 +24,7 @@
</v-row>
<v-row>
<v-col class="pr-0 pt-0">
<v-btn height="80px" color="primary" density="compact" size="small" block stacked>
<v-btn height="80px" color="primary" density="compact" size="small" :to="{name: 'ModelEditPage', params: {model: 'Food', id: props.shoppingListFood?.food.id!}}" target="_blank" block stacked>
<i class="fa-solid fa-pencil fa-2x mb-2"></i>
{{ $t('Edit_Food') }}
</v-btn>
@@ -67,7 +67,7 @@
</v-btn>
</template>
<!-- TODO make properly reactive or delete from the food instance in this component as well-->
<!-- TODO make properly reactive or delete from the food instance in this component as well | ADD functionality once reactive -->
<model-edit-dialog model="ShoppingListEntry" :item="e" @delete="useShoppingStore().entries.delete(e.id!);" v-if="!e.recipeMealplan"></model-edit-dialog>
</v-list-item>
</template>
@@ -86,7 +86,7 @@
<script setup lang="ts">
import {PropType} from "vue";
import {compile, computed, PropType, watch} from "vue";
import {ShoppingListEntry} from "@/openapi";
import ModelSelect from "@/components/inputs/ModelSelect.vue";
import {IShoppingList, IShoppingListFood} from "@/types/Shopping";
@@ -96,6 +96,7 @@ import {DateTime} from "luxon";
import {useDisplay} from "vuetify";
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
import {useShoppingStore} from "@/stores/ShoppingStore";
import ShoppingListEntryEditor from "@/components/model_editors/ShoppingListEntryEditor.vue";
const {mobile} = useDisplay()
@@ -105,6 +106,28 @@ const props = defineProps({
shoppingListFood: {type: {} as PropType<IShoppingListFood>, required: true},
})
watch(() => {props.shoppingListFood}, () => {
console.log('PROP WATCH')
})
const entriesList = computed(() => {
let list = [] as ShoppingListEntry[]
props.shoppingListFood?.entries.forEach(e => {
list.push(e)
})
return list
})
const isDelayed = computed(() => {
let isDelayed = false
props.shoppingListFood.entries.forEach(e => {
isDelayed = isDelayed || e.delayUntil != null
})
console.log('computing is delayed', isDelayed)
return isDelayed
})
</script>
<style scoped>

View File

@@ -6,20 +6,15 @@
<!-- <i class="swipe-icon fa-fw fas" :class="{'fa-check': !isChecked , 'fa-cart-plus': isChecked }"></i>-->
<!-- </div>-->
<template #prepend>
<v-btn color="primary" v-if="isDelayed">
<i class="fa-fw fas fa-hourglass-half"></i>
</v-btn>
</template>
<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.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>
<i class="fas fa-check text-warning" v-if="a.checked && !isChecked"></i>
<i class="fas fa-hourglass-half text-primary" v-if="a.delayed && !a.checked"></i> <b>
{{ a.amount }}
<span v-if="a.unit">{{ a.unit.name }}</span>
</b>
@@ -58,12 +53,13 @@ import {useShoppingStore} from "@/stores/ShoppingStore.js";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.js";
import {ApiApi, Food, ShoppingListEntry} from '@/openapi'
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
import {ShoppingLineAmount} from "@/types/Shopping";
import {IShoppingListFood, ShoppingLineAmount} from "@/types/Shopping";
const emit = defineEmits(['clicked'])
const props = defineProps({
entries: {type: Array as PropType<Array<ShoppingListEntry>>, required: true},
shoppingListFood: {type: {} as PropType<IShoppingListFood>, required: true},
})
const itemContainerId = computed(() => {

View File

@@ -1,7 +1,33 @@
<template>
<v-tabs v-model="currentTab" >
<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-menu :close-on-content-click="false">
<template v-slot:activator="{ props }">
<v-btn
class="me-4 float-right"
height="100%"
rounded="0"
variant="plain"
v-bind="props"
>
<i class="fa-solid fa-sliders"></i>
</v-btn>
</template>
<v-list density="compact">
<v-list-item @click="useShoppingStore().undoChange()" prepend-icon="fa-solid fa-arrow-rotate-left">{{ $t('Undo') }}</v-list-item>
<v-divider></v-divider>
<v-list-item>
<v-switch color="primary" hide-details :label="$t('ShowDelayed')" v-model="useUserPreferenceStore().deviceSettings.shopping_show_delayed_entries"></v-switch>
</v-list-item>
<v-list-item>
<v-switch color="primary" hide-details :label="$t('ShowRecentlyCompleted')" v-model="useUserPreferenceStore().deviceSettings.shopping_show_checked_entries"></v-switch>
</v-list-item>
</v-list>
</v-menu>
</v-tabs>
<v-window v-model="currentTab">
@@ -31,7 +57,8 @@
<v-divider></v-divider>
<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>
<shopping-line-item :shopping-list-food="value" :entries="Array.from(value.entries.values())"
@clicked="args => {shoppingLineItemDialog = true; shoppingLineItemDialogFood = value; console.log('SETTING ITEMS')}"></shopping-line-item>
</template>
</template>
@@ -52,7 +79,7 @@
<v-label>{{ $t('Recipes') }}</v-label>
<v-list>
<v-list-item v-for="r in useShoppingStore().getAssociatedRecipes()">
{{r}}
{{ r }}
</v-list-item>
</v-list>
</v-card-text>

View File

@@ -1,5 +1,5 @@
import {acceptHMRUpdate, defineStore} from "pinia"
import {ApiApi, ShoppingListEntry, Supermarket, SupermarketCategory} from "@/openapi";
import {ApiApi, Food, ShoppingListEntry, Supermarket, SupermarketCategory} from "@/openapi";
import {computed, ref} from "vue";
import {
IShoppingExportEntry,
@@ -7,11 +7,12 @@ import {
IShoppingListCategory,
IShoppingListFood,
IShoppingSyncQueueEntry,
ShoppingGroupingOptions, ShoppingListStats,
ShoppingGroupingOptions,
ShoppingListStats,
ShoppingOperationHistoryEntry,
ShoppingOperationHistoryType
} from "@/types/Shopping";
import {ErrorMessageType, MessageType, useMessageStore} from "@/stores/MessageStore";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
const _STORE_ID = "shopping_store"
@@ -72,7 +73,7 @@ export const useShoppingStore = defineStore(_STORE_ID, () => {
categoryStats.countChecked++
} else {
categoryStats.countUnchecked++
if(entry.delayUntil != null) {
if (entry.delayUntil != null) {
categoryStats.countUncheckedDelayed++
}
}
@@ -418,18 +419,48 @@ export const useShoppingStore = defineStore(_STORE_ID, () => {
* @param delay if entries should be delayed or if delay should be removed
* @param undo if the user should be able to undo the change or not
*/
function delayEntries(entries: ShoppingListEntry[], delay: boolean, undo: boolean) {
function setEntriesDelayedState(entries: ShoppingListEntry[], delay: boolean, undo: boolean) {
let delay_hours = useUserPreferenceStore().userSettings.defaultDelay!
let delayDate = new Date(Date.now() + delay_hours * (60 * 60 * 1000))
if (undo) {
registerChange((delay ? 'DELAY' : 'UNDELAY'), entries)
}
entries.forEach(entry => {
entry.delayUntil = (delay ? delayDate : null)
console.log('DELAY: ', delay, entry.delayUntil, entry)
updateObject(entry)
})
}
for (let i in entries) {
entries[i].delayUntil = (delay ? delayDate : null)
updateObject(entries[i])
/**
* ignore all foods of the given entries for shopping in the future and check associated entries from the list
* @param ignored if the food should be ignored or not ignored (for undo)
* @param {{}} entries set of entries associated with food to set checked
* @param undo if the user should be able to undo the change or not
*/
function setFoodIgnoredState(entries: ShoppingListEntry[], ignored: boolean, undo: boolean) {
const api = new ApiApi()
if (undo) {
registerChange((ignored ? 'IGNORE' : 'UNIGNORE'), entries)
}
let foods = [] as Food[]
entries.forEach(e => {
if (!foods.includes(e.food!)) {
foods.push(e.food!)
}
})
setEntriesCheckedState(entries, ignored, false)
foods.forEach(food => {
food.ignoreShopping = ignored
api.apiFoodUpdate({food: food, id: food.id!}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
})
}
/**
@@ -482,12 +513,14 @@ export const useShoppingStore = defineStore(_STORE_ID, () => {
if (type === 'CHECKED' || type === 'UNCHECKED') {
setEntriesCheckedState(entries, (type === 'UNCHECKED'), false)
} else if (type === 'DELAY' || type === 'UNDELAY') {
delayEntries(entries, (type === 'UNDELAY'), false)
setEntriesDelayedState(entries, (type === 'UNDELAY'), false)
} else if (type === 'CREATED') {
for (let i in entries) {
let e = entries[i]
deleteObject(e)
}
} else if (type === 'IGNORE' || type === 'UNIGNORE') {
setFoodIgnoredState(entries, (type === 'UNIGNORE'), false)
}
} else {
// can use localization in store
@@ -509,7 +542,8 @@ export const useShoppingStore = defineStore(_STORE_ID, () => {
updateObject,
undoChange,
setEntriesCheckedState,
delayEntries,
setFoodIgnoredState,
delayEntries: setEntriesDelayedState,
getAssociatedRecipes,
}

View File

@@ -79,7 +79,7 @@ export type ShoppingListStats = {
* DELAY: ShoppingListEntry was postponed/delayed
* UNDELAY: ShoppingListEntry delay was removed
*/
export type ShoppingOperationHistoryType = 'CREATED' | 'CHECKED' | 'UNCHECKED' | 'DELAY' | 'UNDELAY'
export type ShoppingOperationHistoryType = 'CREATED' | 'CHECKED' | 'UNCHECKED' | 'DELAY' | 'UNDELAY' | 'IGNORE' | 'UNIGNORE'
/**
* history event consisting of a type and affected entries