| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  | <template> | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |   <div v-if="yieldDisplay"> | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |     <div class="text-center d-flex align-center"> | 
					
						
							|  |  |  |       <div> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         <v-menu | 
					
						
							|  |  |  |           v-model="menu" | 
					
						
							|  |  |  |           :disabled="!canEditScale" | 
					
						
							|  |  |  |           offset-y | 
					
						
							|  |  |  |           top | 
					
						
							|  |  |  |           nudge-top="6" | 
					
						
							|  |  |  |           :close-on-content-click="false" | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           <template #activator="{ props }"> | 
					
						
							|  |  |  |             <v-tooltip | 
					
						
							|  |  |  |               v-if="canEditScale" | 
					
						
							|  |  |  |               size="small" | 
					
						
							|  |  |  |               top | 
					
						
							|  |  |  |               color="secondary-darken-1" | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |               <template #activator="{ props: tooltipProps }"> | 
					
						
							|  |  |  |                 <v-card | 
					
						
							|  |  |  |                   class="pa-1 px-2" | 
					
						
							|  |  |  |                   dark | 
					
						
							|  |  |  |                   color="secondary-darken-1" | 
					
						
							|  |  |  |                   size="small" | 
					
						
							|  |  |  |                   v-bind="{ ...props, ...tooltipProps }" | 
					
						
							|  |  |  |                   :style="{ cursor: canEditScale ? '' : 'default' }" | 
					
						
							|  |  |  |                 > | 
					
						
							|  |  |  |                   <v-icon | 
					
						
							|  |  |  |                     v-if="canEditScale" | 
					
						
							|  |  |  |                     size="small" | 
					
						
							|  |  |  |                     class="mr-2" | 
					
						
							|  |  |  |                   > | 
					
						
							|  |  |  |                     {{ $globals.icons.edit }} | 
					
						
							|  |  |  |                   </v-icon> | 
					
						
							|  |  |  |                   <!-- eslint-disable-next-line vue/no-v-html --> | 
					
						
							|  |  |  |                   <span v-html="yieldDisplay" /> | 
					
						
							|  |  |  |                 </v-card> | 
					
						
							|  |  |  |               </template> | 
					
						
							|  |  |  |               <span> {{ $t("recipe.edit-scale") }} </span> | 
					
						
							|  |  |  |             </v-tooltip> | 
					
						
							| 
									
										
										
										
											2025-01-07 18:26:36 +01:00
										 |  |  |             <v-card | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |               v-else | 
					
						
							| 
									
										
										
										
											2025-01-07 18:26:36 +01:00
										 |  |  |               class="pa-1 px-2" | 
					
						
							|  |  |  |               dark | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |               color="secondary-darken-1" | 
					
						
							|  |  |  |               size="small" | 
					
						
							|  |  |  |               v-bind="props" | 
					
						
							| 
									
										
										
										
											2025-01-07 18:26:36 +01:00
										 |  |  |               :style="{ cursor: canEditScale ? '' : 'default' }" | 
					
						
							|  |  |  |             > | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |               <v-icon | 
					
						
							|  |  |  |                 v-if="canEditScale" | 
					
						
							|  |  |  |                 size="small" | 
					
						
							|  |  |  |                 class="mr-2" | 
					
						
							|  |  |  |               > | 
					
						
							|  |  |  |                 {{ $globals.icons.edit }} | 
					
						
							|  |  |  |               </v-icon> | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |               <!-- eslint-disable-next-line vue/no-v-html --> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |               <span v-html="yieldDisplay" /> | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |             </v-card> | 
					
						
							|  |  |  |           </template> | 
					
						
							|  |  |  |           <v-card min-width="300px"> | 
					
						
							|  |  |  |             <v-card-title class="mb-0"> | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |               {{ $t("recipe.servings") }} | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |             </v-card-title> | 
					
						
							|  |  |  |             <v-card-text class="mt-n5"> | 
					
						
							|  |  |  |               <div class="mt-4 d-flex align-center"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |                 <v-text-field | 
					
						
							|  |  |  |                   :model-value="yieldQuantityEditorValue" | 
					
						
							|  |  |  |                   type="number" | 
					
						
							|  |  |  |                   :min="0" | 
					
						
							|  |  |  |                   variant="underlined" | 
					
						
							|  |  |  |                   hide-spin-buttons | 
					
						
							|  |  |  |                   @update:model-value="recalculateScale(yieldQuantityEditorValue)" | 
					
						
							|  |  |  |                 /> | 
					
						
							|  |  |  |                 <v-tooltip | 
					
						
							|  |  |  |                   end | 
					
						
							|  |  |  |                   color="secondary-darken-1" | 
					
						
							|  |  |  |                 > | 
					
						
							|  |  |  |                   <template #activator="{ props }"> | 
					
						
							|  |  |  |                     <v-btn | 
					
						
							|  |  |  |                       v-bind="props" | 
					
						
							|  |  |  |                       icon | 
					
						
							|  |  |  |                       class="mx-1" | 
					
						
							|  |  |  |                       size="small" | 
					
						
							|  |  |  |                       @click="scale = 1" | 
					
						
							|  |  |  |                     > | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |                       <v-icon> | 
					
						
							|  |  |  |                         {{ $globals.icons.undo }} | 
					
						
							|  |  |  |                       </v-icon> | 
					
						
							|  |  |  |                     </v-btn> | 
					
						
							|  |  |  |                   </template> | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |                   <span> {{ $t("recipe.reset-servings-count") }} </span> | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |                 </v-tooltip> | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |             </v-card-text> | 
					
						
							|  |  |  |           </v-card> | 
					
						
							|  |  |  |         </v-menu> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |       <BaseButtonGroup | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |         v-if="canEditScale" | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |         class="pl-2" | 
					
						
							|  |  |  |         :large="false" | 
					
						
							|  |  |  |         :buttons="[ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             icon: $globals.icons.minus, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             text: $t('recipe.decrease-scale-label'), | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |             event: 'decrement', | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |             disabled: disableDecrement, | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             icon: $globals.icons.createAlt, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             text: $t('recipe.increase-scale-label'), | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |             event: 'increment', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ]" | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |         @decrement="recalculateScale(yieldQuantity - 1)" | 
					
						
							|  |  |  |         @increment="recalculateScale(yieldQuantity + 1)" | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |       /> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  |   </div> | 
					
						
							|  |  |  | </template> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  | import { useScaledAmount } from "~/composables/recipes/use-scaled-amount"; | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  | export default defineNuxtComponent({ | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |   props: { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     modelValue: { | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |       type: Number, | 
					
						
							|  |  |  |       required: true, | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |     }, | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |     recipeServings: { | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |       type: Number, | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |       default: 0, | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  |     editScale: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: false, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |   emits: ["update:modelValue"], | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |   setup(props, { emit }) { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     const i18n = useI18n(); | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |     const menu = ref<boolean>(false); | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |     const canEditScale = computed(() => props.editScale && props.recipeServings > 0); | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const scale = computed({ | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       get: () => props.modelValue, | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |       set: (value) => { | 
					
						
							|  |  |  |         const newScaleNumber = parseFloat(`${value}`); | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         emit("update:modelValue", isNaN(newScaleNumber) ? 0 : newScaleNumber); | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |       }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |     function recalculateScale(newYield: number) { | 
					
						
							|  |  |  |       if (isNaN(newYield) || newYield <= 0) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (props.recipeServings <= 0) { | 
					
						
							|  |  |  |         scale.value = 1; | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |         scale.value = newYield / props.recipeServings; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |     const recipeYieldAmount = computed(() => { | 
					
						
							|  |  |  |       return useScaledAmount(props.recipeServings, scale.value); | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |     const yieldQuantity = computed(() => recipeYieldAmount.value.scaledAmount); | 
					
						
							|  |  |  |     const yieldDisplay = computed(() => { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       return yieldQuantity.value | 
					
						
							|  |  |  |         ? i18n.t( | 
					
						
							|  |  |  |           "recipe.serves-amount", { amount: recipeYieldAmount.value.scaledAmountDisplay }, | 
					
						
							|  |  |  |         ) as string | 
					
						
							|  |  |  |         : ""; | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |     // only update yield quantity when the menu opens, so we don't override the user's input
 | 
					
						
							|  |  |  |     const yieldQuantityEditorValue = ref(recipeYieldAmount.value.scaledAmount); | 
					
						
							|  |  |  |     watch( | 
					
						
							|  |  |  |       () => menu.value, | 
					
						
							|  |  |  |       () => { | 
					
						
							|  |  |  |         if (!menu.value) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         yieldQuantityEditorValue.value = recipeYieldAmount.value.scaledAmount; | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const disableDecrement = computed(() => { | 
					
						
							|  |  |  |       return recipeYieldAmount.value.scaledAmount <= 1; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |     return { | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |       menu, | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |       canEditScale, | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |       scale, | 
					
						
							| 
									
										
										
										
											2024-11-20 08:46:27 -06:00
										 |  |  |       recalculateScale, | 
					
						
							|  |  |  |       yieldDisplay, | 
					
						
							|  |  |  |       yieldQuantity, | 
					
						
							|  |  |  |       yieldQuantityEditorValue, | 
					
						
							| 
									
										
										
										
											2024-10-01 16:31:04 +02:00
										 |  |  |       disableDecrement, | 
					
						
							| 
									
										
										
										
											2022-06-09 18:01:25 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | </script> |