← back to Dw Boardroom V2

frontend/src/components/LiveFeed.tsx

78 lines

import { useEffect, useRef } from 'react';
import type { MeetingMessage } from '../types';

const TYPE_COLORS: Record<string, string> = {
  dialogue: '#e8eaf0',
  phase: '#8b5cf6',
  system: '#7a7f96',
  action: '#f59e0b',
  decision: '#22c55e',
};

interface Props {
  messages: MeetingMessage[];
  meetingActive: boolean;
}

export default function LiveFeed({ messages, meetingActive }: Props) {
  const feedRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (feedRef.current) {
      feedRef.current.scrollTop = feedRef.current.scrollHeight;
    }
  }, [messages]);

  return (
    <div style={styles.card}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
        <h3 style={{ margin: 0, fontSize: 14, fontWeight: 700 }}>Live Feed</h3>
        <span style={{ fontSize: 11, color: '#7a7f96' }}>
          {messages.length} message{messages.length !== 1 ? 's' : ''}
        </span>
      </div>

      <div ref={feedRef} style={styles.feed}>
        {messages.length === 0 && (
          <div style={styles.empty}>
            {meetingActive ? 'Waiting for dialogue...' : 'No active meeting. Start one above.'}
          </div>
        )}
        {messages.map((msg) => (
          <div key={msg.id} style={styles.message}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 2 }}>
              <span style={{ fontWeight: 700, fontSize: 12, color: TYPE_COLORS[msg.message_type] || '#e8eaf0' }}>
                {msg.agent_name}
              </span>
              {msg.message_type !== 'dialogue' && (
                <span style={{
                  padding: '1px 6px', borderRadius: 3, fontSize: 9, fontWeight: 600,
                  background: (TYPE_COLORS[msg.message_type] || '#7a7f96') + '22',
                  color: TYPE_COLORS[msg.message_type] || '#7a7f96',
                }}>
                  {msg.message_type}
                </span>
              )}
              <span style={{ fontSize: 9, color: '#555', marginLeft: 'auto' }}>
                {msg.phase}
              </span>
            </div>
            <div style={{ fontSize: 12, color: '#b0b3c0', lineHeight: 1.5 }}>{msg.message}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

const styles: Record<string, React.CSSProperties> = {
  card: { background: '#1a1a2e', borderRadius: 12, padding: 16, border: '1px solid #252540' },
  feed: {
    maxHeight: 500, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 8,
  },
  message: {
    padding: '8px 12px', background: '#12121f', borderRadius: 8, borderLeft: '3px solid #252540',
  },
  empty: { color: '#7a7f96', fontSize: 13, textAlign: 'center' as const, padding: 40 },
};