69
69
@toggle-dense-view =" toggleMobileCards()"
70
70
/>
71
71
</v-app-bar >
72
- <div v-if =" recipes" class =" mt-2" >
73
- <v-row v-if =" !useMobileCards" >
74
- <v-col v-for =" (recipe, index) in recipes" :key =" recipe.slug + index" :sm =" 6" :md =" 6" :lg =" 4" :xl =" 3" >
75
- <v-lazy >
76
- <RecipeCard
77
- :name =" recipe.name"
78
- :description =" recipe.description"
79
- :slug =" recipe.slug"
80
- :rating =" recipe.rating"
81
- :image =" recipe.image"
82
- :tags =" recipe.tags"
83
- :recipe-id =" recipe.id"
84
- />
85
- </v-lazy >
86
- </v-col >
87
- </v-row >
88
- <v-row v-else dense >
89
- <v-col
90
- v-for =" recipe in recipes"
91
- :key =" recipe.name"
92
- cols =" 12"
93
- :sm =" singleColumn ? '12' : '12'"
94
- :md =" singleColumn ? '12' : '6'"
95
- :lg =" singleColumn ? '12' : '4'"
96
- :xl =" singleColumn ? '12' : '3'"
97
- >
98
- <v-lazy >
99
- <RecipeCardMobile
100
- :name =" recipe.name"
101
- :description =" recipe.description"
102
- :slug =" recipe.slug"
103
- :rating =" recipe.rating"
104
- :image =" recipe.image"
105
- :tags =" recipe.tags"
106
- :recipe-id =" recipe.id"
107
- />
108
- </v-lazy >
109
- </v-col >
110
- </v-row >
72
+ <div v-if =" recipes && ready" >
73
+ <div class =" mt-2" >
74
+ <v-row v-if =" !useMobileCards" >
75
+ <v-col v-for =" (recipe, index) in recipes" :key =" recipe.slug + index" :sm =" 6" :md =" 6" :lg =" 4" :xl =" 3" >
76
+ <v-lazy >
77
+ <RecipeCard
78
+ :name =" recipe.name"
79
+ :description =" recipe.description"
80
+ :slug =" recipe.slug"
81
+ :rating =" recipe.rating"
82
+ :image =" recipe.image"
83
+ :tags =" recipe.tags"
84
+ :recipe-id =" recipe.id"
85
+ />
86
+ </v-lazy >
87
+ </v-col >
88
+ </v-row >
89
+ <v-row v-else dense >
90
+ <v-col
91
+ v-for =" recipe in recipes"
92
+ :key =" recipe.name"
93
+ cols =" 12"
94
+ :sm =" singleColumn ? '12' : '12'"
95
+ :md =" singleColumn ? '12' : '6'"
96
+ :lg =" singleColumn ? '12' : '4'"
97
+ :xl =" singleColumn ? '12' : '3'"
98
+ >
99
+ <v-lazy >
100
+ <RecipeCardMobile
101
+ :name =" recipe.name"
102
+ :description =" recipe.description"
103
+ :slug =" recipe.slug"
104
+ :rating =" recipe.rating"
105
+ :image =" recipe.image"
106
+ :tags =" recipe.tags"
107
+ :recipe-id =" recipe.id"
108
+ />
109
+ </v-lazy >
110
+ </v-col >
111
+ </v-row >
112
+ </div >
113
+ <v-card v-intersect =" infiniteScroll" ></v-card >
114
+ <v-fade-transition >
115
+ <AppLoader v-if =" loading" :loading =" loading" />
116
+ </v-fade-transition >
111
117
</div >
112
- <v-card v-intersect =" infiniteScroll" ></v-card >
113
- <v-fade-transition >
114
- <AppLoader v-if =" loading" :loading =" loading" />
115
- </v-fade-transition >
116
118
</div >
117
119
</template >
118
120
@@ -223,36 +225,42 @@ export default defineComponent({
223
225
224
226
const queryFilter = computed (() => {
225
227
const orderBy = props .query ?.orderBy || preferences .value .orderBy ;
226
- return preferences .value .filterNull && orderBy ? ` ${orderBy } IS NOT NULL ` : null ;
228
+ const orderByFilter = preferences .value .filterNull && orderBy ? ` ${orderBy } IS NOT NULL ` : null ;
229
+
230
+ if (props .query .queryFilter && orderByFilter ) {
231
+ return ` (${props .query .queryFilter }) AND ${orderByFilter } ` ;
232
+ } else if (props .query .queryFilter ) {
233
+ return props .query .queryFilter ;
234
+ } else {
235
+ return orderByFilter ;
236
+ }
227
237
});
228
238
229
239
async function fetchRecipes(pageCount = 1 ) {
230
240
return await fetchMore (
231
241
page .value ,
232
- // we double-up the first call to avoid a bug with large screens that render the entire first page without scrolling, preventing additional loading
233
242
perPage * pageCount ,
234
243
props .query ?.orderBy || preferences .value .orderBy ,
235
244
props .query ?.orderDirection || preferences .value .orderDirection ,
236
245
props .query ,
237
- // filter out recipes that have a null value for the property we're sorting by
246
+ // we use a computed queryFilter to filter out recipes that have a null value for the property we're sorting by
238
247
queryFilter .value
239
248
);
240
249
}
241
250
242
251
onMounted (async () => {
243
- if (props .query ) {
244
- await initRecipes ();
245
- ready .value = true ;
246
- }
252
+ await initRecipes ();
253
+ ready .value = true ;
247
254
});
248
255
249
- let lastQuery: string | undefined ;
256
+ let lastQuery: string | undefined = JSON . stringify ( props . query ) ;
250
257
watch (
251
258
() => props .query ,
252
259
async (newValue : RecipeSearchQuery | undefined ) => {
253
260
const newValueString = JSON .stringify (newValue )
254
- if (newValue && ( ! ready . value || lastQuery !== newValueString ) ) {
261
+ if (lastQuery !== newValueString ) {
255
262
lastQuery = newValueString ;
263
+ ready .value = false ;
256
264
await initRecipes ();
257
265
ready .value = true ;
258
266
}
@@ -261,8 +269,12 @@ export default defineComponent({
261
269
262
270
async function initRecipes() {
263
271
page .value = 1 ;
264
- const newRecipes = await fetchRecipes (2 );
265
- if (! newRecipes .length ) {
272
+ hasMore .value = true ;
273
+
274
+ // we double-up the first call to avoid a bug with large screens that render
275
+ // the entire first page without scrolling, preventing additional loading
276
+ const newRecipes = await fetchRecipes (page .value + 1 );
277
+ if (newRecipes .length < perPage ) {
266
278
hasMore .value = false ;
267
279
}
268
280
@@ -274,17 +286,18 @@ export default defineComponent({
274
286
275
287
const infiniteScroll = useThrottleFn (() => {
276
288
useAsync (async () => {
277
- if (! ready . value || ! hasMore .value || loading .value ) {
289
+ if (! hasMore .value || loading .value ) {
278
290
return ;
279
291
}
280
292
281
293
loading .value = true ;
282
294
page .value = page .value + 1 ;
283
295
284
296
const newRecipes = await fetchRecipes ();
285
- if (! newRecipes .length ) {
297
+ if (newRecipes .length < perPage ) {
286
298
hasMore .value = false ;
287
- } else {
299
+ }
300
+ if (newRecipes .length ) {
288
301
context .emit (APPEND_RECIPES_EVENT , newRecipes );
289
302
}
290
303
@@ -379,6 +392,7 @@ export default defineComponent({
379
392
displayTitleIcon ,
380
393
EVENTS ,
381
394
infiniteScroll ,
395
+ ready ,
382
396
loading ,
383
397
navigateRandom ,
384
398
preferences ,
0 commit comments