@@ -17,7 +17,50 @@ interface SessionData {
1717 sessionType : 'live-training' | 'workshop' | null ;
1818}
1919
20+ console . log ( 'template-page.ts' ) ;
21+
2022const NUM_OCCURRENCES_TO_SHOW = 3 ;
23+ const EMPTY_STATE_ID = 'pro-session-empty-state' ;
24+ const EMPTY_STATE_MESSAGE = 'No upcoming sessions are scheduled right now. Check back soon.' ;
25+
26+ function showNoUpcomingSessionsMessage ( ) : void {
27+ const tabsContainer = document . querySelector ( '.cc_pro_session-tabs' ) as HTMLElement | null ;
28+ if ( ! tabsContainer || document . getElementById ( EMPTY_STATE_ID ) ) {
29+ return ;
30+ }
31+
32+ const tabMenu = document . querySelector ( '.cc_pro_session-tab-menu' ) as HTMLElement | null ;
33+ const tabButtons = document . querySelectorAll < HTMLElement > ( '.cc_pro_tabs_button' ) ;
34+ tabMenu ?. style . setProperty ( 'display' , 'none' ) ;
35+ tabButtons . forEach ( ( button ) => {
36+ button . style . display = 'none' ;
37+ } ) ;
38+
39+ const emptyState = document . createElement ( 'p' ) ;
40+ emptyState . id = EMPTY_STATE_ID ;
41+ emptyState . className = 'cc_pro-session_empty-state' ;
42+ emptyState . textContent = EMPTY_STATE_MESSAGE ;
43+ emptyState . setAttribute ( 'role' , 'status' ) ;
44+ emptyState . style . margin = '1.5rem 0 0' ;
45+ emptyState . style . color = 'rgba(255, 255, 255, 0.7)' ;
46+ emptyState . style . fontSize = '1rem' ;
47+ emptyState . style . lineHeight = '1.5' ;
48+
49+ tabsContainer . appendChild ( emptyState ) ;
50+ }
51+
52+ function renderEmptyRecurrenceMessage ( listElement : Element ) : void {
53+ const emptyItem = document . createElement ( 'li' ) ;
54+ emptyItem . className = 'cc_pro-session_empty-state' ;
55+ emptyItem . textContent = EMPTY_STATE_MESSAGE ;
56+ emptyItem . setAttribute ( 'role' , 'status' ) ;
57+ emptyItem . style . listStyle = 'none' ;
58+ emptyItem . style . color = 'rgba(255, 255, 255, 0.7)' ;
59+ emptyItem . style . fontSize = '1rem' ;
60+ emptyItem . style . lineHeight = '1.5' ;
61+
62+ listElement . appendChild ( emptyItem ) ;
63+ }
2164
2265/**
2366 * Parse session data from the #data-saver element
@@ -160,11 +203,11 @@ function updateRecurrenceUI(
160203 blackoutDates : DateTime [ ] ,
161204 registrationLink : string ,
162205 sessionType : 'live-training' | 'workshop' | null
163- ) : void {
206+ ) : boolean {
164207 const container = document . querySelector ( `#datetimes-${ index } ` ) ;
165208 if ( ! container ) {
166209 console . error ( `[updateRecurrenceUI] Container #datetimes-${ index } not found` ) ;
167- return ;
210+ return false ;
168211 }
169212
170213 // Get next NUM_OCCURRENCES_TO_SHOW occurrences
@@ -176,12 +219,6 @@ function updateRecurrenceUI(
176219 recurrence . until
177220 ) ;
178221
179- if ( occurrences . length === 0 ) {
180- // Hide the container if no occurrences
181- ( container as HTMLElement ) . style . display = 'none' ;
182- return ;
183- }
184-
185222 // Show the container
186223 ( container as HTMLElement ) . style . display = '' ;
187224
@@ -214,12 +251,23 @@ function updateRecurrenceUI(
214251 const listElement = container . querySelector ( 'ul.cc_pro-session_tab-list' ) ;
215252 if ( ! listElement ) {
216253 console . error ( `[updateRecurrenceUI] List element not found in container ${ index } ` ) ;
217- return ;
254+ return false ;
218255 }
219256
220257 // Clear existing items
221258 listElement . innerHTML = '' ;
222259
260+ if ( occurrences . length === 0 ) {
261+ renderEmptyRecurrenceMessage ( listElement ) ;
262+
263+ const linkElement = container . querySelector ( 'a.button' ) ;
264+ if ( linkElement ) {
265+ ( linkElement as HTMLElement ) . style . display = 'none' ;
266+ }
267+
268+ return false ;
269+ }
270+
223271 // Add new items with the new structure
224272 occurrences . forEach ( ( occurrence ) => {
225273 // Always convert to user's local timezone (dates are input in America/New_York)
@@ -269,44 +317,57 @@ function updateRecurrenceUI(
269317 } else if ( linkElement ) {
270318 ( linkElement as HTMLElement ) . style . display = 'none' ;
271319 }
320+
321+ return true ;
272322}
273323
274324/**
275325 * Initialize the template page
276326 * Times are always displayed in the user's local timezone
277327 */
278- function initTemplatePage ( ) : void {
328+ function initTemplatePage ( ) : boolean {
279329 const dataSaver = document . querySelector ( '#data-saver' ) as HTMLElement ;
280330 if ( ! dataSaver ) {
281331 console . error ( '[initTemplatePage] #data-saver element not found' ) ;
282- return ;
332+ return false ;
283333 }
284334
285335 const sessionData = parseSessionData ( dataSaver ) ;
286336 if ( ! sessionData ) {
287337 console . error ( '[initTemplatePage] Failed to parse session data' ) ;
288- return ;
338+ showNoUpcomingSessionsMessage ( ) ;
339+ return false ;
289340 }
290341
291342 // Update all recurrences (always show in user's local timezone)
343+ let hasUpcomingSessions = false ;
292344 sessionData . recurrences . forEach ( ( recurrence , index ) => {
293- updateRecurrenceUI (
345+ const recurrenceHasUpcomingSessions = updateRecurrenceUI (
294346 index + 1 ,
295347 recurrence ,
296348 sessionData . blackoutDates ,
297349 sessionData . registrationLinks [ index ] ,
298350 sessionData . sessionType
299351 ) ;
352+ hasUpcomingSessions = hasUpcomingSessions || recurrenceHasUpcomingSessions ;
300353 } ) ;
354+
355+ if ( ! hasUpcomingSessions ) {
356+ showNoUpcomingSessionsMessage ( ) ;
357+ }
358+
359+ return hasUpcomingSessions ;
360+ }
361+
362+ function initTemplatePageWithTabs ( ) : void {
363+ if ( initTemplatePage ( ) ) {
364+ initTabMenuScrolling ( ) ;
365+ }
301366}
302367
303368// Run when DOM is ready
304369if ( document . readyState === 'loading' ) {
305- document . addEventListener ( 'DOMContentLoaded' , ( ) => {
306- initTemplatePage ( ) ;
307- initTabMenuScrolling ( ) ;
308- } ) ;
370+ document . addEventListener ( 'DOMContentLoaded' , initTemplatePageWithTabs ) ;
309371} else {
310- initTemplatePage ( ) ;
311- initTabMenuScrolling ( ) ;
372+ initTemplatePageWithTabs ( ) ;
312373}
0 commit comments