| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | <template> | 
					
						
							|  |  |  |   <v-container> | 
					
						
							|  |  |  |     <BasePageTitle divider> | 
					
						
							|  |  |  |       <template #header> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         <v-img | 
					
						
							|  |  |  |           width="100" | 
					
						
							|  |  |  |           max-height="100" | 
					
						
							|  |  |  |           max-width="100" | 
					
						
							|  |  |  |           :src="require('~/static/svgs/manage-cookbooks.svg')" | 
					
						
							|  |  |  |         /> | 
					
						
							|  |  |  |       </template> | 
					
						
							|  |  |  |       <template #title> | 
					
						
							|  |  |  |         {{ $t('recipe-finder.recipe-finder') }} | 
					
						
							|  |  |  |       </template> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       <template #content> | 
					
						
							|  |  |  |         {{ $t('recipe-finder.recipe-finder-description') }} | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |       </template> | 
					
						
							|  |  |  |     </BasePageTitle> | 
					
						
							|  |  |  |     <v-container v-if="ready"> | 
					
						
							|  |  |  |       <v-row> | 
					
						
							|  |  |  |         <v-col :cols="useMobile ? 12 : 3"> | 
					
						
							|  |  |  |           <v-container class="ma-0 pa-0"> | 
					
						
							|  |  |  |             <v-row no-gutters> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |               <v-col | 
					
						
							|  |  |  |                 cols="12" | 
					
						
							|  |  |  |                 no-gutters | 
					
						
							|  |  |  |                 :class="attrs.searchFilter.colClass" | 
					
						
							|  |  |  |               > | 
					
						
							|  |  |  |                 <SearchFilter | 
					
						
							|  |  |  |                   v-if="foods" | 
					
						
							|  |  |  |                   v-model="selectedFoods" | 
					
						
							|  |  |  |                   :items="foods" | 
					
						
							|  |  |  |                   :class="attrs.searchFilter.filterClass" | 
					
						
							|  |  |  |                 > | 
					
						
							|  |  |  |                   <v-icon start> | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                     {{ $globals.icons.foods }} | 
					
						
							|  |  |  |                   </v-icon> | 
					
						
							|  |  |  |                   {{ $t("general.foods") }} | 
					
						
							|  |  |  |                 </SearchFilter> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                 <SearchFilter | 
					
						
							|  |  |  |                   v-if="tools" | 
					
						
							|  |  |  |                   v-model="selectedTools" | 
					
						
							|  |  |  |                   :items="tools" | 
					
						
							|  |  |  |                   :class="attrs.searchFilter.filterClass" | 
					
						
							|  |  |  |                 > | 
					
						
							|  |  |  |                   <v-icon start> | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                     {{ $globals.icons.potSteam }} | 
					
						
							|  |  |  |                   </v-icon> | 
					
						
							|  |  |  |                   {{ $t("tool.tools") }} | 
					
						
							|  |  |  |                 </SearchFilter> | 
					
						
							|  |  |  |                 <div :class="attrs.searchFilter.filterClass"> | 
					
						
							|  |  |  |                   <v-badge | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                     :model-value="!!queryFilterJSON.parts && queryFilterJSON.parts.length > 0" | 
					
						
							|  |  |  |                     size="small" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                     color="primary" | 
					
						
							|  |  |  |                     :content="(queryFilterJSON.parts || []).length" | 
					
						
							|  |  |  |                   > | 
					
						
							|  |  |  |                     <v-btn | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                       size="small" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                       color="accent" | 
					
						
							|  |  |  |                       dark | 
					
						
							|  |  |  |                       @click="queryFilterMenu = !queryFilterMenu" | 
					
						
							|  |  |  |                     > | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                       <v-icon start> | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         {{ $globals.icons.filter }} | 
					
						
							|  |  |  |                       </v-icon> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                       {{ $t("recipe-finder.other-filters") }} | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                       <BaseDialog | 
					
						
							|  |  |  |                         v-model="queryFilterMenu" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                         :title="$t('recipe-finder.other-filters')" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         :icon="$globals.icons.filter" | 
					
						
							|  |  |  |                         width="100%" | 
					
						
							|  |  |  |                         max-width="1100px" | 
					
						
							|  |  |  |                         :submit-disabled="!queryFilterEditorValue" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                         can-confirm | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         @confirm="saveQueryFilter" | 
					
						
							|  |  |  |                       > | 
					
						
							|  |  |  |                         <QueryFilterBuilder | 
					
						
							|  |  |  |                           :key="queryFilterMenuKey" | 
					
						
							|  |  |  |                           :initial-query-filter="queryFilterJSON" | 
					
						
							|  |  |  |                           :field-defs="queryFilterBuilderFields" | 
					
						
							|  |  |  |                           @input="(value) => queryFilterEditorValue = value" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                           @input-j-s-o-n="(value) => queryFilterEditorValueJSON = value" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         /> | 
					
						
							|  |  |  |                         <template #custom-card-action> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                           <BaseButton | 
					
						
							|  |  |  |                             color="error" | 
					
						
							|  |  |  |                             type="submit" | 
					
						
							|  |  |  |                             @click="clearQueryFilter" | 
					
						
							|  |  |  |                           > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                             <template #icon> | 
					
						
							|  |  |  |                               {{ $globals.icons.close }} | 
					
						
							|  |  |  |                             </template> | 
					
						
							|  |  |  |                             {{ $t("search.clear-selection") }} | 
					
						
							|  |  |  |                           </BaseButton> | 
					
						
							|  |  |  |                         </template> | 
					
						
							|  |  |  |                       </BaseDialog> | 
					
						
							|  |  |  |                     </v-btn> | 
					
						
							|  |  |  |                   </v-badge> | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |               </v-col> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							|  |  |  |             <!-- Settings Menu --> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <v-row | 
					
						
							|  |  |  |               no-gutters | 
					
						
							|  |  |  |               class="mb-2" | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |               <v-col | 
					
						
							|  |  |  |                 cols="12" | 
					
						
							|  |  |  |                 :class="attrs.settings.colClass" | 
					
						
							|  |  |  |               > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                 <v-menu | 
					
						
							|  |  |  |                   v-model="settingsMenu" | 
					
						
							|  |  |  |                   offset-y | 
					
						
							|  |  |  |                   nudge-bottom="3" | 
					
						
							|  |  |  |                   :close-on-content-click="false" | 
					
						
							|  |  |  |                 > | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                   <template #activator="{ props }"> | 
					
						
							|  |  |  |                     <v-btn | 
					
						
							|  |  |  |                       size="small" | 
					
						
							|  |  |  |                       color="primary" | 
					
						
							|  |  |  |                       dark | 
					
						
							|  |  |  |                       v-bind="props" | 
					
						
							|  |  |  |                     > | 
					
						
							|  |  |  |                       <v-icon start> | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         {{ $globals.icons.cog }} | 
					
						
							|  |  |  |                       </v-icon> | 
					
						
							|  |  |  |                       {{ $t("general.settings") }} | 
					
						
							|  |  |  |                     </v-btn> | 
					
						
							|  |  |  |                   </template> | 
					
						
							|  |  |  |                   <v-card> | 
					
						
							|  |  |  |                     <v-card-text> | 
					
						
							|  |  |  |                       <div> | 
					
						
							|  |  |  |                         <v-text-field | 
					
						
							|  |  |  |                           v-model="settings.maxMissingFoods" | 
					
						
							|  |  |  |                           type="number" | 
					
						
							|  |  |  |                           hide-details | 
					
						
							|  |  |  |                           hide-spin-buttons | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                           :label="$t('recipe-finder.max-missing-ingredients')" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         /> | 
					
						
							|  |  |  |                         <v-text-field | 
					
						
							|  |  |  |                           v-model="settings.maxMissingTools" | 
					
						
							|  |  |  |                           type="number" | 
					
						
							|  |  |  |                           hide-details | 
					
						
							|  |  |  |                           hide-spin-buttons | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                           :label="$t('recipe-finder.max-missing-tools')" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                           class="mt-4" | 
					
						
							|  |  |  |                         /> | 
					
						
							|  |  |  |                       </div> | 
					
						
							|  |  |  |                       <div class="mt-1"> | 
					
						
							|  |  |  |                         <v-checkbox | 
					
						
							|  |  |  |                           v-if="isOwnGroup" | 
					
						
							|  |  |  |                           v-model="settings.includeFoodsOnHand" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                           density="compact" | 
					
						
							|  |  |  |                           size="small" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                           hide-details | 
					
						
							|  |  |  |                           class="my-auto" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                           :label="$t('recipe-finder.include-ingredients-on-hand')" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         /> | 
					
						
							|  |  |  |                         <v-checkbox | 
					
						
							|  |  |  |                           v-if="isOwnGroup" | 
					
						
							|  |  |  |                           v-model="settings.includeToolsOnHand" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                           density="compact" | 
					
						
							|  |  |  |                           size="small" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                           hide-details | 
					
						
							|  |  |  |                           class="my-auto" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                           :label="$t('recipe-finder.include-tools-on-hand')" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         /> | 
					
						
							|  |  |  |                       </div> | 
					
						
							|  |  |  |                     </v-card-text> | 
					
						
							|  |  |  |                   </v-card> | 
					
						
							|  |  |  |                 </v-menu> | 
					
						
							|  |  |  |               </v-col> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <v-row | 
					
						
							|  |  |  |               no-gutters | 
					
						
							|  |  |  |               class="my-2" | 
					
						
							|  |  |  |             > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |               <v-col cols="12"> | 
					
						
							|  |  |  |                 <v-divider /> | 
					
						
							|  |  |  |               </v-col> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <v-row | 
					
						
							|  |  |  |               no-gutters | 
					
						
							|  |  |  |               class="mt-5" | 
					
						
							|  |  |  |             > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |               <v-card-title class="ma-0 pa-0"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                 {{ $t("recipe-finder.selected-ingredients") }} | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |               </v-card-title> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |               <v-container | 
					
						
							|  |  |  |                 class="ma-0 pa-0" | 
					
						
							|  |  |  |                 style="max-height: 60vh; overflow-y: auto;" | 
					
						
							|  |  |  |               > | 
					
						
							|  |  |  |                 <v-card-text | 
					
						
							|  |  |  |                   v-if="!selectedFoods.length" | 
					
						
							|  |  |  |                   class="ma-0 pa-0" | 
					
						
							|  |  |  |                 > | 
					
						
							|  |  |  |                   {{ $t("recipe-finder.no-ingredients-selected") }} | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                 </v-card-text> | 
					
						
							|  |  |  |                 <div v-if="useMobile"> | 
					
						
							|  |  |  |                   <v-row no-gutters> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                     <v-col | 
					
						
							|  |  |  |                       cols="12" | 
					
						
							|  |  |  |                       class="d-flex flex-wrap justify-end" | 
					
						
							|  |  |  |                     > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                       <v-chip | 
					
						
							|  |  |  |                         v-for="food in selectedFoods" | 
					
						
							|  |  |  |                         :key="food.id" | 
					
						
							|  |  |  |                         label | 
					
						
							|  |  |  |                         class="ma-1" | 
					
						
							|  |  |  |                         color="accent custom-transparent" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                         closable | 
					
						
							|  |  |  |                         variant="flat" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         @click:close="removeFood(food)" | 
					
						
							|  |  |  |                       > | 
					
						
							|  |  |  |                         <span class="text-hide-overflow">{{ food.pluralName || food.name }}</span> | 
					
						
							|  |  |  |                       </v-chip> | 
					
						
							|  |  |  |                     </v-col> | 
					
						
							|  |  |  |                   </v-row> | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |                 <div v-else> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                   <v-row | 
					
						
							|  |  |  |                     v-for="food in selectedFoods" | 
					
						
							|  |  |  |                     :key="food.id" | 
					
						
							|  |  |  |                     no-gutters | 
					
						
							|  |  |  |                     class="mb-1" | 
					
						
							|  |  |  |                   > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                     <v-col cols="12"> | 
					
						
							|  |  |  |                       <v-chip | 
					
						
							|  |  |  |                         label | 
					
						
							|  |  |  |                         color="accent custom-transparent" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                         variant="flat" | 
					
						
							|  |  |  |                         closable | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         @click:close="removeFood(food)" | 
					
						
							|  |  |  |                       > | 
					
						
							|  |  |  |                         <span class="text-hide-overflow">{{ food.pluralName || food.name }}</span> | 
					
						
							|  |  |  |                       </v-chip> | 
					
						
							|  |  |  |                     </v-col> | 
					
						
							|  |  |  |                   </v-row> | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |               </v-container> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <v-row | 
					
						
							|  |  |  |               v-if="selectedTools.length" | 
					
						
							|  |  |  |               no-gutters | 
					
						
							|  |  |  |               class="mt-5" | 
					
						
							|  |  |  |             > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |               <v-card-title class="ma-0 pa-0"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                 {{ $t("recipe-finder.selected-tools") }} | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |               </v-card-title> | 
					
						
							|  |  |  |               <v-container class="ma-0 pa-0"> | 
					
						
							|  |  |  |                 <div v-if="useMobile"> | 
					
						
							|  |  |  |                   <v-row no-gutters> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                     <v-col | 
					
						
							|  |  |  |                       cols="12" | 
					
						
							|  |  |  |                       class="d-flex flex-wrap justify-end" | 
					
						
							|  |  |  |                     > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                       <v-chip | 
					
						
							|  |  |  |                         v-for="tool in selectedTools" | 
					
						
							|  |  |  |                         :key="tool.id" | 
					
						
							|  |  |  |                         label | 
					
						
							|  |  |  |                         class="ma-1" | 
					
						
							|  |  |  |                         color="accent custom-transparent" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                         closeable | 
					
						
							|  |  |  |                         variant="flat" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         @click:close="removeTool(tool)" | 
					
						
							|  |  |  |                       > | 
					
						
							|  |  |  |                         <span class="text-hide-overflow">{{ tool.name }}</span> | 
					
						
							|  |  |  |                       </v-chip> | 
					
						
							|  |  |  |                     </v-col> | 
					
						
							|  |  |  |                   </v-row> | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |                 <div v-else> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                   <v-row | 
					
						
							|  |  |  |                     v-for="tool in selectedTools" | 
					
						
							|  |  |  |                     :key="tool.id" | 
					
						
							|  |  |  |                     no-gutters | 
					
						
							|  |  |  |                     class="mb-1" | 
					
						
							|  |  |  |                   > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                     <v-col cols="12"> | 
					
						
							|  |  |  |                       <v-chip | 
					
						
							|  |  |  |                         label | 
					
						
							|  |  |  |                         color="accent custom-transparent" | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                         closable | 
					
						
							|  |  |  |                         variant="flat" | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                         @click:close="removeTool(tool)" | 
					
						
							|  |  |  |                       > | 
					
						
							|  |  |  |                         <span class="text-hide-overflow">{{ tool.name }}</span> | 
					
						
							|  |  |  |                       </v-chip> | 
					
						
							|  |  |  |                     </v-col> | 
					
						
							|  |  |  |                   </v-row> | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |               </v-container> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							|  |  |  |           </v-container> | 
					
						
							|  |  |  |         </v-col> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         <v-col | 
					
						
							|  |  |  |           :cols="useMobile ? 12 : 9" | 
					
						
							|  |  |  |           :style="useMobile ? '' : 'max-height: 70vh; overflow-y: auto'" | 
					
						
							|  |  |  |         > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |           <v-container | 
					
						
							|  |  |  |             v-if="recipeSuggestions.readyToMake.length || recipeSuggestions.missingItems.length" | 
					
						
							|  |  |  |             class="ma-0 pa-0" | 
					
						
							|  |  |  |           > | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <v-row | 
					
						
							|  |  |  |               v-if="recipeSuggestions.readyToMake.length" | 
					
						
							|  |  |  |               density="compact" | 
					
						
							|  |  |  |             > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |               <v-col cols="12"> | 
					
						
							|  |  |  |                 <v-card-title :class="attrs.title.class.readyToMake"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                   {{ $t("recipe-finder.ready-to-make") }} | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                 </v-card-title> | 
					
						
							|  |  |  |               </v-col> | 
					
						
							|  |  |  |               <v-col | 
					
						
							|  |  |  |                 v-for="(item, idx) in recipeSuggestions.readyToMake" | 
					
						
							|  |  |  |                 :key="`${idx}-ready`" | 
					
						
							|  |  |  |                 cols="12" | 
					
						
							|  |  |  |               > | 
					
						
							|  |  |  |                 <v-lazy> | 
					
						
							|  |  |  |                   <RecipeSuggestion | 
					
						
							|  |  |  |                     :recipe="item.recipe" | 
					
						
							|  |  |  |                     :missing-foods="item.missingFoods" | 
					
						
							|  |  |  |                     :missing-tools="item.missingTools" | 
					
						
							|  |  |  |                     :disable-checkbox="loading" | 
					
						
							|  |  |  |                     @add-food="addFood" | 
					
						
							|  |  |  |                     @remove-food="removeFood" | 
					
						
							|  |  |  |                     @add-tool="addTool" | 
					
						
							|  |  |  |                     @remove-tool="removeTool" | 
					
						
							|  |  |  |                   /> | 
					
						
							|  |  |  |                 </v-lazy> | 
					
						
							|  |  |  |               </v-col> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <v-row | 
					
						
							|  |  |  |               v-if="recipeSuggestions.missingItems.length" | 
					
						
							|  |  |  |               density="compact" | 
					
						
							|  |  |  |             > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |               <v-col cols="12"> | 
					
						
							|  |  |  |                 <v-card-title :class="attrs.title.class.missingItems"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                   {{ $t("recipe-finder.almost-ready-to-make") }} | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                 </v-card-title> | 
					
						
							|  |  |  |               </v-col> | 
					
						
							|  |  |  |               <v-col | 
					
						
							|  |  |  |                 v-for="(item, idx) in recipeSuggestions.missingItems" | 
					
						
							|  |  |  |                 :key="`${idx}-missing`" | 
					
						
							|  |  |  |                 cols="12" | 
					
						
							|  |  |  |               > | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                 <v-lazy> | 
					
						
							|  |  |  |                   <RecipeSuggestion | 
					
						
							|  |  |  |                     :recipe="item.recipe" | 
					
						
							|  |  |  |                     :missing-foods="item.missingFoods" | 
					
						
							|  |  |  |                     :missing-tools="item.missingTools" | 
					
						
							|  |  |  |                     :disable-checkbox="loading" | 
					
						
							|  |  |  |                     @add-food="addFood" | 
					
						
							|  |  |  |                     @remove-food="removeFood" | 
					
						
							|  |  |  |                     @add-tool="addTool" | 
					
						
							|  |  |  |                     @remove-tool="removeTool" | 
					
						
							|  |  |  |                   /> | 
					
						
							|  |  |  |                 </v-lazy> | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |               </v-col> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							|  |  |  |           </v-container> | 
					
						
							|  |  |  |           <v-container v-else-if="!recipesReady"> | 
					
						
							|  |  |  |             <v-row> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |               <v-col | 
					
						
							|  |  |  |                 cols="12" | 
					
						
							|  |  |  |                 class="d-flex justify-center" | 
					
						
							|  |  |  |               > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                 <div class="text-center"> | 
					
						
							|  |  |  |                   <AppLoader waiting-text="" /> | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |               </v-col> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							|  |  |  |           </v-container> | 
					
						
							|  |  |  |           <v-container v-else> | 
					
						
							|  |  |  |             <v-row> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |               <v-col | 
					
						
							|  |  |  |                 cols="12" | 
					
						
							|  |  |  |                 class="d-flex flex-column justify-center align-center ga-1" | 
					
						
							|  |  |  |               > | 
					
						
							|  |  |  |                 <v-card-title class="ma-0 pa-0"> | 
					
						
							|  |  |  |                   {{ $t("recipe-finder.no-recipes-found") }} | 
					
						
							|  |  |  |                 </v-card-title> | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                 <v-card-text class="ma-0 pa-0 text-center"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                   {{ $t("recipe-finder.no-recipes-found-description") }} | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |                 </v-card-text> | 
					
						
							|  |  |  |               </v-col> | 
					
						
							|  |  |  |             </v-row> | 
					
						
							|  |  |  |           </v-container> | 
					
						
							|  |  |  |         </v-col> | 
					
						
							|  |  |  |       </v-row> | 
					
						
							|  |  |  |     </v-container> | 
					
						
							|  |  |  |     <v-container v-else> | 
					
						
							|  |  |  |       <v-row> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         <v-col | 
					
						
							|  |  |  |           cols="12" | 
					
						
							|  |  |  |           class="d-flex justify-center" | 
					
						
							|  |  |  |         > | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |           <div class="text-center"> | 
					
						
							|  |  |  |             <AppLoader waiting-text="" /> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         </v-col> | 
					
						
							|  |  |  |       </v-row> | 
					
						
							|  |  |  |     </v-container> | 
					
						
							|  |  |  |   </v-container> | 
					
						
							|  |  |  | </template> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <script lang="ts"> | 
					
						
							|  |  |  | import { watchDebounced } from "@vueuse/core"; | 
					
						
							|  |  |  | import { useUserApi } from "~/composables/api"; | 
					
						
							|  |  |  | import { usePublicExploreApi } from "~/composables/api/api-client"; | 
					
						
							|  |  |  | import { useLoggedInState } from "~/composables/use-logged-in-state"; | 
					
						
							|  |  |  | import { useFoodStore, usePublicFoodStore, useToolStore, usePublicToolStore } from "~/composables/store"; | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  | import type { IngredientFood, RecipeSuggestionQuery, RecipeSuggestionResponseItem, RecipeTool } from "~/lib/api/types/recipe"; | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | import { Organizer } from "~/lib/api/types/non-generated"; | 
					
						
							|  |  |  | import QueryFilterBuilder from "~/components/Domain/QueryFilterBuilder.vue"; | 
					
						
							|  |  |  | import RecipeSuggestion from "~/components/Domain/Recipe/RecipeSuggestion.vue"; | 
					
						
							|  |  |  | import SearchFilter from "~/components/Domain/SearchFilter.vue"; | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  | import type { QueryFilterJSON } from "~/lib/api/types/response"; | 
					
						
							|  |  |  | import type { FieldDefinition } from "~/composables/use-query-filter-builder"; | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | import { useRecipeFinderPreferences } from "~/composables/use-users/preferences"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | interface RecipeSuggestions { | 
					
						
							|  |  |  |   readyToMake: RecipeSuggestionResponseItem[]; | 
					
						
							|  |  |  |   missingItems: RecipeSuggestionResponseItem[]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  | export default defineNuxtComponent({ | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |   components: { QueryFilterBuilder, RecipeSuggestion, SearchFilter }, | 
					
						
							|  |  |  |   setup() { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     const { $vuetify } = useNuxtApp(); | 
					
						
							|  |  |  |     const i18n = useI18n(); | 
					
						
							|  |  |  |     const $auth = useMealieAuth(); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |     const route = useRoute(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     useSeoMeta({ | 
					
						
							|  |  |  |       title: i18n.t("recipe-finder.recipe-finder"), | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const useMobile = computed(() => $vuetify.display.smAndDown.value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || ""); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |     const { isOwnGroup } = useLoggedInState(); | 
					
						
							|  |  |  |     const api = isOwnGroup.value ? useUserApi() : usePublicExploreApi(groupSlug.value).explore; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const preferences = useRecipeFinderPreferences(); | 
					
						
							|  |  |  |     const state = reactive({ | 
					
						
							|  |  |  |       ready: false, | 
					
						
							|  |  |  |       loading: false, | 
					
						
							|  |  |  |       recipesReady: false, | 
					
						
							|  |  |  |       settingsMenu: false, | 
					
						
							|  |  |  |       queryFilterMenu: false, | 
					
						
							|  |  |  |       queryFilterMenuKey: 0, | 
					
						
							|  |  |  |       queryFilterEditorValue: "", | 
					
						
							|  |  |  |       queryFilterEditorValueJSON: {}, | 
					
						
							|  |  |  |       queryFilterJSON: preferences.value.queryFilterJSON, | 
					
						
							|  |  |  |       settings: { | 
					
						
							|  |  |  |         maxMissingFoods: preferences.value.maxMissingFoods, | 
					
						
							|  |  |  |         maxMissingTools: preferences.value.maxMissingTools, | 
					
						
							|  |  |  |         includeFoodsOnHand: preferences.value.includeFoodsOnHand, | 
					
						
							|  |  |  |         includeToolsOnHand: preferences.value.includeToolsOnHand, | 
					
						
							|  |  |  |         queryFilter: preferences.value.queryFilter, | 
					
						
							| 
									
										
										
										
											2024-12-03 11:47:05 -06:00
										 |  |  |         limit: 20, | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |       }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     onMounted(() => { | 
					
						
							|  |  |  |       if (!isOwnGroup.value) { | 
					
						
							|  |  |  |         state.settings.includeFoodsOnHand = false; | 
					
						
							|  |  |  |         state.settings.includeToolsOnHand = false; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     watch( | 
					
						
							|  |  |  |       () => state, | 
					
						
							|  |  |  |       (newState) => { | 
					
						
							|  |  |  |         preferences.value.queryFilter = newState.settings.queryFilter; | 
					
						
							|  |  |  |         preferences.value.queryFilterJSON = newState.queryFilterJSON; | 
					
						
							|  |  |  |         preferences.value.maxMissingFoods = newState.settings.maxMissingFoods; | 
					
						
							|  |  |  |         preferences.value.maxMissingTools = newState.settings.maxMissingTools; | 
					
						
							|  |  |  |         preferences.value.includeFoodsOnHand = newState.settings.includeFoodsOnHand; | 
					
						
							|  |  |  |         preferences.value.includeToolsOnHand = newState.settings.includeToolsOnHand; | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         deep: true, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const attrs = computed(() => { | 
					
						
							|  |  |  |       return { | 
					
						
							|  |  |  |         title: { | 
					
						
							|  |  |  |           class: { | 
					
						
							|  |  |  |             readyToMake: "ma-0 pa-0", | 
					
						
							|  |  |  |             missingItems: recipeSuggestions.value.readyToMake.length ? "ma-0 pa-0 mt-5" : "ma-0 pa-0", | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         searchFilter: { | 
					
						
							|  |  |  |           colClass: useMobile.value ? "d-flex flex-wrap justify-end" : "d-flex flex-wrap justify-start", | 
					
						
							|  |  |  |           filterClass: useMobile.value ? "ml-4 mb-2" : "mr-4 mb-2", | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         settings: { | 
					
						
							|  |  |  |           colClass: useMobile.value ? "d-flex flex-wrap justify-end" : "d-flex flex-wrap justify-start", | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const foodStore = isOwnGroup.value ? useFoodStore() : usePublicFoodStore(groupSlug.value); | 
					
						
							|  |  |  |     const selectedFoods = ref<IngredientFood[]>([]); | 
					
						
							|  |  |  |     function addFood(food: IngredientFood) { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       selectedFoods.value = [...selectedFoods.value, food]; | 
					
						
							| 
									
										
										
										
											2024-12-03 11:47:05 -06:00
										 |  |  |       handleFoodUpdates(); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |     } | 
					
						
							|  |  |  |     function removeFood(food: IngredientFood) { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       selectedFoods.value = selectedFoods.value.filter(f => f.id !== food.id); | 
					
						
							| 
									
										
										
										
											2024-12-03 11:47:05 -06:00
										 |  |  |       handleFoodUpdates(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     function handleFoodUpdates() { | 
					
						
							|  |  |  |       selectedFoods.value.sort((a, b) => (a.pluralName || a.name).localeCompare(b.pluralName || b.name)); | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       preferences.value.foodIds = selectedFoods.value.map(food => food.id); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |     } | 
					
						
							|  |  |  |     watch( | 
					
						
							|  |  |  |       () => selectedFoods.value, | 
					
						
							|  |  |  |       () => { | 
					
						
							| 
									
										
										
										
											2024-12-03 11:47:05 -06:00
										 |  |  |         handleFoodUpdates(); | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     ); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const toolStore = isOwnGroup.value ? useToolStore() : usePublicToolStore(groupSlug.value); | 
					
						
							|  |  |  |     const selectedTools = ref<RecipeTool[]>([]); | 
					
						
							|  |  |  |     function addTool(tool: RecipeTool) { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       selectedTools.value = [...selectedTools.value, tool]; | 
					
						
							| 
									
										
										
										
											2024-12-03 11:47:05 -06:00
										 |  |  |       handleToolUpdates(); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |     } | 
					
						
							|  |  |  |     function removeTool(tool: RecipeTool) { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       selectedTools.value = selectedTools.value.filter(t => t.id !== tool.id); | 
					
						
							| 
									
										
										
										
											2024-12-03 11:47:05 -06:00
										 |  |  |       handleToolUpdates(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     function handleToolUpdates() { | 
					
						
							|  |  |  |       selectedTools.value.sort((a, b) => a.name.localeCompare(b.name)); | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       preferences.value.toolIds = selectedTools.value.map(tool => tool.id); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |     } | 
					
						
							|  |  |  |     watch( | 
					
						
							|  |  |  |       () => selectedTools.value, | 
					
						
							|  |  |  |       () => { | 
					
						
							| 
									
										
										
										
											2024-12-03 11:47:05 -06:00
										 |  |  |         handleToolUpdates(); | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     async function hydrateFoods() { | 
					
						
							|  |  |  |       if (!preferences.value.foodIds.length) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (!foodStore.store.value.length) { | 
					
						
							|  |  |  |         await foodStore.actions.refresh(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const foods = preferences.value.foodIds | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         .map(foodId => foodStore.store.value.find(food => food.id === foodId)) | 
					
						
							|  |  |  |         .filter(food => !!food); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |       selectedFoods.value = foods; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function hydrateTools() { | 
					
						
							|  |  |  |       if (!preferences.value.toolIds.length) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (!toolStore.store.value.length) { | 
					
						
							|  |  |  |         await toolStore.actions.refresh(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const tools = preferences.value.toolIds | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         .map(toolId => toolStore.store.value.find(tool => tool.id === toolId)) | 
					
						
							|  |  |  |         .filter(tool => !!tool); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |       selectedTools.value = tools; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     onMounted(async () => { | 
					
						
							|  |  |  |       await Promise.all([hydrateFoods(), hydrateTools()]); | 
					
						
							|  |  |  |       state.ready = true; | 
					
						
							|  |  |  |       if (!selectedFoods.value.length) { | 
					
						
							|  |  |  |         state.recipesReady = true; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const recipeResponseItems = ref<RecipeSuggestionResponseItem[]>([]); | 
					
						
							|  |  |  |     const recipeSuggestions = computed<RecipeSuggestions>(() => { | 
					
						
							|  |  |  |       const readyToMake: RecipeSuggestionResponseItem[] = []; | 
					
						
							|  |  |  |       const missingItems: RecipeSuggestionResponseItem[] = []; | 
					
						
							|  |  |  |       recipeResponseItems.value.forEach((responseItem) => { | 
					
						
							|  |  |  |         if (responseItem.missingFoods.length === 0 && responseItem.missingTools.length === 0) { | 
					
						
							|  |  |  |           readyToMake.push(responseItem); | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |           missingItems.push(responseItem); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return { | 
					
						
							|  |  |  |         readyToMake, | 
					
						
							|  |  |  |         missingItems, | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     watchDebounced( | 
					
						
							|  |  |  |       [selectedFoods, selectedTools, state.settings], async () => { | 
					
						
							|  |  |  |         // don't search for suggestions if no foods are selected
 | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         if (!selectedFoods.value.length) { | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |           recipeResponseItems.value = []; | 
					
						
							|  |  |  |           state.recipesReady = true; | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         state.loading = true; | 
					
						
							|  |  |  |         const { data } = await api.recipes.getSuggestions( | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             limit: state.settings.limit, | 
					
						
							|  |  |  |             queryFilter: state.settings.queryFilter, | 
					
						
							|  |  |  |             maxMissingFoods: state.settings.maxMissingFoods, | 
					
						
							|  |  |  |             maxMissingTools: state.settings.maxMissingTools, | 
					
						
							|  |  |  |             includeFoodsOnHand: state.settings.includeFoodsOnHand, | 
					
						
							|  |  |  |             includeToolsOnHand: state.settings.includeToolsOnHand, | 
					
						
							|  |  |  |           } as RecipeSuggestionQuery, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |           selectedFoods.value.map(food => food.id), | 
					
						
							|  |  |  |           selectedTools.value.map(tool => tool.id), | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |         ); | 
					
						
							|  |  |  |         state.loading = false; | 
					
						
							|  |  |  |         if (!data) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         recipeResponseItems.value = data.items; | 
					
						
							|  |  |  |         state.recipesReady = true; | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         debounce: 500, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const queryFilterBuilderFields: FieldDefinition[] = [ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         name: "recipe_category.id", | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         label: i18n.t("category.categories"), | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |         type: Organizer.Category, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         name: "tags.id", | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         label: i18n.t("tag.tags"), | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |         type: Organizer.Tag, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         name: "household_id", | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         label: i18n.t("household.households"), | 
					
						
							| 
									
										
										
										
											2024-12-03 07:27:41 -06:00
										 |  |  |         type: Organizer.Household, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function clearQueryFilter() { | 
					
						
							|  |  |  |       state.queryFilterEditorValue = ""; | 
					
						
							|  |  |  |       state.queryFilterEditorValueJSON = { parts: [] } as QueryFilterJSON; | 
					
						
							|  |  |  |       state.settings.queryFilter = ""; | 
					
						
							|  |  |  |       state.queryFilterJSON = { parts: [] } as QueryFilterJSON; | 
					
						
							|  |  |  |       state.queryFilterMenu = false; | 
					
						
							|  |  |  |       state.queryFilterMenuKey += 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function saveQueryFilter() { | 
					
						
							|  |  |  |       state.settings.queryFilter = state.queryFilterEditorValue || ""; | 
					
						
							|  |  |  |       state.queryFilterJSON = state.queryFilterEditorValueJSON || { parts: [] } as QueryFilterJSON; | 
					
						
							|  |  |  |       state.queryFilterMenu = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       ...toRefs(state), | 
					
						
							|  |  |  |       useMobile, | 
					
						
							|  |  |  |       attrs, | 
					
						
							|  |  |  |       isOwnGroup, | 
					
						
							|  |  |  |       foods: foodStore.store, | 
					
						
							|  |  |  |       selectedFoods, | 
					
						
							|  |  |  |       addFood, | 
					
						
							|  |  |  |       removeFood, | 
					
						
							|  |  |  |       tools: toolStore.store, | 
					
						
							|  |  |  |       selectedTools, | 
					
						
							|  |  |  |       addTool, | 
					
						
							|  |  |  |       removeTool, | 
					
						
							|  |  |  |       recipeSuggestions, | 
					
						
							|  |  |  |       queryFilterBuilderFields, | 
					
						
							|  |  |  |       clearQueryFilter, | 
					
						
							|  |  |  |       saveQueryFilter, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | </script> |