6666 <div class =" px-4 py-6 pb-20" >
6767 <!-- Session List -->
6868 <div
69- v-if =" state.selectedDay && groupedSessionsByType && Object.keys(groupedSessionsByType ).length > 0"
69+ v-if =" state.selectedDay && groupedSessionsByTime && Object.keys(groupedSessionsByTime ).length > 0"
7070 class =" space-y-6" >
7171 <div
72- v-for =" (group, sessionType ) in groupedSessionsByType "
73- :key =" sessionType "
72+ v-for =" (group, timeSlot ) in groupedSessionsByTime "
73+ :key =" timeSlot "
7474 class =" space-y-3" >
75- <!-- Session Type Header -->
75+ <!-- Time Slot Header -->
7676 <div class =" bg-blue-50 dark:bg-blue-900/20 rounded-xl p-3 border border-blue-100 dark:border-blue-800" >
7777 <h2 class =" font-bold text-lg text-blue-900 dark:text-blue-100" >
78- {{ formatSessionType(sessionType ) }}
78+ {{ formatTimeSlot(timeSlot ) }}
7979 </h2 >
8080 </div >
8181
82- <!-- Sessions of this type -->
82+ <!-- Sessions of this time -->
8383 <div class =" space-y-3" >
8484 <div
8585 v-for =" session in group"
9797 {{ formatSessionTime(session) }}
9898 </p >
9999 <p
100- v-if =" session.session_host"
100+ v-if =" session.session_host && session.session_host.trim() && session.session_host !== 'TBA' "
101101 class =" text-gray-600 dark:text-gray-300 text-sm mb-1" >
102102 Host: {{ session.session_host }}
103103 </p >
@@ -325,19 +325,71 @@ async function toggleLike(session: Session): Promise<void> {
325325 }
326326}
327327
328+ /**
329+ * Fix UTF-8 encoding issues for text that may contain special characters
330+ */
331+ function fixTextEncoding(text : string | undefined ): string | undefined {
332+ if (! text ) return text ;
333+
334+ try {
335+ // Common double-encoded UTF-8 patterns for Polish and other European characters
336+ let fixed = text
337+ // Polish characters
338+ .replace (/ Å›/ g , ' ś' )
339+ .replace (/ Ä…/ g , ' ą' )
340+ .replace (/ Å„/ g , ' ń' )
341+ .replace (/ Å‚/ g , ' ł' )
342+ .replace (/ ż/ g , ' ż' )
343+ .replace (/ ů/ g , ' ź' )
344+ .replace (/ Ä™/ g , ' ę' )
345+ .replace (/ ć/ g , ' ć' )
346+ .replace (/ ó/ g , ' ó' )
347+
348+ // German/French characters
349+ .replace (/ á/ g , ' á' )
350+ .replace (/ é/ g , ' é' )
351+ .replace (/ Ã/ g , ' í' )
352+ .replace (/ ú/ g , ' ú' )
353+ .replace (/ ñ/ g , ' ñ' )
354+ .replace (/ ü/ g , ' ü' )
355+ .replace (/ ä/ g , ' ä' )
356+ .replace (/ ö/ g , ' ö' )
357+ .replace (/ ß/ g , ' ß' )
358+
359+ // More double-encoded patterns
360+ .replace (/ ’/ g , " '" )
361+ .replace (/ “/ g , ' "' )
362+ .replace (/ â€/ g , ' "' )
363+ .replace (/ â€"/ g , ' –' )
364+ .replace (/ â€"/ g , ' —' );
365+
366+ // Handle question mark replacements for specific known cases
367+ // This is specifically for "Mateusz ?la?y?ski" -> "Mateusz Ślażyński"
368+ if (fixed .includes (' ?la?y?ski' )) {
369+ fixed = fixed .replace (' ?la?y?ski' , ' ślażyński' );
370+ }
371+ if (fixed .includes (' Mateusz ?' )) {
372+ fixed = fixed .replace (' Mateusz ?la?y?ski' , ' Mateusz Ślażyński' );
373+ }
374+
375+ return fixed ;
376+ } catch (error ) {
377+ console .warn (' Error fixing text encoding:' , error );
378+ return text ;
379+ }
380+ }
381+
328382/**
329383 * Process session data and add timezone adjustment and like status
330384 */
331385function processSessions(sessionsData : Record <string , unknown >[]): Session [] {
332386 return sessionsData .map ((session : Record <string , unknown >) => {
333387 const sessionIdAsString = session .id ?.toString ();
334- const isLikedCheck = state .likedSessionIds .has (sessionIdAsString ?? ' ' );
388+ const isLikedCheck = state .likedSessionIds .has (parseInt ( sessionIdAsString ?? ' 0 ' ) );
335389
336- // Add 2 hours to fix timezone misalignment
390+ // Use original times without timezone adjustment
337391 const startTime = new Date (session .startTime as string );
338392 const endTime = new Date (session .endTime as string );
339- startTime .setHours (startTime .getHours () + 2 );
340- endTime .setHours (endTime .getHours () + 2 );
341393
342394 // Format times properly (YYYY-MM-DD HH:MM:SS)
343395 const formatDateTime = (date : Date ) => {
@@ -352,19 +404,19 @@ function processSessions(sessionsData: Record<string, unknown>[]): Session[] {
352404
353405 return {
354406 id: session .id as number ,
355- title: ( session .name ?? session .session_name ?? ' Untitled Session' ) as string ,
356- session_name: ( session .name ?? session .session_name ) as string | undefined ,
357- session_host: ( session .host ?? session .session_host ) as string | undefined ,
358- session_location: ( session .location ?? session .session_location ) as string | undefined ,
407+ title: fixTextEncoding (( session .name ?? session .session_name ?? ' Untitled Session' ) as string ) as string ,
408+ session_name: fixTextEncoding (( session .name ?? session .session_name ) as string | undefined ) ,
409+ session_host: fixTextEncoding (( session .host ?? session .session_host ) as string | undefined ) ,
410+ session_location: fixTextEncoding (( session .location ?? session .session_location ) as string | undefined ) ,
359411 start_time: formatDateTime (startTime ),
360412 end_time: formatDateTime (endTime ),
361413 startTime: formatDateTime (startTime ),
362414 endTime: formatDateTime (endTime ),
363415 type: session .type as string ,
364416 isLiked: isLikedCheck ,
365417 likes: (session .likes ?? 0 ) as number ,
366- abstract: session .abstract as string ,
367- authors: session .authors as string
418+ abstract: fixTextEncoding ( session .abstract as string ) ,
419+ authors: fixTextEncoding ( session .authors as string )
368420 };
369421 });
370422}
@@ -407,7 +459,16 @@ function selectDay(value: string): void {
407459 * Navigate to different agenda type (personal/general) with query parameters
408460 */
409461function navigateToAgendaType(type : string ): void {
410- const query: Record <string , string > = { ... route .query }; // Get current query parameters
462+ const query: Record <string , string > = {};
463+
464+ // Copy existing query parameters
465+ for (const [key, value] of Object .entries (route .query )) {
466+ if (typeof value === ' string' ) {
467+ query [key ] = value ;
468+ } else if (Array .isArray (value ) && value .length > 0 && typeof value [0 ] === ' string' ) {
469+ query [key ] = value [0 ];
470+ }
471+ }
411472
412473 // Add or update the `type` parameter based on the selected segment
413474 if (type === ' personal' ) {
@@ -456,76 +517,32 @@ const filteredSessions = computed(() => {
456517 .sort ((a , b ) => new Date (a .start_time ).getTime () - new Date (b .start_time ).getTime ());
457518});
458519
459- const groupedSessionsByType = computed (() => {
460- const groups: Record <string , Session []> = {};
461-
462- // Define the importance order for session types
463- const typeImportanceOrder = [
464- ' KEYNOTE' ,
465- ' FOOD' ,
466- ' COFFEE' ,
467- ' PRACTICAL' ,
468- ' QnA' ,
469- ' DOCTORALCONSORTIUM' ,
470- ' MAIN' ,
471- ' BPMFORUM' ,
472- ' EDUCATORSFORUM' ,
473- ' PROCESSTECHNOLOGYFORUM' ,
474- ' INDUSTRYFORUM' ,
475- ' RESPONSIBLEBPMFORUM' ,
476- ' JOURNALFIRST' ,
477- ' PANEL' ,
478- ' TUTORIAL' ,
479- ' WORKSHOP' ,
480- ' DEMO' ,
481- ' OTHER'
482- ];
483-
484- for (const session of filteredSessions .value ) {
485- const sessionType = session .type ?? ' OTHER' ;
486- let groupKey = sessionType ;
487-
488- // For workshops, create separate groups based on workshop name
489- if (sessionType === ' WORKSHOP' && session .session_name ) {
490- const workshopName = extractWorkshopName (session .session_name );
491- groupKey = ` WORKSHOP_${workshopName } ` ;
520+ const groupedSessionsByTime = computed (() => {
521+ // Sort all sessions by start time
522+ const sortedSessions = [... filteredSessions .value ].sort ((a , b ) =>
523+ new Date (a .start_time ).getTime () - new Date (b .start_time ).getTime ()
524+ );
525+
526+ // Group sessions by time slots (start time)
527+ const timeGroups: Record <string , Session []> = {};
528+
529+ for (const session of sortedSessions ) {
530+ const timeKey = session .start_time ; // Use full start time as key
531+
532+ if (! timeGroups [timeKey ]) {
533+ timeGroups [timeKey ] = [];
492534 }
493- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
494- groups [groupKey ] = groups [groupKey ] || [];
495- groups [groupKey ].push (session );
535+ timeGroups [timeKey ].push (session );
496536 }
497537
498- // Sort sessions within each type by start time
499- Object .keys (groups ). forEach (( type ) => {
500- groups [ type ]. sort (( a , b ) => new Date (a . start_time ).getTime () - new Date (b . start_time ).getTime ());
501- } );
538+ // Sort time groups chronologically
539+ const sortedTimeKeys = Object .keys (timeGroups ). sort (( a , b ) =>
540+ new Date (a ).getTime () - new Date (b ).getTime ()
541+ );
502542
503- // Convert to ordered object based on type importance
504543 const orderedGroups: Record <string , Session []> = {};
505-
506- // First, add groups in importance order
507- for (const type of typeImportanceOrder ) {
508- if (type in groups ) {
509- orderedGroups [type ] = groups [type ];
510- }
511- }
512-
513- // Then add workshop groups (sorted alphabetically)
514- const workshopGroups = Object .keys (groups )
515- .filter (key => key .startsWith (' WORKSHOP_' ))
516- .sort ();
517-
518- for (const workshopType of workshopGroups ) {
519- if (workshopType in groups ) {
520- orderedGroups [workshopType ] = groups [workshopType ];
521- }
522- }
523-
524- // Finally, add any remaining groups not in the importance order
525- for (const type in groups ) {
526- if (! (type in orderedGroups )) {
527- orderedGroups [type ] = groups [type ];
528- }
544+ for (const timeKey of sortedTimeKeys ) {
545+ orderedGroups [timeKey ] = timeGroups [timeKey ];
529546 }
530547
531548 return orderedGroups ;
@@ -558,15 +575,28 @@ function extractWorkshopName(sessionTitle: string): string {
558575}
559576
560577/**
561- * Format session type for display
578+ * Format time slot for display as header
562579 */
563- function formatSessionType(type : string ): string {
564- // Handle workshop groups
565- if (type .startsWith (' WORKSHOP_' )) {
566- const workshopName = type .replace (' WORKSHOP_' , ' ' );
567- return workshopName ;
580+ function formatTimeSlot(timeSlot : string ): string {
581+ try {
582+ const timePart = timeSlot .split (' ' )[1 ];
583+ if (! timePart ) {
584+ return ' Time TBA' ;
585+ }
586+
587+ // Extract just hours:minutes from HH:MM:SS format
588+ const time = timePart .substring (0 , 5 );
589+ return time ;
590+ } catch (error ) {
591+ console .error (' Error formatting time slot:' , error , timeSlot );
592+ return ' Time TBA' ;
568593 }
594+ }
569595
596+ /**
597+ * Format session type for display (kept for potential future use)
598+ */
599+ function formatSessionType(type : string ): string {
570600 const typeMap: Record <string , string > = {
571601 KEYNOTE: ' Keynote' ,
572602 FOOD: ' Lunch' ,
@@ -587,6 +617,13 @@ function formatSessionType(type: string): string {
587617 JOURNALFIRST: ' Journal First Track' ,
588618 OTHER: ' Other Sessions'
589619 };
620+
621+ // Handle workshop groups
622+ if (type .startsWith (' WORKSHOP_' )) {
623+ const workshopName = type .replace (' WORKSHOP_' , ' ' );
624+ return workshopName ;
625+ }
626+
590627 return typeMap [type ] || type ;
591628}
592629
0 commit comments