@@ -4,9 +4,11 @@ import { DividerWayFinder, SectionStaffArticleList, SectionPagination, TabItem,
4
4
5
5
// HELPERS
6
6
import _get from ' lodash/get'
7
- import FTVAEventSeriesList from ' ../gql/queries/FTVAEventSeriesList.gql '
7
+ import { useWindowSize , useInfiniteScroll } from ' @vueuse/core '
8
8
9
9
// GQL - start
10
+ import FTVAEventSeriesList from ' ../gql/queries/FTVAEventSeriesList.gql'
11
+
10
12
const { $graphql } = useNuxtApp ()
11
13
12
14
const { data , error } = await useAsyncData (' series-list' , async () => {
@@ -19,7 +21,6 @@ if (error.value) {
19
21
})
20
22
}
21
23
if (! data .value .entries ) {
22
- // console.log('no data')
23
24
throw createError ({
24
25
statusCode: 404 ,
25
26
statusMessage: ' Page Not Found' ,
@@ -30,17 +31,81 @@ if (!data.value.entries) {
30
31
const heading = ref (_get (data .value , ' entry' , {}))
31
32
// GQL - End
32
33
33
- // STATE VARIABLES - ARGUMENTS on useEventSeriesListSearchFilter
34
- const series = ref ([]) // Add typescript
35
- const currentView = ref (' current' ) // Tracks 'current' or 'past'
34
+ // STATE MANAGEMENT
35
+ const desktopPage = useState (' desktopPage' , () => 1 ) // Persist desktop page
36
+ const desktopSeries = ref ([]) // Desktop series list
37
+ const mobileSeries = ref ([]) // Mobile series list
38
+ const series = computed (() => (isMobile .value ? mobileSeries .value : desktopSeries .value ))
39
+ const currentView = computed (() => route .query .view || ' current' ) // Tracks 'current' or 'past'
36
40
const noResultsFound = ref (false )
37
41
const documentsPerPage = 10
38
42
const totalPages = ref (0 )
39
43
const currentPage = ref (1 )
40
44
const route = useRoute ()
41
45
42
- // Helper functions copied from event index
43
- // Get data for Image
46
+ // INFINITE SCROLLING
47
+ const isLoading = ref (false )
48
+ const isMobile = ref (false )
49
+ const hasMore = ref (true ) // Flag to control infinite scroll
50
+ const scrollElPast = ref (null )
51
+ const scrollElCurrent = ref (null )
52
+ // const desktopEl = ref(null)
53
+ const pastScroll = useInfiniteScroll (
54
+ scrollElPast,
55
+ async () => {
56
+ if (isMobile .value && hasMore .value && ! isLoading .value ) {
57
+ currentPage .value ++
58
+ await searchES ()
59
+ }
60
+ },
61
+ { distance: 100 }
62
+ )
63
+ const currentScroll = useInfiniteScroll (
64
+ scrollElCurrent,
65
+ async () => {
66
+ if (isMobile .value && hasMore .value && ! isLoading .value ) {
67
+ currentPage .value ++
68
+ await searchES ()
69
+ }
70
+ },
71
+ { distance: 100 }
72
+ )
73
+
74
+ // WINDOW SIZE HANDLING
75
+ const { width } = useWindowSize ()
76
+ watch (width, (newWidth ) => {
77
+ const wasMobile = isMobile .value
78
+ isMobile .value = newWidth <= 750
79
+
80
+ // Reinitialize only when transitioning between mobile and desktop
81
+ if (wasMobile !== isMobile .value ) {
82
+ handleScreenTransition ()
83
+ }
84
+ }, { immediate: true })
85
+
86
+ // HANDLE SCREEN TRANSITIONS
87
+ function handleScreenTransition () {
88
+ if (isMobile .value ) {
89
+ // Switching to mobile: save desktop page, clear query param
90
+
91
+ desktopPage .value = currentPage .value
92
+ currentPage .value = 1
93
+ mobileSeries .value = []
94
+ hasMore .value = true
95
+ const { page , ... remainingQuery } = route .query
96
+ useRouter ().push ({ query: { ... remainingQuery, view: currentView .value } })
97
+ } else {
98
+ // Switching to desktop: restore query param
99
+ if (totalPages .value === 1 )
100
+ desktopPage .value = 1
101
+ const restoredPage = desktopPage .value || 1
102
+ useRouter ().push ({ query: { ... route .query , page: restoredPage .toString (), view: currentView .value } })
103
+ currentPage .value = restoredPage
104
+ desktopSeries .value = []
105
+ }
106
+ }
107
+
108
+ // GET DATA FOR IMAGE
44
109
function parsedImage (obj ) {
45
110
return obj ._source .imageCarousel
46
111
}
@@ -51,7 +116,6 @@ function isImageExists(obj) {
51
116
52
117
// FORMATTED COMPUTED EVENTS
53
118
const parsedEventSeries = computed (() => {
54
- console .log (series .value )
55
119
if (series .value .length === 0 ) return []
56
120
57
121
return series .value .map ((obj ) => {
@@ -69,36 +133,48 @@ const parsedEventSeries = computed(() => {
69
133
70
134
// ES FUNCTION
71
135
async function searchES () {
136
+ if (isLoading .value || ! hasMore .value ) return
137
+
138
+ isLoading .value = true
72
139
// COMPOSABLE
73
140
const { currentEventSeriesQuery , pastEventSeriesQuery } = useEventSeriesListSearchFilter ()
74
141
75
142
try {
76
143
let results
144
+
77
145
if (currentView .value === ' current' ) {
78
146
results = await currentEventSeriesQuery (currentPage .value ,
79
- documentsPerPage . value ,
147
+ documentsPerPage,
80
148
' startDate' ,
81
149
' asc' ,
82
150
[' *' ],)
83
151
} else {
84
152
results = await pastEventSeriesQuery (currentPage .value ,
85
- documentsPerPage . value ,
153
+ documentsPerPage,
86
154
' startDate' ,
87
155
' desc' ,
88
156
[' *' ])
89
157
}
90
158
91
- if (results? .hits ? .total ? .value > 0 ) {
92
- series .value = results .hits .hits
159
+ if (results? .hits ? .hits ? .length > 0 ) {
160
+ const newSeries = results .hits .hits || []
161
+ if (isMobile .value ) {
162
+ mobileSeries .value .push (... newSeries)
163
+ hasMore .value = currentPage .value < Math .ceil (results .hits .total .value / documentsPerPage)
164
+ } else {
165
+ desktopSeries .value = newSeries
166
+ totalPages .value = Math .ceil (results .hits .total .value / documentsPerPage)
167
+ }
93
168
noResultsFound .value = false
94
- totalPages .value = Math .ceil (results .hits .total .value / documentsPerPage)
95
169
} else {
96
- series .value = []
97
170
noResultsFound .value = true
171
+ if (! isMobile .value ) totalPages .value = 0
172
+ hasMore .value = false
98
173
}
99
174
} catch (err) {
100
- console .error (' Error fetching series:' , err)
101
175
noResultsFound .value = true
176
+ } finally {
177
+ isLoading .value = false
102
178
}
103
179
}
104
180
@@ -109,9 +185,11 @@ const parseViewSelection = computed(() => {
109
185
watch (
110
186
() => route .query ,
111
187
(newVal , oldVal ) => {
112
- currentView .value = route .query .view || ' current'
113
- searchES ()
188
+ isLoading .value = false
114
189
currentPage .value = route .query .page ? parseInt (route .query .page ) : 1
190
+ isMobile .value ? mobileSeries .value = [] : desktopSeries .value = []
191
+ hasMore .value = true
192
+ searchES ()
115
193
}, { deep: true , immediate: true }
116
194
)
117
195
< / script>
@@ -128,6 +206,7 @@ watch(
128
206
129
207
< SectionWrapper theme= " paleblue" >
130
208
< TabList
209
+ v- if = " !isMobile"
131
210
alignment= " center"
132
211
: initial- tab= " parseViewSelection"
133
212
>
@@ -139,7 +218,10 @@ watch(
139
218
< SectionStaffArticleList : items= " parsedEventSeries" / >
140
219
141
220
< SectionPagination
142
- v- if = " totalPages !== 1"
221
+ v- if = "
222
+ totalPages
223
+ !== 1"
224
+ class = " pagination"
143
225
: pages= " totalPages"
144
226
: initial- current- page= " currentPage"
145
227
/ >
@@ -191,12 +273,87 @@ watch(
191
273
< / template>
192
274
< / TabItem>
193
275
< / TabList>
276
+
277
+ < TabList
278
+ v- else
279
+ alignment= " center"
280
+ : initial- tab= " parseViewSelection"
281
+ >
282
+ < TabItem
283
+ title= " Past Series"
284
+ class = " tab-content"
285
+ >
286
+ < template v- if = " parsedEventSeries && parsedEventSeries.length > 0" >
287
+ < SectionStaffArticleList
288
+ ref= " scrollElPast"
289
+ : items= " parsedEventSeries"
290
+ / >
291
+
292
+ < SectionPagination
293
+ v- if = "
294
+ totalPages
295
+ !== 1"
296
+ class = " pagination"
297
+ : pages= " totalPages"
298
+ : initial- current- page= " currentPage"
299
+ / >
300
+ < / template>
301
+
302
+ < template v- else >
303
+ < p
304
+ v- if = " noResultsFound"
305
+ class = " empty-tab"
306
+ >
307
+ There are no past event series
308
+ < / p>
309
+ < p
310
+ v- else
311
+ class = " empty-tab"
312
+ >
313
+ Data loading in progress ...
314
+ < / p>
315
+ < / template>
316
+ < / TabItem>
317
+
318
+ < TabItem
319
+ title= " Current and Upcoming Series"
320
+ class = " tab-content"
321
+ >
322
+ < template v- if = " parsedEventSeries && parsedEventSeries.length > 0" >
323
+ < SectionStaffArticleList
324
+ ref= " scrollElCurrent"
325
+ : items= " parsedEventSeries"
326
+ / >
327
+
328
+ < SectionPagination
329
+ v- if = " totalPages !== 1"
330
+ : pages= " totalPages"
331
+ : initial- current- page= " currentPage"
332
+ / >
333
+ < / template>
334
+
335
+ < template v- else >
336
+ < p
337
+ v- if = " noResultsFound"
338
+ class = " empty-tab"
339
+ >
340
+ There are no current or upcoming event series
341
+ < / p>
342
+ < p
343
+ v- else
344
+ class = " empty-tab"
345
+ >
346
+ Data loading in progress ...
347
+ < / p>
348
+ < / template>
349
+ < / TabItem>
350
+ < / TabList>
194
351
< / SectionWrapper>
195
352
< / div>
196
353
< / div>
197
354
< / template>
198
355
199
- < style scoped>
356
+ < style lang = " scss " scoped>
200
357
@import ' assets/styles/listing-pages.scss' ;
201
358
202
359
.page - event - series {
@@ -233,5 +390,11 @@ watch(
233
390
max- width: unset;
234
391
padding: 2.5 % ;
235
392
}
393
+
394
+ @media #{$small} {
395
+ .pagination {
396
+ display: none;
397
+ }
398
+ }
236
399
}
237
400
< / style>
0 commit comments