← back to Dw Boardroom V2

frontend/src/components/AgendaManager.tsx

133 lines

import { useState, useEffect } from 'react';
import { api } from '../api';
import type { AgendaItem, Meeting } from '../types';

export default function AgendaManager() {
  const [meeting, setMeeting] = useState<Meeting | null>(null);
  const [items, setItems] = useState<AgendaItem[]>([]);
  const [topic, setTopic] = useState('');
  const [recommendation, setRecommendation] = useState('');
  const [decisionType, setDecisionType] = useState('B');
  const [owner, setOwner] = useState('');

  useEffect(() => {
    api.getActiveMeeting().then(data => {
      setMeeting(data.meeting);
      if (data.meeting) {
        api.getAgenda(data.meeting.id).then(setItems);
      }
    }).catch(() => {});
  }, []);

  function refresh() {
    if (meeting) {
      api.getAgenda(meeting.id).then(setItems);
    }
  }

  async function addItem() {
    if (!meeting || !topic.trim()) return;
    try {
      await api.addAgendaItem(meeting.id, { topic, recommendation, decisionType, owner: owner || undefined });
      setTopic(''); setRecommendation(''); setOwner('');
      refresh();
    } catch (err: any) {
      alert(err.message);
    }
  }

  async function deleteItem(id: number) {
    if (!meeting) return;
    await api.deleteAgendaItem(meeting.id, id);
    refresh();
  }

  if (!meeting) {
    return (
      <div style={styles.card}>
        <div style={styles.empty}>No active meeting. Start a meeting first to manage its agenda.</div>
      </div>
    );
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* Add Item Form */}
      <div style={styles.card}>
        <h3 style={styles.title}>Add Agenda Item</h3>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          <input style={styles.input} placeholder="Topic" value={topic} onChange={e => setTopic(e.target.value)} />
          <input style={styles.input} placeholder="Recommendation" value={recommendation} onChange={e => setRecommendation(e.target.value)} />
          <select style={styles.select} value={decisionType} onChange={e => setDecisionType(e.target.value)}>
            <option value="A">Type A (Auto)</option>
            <option value="B">Type B (Advisory)</option>
            <option value="C">Type C (Human)</option>
          </select>
          <input style={{ ...styles.input, maxWidth: 120 }} placeholder="Owner" value={owner} onChange={e => setOwner(e.target.value)} />
          <button style={styles.addBtn} onClick={addItem} disabled={items.length >= 5}>
            {items.length >= 5 ? 'Max 5' : 'Add'}
          </button>
        </div>
        <div style={{ fontSize: 11, color: '#7a7f96', marginTop: 6 }}>
          {items.length}/5 items | Meeting: {meeting.meeting_type} ({meeting.id.slice(0, 8)})
        </div>
      </div>

      {/* Items List */}
      <div style={styles.card}>
        <h3 style={styles.title}>Current Agenda</h3>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {items.length === 0 && <div style={styles.empty}>No agenda items yet.</div>}
          {items.map((item, idx) => (
            <div key={item.id} style={styles.item}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={styles.position}>{idx + 1}</span>
                  <span style={{ fontWeight: 600, fontSize: 13 }}>{item.topic}</span>
                </div>
                <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
                  <span style={{
                    ...styles.typeBadge,
                    background: item.decision_type === 'A' ? '#22c55e22' : item.decision_type === 'C' ? '#ef444422' : '#3b82f622',
                    color: item.decision_type === 'A' ? '#22c55e' : item.decision_type === 'C' ? '#ef4444' : '#3b82f6',
                  }}>
                    Type {item.decision_type}
                  </span>
                  <span style={{
                    ...styles.statusBadge,
                    background: item.status === 'discussed' ? '#f59e0b22' : item.status === 'resolved' ? '#22c55e22' : '#7a7f9622',
                    color: item.status === 'discussed' ? '#f59e0b' : item.status === 'resolved' ? '#22c55e' : '#7a7f96',
                  }}>
                    {item.status}
                  </span>
                  <button style={styles.deleteBtn} onClick={() => deleteItem(item.id)}>x</button>
                </div>
              </div>
              {item.recommendation && (
                <div style={{ fontSize: 11, color: '#7a7f96', marginTop: 4 }}>Rec: {item.recommendation}</div>
              )}
              {item.owner && (
                <div style={{ fontSize: 11, color: '#7a7f96', marginTop: 2 }}>Owner: {item.owner}</div>
              )}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

const styles: Record<string, React.CSSProperties> = {
  card: { background: '#1a1a2e', borderRadius: 12, padding: 20, border: '1px solid #252540' },
  title: { margin: '0 0 12px', fontSize: 15, fontWeight: 700 },
  input: { padding: '8px 10px', borderRadius: 6, border: '1px solid #252540', background: '#0a0a12', color: '#e8eaf0', fontSize: 12, fontFamily: 'inherit', flex: 1, minWidth: 140 },
  select: { padding: '8px', borderRadius: 6, border: '1px solid #252540', background: '#0a0a12', color: '#e8eaf0', fontSize: 12, fontFamily: 'inherit' },
  addBtn: { padding: '8px 16px', borderRadius: 6, border: 'none', background: '#8b5cf6', color: '#fff', fontWeight: 600, fontSize: 12, cursor: 'pointer', fontFamily: 'inherit' },
  empty: { color: '#7a7f96', fontSize: 13, textAlign: 'center' as const, padding: 30 },
  item: { background: '#12121f', borderRadius: 8, padding: 12, border: '1px solid #252540' },
  position: { width: 22, height: 22, borderRadius: '50%', background: '#8b5cf622', color: '#8b5cf6', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 10, fontWeight: 700 },
  typeBadge: { padding: '2px 8px', borderRadius: 4, fontSize: 10, fontWeight: 600 },
  statusBadge: { padding: '2px 8px', borderRadius: 4, fontSize: 10, fontWeight: 600 },
  deleteBtn: { width: 20, height: 20, borderRadius: 4, border: '1px solid #ef444466', background: 'transparent', color: '#ef4444', fontSize: 11, cursor: 'pointer', fontFamily: 'inherit' },
};