@@ -44,6 +44,81 @@ export const scheduleTimeToIso = (
4444 return `${ date } T${ String ( hours ) . padStart ( 2 , '0' ) } :${ String ( minutes ) . padStart ( 2 , '0' ) } :00+03:30` ;
4545} ;
4646
47+ const addMinutesToIso = ( iso : string , minutes : number ) : string | undefined => {
48+ const match = iso . match (
49+ / ^ ( \d { 4 } - \d { 2 } - \d { 2 } ) T ( \d { 2 } ) : ( \d { 2 } ) : ( \d { 2 } ) \+ 0 3 : 3 0 $ /
50+ ) ;
51+ if ( ! match ) return undefined ;
52+
53+ const totalMinutes = Number ( match [ 2 ] ) * 60 + Number ( match [ 3 ] ) + minutes ;
54+ const minutesInDay = ( ( totalMinutes % ( 24 * 60 ) ) + 24 * 60 ) % ( 24 * 60 ) ;
55+ const hours = Math . floor ( minutesInDay / 60 ) ;
56+ const mins = minutesInDay % 60 ;
57+
58+ return `${ match [ 1 ] } T${ String ( hours ) . padStart ( 2 , '0' ) } :${ String ( mins ) . padStart ( 2 , '0' ) } :${ match [ 4 ] } +03:30` ;
59+ } ;
60+
61+ const resolveScheduleEndDate = (
62+ schedule : ScheduleEvent [ ] ,
63+ scheduleIndex : number ,
64+ eventDate : string ,
65+ conference : ConferenceProfile
66+ ) : string | undefined => {
67+ const event = schedule [ scheduleIndex ] ;
68+
69+ if ( event . endTime ) {
70+ return scheduleTimeToIso ( eventDate , event . endTime ) ;
71+ }
72+
73+ const next = schedule [ scheduleIndex + 1 ] ;
74+ if ( next ) {
75+ const nextDate = next . date ?? eventDate ;
76+ return scheduleTimeToIso ( nextDate , next . time ) ;
77+ }
78+
79+ const startDate = scheduleTimeToIso ( eventDate , event . time ) ;
80+ if ( startDate ) {
81+ return addMinutesToIso ( startDate , 30 ) ;
82+ }
83+
84+ if ( conference . endDate ?. includes ( 'T' ) ) {
85+ return conference . endDate ;
86+ }
87+
88+ return undefined ;
89+ } ;
90+
91+ const resolveConferenceEventDates = ( conference : ConferenceProfile ) => {
92+ const schedule = conference . schedule ?? [ ] ;
93+ let startDate = conference . startDate ;
94+ let endDate = conference . endDate ;
95+
96+ if ( ! startDate . includes ( 'T' ) && schedule . length > 0 ) {
97+ const first = schedule [ 0 ] ;
98+ const firstDate = first . date ?? conference . startDate ;
99+ startDate =
100+ scheduleTimeToIso ( firstDate , first . time ) ?? conference . startDate ;
101+ }
102+
103+ if ( schedule . length > 0 ) {
104+ const lastIndex = schedule . length - 1 ;
105+ const last = schedule [ lastIndex ] ;
106+ const lastDate = last . date ?? conference . endDate ?? conference . startDate ;
107+ const resolvedEnd = resolveScheduleEndDate (
108+ schedule ,
109+ lastIndex ,
110+ lastDate ,
111+ conference
112+ ) ;
113+
114+ if ( resolvedEnd ) {
115+ endDate = resolvedEnd ;
116+ }
117+ }
118+
119+ return { startDate, endDate } ;
120+ } ;
121+
47122export const parseConferenceLocation = ( locationName : string ) => {
48123 const [ localityPart , venuePart ] = locationName
49124 . split ( '—' )
@@ -313,17 +388,25 @@ const buildScheduleSubEvents = (
313388) : Record < string , unknown > [ ] => {
314389 if ( ! conference . schedule ?. length ) return [ ] ;
315390
316- return conference . schedule
317- . filter ( ( event ) =>
391+ const schedule = conference . schedule ;
392+ let sessionIndex = 0 ;
393+
394+ return schedule
395+ . map ( ( event , scheduleIndex ) => ( { event, scheduleIndex } ) )
396+ . filter ( ( { event } ) =>
318397 [ 'talk' , 'panel' , 'competition' , 'workshop' ] . includes ( event . type )
319398 )
320- . map ( ( event : ScheduleEvent , index ) => {
399+ . map ( ( { event, scheduleIndex } ) => {
400+ sessionIndex += 1 ;
321401 const eventDate = event . date ?? conference . startDate ;
322402 const startDate = scheduleTimeToIso ( eventDate , event . time ) ;
323- const endDate = event . endTime
324- ? scheduleTimeToIso ( eventDate , event . endTime )
325- : undefined ;
326- const sessionUrl = `${ eventUrl } #session-${ index + 1 } ` ;
403+ const endDate = resolveScheduleEndDate (
404+ schedule ,
405+ scheduleIndex ,
406+ eventDate ,
407+ conference
408+ ) ;
409+ const sessionUrl = `${ eventUrl } #session-${ sessionIndex } ` ;
327410 const sessionStartDate = startDate ?? conference . startDate ;
328411
329412 return {
@@ -364,7 +447,13 @@ const buildScheduleSubEvents = (
364447 name : speaker . name ,
365448 } ) ) ,
366449 }
367- : { } ) ,
450+ : event . type === 'competition'
451+ ? {
452+ performer : {
453+ '@id' : organizationId ,
454+ } ,
455+ }
456+ : { } ) ,
368457 superEvent : {
369458 '@id' : `${ eventUrl } #event` ,
370459 } ,
@@ -374,7 +463,9 @@ const buildScheduleSubEvents = (
374463
375464export const buildConferenceJsonLd = ( conference : ConferenceProfile ) => {
376465 const eventUrl = `${ SITE_URL } ${ conferencePath ( conference . slug ) } ` ;
377- const isPastEvent = new Date ( conference . startDate ) . getTime ( ) < Date . now ( ) ;
466+ const { startDate : eventStartDate , endDate : eventEndDate } =
467+ resolveConferenceEventDates ( conference ) ;
468+ const isPastEvent = new Date ( eventStartDate ) . getTime ( ) < Date . now ( ) ;
378469 const { locality, region, venue } = parseConferenceLocation (
379470 conference . locationName
380471 ) ;
@@ -448,8 +539,8 @@ export const buildConferenceJsonLd = (conference: ConferenceProfile) => {
448539 name : pageName ,
449540 alternateName : [ `همایش فرانتچپتر ${ conference . year } ` , conference . title ] ,
450541 description : plainifySync ( conference . description ) ,
451- startDate : conference . startDate ,
452- ...( conference . endDate ? { endDate : conference . endDate } : { } ) ,
542+ startDate : eventStartDate ,
543+ ...( eventEndDate ? { endDate : eventEndDate } : { } ) ,
453544 eventAttendanceMode : 'https://schema.org/OfflineEventAttendanceMode' ,
454545 eventStatus : 'https://schema.org/EventScheduled' ,
455546 inLanguage : 'fa-IR' ,
@@ -464,8 +555,8 @@ export const buildConferenceJsonLd = (conference: ConferenceProfile) => {
464555 ...( attendeeCount ? { maximumAttendeeCapacity : attendeeCount } : { } ) ,
465556 offers : buildEventOffers (
466557 eventUrl ,
467- conference . startDate ,
468- conference . endDate ,
558+ eventStartDate ,
559+ eventEndDate ,
469560 isPastEvent
470561 ) ,
471562 ...( subEvents . length ? { subEvent : subEvents } : { } ) ,
0 commit comments