mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-07-14 03:30:19 -04:00
fix: shopping list UI improvements (#7215)
This commit is contained in:
@@ -170,12 +170,12 @@
|
||||
<BaseButtonGroup
|
||||
:buttons="[
|
||||
{
|
||||
icon: $globals.icons.checkboxBlankOutline,
|
||||
icon: $globals.icons.checkboxMultipleBlankOutline,
|
||||
text: $t('shopping-list.uncheck-all-items'),
|
||||
event: 'uncheck',
|
||||
},
|
||||
{
|
||||
icon: $globals.icons.checkboxOutline,
|
||||
icon: $globals.icons.checkboxMultipleMarkedOutline,
|
||||
text: $t('shopping-list.check-all-items'),
|
||||
event: 'check',
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<v-list :class="tile ? 'd-flex flex-wrap background' : 'background'" style="background-color: transparent;">
|
||||
<v-list :class="attrs.class.list">
|
||||
<v-sheet
|
||||
v-for="recipe, index in recipes"
|
||||
:key="recipe.id"
|
||||
:key="recipe.id || recipe.slug"
|
||||
:elevation="2"
|
||||
:class="attrs.class.sheet"
|
||||
:style="tile ? 'max-width: 100%; width: fit-content;' : 'width: 100%;'"
|
||||
:style="attrs.style.sheet"
|
||||
>
|
||||
<v-list-item
|
||||
:to="disabled ? '' : '/g/' + groupSlug + '/r/' + recipe.slug"
|
||||
@@ -13,10 +13,15 @@
|
||||
>
|
||||
<template #prepend>
|
||||
<v-avatar color="primary" :class="attrs.class.avatar">
|
||||
<v-img
|
||||
v-if="recipe.image"
|
||||
:src="getRecipeImageUrl(recipe)"
|
||||
/>
|
||||
<v-icon
|
||||
v-else
|
||||
:class="attrs.class.icon"
|
||||
dark
|
||||
:size="small ? 'small' : 'default'"
|
||||
size="x-large"
|
||||
>
|
||||
{{ $globals.icons.primary }}
|
||||
</v-icon>
|
||||
@@ -54,20 +59,19 @@
|
||||
<script setup lang="ts">
|
||||
import DOMPurify from "dompurify";
|
||||
import { useFraction } from "~/composables/recipes/use-fraction";
|
||||
import { useStaticRoutes } from "~/composables/api";
|
||||
import type { ShoppingListItemOut } from "~/lib/api/types/household";
|
||||
import type { RecipeSummary } from "~/lib/api/types/recipe";
|
||||
|
||||
interface Props {
|
||||
recipes: RecipeSummary[];
|
||||
listItem?: ShoppingListItemOut;
|
||||
small?: boolean;
|
||||
tile?: boolean;
|
||||
showDescription?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
listItem: undefined,
|
||||
small: false,
|
||||
tile: false,
|
||||
showDescription: false,
|
||||
disabled: false,
|
||||
@@ -75,41 +79,46 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
|
||||
const auth = useMealieAuth();
|
||||
const { frac } = useFraction();
|
||||
const { recipeTinyImage } = useStaticRoutes();
|
||||
const route = useRoute();
|
||||
const display = useDisplay();
|
||||
const groupSlug = computed(() => route.params.groupSlug || auth.user?.value?.groupSlug || "");
|
||||
|
||||
// Determine if we should show tiles based on screen size and number of recipes
|
||||
const shouldShowTiles = computed(() => {
|
||||
return props.tile && display.smAndUp.value;
|
||||
});
|
||||
|
||||
function getRecipeImageUrl(recipe: RecipeSummary) {
|
||||
return recipeTinyImage(String(recipe.id), recipe.image ?? "");
|
||||
}
|
||||
|
||||
const attrs = computed(() => {
|
||||
return props.small
|
||||
? {
|
||||
class: {
|
||||
sheet: props.tile ? "mb-1 me-1 justify-center align-center" : "mb-1 justify-center align-center",
|
||||
listItem: "px-0",
|
||||
avatar: "ma-0",
|
||||
icon: "ma-0 pa-0 primary",
|
||||
text: "pa-0",
|
||||
},
|
||||
style: {
|
||||
text: {
|
||||
title: "font-size: small;",
|
||||
subTitle: "font-size: x-small;",
|
||||
},
|
||||
},
|
||||
}
|
||||
: {
|
||||
class: {
|
||||
sheet: props.tile ? "mx-1 justify-center align-center" : "mb-1 justify-center align-center",
|
||||
listItem: "px-4",
|
||||
avatar: "",
|
||||
icon: "pa-1 primary",
|
||||
text: "",
|
||||
},
|
||||
style: {
|
||||
text: {
|
||||
title: "",
|
||||
subTitle: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
const tileClasses = shouldShowTiles.value ? "d-flex flex-wrap" : "bg-transparent";
|
||||
const sheetClasses = shouldShowTiles.value
|
||||
? "flex-grow-0 flex-shrink-0 mb-2 me-3"
|
||||
: props.tile ? "mb-2 mx-2" : "mb-1";
|
||||
const sheetStyle = shouldShowTiles.value
|
||||
? { flexBasis: "calc(50% - 12px)", width: "calc(50% - 12px)" }
|
||||
: {};
|
||||
|
||||
return {
|
||||
class: {
|
||||
list: tileClasses,
|
||||
sheet: sheetClasses,
|
||||
listItem: "px-4 py-2",
|
||||
avatar: "",
|
||||
icon: "pa-1 primary",
|
||||
text: "",
|
||||
},
|
||||
style: {
|
||||
sheet: sheetStyle,
|
||||
text: {
|
||||
title: "",
|
||||
subTitle: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
function sanitizeHTML(rawHtml: string) {
|
||||
@@ -158,6 +167,10 @@ const listItemDescriptions = computed<string[]>(() => {
|
||||
|
||||
listItemDescription += ` ${unitDisplay}`;
|
||||
}
|
||||
if (props.listItem.food) {
|
||||
const foodName = props.listItem.food.name;
|
||||
listItemDescription += ` ${foodName}`;
|
||||
}
|
||||
|
||||
if (itemRef.recipeNote) {
|
||||
listItemDescription += `, ${itemRef.recipeNote}`;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
label
|
||||
variant="flat"
|
||||
:color="label.color || undefined"
|
||||
:text-color="textColor"
|
||||
>
|
||||
<span style="max-width: 100%; overflow: hidden; text-overflow: ellipsis;">
|
||||
{{ label.name }}
|
||||
@@ -13,12 +12,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getTextColor } from "~/composables/use-text-color";
|
||||
import type { MultiPurposeLabelSummary } from "~/lib/api/types/recipe";
|
||||
|
||||
const props = defineProps<{
|
||||
defineProps<{
|
||||
label: MultiPurposeLabelSummary;
|
||||
}>();
|
||||
|
||||
const textColor = computed(() => getTextColor(props.label.color));
|
||||
</script>
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
@click="displayRecipeRefs = !displayRecipeRefs"
|
||||
>
|
||||
<v-icon>
|
||||
{{ $globals.icons.potSteam }}
|
||||
{{ $globals.icons.silverwareForkKnife }}
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
@@ -79,7 +79,7 @@
|
||||
variant="text"
|
||||
class="ml-2"
|
||||
icon
|
||||
@click="toggleEdit(true)"
|
||||
@click="toggleEdit(!edit)"
|
||||
>
|
||||
<v-icon>
|
||||
{{ $globals.icons.edit }}
|
||||
@@ -113,24 +113,17 @@
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row
|
||||
<v-container
|
||||
v-if="!listItem.checked && recipeList && recipeList.length && displayRecipeRefs"
|
||||
no-gutters
|
||||
class="mb-2"
|
||||
class="pa-0"
|
||||
>
|
||||
<v-col
|
||||
cols="auto"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<RecipeList
|
||||
:recipes="recipeList"
|
||||
:list-item="listItem"
|
||||
:disabled="isOffline"
|
||||
size="small"
|
||||
tile
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<RecipeList
|
||||
:recipes="recipeList"
|
||||
:list-item="listItem"
|
||||
:disabled="isOffline"
|
||||
:tile="true"
|
||||
/>
|
||||
</v-container>
|
||||
<v-row
|
||||
v-if="listItem.checked"
|
||||
no-gutters
|
||||
@@ -146,8 +139,8 @@
|
||||
</v-row>
|
||||
</v-container>
|
||||
<div
|
||||
v-else
|
||||
class="mb-1 mt-6"
|
||||
v-if="edit"
|
||||
class="mb-4"
|
||||
>
|
||||
<ShoppingListItemEditor
|
||||
v-model="localListItem"
|
||||
|
||||
Reference in New Issue
Block a user