mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-11-03 02:33:31 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			107 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<template>
 | 
						|
  <div v-if="value && value.length > 0">
 | 
						|
    <div
 | 
						|
      v-if="!isCookMode"
 | 
						|
      class="d-flex justify-start"
 | 
						|
    >
 | 
						|
      <h2 class="mt-1 text-h5 font-weight-medium opacity-80">
 | 
						|
        {{ $t("recipe.ingredients") }}
 | 
						|
      </h2>
 | 
						|
      <AppButtonCopy
 | 
						|
        btn-class="ml-auto"
 | 
						|
        :copy-text="ingredientCopyText"
 | 
						|
      />
 | 
						|
    </div>
 | 
						|
    <div>
 | 
						|
      <div
 | 
						|
        v-for="(ingredient, index) in value"
 | 
						|
        :key="'ingredient' + index"
 | 
						|
      >
 | 
						|
        <template v-if="!isCookMode">
 | 
						|
          <h3
 | 
						|
            v-if="showTitleEditor[index]"
 | 
						|
            class="mt-2"
 | 
						|
          >
 | 
						|
            {{ ingredient.title }}
 | 
						|
          </h3>
 | 
						|
          <v-divider v-if="showTitleEditor[index]" />
 | 
						|
        </template>
 | 
						|
        <v-list-item
 | 
						|
          density="compact"
 | 
						|
          class="pa-0"
 | 
						|
          @click.stop="toggleChecked(index)"
 | 
						|
        >
 | 
						|
          <template #prepend>
 | 
						|
            <v-checkbox
 | 
						|
              v-model="checked[index]"
 | 
						|
              hide-details
 | 
						|
              class="pt-0 my-auto py-auto"
 | 
						|
              color="secondary"
 | 
						|
              density="comfortable"
 | 
						|
            />
 | 
						|
          </template>
 | 
						|
          <v-list-item-title>
 | 
						|
            <RecipeIngredientListItem
 | 
						|
              :ingredient="ingredient"
 | 
						|
              :scale="scale"
 | 
						|
            />
 | 
						|
          </v-list-item-title>
 | 
						|
        </v-list-item>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
</template>
 | 
						|
 | 
						|
<script setup lang="ts">
 | 
						|
import RecipeIngredientListItem from "./RecipeIngredientListItem.vue";
 | 
						|
import { parseIngredientText } from "~/composables/recipes";
 | 
						|
import type { RecipeIngredient } from "~/lib/api/types/recipe";
 | 
						|
 | 
						|
interface Props {
 | 
						|
  value?: RecipeIngredient[];
 | 
						|
  scale?: number;
 | 
						|
  isCookMode?: boolean;
 | 
						|
}
 | 
						|
const props = withDefaults(defineProps<Props>(), {
 | 
						|
  value: () => [],
 | 
						|
  scale: 1,
 | 
						|
  isCookMode: false,
 | 
						|
});
 | 
						|
 | 
						|
function validateTitle(title?: string | null) {
 | 
						|
  return !(title === undefined || title === "" || title === null);
 | 
						|
}
 | 
						|
 | 
						|
const checked = ref(props.value.map(() => false));
 | 
						|
const showTitleEditor = computed(() => props.value.map(x => validateTitle(x.title)));
 | 
						|
 | 
						|
const ingredientCopyText = computed(() => {
 | 
						|
  const components: string[] = [];
 | 
						|
  props.value.forEach((ingredient) => {
 | 
						|
    if (ingredient.title) {
 | 
						|
      if (components.length) {
 | 
						|
        components.push("");
 | 
						|
      }
 | 
						|
 | 
						|
      components.push(`[${ingredient.title}]`);
 | 
						|
    }
 | 
						|
 | 
						|
    components.push(parseIngredientText(ingredient, props.scale, false));
 | 
						|
  });
 | 
						|
 | 
						|
  return components.join("\n");
 | 
						|
});
 | 
						|
 | 
						|
function toggleChecked(index: number) {
 | 
						|
  // TODO Find a better way to do this - $set is not available, and
 | 
						|
  // direct array modifications are not propagated for some reason
 | 
						|
  checked.value.splice(index, 1, !checked.value[index]);
 | 
						|
}
 | 
						|
</script>
 | 
						|
 | 
						|
<style>
 | 
						|
.dense-markdown p {
 | 
						|
  margin: auto !important;
 | 
						|
}
 | 
						|
</style>
 |