69
69
></v-select >
70
70
</v-card-text >
71
71
</BaseDialog >
72
- <BaseDialog v-model =" shoppingListDialog" :title =" $t('recipe.add-to-list')" :icon =" $globals.icons.cartCheck" >
73
- <v-card-text >
74
- <v-card
75
- v-for =" list in shoppingLists"
76
- :key =" list.id"
77
- hover
78
- class =" my-2 left-border"
79
- @click =" openShoppingListIngredientDialog(list)"
80
- >
81
- <v-card-title class =" py-2" >
82
- {{ list.name }}
83
- </v-card-title >
84
- </v-card >
85
- </v-card-text >
86
- </BaseDialog >
87
- <BaseDialog
88
- v-model =" shoppingListIngredientDialog"
89
- :title =" selectedShoppingList ? selectedShoppingList.name : $t('recipe.add-to-list')"
90
- :icon =" $globals.icons.cartCheck"
91
- width =" 70%"
92
- :submit-text =" $tc('recipe.add-to-list')"
93
- @submit =" addRecipeToList()"
94
- >
95
- <v-card
96
- elevation =" 0"
97
- height =" fit-content"
98
- max-height =" 60vh"
99
- width =" 100%"
100
- :class =" $vuetify.breakpoint.smAndDown ? '' : 'ingredient-grid'"
101
- :style =" $vuetify.breakpoint.smAndDown ? '' : { gridTemplateRows: `repeat(${Math.ceil(recipeIngredients.length / 2)}, min-content)` }"
102
- style =" overflow-y : auto "
103
- >
104
- <v-list-item
105
- v-for =" (ingredientData, i) in recipeIngredients"
106
- :key =" 'ingredient' + i"
107
- dense
108
- @click =" recipeIngredients[i].checked = !recipeIngredients[i].checked"
109
- >
110
- <v-checkbox
111
- hide-details
112
- :input-value =" ingredientData.checked"
113
- class =" pt-0 my-auto py-auto"
114
- color =" secondary"
115
- />
116
- <v-list-item-content :key =" ingredientData.ingredient.quantity" >
117
- <RecipeIngredientListItem
118
- :ingredient =" ingredientData.ingredient"
119
- :disable-amount =" ingredientData.disableAmount"
120
- :scale =" recipeScale" />
121
- </v-list-item-content >
122
- </v-list-item >
123
- </v-card >
124
- <div class =" d-flex justify-end mb-4 mt-2" >
125
- <BaseButtonGroup
126
- :buttons =" [
127
- {
128
- icon: $globals.icons.checkboxBlankOutline,
129
- text: $tc('shopping-list.uncheck-all-items'),
130
- event: 'uncheck',
131
- },
132
- {
133
- icon: $globals.icons.checkboxOutline,
134
- text: $tc('shopping-list.check-all-items'),
135
- event: 'check',
136
- },
137
- ]"
138
- @uncheck =" bulkCheckIngredients(false)"
139
- @check =" bulkCheckIngredients(true)"
140
- />
141
- </div >
142
- </BaseDialog >
72
+ <RecipeDialogAddToShoppingList
73
+ v-if =" shoppingLists && recipeRefWithScale"
74
+ v-model =" shoppingListDialog"
75
+ :recipes =" [recipeRefWithScale]"
76
+ :shopping-lists =" shoppingLists"
77
+ />
143
78
<v-menu
144
79
offset-y
145
80
left
171
106
172
107
<script lang="ts">
173
108
import { computed , defineComponent , reactive , toRefs , useContext , useRoute , useRouter , ref } from " @nuxtjs/composition-api" ;
174
- import RecipeIngredientListItem from " ./RecipeIngredientListItem .vue" ;
109
+ import RecipeDialogAddToShoppingList from " ./RecipeDialogAddToShoppingList .vue" ;
175
110
import RecipeDialogPrintPreferences from " ./RecipeDialogPrintPreferences.vue" ;
176
111
import RecipeDialogShare from " ./RecipeDialogShare.vue" ;
177
112
import { useLoggedInState } from " ~/composables/use-logged-in-state" ;
178
113
import { useUserApi } from " ~/composables/api" ;
179
114
import { alert } from " ~/composables/use-toast" ;
180
115
import { usePlanTypeOptions } from " ~/composables/use-group-mealplan" ;
181
- import { Recipe , RecipeIngredient } from " ~/lib/api/types/recipe" ;
116
+ import { Recipe } from " ~/lib/api/types/recipe" ;
182
117
import { ShoppingListSummary } from " ~/lib/api/types/group" ;
183
118
import { PlanEntryType } from " ~/lib/api/types/meal-plan" ;
184
119
import { useAxiosDownloader } from " ~/composables/api/use-axios-download" ;
@@ -204,9 +139,9 @@ export interface ContextMenuItem {
204
139
205
140
export default defineComponent ({
206
141
components: {
142
+ RecipeDialogAddToShoppingList ,
207
143
RecipeDialogPrintPreferences ,
208
144
RecipeDialogShare ,
209
- RecipeIngredientListItem
210
145
},
211
146
props: {
212
147
useItems: {
@@ -279,7 +214,6 @@ export default defineComponent({
279
214
recipeDeleteDialog: false ,
280
215
mealplannerDialog: false ,
281
216
shoppingListDialog: false ,
282
- shoppingListIngredientDialog: false ,
283
217
recipeDuplicateDialog: false ,
284
218
recipeName: props .name ,
285
219
loading: false ,
@@ -374,7 +308,7 @@ export default defineComponent({
374
308
}
375
309
}
376
310
377
- // Add leading and Apppending Items
311
+ // Add leading and Appending Items
378
312
state .menuItems = [... state .menuItems , ... props .leadingItems , ... props .appendItems ];
379
313
380
314
const icon = props .menuIcon || $globals .icons .dotsVertical ;
@@ -383,9 +317,8 @@ export default defineComponent({
383
317
// Context Menu Event Handler
384
318
385
319
const shoppingLists = ref <ShoppingListSummary []>();
386
- const selectedShoppingList = ref <ShoppingListSummary >();
387
320
const recipeRef = ref <Recipe >(props .recipe );
388
- const recipeIngredients = ref <{ checked : boolean ; ingredient : RecipeIngredient , disableAmount : boolean }[]>([] );
321
+ const recipeRefWithScale = computed (() => recipeRef . value ? { scale: props . recipeScale , ... recipeRef . value } : undefined );
389
322
390
323
async function getShoppingLists() {
391
324
const { data } = await api .shopping .lists .getAll ();
@@ -401,61 +334,6 @@ export default defineComponent({
401
334
}
402
335
}
403
336
404
- async function openShoppingListIngredientDialog(list : ShoppingListSummary ) {
405
- selectedShoppingList .value = list ;
406
- if (! recipeRef .value ) {
407
- await refreshRecipe ();
408
- }
409
-
410
- if (recipeRef .value ?.recipeIngredient ) {
411
- recipeIngredients .value = recipeRef .value .recipeIngredient .map ((ingredient ) => {
412
- return {
413
- checked: true ,
414
- ingredient ,
415
- disableAmount: recipeRef .value .settings ?.disableAmount || false
416
- };
417
- });
418
- }
419
-
420
- state .shoppingListDialog = false ;
421
- state .shoppingListIngredientDialog = true ;
422
- }
423
-
424
- function bulkCheckIngredients(value = true ) {
425
- recipeIngredients .value .forEach ((data ) => {
426
- data .checked = value ;
427
- });
428
- }
429
-
430
- async function addRecipeToList() {
431
- if (! selectedShoppingList .value ) {
432
- return ;
433
- }
434
-
435
- const ingredients: RecipeIngredient [] = [];
436
- recipeIngredients .value .forEach ((data ) => {
437
- if (data .checked ) {
438
- ingredients .push (data .ingredient );
439
- }
440
- });
441
-
442
- if (! ingredients .length ) {
443
- return ;
444
- }
445
-
446
- const { data } = await api .shopping .lists .addRecipe (
447
- selectedShoppingList .value .id ,
448
- props .recipeId ,
449
- props .recipeScale ,
450
- ingredients
451
- );
452
- if (data ) {
453
- alert .success (i18n .t (" recipe.recipe-added-to-list" ) as string );
454
- state .shoppingListDialog = false ;
455
- state .shoppingListIngredientDialog = false ;
456
- }
457
- }
458
-
459
337
const router = useRouter ();
460
338
461
339
async function deleteRecipe() {
@@ -516,10 +394,12 @@ export default defineComponent({
516
394
state .printPreferencesDialog = true ;
517
395
},
518
396
shoppingList : () => {
519
- getShoppingLists ();
397
+ const promises: Promise <void >[] = [getShoppingLists ()];
398
+ if (! recipeRef .value ) {
399
+ promises .push (refreshRecipe ());
400
+ }
520
401
521
- state .shoppingListDialog = true ;
522
- state .shoppingListIngredientDialog = false ;
402
+ Promise .allSettled (promises ).then (() => { state .shoppingListDialog = true });
523
403
},
524
404
share : () => {
525
405
state .shareDialog = true ;
@@ -544,28 +424,15 @@ export default defineComponent({
544
424
return {
545
425
... toRefs (state ),
546
426
recipeRef ,
427
+ recipeRefWithScale ,
547
428
shoppingLists ,
548
- selectedShoppingList ,
549
- openShoppingListIngredientDialog ,
550
- addRecipeToList ,
551
- bulkCheckIngredients ,
552
429
duplicateRecipe ,
553
430
contextMenuEventHandler ,
554
431
deleteRecipe ,
555
432
addRecipeToPlan ,
556
433
icon ,
557
434
planTypeOptions ,
558
- recipeIngredients ,
559
435
};
560
436
},
561
437
});
562
438
</script >
563
-
564
- <style scoped lang="css">
565
- .ingredient-grid {
566
- display : grid ;
567
- grid-auto-flow : column ;
568
- grid-template-columns : 1fr 1fr ;
569
- grid-gap : 0.5rem ;
570
- }
571
- </style >
0 commit comments