// ======================================== // TickerMarquee Component // ======================================== // Real-time scrolling ticker with CSS marquee animation and WebSocket messages import { useIntl } from 'react-intl'; import { cn } from '@/lib/utils'; import { useRealtimeUpdates, type TickerMessage } from '@/hooks/useRealtimeUpdates'; import { Play, CheckCircle2, Workflow, Activity, WifiOff, type LucideIcon, } from 'lucide-react'; // --- Types --- export interface TickerMarqueeProps { /** WebSocket endpoint path (default: 'ws/ticker-stream') */ endpoint?: string; /** Animation duration in seconds (default: 30) */ duration?: number; /** Additional CSS classes */ className?: string; /** Mock messages for development/testing */ mockMessages?: TickerMessage[]; } // --- Icon map --- const typeIcons: Record = { session: Play, task: CheckCircle2, workflow: Workflow, status: Activity, }; const typeColors: Record = { session: 'text-primary', task: 'text-success', workflow: 'text-info', status: 'text-warning', }; // --- Component --- function TickerItem({ message }: { message: TickerMessage }) { const Icon = typeIcons[message.type] || Activity; const colorClass = typeColors[message.type] || 'text-muted-foreground'; const content = ( {message.text} ); if (message.link) { return ( {content} ); } return content; } function MessageList({ messages }: { messages: TickerMessage[] }) { return ( <> {messages.map((msg) => ( ))} ); } export function TickerMarquee({ endpoint = 'ws/ticker-stream', duration = 30, className, mockMessages, }: TickerMarqueeProps) { const { formatMessage } = useIntl(); const { messages: wsMessages, connectionStatus } = useRealtimeUpdates(endpoint); const messages = mockMessages && mockMessages.length > 0 ? mockMessages : wsMessages; if (messages.length === 0) { return (
{connectionStatus === 'connected' ? ( {formatMessage({ id: 'common.ticker.waiting' })} ) : ( {formatMessage({ id: 'common.ticker.disconnected' })} )}
); } return (
{/* Fade edges */}
{/* Scrolling content - duplicate for seamless loop */}
{/* Duplicate for seamless loop */}
); } export default TickerMarquee;