File size: 2,120 Bytes
0bb4dfa
 
 
 
 
 
 
 
 
 
e661e91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0bb4dfa
e661e91
0bb4dfa
 
 
 
 
 
 
e661e91
0bb4dfa
 
 
 
 
 
 
 
 
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
import React from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

/**
 * Distinct rendering for orchestrator messages. Centered, italic, and
 * a different color than participant bubbles so users always know who's
 * speaking. Used for status updates, follow-up announcements, factor
 * surfacing, and the final majority/no-consensus reports.
 */
// Orchestrator message `kind` values that should get the "report"
// visual treatment (border, larger text). Includes the originals
// from the Consensus decision path plus the new ones emitted by the
// majority-rules, ranked-choice, and Robert's Rules vote plugins.
const REPORT_KINDS = new Set([
  'majority_report',
  'no_consensus_report',
  'vote_result',
  'ranked_choice_result',
]);

function labelSuffixForKind(kind, message) {
  switch (kind) {
    case 'majority_report': return ' - Majority Report';
    case 'no_consensus_report': return ' - No-Consensus Report';
    case 'factor': return ' - New Consideration';
    case 'motion': return ' - Motion on the Floor';
    case 'ballot_options': return ' - Ballot';
    case 'rr_opening': return ' - Chair';
    case 'rr_call_the_question': return ' - Chair Calls the Question';
    case 'vote_result':
      if (message?.flavor === 'roberts_rules') return ' - Vote Result (RR)';
      if (message?.vote_kind === 'yesno') return ' - Vote Result (Aye/Nay)';
      return ' - Vote Result';
    case 'ranked_choice_result': return ' - Ranked-Choice Result';
    default: return '';
  }
}

export default function OrchestratorMessage({ message }) {
  const isReport = REPORT_KINDS.has(message.kind);
  const className = (
    'ccai-orchestrator-msg' +
    (isReport ? ' ccai-orchestrator-msg-report' : '')
  );
  return (
    <div className={className}>
      <div className="ccai-orchestrator-msg-label">
        Orchestrator{labelSuffixForKind(message.kind, message)}
      </div>
      <div className="ccai-orchestrator-msg-body">
        <ReactMarkdown remarkPlugins={[remarkGfm]}>
          {message.text || ''}
        </ReactMarkdown>
      </div>
    </div>
  );
}