| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | <template> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |   <section @keyup.ctrl.90="undoMerge"> | 
					
						
							|  |  |  |     <!-- Ingredient Link Editor --> | 
					
						
							|  |  |  |     <v-dialog v-model="dialog" width="600"> | 
					
						
							| 
									
										
										
										
											2021-11-20 14:30:38 -09:00
										 |  |  |       <v-card :ripple="false"> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         <v-app-bar dark color="primary" class="mt-n1 mb-3"> | 
					
						
							|  |  |  |           <v-icon large left> | 
					
						
							|  |  |  |             {{ $globals.icons.link }} | 
					
						
							|  |  |  |           </v-icon> | 
					
						
							|  |  |  |           <v-toolbar-title class="headline"> Ingredient Linker </v-toolbar-title> | 
					
						
							|  |  |  |           <v-spacer></v-spacer> | 
					
						
							|  |  |  |         </v-app-bar> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <v-card-text class="pt-4"> | 
					
						
							|  |  |  |           <p> | 
					
						
							|  |  |  |             {{ activeText }} | 
					
						
							|  |  |  |           </p> | 
					
						
							|  |  |  |           <v-divider class="mb-4"></v-divider> | 
					
						
							|  |  |  |           <v-checkbox | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |             v-for="ing in unusedIngredients" | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |             :key="ing.referenceId" | 
					
						
							|  |  |  |             v-model="activeRefs" | 
					
						
							|  |  |  |             :value="ing.referenceId" | 
					
						
							|  |  |  |             class="mb-n2 mt-n2" | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |           > | 
					
						
							|  |  |  |             <template #label> | 
					
						
							|  |  |  |               <div v-html="parseIngredientText(ing, disableAmount)"></div> | 
					
						
							|  |  |  |             </template> | 
					
						
							|  |  |  |           </v-checkbox> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           <template v-if="usedIngredients.length > 0"> | 
					
						
							|  |  |  |             <h4 class="py-3 ml-1">Linked to other step</h4> | 
					
						
							|  |  |  |             <v-checkbox | 
					
						
							|  |  |  |               v-for="ing in usedIngredients" | 
					
						
							|  |  |  |               :key="ing.referenceId" | 
					
						
							|  |  |  |               v-model="activeRefs" | 
					
						
							|  |  |  |               :value="ing.referenceId" | 
					
						
							|  |  |  |               class="mb-n2 mt-n2" | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |               <template #label> | 
					
						
							|  |  |  |                 <div v-html="parseIngredientText(ing, disableAmount)"></div> | 
					
						
							|  |  |  |               </template> | 
					
						
							|  |  |  |             </v-checkbox> | 
					
						
							|  |  |  |           </template> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         </v-card-text> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <v-divider></v-divider> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <v-card-actions> | 
					
						
							|  |  |  |           <BaseButton cancel @click="dialog = false"> </BaseButton> | 
					
						
							|  |  |  |           <v-spacer></v-spacer> | 
					
						
							|  |  |  |           <BaseButton color="info" @click="autoSetReferences"> | 
					
						
							|  |  |  |             <template #icon> {{ $globals.icons.robot }}</template> | 
					
						
							|  |  |  |             Auto | 
					
						
							|  |  |  |           </BaseButton> | 
					
						
							|  |  |  |           <BaseButton save @click="setIngredientIds"> </BaseButton> | 
					
						
							|  |  |  |         </v-card-actions> | 
					
						
							|  |  |  |       </v-card> | 
					
						
							|  |  |  |     </v-dialog> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     <div class="d-flex justify-space-between justify-start"> | 
					
						
							|  |  |  |       <h2 class="mb-4 mt-1">{{ $t("recipe.instructions") }}</h2> | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |       <BaseButton v-if="!public" minor :to="$router.currentRoute.path + '/cook'" cancel color="primary"> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         <template #icon> | 
					
						
							|  |  |  |           {{ $globals.icons.primary }} | 
					
						
							|  |  |  |         </template> | 
					
						
							|  |  |  |         Cook | 
					
						
							|  |  |  |       </BaseButton> | 
					
						
							|  |  |  |     </div> | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |     <draggable | 
					
						
							|  |  |  |       :disabled="!edit" | 
					
						
							|  |  |  |       :value="value" | 
					
						
							|  |  |  |       handle=".handle" | 
					
						
							|  |  |  |       @input="updateIndex" | 
					
						
							|  |  |  |       @start="drag = true" | 
					
						
							|  |  |  |       @end="drag = false" | 
					
						
							|  |  |  |     > | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       <div v-for="(step, index) in value" :key="step.id"> | 
					
						
							|  |  |  |         <v-app-bar v-if="showTitleEditor[step.id]" class="primary mx-1 mt-6" dark dense rounded> | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |           <v-toolbar-title v-if="!edit" class="headline"> | 
					
						
							|  |  |  |             <v-app-bar-title v-text="step.title"> </v-app-bar-title> | 
					
						
							|  |  |  |           </v-toolbar-title> | 
					
						
							|  |  |  |           <v-text-field | 
					
						
							|  |  |  |             v-if="edit" | 
					
						
							|  |  |  |             v-model="step.title" | 
					
						
							|  |  |  |             class="headline pa-0 mt-5" | 
					
						
							|  |  |  |             dense | 
					
						
							|  |  |  |             solo | 
					
						
							|  |  |  |             flat | 
					
						
							|  |  |  |             :placeholder="$t('recipe.section-title')" | 
					
						
							|  |  |  |             background-color="primary" | 
					
						
							|  |  |  |           > | 
					
						
							|  |  |  |           </v-text-field> | 
					
						
							|  |  |  |         </v-app-bar> | 
					
						
							|  |  |  |         <v-hover v-slot="{ hover }"> | 
					
						
							|  |  |  |           <v-card | 
					
						
							|  |  |  |             class="ma-1" | 
					
						
							|  |  |  |             :class="[{ 'on-hover': hover }, isChecked(index)]" | 
					
						
							|  |  |  |             :elevation="hover ? 12 : 2" | 
					
						
							|  |  |  |             :ripple="false" | 
					
						
							|  |  |  |             @click="toggleDisabled(index)" | 
					
						
							|  |  |  |           > | 
					
						
							|  |  |  |             <v-card-title :class="{ 'pb-0': !isChecked(index) }"> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |               <v-btn v-if="edit" fab x-small color="white" class="mr-2" elevation="0" @click="value.splice(index, 1)"> | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |                 <v-icon size="24" color="error">{{ $globals.icons.delete }}</v-icon> | 
					
						
							|  |  |  |               </v-btn> | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |               {{ $t("recipe.step-index", { step: index + 1 }) }} | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |               <div class="ml-auto"> | 
					
						
							|  |  |  |                 <BaseOverflowButton | 
					
						
							|  |  |  |                   v-if="edit" | 
					
						
							|  |  |  |                   small | 
					
						
							|  |  |  |                   mode="event" | 
					
						
							|  |  |  |                   :items="actionEvents || []" | 
					
						
							|  |  |  |                   @merge-above="mergeAbove(index - 1, index)" | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |                   @toggle-section="toggleShowTitle(step.id)" | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |                   @link-ingredients="openDialog(index, step.ingredientReferences, step.text)" | 
					
						
							|  |  |  |                 > | 
					
						
							|  |  |  |                 </BaseOverflowButton> | 
					
						
							|  |  |  |               </div> | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |               <v-icon v-if="edit" class="handle">{{ $globals.icons.arrowUpDown }}</v-icon> | 
					
						
							|  |  |  |               <v-fade-transition> | 
					
						
							|  |  |  |                 <v-icon v-show="isChecked(index)" size="24" class="ml-auto" color="success"> | 
					
						
							|  |  |  |                   {{ $globals.icons.checkboxMarkedCircle }} | 
					
						
							|  |  |  |                 </v-icon> | 
					
						
							|  |  |  |               </v-fade-transition> | 
					
						
							|  |  |  |             </v-card-title> | 
					
						
							|  |  |  |             <v-card-text v-if="edit"> | 
					
						
							| 
									
										
										
										
											2021-11-20 14:30:38 -09:00
										 |  |  |               <MarkdownEditor v-model="value[index]['text']" /> | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |               <div | 
					
						
							|  |  |  |                 v-for="ing in step.ingredientReferences" | 
					
						
							|  |  |  |                 :key="ing.referenceId" | 
					
						
							|  |  |  |                 v-html="getIngredientByRefId(ing.referenceId)" | 
					
						
							|  |  |  |               /> | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |             </v-card-text> | 
					
						
							|  |  |  |             <v-expand-transition> | 
					
						
							|  |  |  |               <div v-show="!isChecked(index) && !edit" class="m-0 p-0"> | 
					
						
							|  |  |  |                 <v-card-text> | 
					
						
							|  |  |  |                   <VueMarkdown :source="step.text"> </VueMarkdown> | 
					
						
							|  |  |  |                 </v-card-text> | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |             </v-expand-transition> | 
					
						
							|  |  |  |           </v-card> | 
					
						
							|  |  |  |         </v-hover> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     </draggable> | 
					
						
							|  |  |  |   </section> | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | </template> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | import draggable from "vuedraggable"; | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | import VueMarkdown from "@adapttive/vue-markdown"; | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | import { ref, toRefs, reactive, defineComponent, watch, onMounted } from "@nuxtjs/composition-api"; | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  | import { RecipeStep, IngredientReferences, RecipeIngredient } from "~/types/api-types/recipe"; | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  | import { parseIngredientText } from "~/composables/recipes"; | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  | import { uuid4 } from "~/composables/use-utils"; | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | interface MergerHistory { | 
					
						
							|  |  |  |   target: number; | 
					
						
							|  |  |  |   source: number; | 
					
						
							|  |  |  |   targetText: string; | 
					
						
							|  |  |  |   sourceText: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default defineComponent({ | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |   components: { | 
					
						
							|  |  |  |     VueMarkdown, | 
					
						
							|  |  |  |     draggable, | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   props: { | 
					
						
							|  |  |  |     value: { | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |       type: Array as () => RecipeStep[], | 
					
						
							| 
									
										
										
										
											2021-08-07 16:49:55 -08:00
										 |  |  |       required: true, | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |     }, | 
					
						
							|  |  |  |     edit: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: true, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     ingredients: { | 
					
						
							|  |  |  |       type: Array as () => RecipeIngredient[], | 
					
						
							|  |  |  |       default: () => [], | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |     disableAmount: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: false, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |     public: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: false, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |   }, | 
					
						
							| 
									
										
										
										
											2021-10-31 14:46:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |   setup(props, context) { | 
					
						
							|  |  |  |     const state = reactive({ | 
					
						
							|  |  |  |       dialog: false, | 
					
						
							|  |  |  |       disabledSteps: [] as number[], | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       unusedIngredients: [] as RecipeIngredient[], | 
					
						
							|  |  |  |       usedIngredients: [] as RecipeIngredient[], | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |     const showTitleEditor = ref<{ [key: string]: boolean }>({}); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     const actionEvents = [ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         text: "Toggle Section", | 
					
						
							|  |  |  |         event: "toggle-section", | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         text: "Link Ingredients", | 
					
						
							|  |  |  |         event: "link-ingredients", | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         text: "Merge Above", | 
					
						
							|  |  |  |         event: "merge-above", | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2021-08-01 19:24:47 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     // ===============================================================
 | 
					
						
							|  |  |  |     // UI State Helpers
 | 
					
						
							|  |  |  |     function validateTitle(title: string | undefined) { | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |       return !(title === null || title === ""); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     watch(props.value, (v) => { | 
					
						
							|  |  |  |       state.disabledSteps = []; | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  | 
 | 
					
						
							|  |  |  |       v.forEach((element) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         if (element.id !== undefined) { | 
					
						
							|  |  |  |           showTitleEditor.value[element.id] = validateTitle(element.title); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Eliminate state with an eager call to watcher?
 | 
					
						
							|  |  |  |     onMounted(() => { | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       props.value.forEach((element) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         if (element.id !== undefined) { | 
					
						
							|  |  |  |           showTitleEditor.value[element.id] = validateTitle(element.title); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function toggleDisabled(stepIndex: number) { | 
					
						
							|  |  |  |       if (props.edit) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (state.disabledSteps.includes(stepIndex)) { | 
					
						
							|  |  |  |         const index = state.disabledSteps.indexOf(stepIndex); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |         if (index !== -1) { | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |           state.disabledSteps.splice(index, 1); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         state.disabledSteps.push(stepIndex); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     function isChecked(stepIndex: number) { | 
					
						
							|  |  |  |       if (state.disabledSteps.includes(stepIndex) && !props.edit) { | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |         return "disabled-card"; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |     function toggleShowTitle(id: string) { | 
					
						
							|  |  |  |       showTitleEditor.value[id] = !showTitleEditor.value[id]; | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       const temp = { ...showTitleEditor.value }; | 
					
						
							|  |  |  |       showTitleEditor.value = temp; | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     function updateIndex(data: RecipeStep) { | 
					
						
							|  |  |  |       context.emit("input", data); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // ===============================================================
 | 
					
						
							|  |  |  |     // Ingredient Linker
 | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |     const activeRefs = ref<string[]>([]); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     const activeIndex = ref(0); | 
					
						
							|  |  |  |     const activeText = ref(""); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |     function openDialog(idx: number, refs: IngredientReferences[], text: string) { | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       setUsedIngredients(); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |       activeText.value = text; | 
					
						
							|  |  |  |       activeIndex.value = idx; | 
					
						
							|  |  |  |       state.dialog = true; | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |       activeRefs.value = refs.map((ref) => ref.referenceId ?? ""); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function setIngredientIds() { | 
					
						
							|  |  |  |       const instruction = props.value[activeIndex.value]; | 
					
						
							|  |  |  |       instruction.ingredientReferences = activeRefs.value.map((ref) => { | 
					
						
							|  |  |  |         return { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |           referenceId: ref, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         }; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       state.dialog = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |     function setUsedIngredients() { | 
					
						
							|  |  |  |       const usedRefs: { [key: string]: boolean } = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       props.value.forEach((element) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         element.ingredientReferences?.forEach((ref) => { | 
					
						
							|  |  |  |           if (ref.referenceId !== undefined) { | 
					
						
							|  |  |  |             usedRefs[ref.referenceId] = true; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       state.usedIngredients = props.ingredients.filter((ing) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         return ing.referenceId !== undefined && ing.referenceId in usedRefs; | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       state.unusedIngredients = props.ingredients.filter((ing) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         return !(ing.referenceId !== undefined && ing.referenceId in usedRefs); | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     function autoSetReferences() { | 
					
						
							|  |  |  |       // Ingore matching blacklisted words when auto-linking - This is kind of a cludgey implementation. We're blacklisting common words but
 | 
					
						
							|  |  |  |       // other common phrases trigger false positives and I'm not sure how else to approach this. In the future I maybe look at looking directly
 | 
					
						
							|  |  |  |       // at the food variable and seeing if the food is in the instructions, but I still need to support those who don't want to provide the value
 | 
					
						
							|  |  |  |       // and only use the "notes" feature.
 | 
					
						
							|  |  |  |       const blackListedText = [ | 
					
						
							|  |  |  |         "and", | 
					
						
							|  |  |  |         "or", | 
					
						
							|  |  |  |         "the", | 
					
						
							|  |  |  |         "a", | 
					
						
							|  |  |  |         "an", | 
					
						
							|  |  |  |         "of", | 
					
						
							|  |  |  |         "in", | 
					
						
							|  |  |  |         "on", | 
					
						
							|  |  |  |         "to", | 
					
						
							|  |  |  |         "for", | 
					
						
							|  |  |  |         "by", | 
					
						
							|  |  |  |         "with", | 
					
						
							|  |  |  |         "without", | 
					
						
							|  |  |  |         "", | 
					
						
							|  |  |  |         " ", | 
					
						
							|  |  |  |       ]; | 
					
						
							|  |  |  |       const blackListedRegexMatch = /\d/gm; // Match Any Number
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Check if any of the words in the active text match the ingredient text
 | 
					
						
							|  |  |  |       const instructionsByWord = activeText.value.toLowerCase().split(" "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       instructionsByWord.forEach((word) => { | 
					
						
							|  |  |  |         if (blackListedText.includes(word) || word.match(blackListedRegexMatch)) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         props.ingredients.forEach((ingredient) => { | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |           const searchText = parseIngredientText(ingredient, props.disableAmount); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |           if (ingredient.referenceId === undefined) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |           if (searchText.toLowerCase().includes(" " + word) && !activeRefs.value.includes(ingredient.referenceId)) { | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |             console.info("Word Matched", `'${word}'`, ingredient.note); | 
					
						
							|  |  |  |             activeRefs.value.push(ingredient.referenceId); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |     function getIngredientByRefId(refId: string) { | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       const ing = props.ingredients.find((ing) => ing.referenceId === refId) || ""; | 
					
						
							|  |  |  |       if (ing === "") { | 
					
						
							|  |  |  |         return ""; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return parseIngredientText(ing, props.disableAmount); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // ===============================================================
 | 
					
						
							|  |  |  |     // Instruction Merger
 | 
					
						
							|  |  |  |     const mergeHistory = ref<MergerHistory[]>([]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function mergeAbove(target: number, source: number) { | 
					
						
							|  |  |  |       if (target < 0) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       mergeHistory.value.push({ | 
					
						
							|  |  |  |         target, | 
					
						
							|  |  |  |         source, | 
					
						
							|  |  |  |         targetText: props.value[target].text, | 
					
						
							|  |  |  |         sourceText: props.value[source].text, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       props.value[target].text += " " + props.value[source].text; | 
					
						
							|  |  |  |       props.value.splice(source, 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function undoMerge(event: KeyboardEvent) { | 
					
						
							|  |  |  |       if (event.ctrlKey && event.code === "KeyZ") { | 
					
						
							|  |  |  |         if (!(mergeHistory.value?.length > 0)) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const lastMerge = mergeHistory.value.pop(); | 
					
						
							|  |  |  |         if (!lastMerge) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         props.value[lastMerge.target].text = lastMerge.targetText; | 
					
						
							|  |  |  |         props.value.splice(lastMerge.source, 0, { | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |           id: uuid4(), | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |           title: "", | 
					
						
							|  |  |  |           text: lastMerge.sourceText, | 
					
						
							|  |  |  |           ingredientReferences: [], | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       ...toRefs(state), | 
					
						
							|  |  |  |       actionEvents, | 
					
						
							|  |  |  |       activeRefs, | 
					
						
							|  |  |  |       activeText, | 
					
						
							|  |  |  |       getIngredientByRefId, | 
					
						
							|  |  |  |       showTitleEditor, | 
					
						
							|  |  |  |       mergeAbove, | 
					
						
							|  |  |  |       openDialog, | 
					
						
							|  |  |  |       setIngredientIds, | 
					
						
							|  |  |  |       undoMerge, | 
					
						
							|  |  |  |       toggleDisabled, | 
					
						
							|  |  |  |       isChecked, | 
					
						
							|  |  |  |       toggleShowTitle, | 
					
						
							|  |  |  |       updateIndex, | 
					
						
							|  |  |  |       autoSetReferences, | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       parseIngredientText, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |   }, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 14:30:38 -09:00
										 |  |  | <style scoped> | 
					
						
							|  |  |  | .v-card--link:before { | 
					
						
							|  |  |  |   background: none; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | </style> | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | 
 |