All files / src/components/organizer/LiveControl AgendaList.tsx

0% Statements 0/18
0% Branches 0/25
0% Functions 0/6
0% Lines 0/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95                                                                                                                                                                                             
import React from 'react';
import { cn } from '@/lib/utils';
import type { components } from '@/types/generated/event-watch-api.types';
 
type WatchSessionDetail = components['schemas']['WatchSessionDetail'];
 
interface AgendaListProps {
  sessions: WatchSessionDetail[];
}
 
const BREAK_TYPES = new Set(['break', 'lunch', 'networking', 'aperitif']);
 
function formatTime(iso: string | null | undefined): string {
  if (!iso) return '—';
  return new Date(iso).toLocaleTimeString('de-CH', { hour: '2-digit', minute: '2-digit' });
}
 
function speakerNames(session: WatchSessionDetail): string {
  if (!session.speakers?.length) return '';
  return session.speakers
    .map((s) => [s.firstName, s.lastName].filter(Boolean).join(' '))
    .filter(Boolean)
    .join(', ');
}
 
function SessionRow({ session }: { session: WatchSessionDetail }) {
  const isActive = session.status === 'ACTIVE';
  const isDone = session.status === 'COMPLETED';
  const isBreak = BREAK_TYPES.has(session.sessionType ?? '');
  const speakers = speakerNames(session);
 
  return (
    <div
      className={cn(
        'flex items-start gap-3 py-3 px-2 rounded-lg mb-1 border-l-2 transition-colors',
        isActive ? 'bg-primary/10 border-primary' : 'border-transparent'
      )}
    >
      {/* Status icon */}
      <div className="mt-0.5 shrink-0">
        {isDone ? (
          <span className="text-green-500 text-lg">✓</span>
        ) : isActive ? (
          <span className="text-primary text-lg">▶</span>
        ) : isBreak ? (
          <span className="text-muted-foreground text-lg">☕</span>
        ) : (
          <span className="text-muted-foreground/40 text-lg">○</span>
        )}
      </div>
 
      {/* Content */}
      <div className="flex-1 min-w-0">
        <p
          className={cn(
            'text-base font-medium leading-snug',
            isDone
              ? 'line-through text-muted-foreground/50'
              : isActive
                ? 'text-foreground font-bold'
                : 'text-foreground/80'
          )}
        >
          {session.title}
        </p>
        {speakers && !isDone && <p className="text-sm text-muted-foreground mt-0.5">{speakers}</p>}
        <p className="text-sm text-muted-foreground/60 font-mono mt-0.5">
          {formatTime(session.scheduledStartTime)}
          {session.durationMinutes != null ? ` · ${session.durationMinutes} min` : ''}
        </p>
      </div>
    </div>
  );
}
 
export const AgendaList: React.FC<AgendaListProps> = ({ sessions }) => {
  if (sessions.length === 0) {
    return <p className="text-center text-muted-foreground py-6">Keine Sessions verfügbar</p>;
  }
 
  return (
    <div>
      <p className="text-xs font-semibold text-muted-foreground uppercase tracking-[0.2em] mb-2">
        Programm
      </p>
      <div className="border-t border-border mb-2" />
      <div>
        {sessions.map((session) => (
          <SessionRow key={session.sessionSlug} session={session} />
        ))}
      </div>
    </div>
  );
};