// Comms Hub — Email · SMS · Calls — linked to deals & contacts

const MOCK_THREADS = [
  { id:'t1', name:'Sarah & James Thornton', type:'email', subject:'Re: Kitchen design proposal', preview:'Thanks for the updated quote — we have one more question about the island bench…', time:'10:42 am', unread:true, dealId:'BAY 51234', tag:'deal', avatar:'ST' },
  { id:'t2', name:'Marcus Webb', type:'sms', subject:'SMS · +61 412 334 XXX', preview:'Hi, can we push the site measure to next Friday? Something came up with the builder.', time:'9:15 am', unread:true, dealId:'CHE 51891', tag:'deal', avatar:'MW' },
  { id:'t3', name:'Priya Nair', type:'email', subject:'Fwd: Quote CHE 51788 — approved', preview:'The board has signed off. We are ready to proceed — please confirm deposit details.', time:'Yesterday', unread:false, dealId:'CHE 51788', tag:'deal', avatar:'PN' },
  { id:'t4', name:'Tom Bradley', type:'call', subject:'Inbound call · 4m 12s', preview:'Discussed timeline, confirmed budget range $65–80k. Follow-up booked for Thursday.', time:'Yesterday', unread:false, dealId:null, tag:'contact', avatar:'TB' },
  { id:'t5', name:'Emma & Ryan Holloway', type:'email', subject:'Re: Site visit checklist', preview:'We have signed the WHS form. Looking forward to seeing you on Monday!', time:'Mon', unread:false, dealId:'BAY 52100', tag:'deal', avatar:'EH' },
  { id:'t6', name:'David Chen', type:'sms', subject:'SMS · +61 405 112 XXX', preview:'Got your message. Still thinking about it — will call you this week.', time:'Mon', unread:false, dealId:'PAK 50934', tag:'deal', avatar:'DC' },
  { id:'t7', name:'Natalie Ross', type:'email', subject:'Initial enquiry — kitchen renovation', preview:'Hello, I found you through a friend and would love to get a quote for a full kitchen reno…', time:'Sun', unread:false, dealId:null, tag:'lead', avatar:'NR' },
  { id:'t8', name:'James Worthington', type:'call', subject:'Outbound call · 1m 45s', preview:'Left voicemail. Deal has been stale for 18 days — tried to re-engage.', time:'Fri', unread:false, dealId:'CHE 51902', tag:'deal', avatar:'JW' },
];

const THREAD_MESSAGES = {
  t1: [
    { from:'Sarah Thornton', dir:'in', time:'10:42 am', body:`Thanks for the updated quote — we have one more question about the island bench. Can you confirm whether the waterfall edge is included in the $72,400 figure, or is that an additional cost?\n\nAlso, is there any flexibility on the lead time? We're hoping to have the kitchen done before Christmas.` },
    { from:'You', dir:'out', time:'10:05 am', body:`Hi Sarah — great to hear from you! I've attached the updated proposal with the revised island bench spec. The waterfall edge is included in the total.\n\nI'll check with our installer on lead time and get back to you today.` },
    { from:'Sarah Thornton', dir:'in', time:'Yesterday 3:18 pm', body:`Hi, just following up on the proposal you sent last week. We've had a chance to review it and we're very interested. Could we schedule a time to discuss a few details?` },
  ],
  t2: [
    { from:'Marcus Webb', dir:'in', time:'9:15 am', body:`Hi, can we push the site measure to next Friday? Something came up with the builder.` },
    { from:'You', dir:'out', time:'9:02 am', body:`Hi Marcus — confirming your site measure for Wednesday 18 June at 10am. See you then!` },
    { from:'Marcus Webb', dir:'in', time:'Mon 2:30 pm', body:`Thanks! Will be home all morning.` },
  ],
};

function CommTypeIcon({ type, size=14 }) {
  const icons = {
    email: <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><rect x="1" y="3" width="14" height="10" rx="2" stroke="currentColor" strokeWidth="1.5"/><path d="M1 5l7 5 7-5" stroke="currentColor" strokeWidth="1.5"/></svg>,
    sms: <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><rect x="1" y="2" width="14" height="10" rx="2" stroke="currentColor" strokeWidth="1.5"/><path d="M4 14l2-2h6" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>,
    call: <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><path d="M3 3a1 1 0 011-1h2l1.5 3.5-1.5 1 3.5 3.5 1-1.5L14 10v2a1 1 0 01-1 1A11 11 0 013 3z" stroke="currentColor" strokeWidth="1.5" strokeLinejoin="round"/></svg>,
  };
  return icons[type] || null;
}

function commsRelTime(iso) {
  if (!iso) return '';
  const d = new Date(iso); const diff = (Date.now() - d.getTime()) / 1000;
  if (diff < 3600) return Math.max(1, Math.round(diff / 60)) + 'm';
  if (diff < 86400) return Math.round(diff / 3600) + 'h';
  if (diff < 7 * 86400) return Math.round(diff / 86400) + 'd';
  return d.toLocaleDateString('en-AU', { day: 'numeric', month: 'short' });
}
function commsInitials(name) {
  return String(name || '?').split(/\s+/).map(p => p[0]).filter(Boolean).slice(0, 2).join('').toUpperCase();
}

function CommsHub({ contacts, deals, showToast }) {
  const toast = showToast || (() => {});
  const LIVE = !!window.STAGEVO_AUTHED && !!window.StagevoData;
  const AI_OK = window.claude && typeof window.claude.complete === 'function';
  const [filter, setFilter] = React.useState('all');
  const [threads, setThreads] = React.useState(LIVE ? [] : MOCK_THREADS);
  const [msgMap, setMsgMap] = React.useState(LIVE ? {} : THREAD_MESSAGES);
  const [activeId, setActiveId] = React.useState(LIVE ? null : 't1');
  const [compose, setCompose] = React.useState(false);
  const [composeDraft, setComposeDraft] = React.useState({ name: '', channel: 'email', body: '' });
  const [replyText, setReplyText] = React.useState('');
  const [loading, setLoading] = React.useState(LIVE);
  const [aiBusy, setAiBusy] = React.useState(false);
  const [sending, setSending] = React.useState(false);
  const [callSummary, setCallSummary] = React.useState('');

  function submitCompose() {
    const name = composeDraft.name.trim();
    const body = composeDraft.body.trim();
    if (!name || !body) return;
    const id = 'tnew_' + Date.now();
    const newThread = {
      id, name, type: composeDraft.channel,
      subject: composeDraft.channel === 'sms' ? 'SMS' : composeDraft.channel === 'call' ? 'Call' : 'New message',
      preview: body.slice(0, 90), time: 'now', unread: false, dealId: null, tag: 'lead', avatar: commsInitials(name),
    };
    setThreads(ts => [newThread, ...ts]);
    setMsgMap(m => ({ ...m, [id]: [{ from: 'You', dir: 'out', time: 'now', body }] }));
    setActiveId(id);
    setCompose(false);
    setComposeDraft({ name: '', channel: 'email', body: '' });
    toast('Message sent to ' + name);
  }

  function logCallNote(label) { toast(label); }

  const dealName = (id) => { const d = (deals || []).find(x => x.id === id); return d ? d.customer : null; };

  React.useEffect(() => {
    if (!LIVE) return; let alive = true;
    (async () => {
      setLoading(true);
      try {
        const raw = await window.StagevoData.loadThreads();
        const mapped = []; const mm = {};
        (raw || []).forEach((t) => {
          const msgs = [...(t.messages || [])].sort((a, b) => new Date(a.sent_at) - new Date(b.sent_at));
          const last = msgs[msgs.length - 1] || {};
          const nm = dealName(t.deal_id) || last.from_address || 'Customer';
          mapped.push({
            id: t.id, name: nm, type: t.channel || 'email',
            subject: last.subject || (t.channel === 'sms' ? 'SMS' : t.channel === 'call' ? 'Call' : 'Email'),
            preview: (last.body || '').slice(0, 90), time: commsRelTime(last.sent_at),
            unread: msgs.some((m) => m.direction === 'inbound' && !m.read_at),
            dealId: t.deal_id, contactId: t.contact_id, tag: 'deal', avatar: commsInitials(nm),
            _sortAt: last.sent_at || 0,
          });
          mm[t.id] = msgs.map((m) => ({ from: m.direction === 'outbound' ? 'You' : nm, dir: m.direction === 'outbound' ? 'out' : 'in', time: commsRelTime(m.sent_at), body: m.body || '' }));
        });
        mapped.sort((a, b) => new Date(b._sortAt) - new Date(a._sortAt));
        if (alive) { setThreads(mapped); setMsgMap(mm); setActiveId(mapped[0] ? mapped[0].id : null); }
      } catch (e) { /* leave empty */ }
      if (alive) setLoading(false);
    })();
    return () => { alive = false; };
  }, [LIVE]);

  const typeColors = { email:'var(--info)', sms:'var(--won)', call: 'var(--warn)' };
  const typeLabels = { email:'Email', sms:'SMS', call:'Call' };

  const visible = filter === 'all' ? threads : threads.filter(t=>t.type===filter);
  const active = threads.find(t=>t.id===activeId);
  const messages = msgMap[activeId] || [];

  async function sendReply() {
    const body = replyText.trim();
    if (!body || !active || sending) return;
    setSending(true);
    setMsgMap(m => ({ ...m, [active.id]: [...(m[active.id] || []), { from:'You', dir:'out', time:'now', body }] }));
    setThreads(ts => ts.map(t => t.id === active.id ? { ...t, preview: body.slice(0,90), time:'now', unread:false } : t));
    setReplyText('');
    if (LIVE) { try { await window.StagevoData.sendMessage(active.id, active.dealId, active.contactId || null, active.type, body, active.subject); } catch (e) {} }
    setSending(false);
  }

  async function aiAssist(kind) {
    if (!AI_OK || !active || aiBusy) return;
    setAiBusy(true);
    try {
      const convo = (msgMap[active.id] || []).map(m => `${m.dir === 'out' ? 'Designer' : active.name}: ${m.body}`).join('\n');
      const prompt = kind === 'summary'
        ? `Summarise this sales call into 2–3 crisp bullet points a kitchen designer can paste into the deal notes. Call context:\n${convo || active.preview}\n\nReturn just the bullets, no preamble.`
        : `You are a kitchen & cabinetry sales designer. Draft a warm, concise ${active.type === 'sms' ? 'SMS reply (under 30 words)' : 'email reply'} to ${active.name} that continues this conversation and moves the deal forward. Return ONLY the message text — no subject, no greeting placeholders, no preamble.\n\nConversation so far:\n${convo || '(new conversation)'}`;
      const raw = await window.claude.complete({ messages: [{ role: 'user', content: prompt }] });
      const text = (raw || '').trim();
      if (kind === 'summary') setCallSummary(text); else setReplyText(text);
    } catch (e) {}
    setAiBusy(false);
  }

  React.useEffect(() => { setCallSummary(''); }, [activeId]);

  return (
    <div style={{ display:'grid', gridTemplateColumns:'300px 1fr', gap:0, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:'var(--r-lg)', overflow:'hidden', height:'calc(100vh - 200px)', minHeight:560 }}>

      {/* Left panel */}
      <div style={{ borderRight:'1px solid var(--border)', display:'flex', flexDirection:'column', background:'var(--surface)' }}>
        {/* Filter tabs */}
        <div style={{ padding:'12px 12px 8px', borderBottom:'1px solid var(--border)' }}>
          <div style={{ display:'flex', gap:2, background:'var(--surface-2)', borderRadius:7, padding:3 }}>
            {[['all','All'],['email','Email'],['sms','SMS'],['call','Calls']].map(([id,label]) => (
              <button key={id} onClick={() => setFilter(id)}
                style={{ flex:1, padding:'5px 6px', borderRadius:5, border:'none', fontSize:12, fontWeight:filter===id?600:400,
                  background: filter===id ? 'var(--surface)' : 'transparent',
                  color: filter===id ? 'var(--ink)' : 'var(--ink-3)',
                  boxShadow: filter===id ? 'var(--shadow-sm)' : 'none', cursor:'pointer' }}>
                {label}
              </button>
            ))}
          </div>
        </div>

        {/* Thread list */}
        <div style={{ flex:1, overflowY:'auto' }}>
          {loading && <div style={{ padding:24, textAlign:'center', color:'var(--ink-3)', fontSize:13 }}>Loading conversations…</div>}
          {!loading && visible.length === 0 && <div style={{ padding:24, textAlign:'center', color:'var(--ink-3)', fontSize:13, lineHeight:1.6 }}>No conversations yet.<br/>Replies and logged calls will appear here.</div>}
          {visible.map(t => (
            <div key={t.id} onClick={() => setActiveId(t.id)}
              style={{ padding:'11px 14px', borderBottom:'1px solid var(--border)', cursor:'pointer', display:'flex', gap:10,
                background: activeId===t.id ? 'var(--accent-soft)' : t.unread ? 'var(--surface)' : 'var(--surface)',
                borderLeft: activeId===t.id ? '3px solid var(--accent)' : '3px solid transparent' }}>
              <div style={{ width:34, height:34, borderRadius:99, background: activeId===t.id ? 'var(--accent)' : 'var(--surface-3)', color: activeId===t.id ? 'white' : 'var(--ink-3)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:11, fontWeight:700, flexShrink:0 }}>{t.avatar}</div>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ display:'flex', alignItems:'center', gap:6, marginBottom:2 }}>
                  <span style={{ fontSize:12.5, fontWeight: t.unread ? 700 : 600, color:'var(--ink)', flex:1, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{t.name}</span>
                  <span style={{ fontSize:11, color:'var(--ink-4)', flexShrink:0 }}>{t.time}</span>
                </div>
                <div style={{ display:'flex', alignItems:'center', gap:5, marginBottom:3 }}>
                  <span style={{ color: typeColors[t.type], display:'inline-flex' }}><CommTypeIcon type={t.type} size={11}/></span>
                  <span style={{ fontSize:11.5, color: t.unread ? 'var(--ink-2)' : 'var(--ink-3)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{t.subject}</span>
                </div>
                <div style={{ fontSize:11, color:'var(--ink-4)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{t.preview}</div>
              </div>
              {t.unread && <div style={{ width:7, height:7, borderRadius:99, background:'var(--accent)', flexShrink:0, marginTop:4 }}></div>}
            </div>
          ))}
        </div>

        {/* Compose */}
        <div style={{ padding:10, borderTop:'1px solid var(--border)' }}>
          <button className="btn primary" style={{ width:'100%', justifyContent:'center' }} onClick={() => setCompose(true)}>
            + Compose
          </button>
        </div>
      </div>

      {/* Right panel — thread view */}
      <div style={{ display:'flex', flexDirection:'column', background:'var(--bg)' }}>
        {!active && (
          <div style={{ flex:1, display:'flex', alignItems:'center', justifyContent:'center', color:'var(--ink-3)', fontSize:13 }}>
            {loading ? 'Loading…' : 'Select a conversation to view it here'}
          </div>
        )}
        {active && (
          <>
            {/* Thread header */}
            <div style={{ padding:'12px 20px', background:'var(--surface)', borderBottom:'1px solid var(--border)', display:'flex', alignItems:'center', gap:12 }}>
              <div style={{ flex:1 }}>
                <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                  <span style={{ fontSize:15, fontWeight:600, color:'var(--ink)' }}>{active.name}</span>
                  <span style={{ display:'inline-flex', alignItems:'center', gap:4, fontSize:11, fontWeight:600, color: typeColors[active.type], background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:99, padding:'2px 8px' }}>
                    <CommTypeIcon type={active.type} size={10}/> {typeLabels[active.type]}
                  </span>
                  {active.unread && <span style={{ background:'var(--accent)', color:'white', fontSize:10, fontWeight:700, borderRadius:99, padding:'1px 7px' }}>New</span>}
                </div>
                <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>{active.subject}</div>
              </div>
              {active.dealId && (
                <div style={{ background:'var(--accent-soft)', border:'1px solid var(--accent)', borderRadius:6, padding:'4px 10px', fontSize:11.5, color:'var(--accent-ink)', fontWeight:600 }}>
                  ↗ {active.dealId}
                </div>
              )}
              <div style={{ display:'flex', gap:6 }}>
                <button className="btn sm" onClick={() => toast('Calling ' + active.name + '…')}><CommTypeIcon type="call" size={11}/> Call</button>
                <button className="btn sm" onClick={() => toast('Conversation marked as read')}>⋯</button>
              </div>
            </div>

            {/* Messages */}
            <div style={{ flex:1, overflowY:'auto', padding:'20px', display:'flex', flexDirection:'column', gap:14 }}>
              {messages.map((m, i) => (
                <div key={i} style={{ display:'flex', flexDirection: m.dir==='out'?'row-reverse':'row', gap:10, alignItems:'flex-start' }}>
                  <div style={{ width:30, height:30, borderRadius:99, background: m.dir==='out'?'var(--accent)':'var(--surface-3)', color: m.dir==='out'?'white':'var(--ink-3)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:10, fontWeight:700, flexShrink:0 }}>
                    {m.dir==='out' ? 'Me' : active.avatar}
                  </div>
                  <div style={{ maxWidth:'70%' }}>
                    <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4, flexDirection: m.dir==='out'?'row-reverse':'row' }}>
                      <span style={{ fontSize:12, fontWeight:600, color:'var(--ink)' }}>{m.from}</span>
                      <span style={{ fontSize:11, color:'var(--ink-4)' }}>{m.time}</span>
                    </div>
                    <div style={{ background: m.dir==='out'?'var(--accent)':'var(--surface)', color: m.dir==='out'?'white':'var(--ink-2)', borderRadius: m.dir==='out'?'12px 4px 12px 12px':'4px 12px 12px 12px', padding:'10px 14px', fontSize:13, lineHeight:1.65, border: m.dir==='out'?'none':'1px solid var(--border)', whiteSpace:'pre-wrap' }}>
                      {m.body}
                    </div>
                  </div>
                </div>
              ))}
            </div>

            {/* Reply bar */}
            {active.type !== 'call' && (
              <div style={{ padding:'12px 16px', background:'var(--surface)', borderTop:'1px solid var(--border)' }}>
                <div style={{ display:'flex', gap:10, alignItems:'flex-end' }}>
                  <textarea
                    value={replyText}
                    onChange={e => setReplyText(e.target.value)}
                    placeholder={`Reply via ${typeLabels[active.type]}…`}
                    rows={2}
                    style={{ flex:1, background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:8, padding:'9px 12px', fontSize:13, resize:'none', outline:'none', fontFamily:'var(--font)', lineHeight:1.5 }}
                  />
                  <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
                    <button className="btn primary sm" style={{ whiteSpace:'nowrap' }} disabled={sending || !replyText.trim()} onClick={sendReply}>{sending ? 'Sending…' : 'Send ↑'}</button>
                    <button className="btn sm" style={{ fontSize:11, color:'var(--ink-3)' }} disabled={aiBusy || !AI_OK} onClick={() => aiAssist('reply')}>{aiBusy ? '✦ Drafting…' : '✦ AI draft'}</button>
                  </div>
                </div>
              </div>
            )}
            {active.type === 'call' && (
              <div style={{ background:'var(--surface)', borderTop:'1px solid var(--border)' }}>
                {callSummary && (
                  <div style={{ margin:'12px 16px 0', padding:'10px 12px', background:'var(--accent-soft)', border:'1px solid var(--accent)', borderRadius:8, fontSize:12.5, color:'var(--accent-ink)', lineHeight:1.6, whiteSpace:'pre-wrap' }}>
                    <div style={{ fontWeight:700, marginBottom:4 }}>✦ AI call summary</div>{callSummary}
                  </div>
                )}
                <div style={{ padding:'12px 16px', display:'flex', gap:10 }}>
                  <button className="btn primary sm" onClick={() => logCallNote('Follow-up call logged for ' + active.name)}>+ Log follow-up call</button>
                  <button className="btn sm" onClick={() => logCallNote('Note added to ' + (active.dealId || 'deal'))}>+ Add note to deal</button>
                  <button className="btn sm" style={{ marginLeft:'auto', fontSize:11, color:'var(--ink-3)' }} disabled={aiBusy || !AI_OK} onClick={() => aiAssist('summary')}>{aiBusy ? '✦ Summarising…' : '✦ AI summarise call'}</button>
                </div>
              </div>
            )}
          </>
        )}
      </div>

      {/* Compose modal */}
      {compose && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.4)', zIndex:200, display:'flex', alignItems:'center', justifyContent:'center' }} onClick={() => setCompose(false)}>
          <div style={{ background:'var(--surface)', borderRadius:'var(--r-xl)', width:440, boxShadow:'var(--shadow-lg)', overflow:'hidden' }} onClick={e => e.stopPropagation()}>
            <div style={{ padding:'16px 20px', borderBottom:'1px solid var(--border)', display:'flex', alignItems:'center', gap:10 }}>
              <div style={{ fontSize:15, fontWeight:600, color:'var(--ink)' }}>New message</div>
              <button onClick={() => setCompose(false)} style={{ marginLeft:'auto', background:'none', border:'none', fontSize:18, color:'var(--ink-3)', cursor:'pointer', lineHeight:1 }}>×</button>
            </div>
            <div style={{ padding:'18px 20px', display:'flex', flexDirection:'column', gap:12 }}>
              <div>
                <label style={{ fontSize:11, fontWeight:600, textTransform:'uppercase', letterSpacing:'0.06em', color:'var(--ink-3)', display:'block', marginBottom:6 }}>To</label>
                <input value={composeDraft.name} onChange={e => setComposeDraft(d => ({ ...d, name: e.target.value }))} placeholder="Customer or contact name"
                  style={{ width:'100%', padding:'9px 12px', border:'1px solid var(--border)', borderRadius:7, fontSize:13, outline:'none', background:'var(--surface-2)', boxSizing:'border-box' }} autoFocus />
              </div>
              <div>
                <label style={{ fontSize:11, fontWeight:600, textTransform:'uppercase', letterSpacing:'0.06em', color:'var(--ink-3)', display:'block', marginBottom:6 }}>Channel</label>
                <div style={{ display:'flex', gap:6 }}>
                  {[['email','Email'],['sms','SMS'],['call','Call']].map(([id,label]) => (
                    <button key={id} onClick={() => setComposeDraft(d => ({ ...d, channel: id }))}
                      style={{ flex:1, padding:'7px', borderRadius:6, fontSize:12, fontWeight: composeDraft.channel===id?600:400, cursor:'pointer',
                        border:'1px solid ' + (composeDraft.channel===id?'var(--accent)':'var(--border)'),
                        background: composeDraft.channel===id?'var(--accent-soft)':'var(--surface-2)',
                        color: composeDraft.channel===id?'var(--accent-ink)':'var(--ink-3)' }}>{label}</button>
                  ))}
                </div>
              </div>
              <div>
                <label style={{ fontSize:11, fontWeight:600, textTransform:'uppercase', letterSpacing:'0.06em', color:'var(--ink-3)', display:'block', marginBottom:6 }}>Message</label>
                <textarea value={composeDraft.body} onChange={e => setComposeDraft(d => ({ ...d, body: e.target.value }))} placeholder="Type your message…" rows={4}
                  style={{ width:'100%', padding:'9px 12px', border:'1px solid var(--border)', borderRadius:7, fontSize:13, outline:'none', background:'var(--surface-2)', resize:'none', fontFamily:'var(--font)', lineHeight:1.5, boxSizing:'border-box' }} />
              </div>
            </div>
            <div style={{ padding:'12px 20px', borderTop:'1px solid var(--border)', display:'flex', gap:8, justifyContent:'flex-end' }}>
              <button className="btn sm" onClick={() => setCompose(false)}>Cancel</button>
              <button className="btn sm primary" disabled={!composeDraft.name.trim() || !composeDraft.body.trim()} onClick={submitCompose}>Send message ↑</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

window.CommsHub = CommsHub;
