// ============ TaskQuest — Modals ============
const { useState, useEffect, useRef } = React;
const { ROLES: R5, PROJECTS: P5, CONSULTANTS: C5, COLUMNS: COLS5 } = window.TQ;

function ModalShell({ icon, iconColor, title, desc, onClose, children, footer, wide }) {
  useEffect(() => {
    function esc(e) { if (e.key === "Escape") onClose(); }
    document.addEventListener("keydown", esc);
    return () => document.removeEventListener("keydown", esc);
  }, []);
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className={`modal ${wide ? "wide" : ""}`} onClick={e => e.stopPropagation()}>
        <div className="modal-head">
          {icon && <span className="mh-ic" style={{ background: iconColor + "22", color: iconColor }}>{React.createElement(icon, { size: 18 })}</span>}
          <div style={{ flex: 1 }}>
            <div className="modal-title">{title}</div>
            {desc && <div className="modal-desc">{desc}</div>}
          </div>
          <button className="icon-btn modal-x" onClick={onClose}><Ic.X size={18} /></button>
        </div>
        <div className="modal-body">{children}</div>
        {footer && <div className="modal-foot">{footer}</div>}
      </div>
    </div>
  );
}

function ProjectTag({ pk }) {
  const p = P5[pk];
  return <span className="tile-project"><span className="pdot" style={{ background: p.color }} />{p.name}</span>;
}

// ---------- Task detail ----------
function TaskDetailModal({ task, role, onClose, onComment, onApproveDate, onRejectDate, onApproveDone, onAwardBonus, onReassign, onDelete, onEdit, onMoveBackHint }) {
  const { fmtDateLong, relDue, daysUntil } = window.TQ;
  const r = R5[role];
  const isManager = r.type === "pm" || r.type === "dm";
  const col = COLS5.find(c => c.key === task.status);
  const [text, setText] = useState("");
  const [editDate, setEditDate] = useState(task.request ? task.request.newDate : task.due);
  const [reassignOpen, setReassignOpen] = useState(false);
  const [confirmDelete, setConfirmDelete] = useState(false);
  const [editing, setEditing] = useState(false);
  // edit form state
  const SUBCATS = window.TQ.SUBCATEGORIES;
  const [editName, setEditName] = useState(task.name);
  const [editDue, setEditDue] = useState(task.due);
  const [editAssignee, setEditAssignee] = useState(task.assignee);
  const [editSubcat, setEditSubcat] = useState(task.subcategory || "");
  const [editDesc, setEditDesc] = useState(task.description || "");
  const overdue = task.status !== "done" && daysUntil(task.due) < 0;
  const subcat = task.subcategory && SUBCATS.find(s => s.key === task.subcategory);
  const canReassign = isManager && (task.status === "happy" || task.status === "unhappy");
  const reassignPool = C5.filter(c => R5[c] && window.TQ.projectsOf(R5[c]).indexOf(task.project) >= 0);
  const pool = reassignPool.length ? reassignPool : C5;

  const datePending = task.request && task.request.status === "pending";
  const donePending = task.completion && task.completion.status === "pending";

  function submitComment() {
    if (!text.trim()) return;
    onComment(task, text.trim());
    setText("");
  }

  return (
    <ModalShell icon={Ic.Flag} iconColor={col.color} title={task.name}
      desc={<span style={{ display: "inline-flex", gap: 8, alignItems: "center" }}>{task.id}<span style={{ color: "var(--border-strong)" }}>·</span><ProjectTag pk={task.project} /></span>}
      onClose={onClose}
      footer={
        <>
          {r.type === "dm" && (
            <button className="btn btn-ghost" onClick={() => onAwardBonus(task.assignee, task.project)}>
              <Ic.Gift size={15} />Award bonus
            </button>
          )}
          {isManager && !editing && (
            <button className="btn btn-ghost" style={{ color: "var(--text-2)" }} onClick={() => { setEditing(true); setEditName(task.name); setEditDue(task.due); setEditAssignee(task.assignee); setEditSubcat(task.subcategory||""); setEditDesc(task.description||""); }}>
              <Ic.Edit size={15} />Edit
            </button>
          )}
          {isManager && editing && (
            <div style={{ display:"flex", alignItems:"center", gap:8, flex:1 }}>
              <button className="btn btn-primary" disabled={!editName.trim()} onClick={() => { onEdit && onEdit(task.id, { name:editName.trim(), due:editDue, assignee:editAssignee, subcategory:editSubcat||null, description:editDesc }); setEditing(false); onClose(); }}><Ic.Check size={14} />Save changes</button>
              <button className="btn btn-ghost" onClick={() => setEditing(false)}>Cancel</button>
            </div>
          )}
          <span className="spacer" />
          <button className="btn btn-ghost" onClick={onClose}>Close</button>
        </>
      }>

      {/* Inline edit form — managers only */}
      {isManager && editing && (
        <div className="task-edit-form">
          <div className="field">
            <label className="field-label">Task name</label>
            <input className="input" value={editName} onChange={e => setEditName(e.target.value)} />
          </div>
          <div className="field">
            <label className="field-label">Sub-category</label>
            <div className="subcat-grid">
              {SUBCATS.map(s => (
                <button type="button" key={s.key} className={`subcat-opt ${editSubcat === s.key ? "sel" : ""}`}
                  style={editSubcat === s.key ? { borderColor: s.color, background: s.color + "1a", color: s.color } : {}}
                  onClick={() => setEditSubcat(editSubcat === s.key ? "" : s.key)}>
                  <span className="subcat-dot" style={{ background: s.color }} />{s.name}
                </button>
              ))}
            </div>
          </div>
          <div className="field">
            <label className="field-label">Assign to</label>
            <SearchableSelect options={pool} value={editAssignee} onChange={setEditAssignee}
              placeholder="Search team members…" emptyText="No members"
              getLabel={c => (R5[c] && R5[c].name) || c}
              renderOption={c => (<span className="ssel-person"><Avatar who={c} size="sm" /><span className="ssel-person-name">{R5[c].name}</span><span className="ssel-person-role">{R5[c].label}</span></span>)} />
          </div>
          <div className="field">
            <label className="field-label">Due date</label>
            <DateField value={editDue} onChange={setEditDue} min={window.TQ.isoFromOffset(0)} />
          </div>
          <div className="field">
            <label className="field-label">Description</label>
            <textarea className="textarea" value={editDesc} onChange={e => setEditDesc(e.target.value)} />
          </div>
          <div style={{ borderTop:"1px solid var(--border)", paddingTop:14 }}>
            {!confirmDelete ? (
              <button type="button" className="btn btn-ghost" style={{ color:"var(--red, #e05252)", width:"100%" }} onClick={() => setConfirmDelete(true)}>
                <Ic.Trash size={14} />Delete this task
              </button>
            ) : (
              <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                <span style={{ fontSize:13, color:"var(--text-2)", fontWeight:600, flex:1 }}>Are you sure? This cannot be undone.</span>
                <button className="btn btn-danger" onClick={() => { onDelete && onDelete(task.id); onClose(); }}><Ic.Trash size={14} />Yes, delete</button>
                <button className="btn btn-ghost" onClick={() => setConfirmDelete(false)}>Cancel</button>
              </div>
            )}
          </div>
        </div>
      )}

      {/* Manager approval surfaces */}
      {isManager && datePending && (
        <div className="approval-box">
          <div className="approval-title"><Ic.Calendar size={15} style={{ color: "#b88a00" }} />Date change requested</div>
          <div className="approval-meta">
            <b>{R5[task.assignee].name}</b> wants to move the due date from <b>{fmtDateLong(task.due)}</b> to <b>{fmtDateLong(task.request.newDate)}</b>.<br />
            Reason: {task.request.reason}
          </div>
          <div className="approval-date-edit">
            <span style={{ fontSize: 12, color: "var(--muted)", fontWeight: 600, whiteSpace: "nowrap" }}>Approve as:</span>
            <input className="input" type="date" value={editDate} min={window.TQ.isoFromOffset(0)} onChange={e => setEditDate(e.target.value)} style={{ maxWidth: 170 }} />
          </div>
          <div className="approval-actions">
            <button className="btn btn-success" onClick={() => onApproveDate(task, editDate)}><Ic.Check size={15} />Approve change</button>
            <button className="btn btn-soft-danger" onClick={() => onRejectDate(task)}><Ic.X size={15} />Reject</button>
          </div>
        </div>
      )}
      {isManager && donePending && (
        <div className="approval-box done">
          <div className="approval-title"><Ic.CheckCircle size={15} style={{ color: "var(--green)" }} />Completion awaiting sign-off</div>
          <div className="approval-meta">
            Marked done {task.completion.onTime ? "on time" : "late"}. {task.completion.comments}
          </div>
          <div className="approval-actions">
            <button className="btn btn-success" onClick={() => onApproveDone(task)}><Ic.Check size={15} />Approve completion</button>
          </div>
        </div>
      )}

      {/* Consultant view of their request status */}
      {!isManager && task.request && task.request.status === "approved" && (
        <div className="approval-box done">
          <div className="approval-title"><Ic.CheckCircle size={15} style={{ color: "var(--green)" }} />Date change approved</div>
          <div className="approval-meta">New due date: <b>{fmtDateLong(task.due)}</b>. Move this task back to <b>Happy Path</b> when you resume work.</div>
        </div>
      )}
      {!isManager && task.request && task.request.status === "rejected" && (
        <div className="approval-box" style={{ background: "var(--red-soft)", borderColor: "rgba(235,87,87,0.35)" }}>
          <div className="approval-title"><Ic.X size={15} style={{ color: "var(--red)" }} />Date change rejected</div>
          <div className="approval-meta">Keep the original due date of <b>{fmtDateLong(task.due)}</b>, or discuss with your manager.</div>
        </div>
      )}
      {!isManager && datePending && (
        <div className="approval-box">
          <div className="approval-title"><Ic.Clock size={15} style={{ color: "#b88a00" }} />Awaiting approval</div>
          <div className="approval-meta">Requested new date: <b>{fmtDateLong(task.request.newDate)}</b>. Your manager has been notified.</div>
        </div>
      )}

      {/* Details */}
      <div style={{ marginBottom: 18 }}>
        <div className="detail-row">
          <span className="detail-k">Status</span>
          <span className="detail-v"><span className="badge" style={{ background: col.color + "22", color: col.color }}>{col.name}</span></span>
        </div>
        {subcat && (
          <div className="detail-row">
            <span className="detail-k">Sub-category</span>
            <span className="detail-v"><span className="badge" style={{ background: subcat.color + "22", color: subcat.color }}>{subcat.name}</span></span>
          </div>
        )}
        <div className="detail-row">
          <span className="detail-k">Assignee</span>
          <span className="detail-v" style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <Avatar who={task.assignee} size="sm" />{R5[task.assignee].name}
            {canReassign && (
              <button className="linklike" style={{ marginLeft: 6 }} onClick={() => setReassignOpen(o => !o)}>{reassignOpen ? "Cancel" : "Reassign"}</button>
            )}
          </span>
        </div>
        {canReassign && reassignOpen && (
          <div className="reassign-box">
            <div className="reassign-label">Reassign to a different team member</div>
            <SearchableSelect options={pool.filter(c => c !== task.assignee)} value="" onChange={(c) => { onReassign && onReassign(task, c); setReassignOpen(false); }}
              placeholder="Search team members…" emptyText="No other members on this project"
              getLabel={c => (R5[c] && R5[c].name) || c}
              renderOption={c => (<span className="ssel-person"><Avatar who={c} size="sm" /><span className="ssel-person-name">{R5[c].name}</span><span className="ssel-person-role">{R5[c].type === "consultant" ? "Consultant" : R5[c].label}</span></span>)} />
          </div>
        )}
        <div className="detail-row">
          <span className="detail-k">Due date</span>
          <span className={`detail-v ${overdue ? "" : ""}`} style={overdue ? { color: "var(--red)" } : {}}>{fmtDateLong(task.due)} · {relDue(task.due)}</span>
        </div>
        {task.status === "done" && task.completion && (
          <div className="detail-row">
            <span className="detail-k">Outcome</span>
            <span className="detail-v">{task.completion.onTime
              ? <span className="badge ontime"><Ic.Check size={11} />On time · +10 pts</span>
              : <span className="badge late">Late · +0 pts</span>}
              {task.completion.status === "pending" && <span className="badge pending" style={{ marginLeft: 6 }}>awaiting sign-off</span>}
            </span>
          </div>
        )}
      </div>

      {task.description && (
        <div style={{ marginBottom: 18 }}>
          <div className="section-label">Description</div>
          <div className="task-desc">{task.description}</div>
        </div>
      )}

      {/* Per-card time logging — consultant logging against their own task */}
      {!isManager && task.assignee === role && window.TaskWeekLogger &&
        React.createElement(window.TaskWeekLogger, { task: task, role: role })}

      {/* Comments */}
      <div className="section-label">Progress comments {isManager && <span style={{ textTransform: "none", color: "var(--faint)", fontWeight: 500 }}>· visible to managers</span>}</div>
      <div className="comment-list">
        {(!task.comments || task.comments.length === 0) && <div className="comment-empty">No comments yet.</div>}
        {task.comments && task.comments.map((c, i) => (
          <div className="comment" key={i}>
            <Avatar who={c.author} size="sm" />
            <div className={`comment-body ${c.system ? "comment-sys" : ""}`}>
              <div className="comment-top">
                <span className="comment-author">{R5[c.author].name}</span>
                <span className="comment-role">{R5[c.author].label}</span>
                <span className="comment-time">{c.time}</span>
              </div>
              <div className="comment-text">{c.text}</div>
            </div>
          </div>
        ))}
      </div>
      <div className="comment-compose">
        <Avatar who={role} size="sm" />
        <textarea className="textarea" style={{ minHeight: 60 }} placeholder="Add a progress update…"
          value={text} onChange={e => setText(e.target.value)}
          onKeyDown={e => { if ((e.metaKey || e.ctrlKey) && e.key === "Enter") submitComment(); }} />
      </div>
      <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 10 }}>
        <button className="btn btn-primary" disabled={!text.trim()} onClick={submitComment}><Ic.Send size={14} />Comment</button>
      </div>
    </ModalShell>
  );
}

// ---------- Move modals (date / hold / done) ----------
function MoveModal({ kind, task, onClose, onSubmit }) {
  const { fmtDateLong, isoFromOffset, daysUntil } = window.TQ;
  const [newDate, setNewDate] = useState(task.due);
  const [reason, setReason] = useState("");
  const [comments, setComments] = useState("");

  if (kind === "date") {
    const valid = newDate && newDate !== task.due;
    return (
      <ModalShell icon={Ic.Calendar} iconColor="#f2c94c" title="Request a date change" wide
        desc={`${task.name} · moving to Needs attention`} onClose={onClose}
        footer={<><button className="btn btn-ghost" onClick={onClose}>Cancel</button><span className="spacer" /><button className="btn btn-primary" disabled={!valid} onClick={() => onSubmit({ newDate, reason, comments })}><Ic.Send size={14} />Submit for approval</button></>}>
        <div className="field">
          <label className="field-label">Current due date</label>
          <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--muted)" }}>{fmtDateLong(task.due)}</div>
        </div>
        <div className="field">
          <label className="field-label">Requested new date <span className="req">*</span></label>
          <DateField value={newDate} onChange={setNewDate} min={window.TQ.isoFromOffset(0)} />
        </div>
        <div className="field">
          <label className="field-label">Reason</label>
          <input className="input" placeholder="e.g. Blocked on vendor access" value={reason} onChange={e => setReason(e.target.value)} />
        </div>
        <div className="field">
          <label className="field-label">Comments</label>
          <textarea className="textarea" placeholder="Add context for your manager…" value={comments} onChange={e => setComments(e.target.value)} />
        </div>
      </ModalShell>
    );
  }

  if (kind === "hold") {
    const valid = reason.trim();
    return (
      <ModalShell icon={Ic.Pause} iconColor="#878b94" title="Move to On Hold"
        desc={task.name} onClose={onClose}
        footer={<><button className="btn btn-ghost" onClick={onClose}>Cancel</button><span className="spacer" /><button className="btn btn-primary" disabled={!valid} onClick={() => onSubmit({ reason, comments })}>Submit</button></>}>
        <div className="field">
          <label className="field-label">Reason <span className="req">*</span></label>
          <select className="select-field" value={reason} onChange={e => setReason(e.target.value)}>
            <option value="">Select a reason…</option>
            <option>Waiting on client</option>
            <option>Blocked by dependency</option>
            <option>Awaiting information</option>
            <option>Resource constraint</option>
            <option>Deprioritized</option>
          </select>
        </div>
        <div className="field">
          <label className="field-label">Comments</label>
          <textarea className="textarea" placeholder="Add any details…" value={comments} onChange={e => setComments(e.target.value)} />
        </div>
      </ModalShell>
    );
  }

  // done
  const cfg = window.TQ.CONFIG;
  const onTime = daysUntil(task.due) >= 0;
  const earn = onTime ? cfg.onTimePoints : cfg.latePoints;
  return (
    <ModalShell icon={Ic.CheckCircle} iconColor="#8b7cf6" title="Mark as Done"
      desc={task.name} onClose={onClose}
      footer={<><button className="btn btn-ghost" onClick={onClose}>Cancel</button><span className="spacer" /><button className="btn btn-success" onClick={() => onSubmit({ comments, onTime })}><Ic.Check size={15} />Submit completion</button></>}>
      <div className={`approval-box ${onTime ? "done" : ""}`} style={onTime ? {} : { background: "var(--surface-3)", borderColor: "var(--border)" }}>
        <div className="approval-title">
          {onTime ? <><Ic.Star size={15} style={{ color: "var(--green)" }} />On-time completion · +{cfg.onTimePoints} points</>
                  : <><Ic.Clock size={15} style={{ color: "var(--muted)" }} />Late completion · +{cfg.latePoints} points</>}
        </div>
        <div className="approval-meta">{onTime ? "Nice work — this lands on or before the due date." : (cfg.latePoints > 0 ? `Past the due date — earns the reduced late rate of +${cfg.latePoints} points.` : "This is past the due date, so it won't earn points. It still counts toward completion.")}</div>
      </div>
      <div className="field">
        <label className="field-label">Completion comments</label>
        <textarea className="textarea" placeholder="Summarize what was delivered…" value={comments} onChange={e => setComments(e.target.value)} />
      </div>
      <div style={{ fontSize: 12, color: "var(--muted)" }}>Your manager will be notified to approve the completion.</div>
    </ModalShell>
  );
}

// ---------- Create task (PM — breaks a deliverable down for the team) ----------
function CreateTaskModal({ role, project, deliverables = [], presetDeliverable = null, onClose, onCreate }) {
  const SUBCATS = window.TQ.SUBCATEGORIES;
  const firstProject = Object.keys(P5)[0] || "";
  const [name, setName] = useState("");
  const [proj, setProj] = useState(() => (project === "all" || !P5[project]) ? firstProject : project);
  const scopedCons = C5.filter(c => R5[c] && window.TQ.projectsOf(R5[c]).indexOf(proj) >= 0);
  const consultants = scopedCons.length ? scopedCons : C5;
  const [assignee, setAssignee] = useState(consultants[0] || "");
  const [due, setDue] = useState(window.TQ.isoFromOffset(7));
  const [description, setDescription] = useState("");
  const [subcategory, setSubcategory] = useState(SUBCATS[0].key);
  const [comments, setComments] = useState("");
  const [deliv, setDeliv] = useState(presetDeliverable || "");

  // keep assignee + linked deliverable valid as the project changes
  useEffect(() => {
    const list = C5.filter(c => R5[c] && window.TQ.projectsOf(R5[c]).indexOf(proj) >= 0);
    const use = list.length ? list : C5;
    if (use.indexOf(assignee) < 0) setAssignee(use[0] || "");
    if (deliv && !deliverables.some(x => x.id === deliv && x.project === proj)) setDeliv("");
  }, [proj]);

  const delivOpts = deliverables.filter(x => x.project === proj && !x.accepted);
  const validAssignee = !!assignee && !!R5[assignee];
  const validProject = !!proj && !!P5[proj];
  const valid = name.trim() && validAssignee && validProject && due;
  const noConsultants = consultants.length === 0;
  return (
    <ModalShell icon={Ic.Plus} iconColor="#5E6AD2" title="Create task" wide
      desc="Adds to the Happy Path" onClose={onClose}
      footer={<><button className="btn btn-ghost" onClick={onClose}>Cancel</button><span className="spacer" /><button className="btn btn-primary" disabled={!valid} onClick={() => onCreate({ name: name.trim(), assignee, due, description: description.trim(), subcategory, comments, project: proj, deliverable: deliv || null })}><Ic.Plus size={15} />Create task</button></>}>
      <div className="field">
        <label className="field-label">Task name <span className="req">*</span></label>
        <input className="input" autoFocus placeholder="e.g. Configure SSO for client tenant" value={name} onChange={e => setName(e.target.value)} />
      </div>
      {project === "all" && (
        <div className="field">
          <label className="field-label">Project</label>
          <select className="select-field" value={proj} onChange={e => setProj(e.target.value)}>
            {Object.values(P5).map(p => <option key={p.key} value={p.key}>{p.name}</option>)}
          </select>
        </div>
      )}
      <div className="field">
        <label className="field-label">Sub-category</label>
        <div className="subcat-grid">
          {SUBCATS.map(s => (
            <button type="button" key={s.key} className={`subcat-opt ${subcategory === s.key ? "sel" : ""}`}
              style={subcategory === s.key ? { borderColor: s.color, background: s.color + "1a", color: s.color } : {}}
              onClick={() => setSubcategory(s.key)}>
              <span className="subcat-dot" style={{ background: s.color }} />{s.name}
            </button>
          ))}
        </div>
      </div>
      {(delivOpts.length > 0 || presetDeliverable) && (
        <div className="field">
          <label className="field-label">Part of deliverable</label>
          <select className="select-field" value={deliv} onChange={e => setDeliv(e.target.value)} disabled={!!presetDeliverable}>
            <option value="">— None —</option>
            {delivOpts.map(x => <option key={x.id} value={x.id}>{x.id} · {x.name}</option>)}
          </select>
        </div>
      )}
      <div className="field">
        <label className="field-label">Assign to <span className="req">*</span></label>
        {noConsultants ? (
          <div className="comment-empty" style={{ padding: "12px 4px" }}>No consultants on this project yet — ask an admin to add one before creating tasks.</div>
        ) : (
          <SearchableSelect options={consultants} value={assignee} onChange={setAssignee}
            placeholder="Search team members…" emptyText="No matching team members"
            getLabel={c => (R5[c] && R5[c].name) || c}
            renderOption={c => (
              <span className="ssel-person">
                <Avatar who={c} size="sm" />
                <span className="ssel-person-name">{R5[c].name}</span>
                <span className="ssel-person-role">{R5[c].type === "consultant" ? "Consultant" : R5[c].label}</span>
              </span>
            )} />
        )}
      </div>
      <div className="field">
        <label className="field-label">Due date <span className="req">*</span></label>
        <DateField value={due} onChange={setDue} min={window.TQ.isoFromOffset(0)} />
      </div>
      <div className="field">
        <label className="field-label">Description</label>
        <textarea className="textarea" placeholder="What needs to be done — scope, acceptance criteria…" value={description} onChange={e => setDescription(e.target.value)} />
      </div>
      <div className="field">
        <label className="field-label">Comments</label>
        <textarea className="textarea" placeholder="Brief, links, extra context…" value={comments} onChange={e => setComments(e.target.value)} />
      </div>
    </ModalShell>
  );
}

// ---------- Bonus points (DM) ----------
function BonusModal({ toKey, project, onClose, onAward }) {
  const tiers = window.TQ.CONFIG.bonusTiers;
  const [pts, setPts] = useState(tiers[Math.min(1, tiers.length - 1)]);
  const [comment, setComment] = useState("");
  const [who, setWho] = useState(toKey || window.TQ.CONSULTANTS[0]);
  const valid = comment.trim();
  return (
    <ModalShell icon={Ic.Gift} iconColor="#e0902b" title="Award bonus points" wide
      desc="Recognition is added to the leaderboard instantly" onClose={onClose}
      footer={<><button className="btn btn-ghost" onClick={onClose}>Cancel</button><span className="spacer" /><button className="btn btn-primary" disabled={!valid} onClick={() => onAward({ to: who, pts, comment: comment.trim(), project })} style={{ background: "var(--amber)", color: "#3a2e00" }}><Ic.Sparkle size={15} />Award +{pts}</button></>}>
      <div className="field">
        <label className="field-label">Recipient</label>
        <div className="assignee-grid">
          {C5.map(c => (
            <div key={c} className={`assignee-opt ${who === c ? "sel" : ""}`} onClick={() => setWho(c)}>
              <Avatar who={c} size="sm" />
              <span className="ao-name">{R5[c].name}</span>
              <span className="ao-check"><Ic.Check size={16} /></span>
            </div>
          ))}
        </div>
      </div>
      <div className="field">
        <label className="field-label">Bonus amount</label>
        <div className="bonus-grid" style={{ gridTemplateColumns: `repeat(${tiers.length}, 1fr)` }}>
          {tiers.map(v => (
            <div key={v} className={`bonus-opt ${pts === v ? "sel" : ""}`} onClick={() => setPts(v)}>
              <div className="bonus-pts"><span className="plus">+</span>{v}</div>
              <div className="bonus-lbl">points</div>
            </div>
          ))}
        </div>
      </div>
      <div className="field">
        <label className="field-label">Recognition comment <span className="req">*</span></label>
        <textarea className="textarea" placeholder="What did they do exceptionally well?" value={comment} onChange={e => setComment(e.target.value)} />
      </div>
    </ModalShell>
  );
}

window.ModalShell = ModalShell;
window.TaskDetailModal = TaskDetailModal;
window.MoveModal = MoveModal;
window.CreateTaskModal = CreateTaskModal;
window.BonusModal = BonusModal;
