shopping export dialog

This commit is contained in:
vabene1111
2025-05-28 19:12:19 +02:00
parent fa8af5596f
commit 81180207ba
36 changed files with 244 additions and 29 deletions

View File

@@ -1,11 +1,13 @@
<template> <template>
<v-btn ref="copyBtn" :color="color" :size="size" :density="density" @click="clickCopy()" :variant="variant"> <v-btn ref="copyBtn" :color="color" :size="size" :density="density" @click="clickCopy()" :variant="variant">
<v-icon icon="$copy"></v-icon> <slot name="default">
<v-tooltip v-model="showToolip" :target="btn" location="top">
<v-icon icon="$copy"></v-icon> <v-icon icon="$copy"></v-icon>
Copied! <v-tooltip v-model="showToolip" :target="btn" location="top">
</v-tooltip> <v-icon icon="$copy"></v-icon>
{{$t('Copied')}}!
</v-tooltip>
</slot>
</v-btn> </v-btn>
</template> </template>

View File

@@ -0,0 +1,173 @@
<template>
<v-dialog v-model="dialog" activator="parent" style="max-width: 75vw;">
<v-card>
<v-closable-card-title :title="$t('Export')" v-model="dialog"></v-closable-card-title>
<v-card-text>
<v-row>
<v-col>
<v-btn-toggle border divided v-model="mode">
<v-btn value="md_list"><i class="fa-solid fa-list-check"></i></v-btn>
<v-btn value="md_table"><i class="fa-solid fa-table-cells"></i></v-btn>
<v-btn value="csv"><i class="fa-solid fa-file-csv"></i></v-btn>
</v-btn-toggle>
</v-col>
</v-row>
<v-row>
<v-col>
<v-text-field :label="$t('csv_delim_label')" :hint="$t('csv_delim_help')" persistent-hint
v-model="useUserPreferenceStore().userSettings.csvDelim"></v-text-field>
</v-col>
<v-col>
<v-text-field :label="$t('csv_prefix_label')" :hint="$t('csv_prefix_help')" persistent-hint
v-model="useUserPreferenceStore().userSettings.csvPrefix"></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col>
<v-textarea :model-value="exportText" auto-grow max-rows="25" readonly>
</v-textarea>
</v-col>
</v-row>
<btn-copy class="float-right" :copy-value="exportText"></btn-copy>
</v-card-text>
<v-card-actions>
<v-btn @click="downloadExport()" prepend-icon="fa-solid fa-download">{{ $t('Download') }}</v-btn>
<v-btn @click="copy(exportText)" prepend-icon="$copy">{{ $t('Copy') }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
import {computed, ref} from "vue";
import {useShoppingStore} from "@/stores/ShoppingStore.ts";
import {isEntryVisible, isShoppingCategoryVisible, isShoppingListFoodVisible} from "@/utils/logic_utils.ts";
import {useI18n} from "vue-i18n";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.ts";
import {ShoppingListEntry} from "@/openapi";
import BtnCopy from "@/components/buttons/BtnCopy.vue";
import {useClipboard} from "@vueuse/core";
const {t} = useI18n()
const {copy} = useClipboard()
const dialog = defineModel<boolean>()
const mode = ref<'md_list' | 'md_table' | 'csv'>('md_list')
/**
* shorthand for csvDelim user preference
*/
const csvDelim = computed(() => {
return useUserPreferenceStore().userSettings.csvDelim
})
/**
* compute the export text
*/
const exportText = computed(() => {
let textArray: string[] = []
textArray.push(formatHeader())
useShoppingStore().getEntriesByGroup.forEach(category => {
if (isShoppingCategoryVisible(category)) {
if (category.name === useShoppingStore().UNDEFINED_CATEGORY) {
textArray.push(formatCategory(t('NoCategory')))
} else {
textArray.push(formatCategory(category.name))
}
category.foods.forEach(food => {
if (isShoppingListFoodVisible(food, useUserPreferenceStore().deviceSettings)) {
food.entries.forEach(entry => {
if (isEntryVisible(entry, useUserPreferenceStore().deviceSettings)) {
textArray.push(formatEntry(entry))
}
})
}
})
}
})
// delete first two empty lines in md list
if (mode.value == 'md_list') {
textArray.splice(0, 2)
}
return textArray.join('\n')
})
/**
* create the header for the exported list depending on the mode
*/
function formatHeader() {
if (mode.value == 'md_list') {
return ''
} else if (mode.value == 'md_table') {
return `|${t('Amount')}|${t('Unit')}|${t('Food')}|\n|-|-|-|`
} else if (mode.value == 'csv') {
return `${t('Amount')} ${csvDelim.value} ${t('Unit')} ${csvDelim.value} ${t('Food')}`
}
return ''
}
/**
* format category lines depending on the mode
* @param categoryName name of the category
*/
function formatCategory(categoryName: string) {
if (mode.value == 'md_list') {
return `\n${categoryName}`
} else if (mode.value == 'md_table') {
return `|${categoryName}|`
} else if (mode.value == 'csv') {
return `${categoryName}${csvDelim.value}${csvDelim.value}`
}
return ''
}
/**
* format the shopping list entry according to the selected mode
* @param entry
*/
function formatEntry(entry: ShoppingListEntry) {
if (mode.value == 'md_list') {
return `${useUserPreferenceStore().userSettings.csvPrefix} ${entry.amount} ${entry.unit?.name} ${entry.food?.name}`
} else if (mode.value == 'md_table') {
return `|${entry.amount}|${entry.unit?.name}|${entry.food?.name}|`
} else if (mode.value == 'csv') {
return `${entry.amount}${csvDelim.value}${entry.unit?.name}${csvDelim.value}${entry.food?.name}`
}
return ''
}
/**
* encode the exportText into a URI and trigger browser to download the export as a file
*/
function downloadExport() {
let data = encodeURI("data:text/text;charset=utf-8," + exportText.value)
let link = document.createElement("a")
link.setAttribute("href", data)
if (mode.value == 'md_list' || mode.value == 'md_table') {
link.setAttribute("download", `${t('Shopping_list')}.md`)
} else if (mode.value == 'csv') {
link.setAttribute("download", `${t('Shopping_list')}.csv`)
}
link.click()
}
</script>
<style scoped>
</style>

View File

@@ -55,7 +55,7 @@
<v-list-item> <v-list-item>
<v-switch color="primary" hide-details :label="$t('CreatedBy')" v-model="useUserPreferenceStore().deviceSettings.shopping_item_info_created_by"></v-switch> <v-switch color="primary" hide-details :label="$t('CreatedBy')" v-model="useUserPreferenceStore().deviceSettings.shopping_item_info_created_by"></v-switch>
</v-list-item> </v-list-item>
<v-list-item > <v-list-item>
<v-switch color="primary" hide-details label="New Input" v-model="useUserPreferenceStore().deviceSettings.shopping_input_autocomplete"></v-switch> <v-switch color="primary" hide-details label="New Input" v-model="useUserPreferenceStore().deviceSettings.shopping_input_autocomplete"></v-switch>
</v-list-item> </v-list-item>
<v-list-item v-if="useUserPreferenceStore().serverSettings.debug"> <v-list-item v-if="useUserPreferenceStore().serverSettings.debug">
@@ -65,6 +65,11 @@
</v-list> </v-list>
</v-menu> </v-menu>
<v-btn height="100%" rounded="0" variant="plain">
<i class="fa-solid fa-download"></i>
<shopping-export-dialog></shopping-export-dialog>
</v-btn>
<v-btn height="100%" rounded="0" variant="plain" @click="useShoppingStore().undoChange()"> <v-btn height="100%" rounded="0" variant="plain" @click="useShoppingStore().undoChange()">
<i class="fa-solid fa-arrow-rotate-left"></i> <i class="fa-solid fa-arrow-rotate-left"></i>
</v-btn> </v-btn>
@@ -96,14 +101,14 @@
</v-list> </v-list>
<v-list class="mt-3" density="compact" v-else> <v-list class="mt-3" density="compact" v-else>
<template v-for="category in useShoppingStore().getEntriesByGroup" :key="category.name"> <template v-for="category in useShoppingStore().getEntriesByGroup" :key="category.name">
<template v-if="isCategoryVisible(category)"> <template v-if="isShoppingCategoryVisible(category)">
<v-list-subheader v-if="category.name === useShoppingStore().UNDEFINED_CATEGORY"><i>{{ $t('NoCategory') }}</i></v-list-subheader> <v-list-subheader v-if="category.name === useShoppingStore().UNDEFINED_CATEGORY"><i>{{ $t('NoCategory') }}</i></v-list-subheader>
<v-list-subheader v-else>{{ category.name }}</v-list-subheader> <v-list-subheader v-else>{{ category.name }}</v-list-subheader>
<v-divider></v-divider> <v-divider></v-divider>
<template v-for="[i, value] in category.foods" :key="value.food.id"> <template v-for="[i, value] in category.foods" :key="value.food.id">
<shopping-line-item :shopping-list-food="value" ></shopping-line-item> <shopping-line-item :shopping-list-food="value"></shopping-line-item>
</template> </template>
</template> </template>
@@ -166,14 +171,14 @@
<v-list> <v-list>
<v-list-item v-for="r in useShoppingStore().getAssociatedRecipes()"> <v-list-item v-for="r in useShoppingStore().getAssociatedRecipes()">
<template #prepend> <template #prepend>
<v-btn color="edit" icon > <v-btn color="edit" icon>
{{ r.servings }} {{ r.servings }}
<number-scaler-dialog <number-scaler-dialog
v-if="r.mealplan == undefined" v-if="r.mealplan == undefined"
:number="r.servings" :number="r.servings"
@confirm="(servings: number) => {updateRecipeServings(r, servings)}" @confirm="(servings: number) => {updateRecipeServings(r, servings)}"
></number-scaler-dialog> ></number-scaler-dialog>
<model-edit-dialog model="MealPlan" :item-id="r.mealplan" v-if="r.mealplan != undefined" activator="parent"> </model-edit-dialog> <model-edit-dialog model="MealPlan" :item-id="r.mealplan" v-if="r.mealplan != undefined" activator="parent"></model-edit-dialog>
</v-btn> </v-btn>
</template> </template>
@@ -207,7 +212,7 @@
<v-row> <v-row>
<v-col> <v-col>
<supermarket-editor :item="useUserPreferenceStore().deviceSettings.shopping_selected_supermarket" <supermarket-editor :item="useUserPreferenceStore().deviceSettings.shopping_selected_supermarket"
@save="(args: Supermarket) => (useUserPreferenceStore().deviceSettings.shopping_selected_supermarket = args)"></supermarket-editor> @save="(args: Supermarket) => (useUserPreferenceStore().deviceSettings.shopping_selected_supermarket = args)"></supermarket-editor>
</v-col> </v-col>
</v-row> </v-row>
</v-container> </v-container>
@@ -237,6 +242,8 @@ import {DateTime} from "luxon";
import MealPlanEditor from "@/components/model_editors/MealPlanEditor.vue"; import MealPlanEditor from "@/components/model_editors/MealPlanEditor.vue";
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue"; import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
import {onBeforeRouteLeave} from "vue-router"; import {onBeforeRouteLeave} from "vue-router";
import {isShoppingCategoryVisible} from "@/utils/logic_utils.ts";
import ShoppingExportDialog from "@/components/dialogs/ShoppingExportDialog.vue";
const {t} = useI18n() const {t} = useI18n()
@@ -274,22 +281,6 @@ onMounted(() => {
} }
}) })
/**
* determines if a category as entries that should be visible
* @param category
*/
function isCategoryVisible(category: IShoppingListCategory) {
let entryCount = category.stats.countUnchecked
if (useUserPreferenceStore().deviceSettings.shopping_show_checked_entries) {
entryCount += category.stats.countChecked
}
if (useUserPreferenceStore().deviceSettings.shopping_show_delayed_entries) {
entryCount += category.stats.countUncheckedDelayed
}
return entryCount > 0
}
/** /**
* update the number of servings for an embedded recipe and with it the ShoppingListEntry amounts * update the number of servings for an embedded recipe and with it the ShoppingListEntry amounts
* @param recipe ShoppingListRecipe to update * @param recipe ShoppingListRecipe to update

View File

@@ -61,6 +61,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "", "Copy": "",
"Copy Link": "", "Copy Link": "",
"Copy Token": "", "Copy Token": "",

View File

@@ -61,6 +61,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Копиране", "Copy": "Копиране",
"Copy_template_reference": "Копирайте препратка към шаблона", "Copy_template_reference": "Копирайте препратка към шаблона",
"CountMore": "...+{count} още", "CountMore": "...+{count} още",

View File

@@ -74,6 +74,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "", "Copy": "",
"Copy Link": "", "Copy Link": "",
"Copy Token": "", "Copy Token": "",

View File

@@ -74,6 +74,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopírovat", "Copy": "Kopírovat",
"Copy Link": "Kopírovat odkaz", "Copy Link": "Kopírovat odkaz",
"Copy Token": "Kopírovat token", "Copy Token": "Kopírovat token",

View File

@@ -73,6 +73,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopier", "Copy": "Kopier",
"Copy Link": "Kopier link", "Copy Link": "Kopier link",
"Copy Token": "Kopier token", "Copy Token": "Kopier token",

View File

@@ -76,6 +76,7 @@
"ConversionsHelp": "Mit Umrechnungen kann die Menge einens Lebensmittels in verschiedenen Einheiten ausgerechnet werden. Aktuell wird dies nur zur berechnung von Eigenschaften verwendet, später jedoch sollen auch andere Funktionen von Tandoor davon profitieren.", "ConversionsHelp": "Mit Umrechnungen kann die Menge einens Lebensmittels in verschiedenen Einheiten ausgerechnet werden. Aktuell wird dies nur zur berechnung von Eigenschaften verwendet, später jedoch sollen auch andere Funktionen von Tandoor davon profitieren.",
"CookLog": "Kochprotokoll", "CookLog": "Kochprotokoll",
"Cooked": "Gekocht", "Cooked": "Gekocht",
"Copied": "Kopiert",
"Copy": "Kopieren", "Copy": "Kopieren",
"Copy Link": "Link Kopieren", "Copy Link": "Link Kopieren",
"Copy Token": "Kopiere Token", "Copy Token": "Kopiere Token",

View File

@@ -72,6 +72,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Αντιγραφή", "Copy": "Αντιγραφή",
"Copy Link": "Αντιγραφή συνδέσμου", "Copy Link": "Αντιγραφή συνδέσμου",
"Copy Token": "Αντιγραφή token", "Copy Token": "Αντιγραφή token",

View File

@@ -74,6 +74,7 @@
"ConversionsHelp": "With conversions you can calculate the amount of a food in different units. Currently this is only used for property calculation, later it might also be used in other parts of tandoor. ", "ConversionsHelp": "With conversions you can calculate the amount of a food in different units. Currently this is only used for property calculation, later it might also be used in other parts of tandoor. ",
"CookLog": "Cook Log", "CookLog": "Cook Log",
"Cooked": "Cooked", "Cooked": "Cooked",
"Copied": "Copied",
"Copy": "Copy", "Copy": "Copy",
"Copy Link": "Copy Link", "Copy Link": "Copy Link",
"Copy Token": "Copy Token", "Copy Token": "Copy Token",

View File

@@ -74,6 +74,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Copiar", "Copy": "Copiar",
"Copy Link": "Copiar Enlace", "Copy Link": "Copiar Enlace",
"Copy Token": "Copiar Token", "Copy Token": "Copiar Token",

View File

@@ -47,6 +47,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopioi", "Copy": "Kopioi",
"Copy_template_reference": "Kopioi malliviittaus", "Copy_template_reference": "Kopioi malliviittaus",
"Create": "Luo", "Create": "Luo",

View File

@@ -73,6 +73,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Copier", "Copy": "Copier",
"Copy Link": "Copier le lien", "Copy Link": "Copier le lien",
"Copy Token": "Copier le jeton", "Copy Token": "Copier le jeton",

View File

@@ -74,6 +74,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "העתקה", "Copy": "העתקה",
"Copy Link": "העתק קישור", "Copy Link": "העתק קישור",
"Copy Token": "העתק טוקן", "Copy Token": "העתק טוקן",

View File

@@ -73,6 +73,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Másolás", "Copy": "Másolás",
"Copy Link": "Link másolása", "Copy Link": "Link másolása",
"Copy Token": "Token másolása", "Copy Token": "Token másolása",

View File

@@ -39,6 +39,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "", "Copy": "",
"Create": "Ստեղծել", "Create": "Ստեղծել",
"Create_New_Food": "Ավելացնել նոր սննդամթերք", "Create_New_Food": "Ավելացնել նոր սննդամթերք",

View File

@@ -65,6 +65,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Salin", "Copy": "Salin",
"Copy Link": "Salin Tautan", "Copy Link": "Salin Tautan",
"Copy Token": "Salin Token", "Copy Token": "Salin Token",

View File

@@ -74,6 +74,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "", "Copy": "",
"Copy Link": "", "Copy Link": "",
"Copy Token": "", "Copy Token": "",

View File

@@ -69,6 +69,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Copia", "Copy": "Copia",
"Copy Link": "Copia link", "Copy Link": "Copia link",
"Copy Token": "Copia token", "Copy Token": "Copia token",

View File

@@ -73,6 +73,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "", "Copy": "",
"Copy Link": "", "Copy Link": "",
"Copy Token": "", "Copy Token": "",

View File

@@ -71,6 +71,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopier", "Copy": "Kopier",
"Copy Link": "Kopier lenke", "Copy Link": "Kopier lenke",
"Copy Token": "Kopier Token", "Copy Token": "Kopier Token",

View File

@@ -74,6 +74,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopie", "Copy": "Kopie",
"Copy Link": "Kopieer Link", "Copy Link": "Kopieer Link",
"Copy Token": "Kopieer Token", "Copy Token": "Kopieer Token",

View File

@@ -75,6 +75,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopiuj", "Copy": "Kopiuj",
"Copy Link": "Skopiuj link", "Copy Link": "Skopiuj link",
"Copy Token": "Kopiuj Token", "Copy Token": "Kopiuj Token",

View File

@@ -60,6 +60,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Copiar", "Copy": "Copiar",
"Copy Link": "Copiar Ligação", "Copy Link": "Copiar Ligação",
"Copy Token": "Copiar Chave", "Copy Token": "Copiar Chave",

View File

@@ -73,6 +73,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Copiar", "Copy": "Copiar",
"Copy Link": "Copiar Link", "Copy Link": "Copiar Link",
"Copy Token": "Copiar Token", "Copy Token": "Copiar Token",

View File

@@ -70,6 +70,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Copie", "Copy": "Copie",
"Copy Link": "Copiere link", "Copy Link": "Copiere link",
"Copy Token": "Copiere token", "Copy Token": "Copiere token",

View File

@@ -55,6 +55,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Копировать", "Copy": "Копировать",
"Copy_template_reference": "Скопировать ссылку на шаблон", "Copy_template_reference": "Скопировать ссылку на шаблон",
"CountMore": "...+{count} больше", "CountMore": "...+{count} больше",

View File

@@ -56,6 +56,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopiraj", "Copy": "Kopiraj",
"Copy_template_reference": "Kopiraj referenco vzorca", "Copy_template_reference": "Kopiraj referenco vzorca",
"CountMore": "...+{count} več", "CountMore": "...+{count} več",

View File

@@ -75,6 +75,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopiera", "Copy": "Kopiera",
"Copy Link": "Kopiera Länk", "Copy Link": "Kopiera Länk",
"Copy Token": "Kopiera token", "Copy Token": "Kopiera token",

View File

@@ -74,6 +74,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Kopyala", "Copy": "Kopyala",
"Copy Link": "Bağlantıyı Kopyala", "Copy Link": "Bağlantıyı Kopyala",
"Copy Token": "Anahtarı Kopyala", "Copy Token": "Anahtarı Kopyala",

View File

@@ -64,6 +64,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "Копіювати", "Copy": "Копіювати",
"Copy Link": "Скопіювати Посилання", "Copy Link": "Скопіювати Посилання",
"Copy Token": "Скопіювати Токен", "Copy Token": "Скопіювати Токен",

View File

@@ -73,6 +73,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "复制", "Copy": "复制",
"Copy Link": "复制链接", "Copy Link": "复制链接",
"Copy Token": "复制令牌", "Copy Token": "复制令牌",

View File

@@ -36,6 +36,7 @@
"ConversionsHelp": "", "ConversionsHelp": "",
"CookLog": "", "CookLog": "",
"Cooked": "", "Cooked": "",
"Copied": "",
"Copy": "", "Copy": "",
"Copy_template_reference": "複製參考模板", "Copy_template_reference": "複製參考模板",
"Create": "", "Create": "",

View File

@@ -294,7 +294,7 @@
</v-col> </v-col>
<v-col cols="12" md="6"> <v-col cols="12" md="6">
<v-list> <v-list>
<vue-draggable v-model="s.ingredients" group="ingredients" handle=".drag-handle" empty-insert-threshold="25"> <vue-draggable v-model="s.ingredients" group="ingredients" handle=".drag-handle" :empty-insert-threshold="25">
<v-list-item v-for="(i, ingredientIndex) in s.ingredients" border> <v-list-item v-for="(i, ingredientIndex) in s.ingredients" border>
<v-icon size="small" class="drag-handle cursor-grab mr-2" icon="$dragHandle"></v-icon> <v-icon size="small" class="drag-handle cursor-grab mr-2" icon="$dragHandle"></v-icon>
<v-chip density="compact" label class="mr-1">{{ i.amount }}</v-chip> <v-chip density="compact" label class="mr-1">{{ i.amount }}</v-chip>

View File

@@ -1,6 +1,7 @@
import {ShoppingListEntry, Space} from "@/openapi"; import {ShoppingListEntry, Space} from "@/openapi";
import {IShoppingListFood} from "@/types/Shopping"; import {IShoppingListCategory, IShoppingListFood} from "@/types/Shopping";
import {DeviceSettings} from "@/types/settings"; import {DeviceSettings} from "@/types/settings";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.ts";
// -------------- SHOPPING RELATED ---------------------- // -------------- SHOPPING RELATED ----------------------
@@ -25,7 +26,7 @@ export function isEntryVisible(entry: ShoppingListEntry, deviceSettings: DeviceS
* @param slf shopping list food holder * @param slf shopping list food holder
* @param deviceSettings user device settings based on which entry visibility is controlled * @param deviceSettings user device settings based on which entry visibility is controlled
*/ */
export function isShoppingListFoodVisible(slf: IShoppingListFood, deviceSettings: DeviceSettings){ export function isShoppingListFoodVisible(slf: IShoppingListFood, deviceSettings: DeviceSettings) {
let foodVisible = false let foodVisible = false
slf.entries.forEach(entry => { slf.entries.forEach(entry => {
foodVisible = foodVisible || isEntryVisible(entry, deviceSettings) foodVisible = foodVisible || isEntryVisible(entry, deviceSettings)
@@ -54,6 +55,23 @@ export function isShoppingListFoodDelayed(slf: IShoppingListFood) {
return hasDelayedEntry return hasDelayedEntry
} }
/**
* determines if a category has entries that should be visible
* @param category
*/
export function isShoppingCategoryVisible(category: IShoppingListCategory) {
let entryCount = category.stats.countUnchecked
if (useUserPreferenceStore().deviceSettings.shopping_show_checked_entries) {
entryCount += category.stats.countChecked
}
if (useUserPreferenceStore().deviceSettings.shopping_show_delayed_entries) {
entryCount += category.stats.countUncheckedDelayed
}
return entryCount > 0
}
// -------------- SPACE RELATED ---------------------- // -------------- SPACE RELATED ----------------------
/** /**