// ============== recruiter dashboard ==============

const APP_STATUSES = ["submitted", "reviewed", "shortlisted", "interviewing", "offered", "placed", "rejected", "withdrawn"];
const ROLE_STATUSES = ["draft", "open", "paused", "closed"];

function RecruiterDashboard({ go }) {
  const { user, logout } = useAuth();
  const [tab, setTab] = React.useState("overview");
  const [inviteOpen, setInviteOpen] = React.useState(false);

  return (
    <main>
      <section className="page-hero">
        <div className="shell">
          <div className="dash-head">
            <div>
              <Eyebrow>Recruiter · {user.email}</Eyebrow>
              <h1 style={{ marginTop: 24, fontSize: "clamp(40px, 6vw, 88px)" }}>Control <em>room.</em></h1>
            </div>
            <div style={{ display: "flex", gap: 12 }}>
              <button className="btn btn--ghost" onClick={() => setInviteOpen(true)}>Invite recruiter <Icon.Arrow /></button>
              <button className="btn btn--quiet" onClick={() => { logout(); go("home"); }}>Sign out</button>
            </div>
          </div>
        </div>
      </section>
      {inviteOpen && <InviteModal onClose={() => setInviteOpen(false)} />}
      <section>
        <div className="shell">
          <Tabs
            value={tab}
            onChange={setTab}
            tabs={[
              { id: "overview", label: "Overview" },
              { id: "roles", label: "Roles" },
              { id: "applications", label: "Applications" },
              { id: "candidates", label: "Candidates" },
              { id: "companies", label: "Companies" },
            ]}
          />
          <div className="dash-body">
            {tab === "overview" && <Overview />}
            {tab === "roles" && <AdminRoles />}
            {tab === "applications" && <AdminApplications />}
            {tab === "candidates" && <AdminCandidates />}
            {tab === "companies" && <AdminCompanies />}
          </div>
        </div>
      </section>
    </main>
  );
}

function Overview() {
  const [stats, setStats] = React.useState(null);
  React.useEffect(() => {
    window.W3J_API.apiFetch("/admin/dashboard").then(setStats).catch(() => setStats({}));
  }, []);
  if (!stats) return <p className="lede">Loading…</p>;
  const cards = [
    { num: stats.open_roles ?? 0, label: "Open roles" },
    { num: stats.total_roles ?? 0, label: "Total roles" },
    { num: stats.candidates ?? 0, label: "Candidates" },
    { num: stats.applications_total ?? 0, label: "Applications" },
  ];
  return (
    <div>
      <div className="stat-row stat-row--4">
        {cards.map((c) => (
          <div className="stat" key={c.label}>
            <div className="stat-num">{c.num}</div>
            <div className="stat-label">{c.label}</div>
          </div>
        ))}
      </div>
      <h4 className="form-h" style={{ marginTop: 40 }}>Applications by status</h4>
      <div className="kv-grid">
        {Object.entries(stats.applications_by_status || {}).map(([k, v]) => (
          <div className="kv" key={k}>
            <div className="kv-key">{k.replace(/_/g, " ")}</div>
            <div className="kv-val">{v}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- roles ----------

function AdminRoles() {
  const [roles, setRoles] = React.useState([]);
  const [companies, setCompanies] = React.useState([]);
  const [editing, setEditing] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  const reload = React.useCallback(async () => {
    const [r, c] = await Promise.all([
      window.W3J_API.apiFetch("/admin/roles"),
      window.W3J_API.apiFetch("/admin/companies"),
    ]);
    setRoles(r); setCompanies(c); setLoading(false);
  }, []);

  React.useEffect(() => { reload(); }, [reload]);
  if (loading) return <p className="lede">Loading…</p>;

  return (
    <div>
      <div className="toolbar-row">
        <h4 className="form-h" style={{ margin: 0 }}>{roles.length} roles</h4>
        <button className="btn btn--primary" onClick={() => setEditing({})}>New role <Icon.Arrow /></button>
      </div>
      <div className="role-list">
        {roles.map((r) => (
          <div className="role-card" key={r.id} onClick={() => setEditing(r)}>
            <span className="rid">{r.public_id}</span>
            <div>
              <div className="rtitle">{r.title}</div>
              <div className="rcompany">{r.company_display} · {r.remote}</div>
            </div>
            <div className="rmeta">
              {r.chain && <span className="chip">{r.chain}</span>}
              <span className={`chip ${r.status === "open" ? "chip--accent" : ""}`}>{r.status}</span>
            </div>
            <div className="rcomp"><span className="ccy">$</span>{r.min_comp_k}–{r.max_comp_k}k</div>
            <div className="rarrow"><Icon.Arrow size={12} /></div>
          </div>
        ))}
      </div>
      {editing && <RoleEditor role={editing} companies={companies} onClose={() => setEditing(null)} onSaved={reload} />}
    </div>
  );
}

const ROLE_CATEGORIES = ["Protocol", "DeFi", "Trading", "Infrastructure", "Security", "DAO", "Gaming/NFT"];
const CHAINS = ["Solana", "EVM", "Bitcoin", "Multi-chain"];
const LEVELS = ["Mid", "Senior", "Lead", "Staff", "Director"];

function RoleEditor({ role, companies, onClose, onSaved }) {
  const isNew = !role.id;
  const [form, setForm] = React.useState({
    public_id: role.public_id || "",
    company_id: role.company_id || (companies[0]?.id || ""),
    title: role.title || "",
    category: role.category || ROLE_CATEGORIES[0],
    chain: role.chain || "",
    stack: (role.stack || []).join(", "),
    type: role.type || "Full-time",
    level: role.level || LEVELS[1],
    remote: role.remote || "Remote · Global",
    min_comp_k: role.min_comp_k ?? 0,
    max_comp_k: role.max_comp_k ?? 0,
    description: role.description || "",
    requirements: (role.requirements || []).join("\n"),
    offer: (role.offer || []).join("\n"),
    status: role.status || "draft",
  });
  const [questions, setQuestions] = React.useState(role.questions || []);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState("");

  const set = (k) => (e) => setForm((f) => ({ ...f, [k]: e.target.value }));

  const submit = async (e) => {
    e.preventDefault();
    setBusy(true); setErr("");
    try {
      const body = {
        ...form,
        chain: form.chain || null,
        min_comp_k: Number(form.min_comp_k),
        max_comp_k: Number(form.max_comp_k),
        stack: form.stack.split(",").map((s) => s.trim()).filter(Boolean),
        requirements: form.requirements.split("\n").map((s) => s.trim()).filter(Boolean),
        offer: form.offer.split("\n").map((s) => s.trim()).filter(Boolean),
        questions: questions.filter((q) => q.label?.trim()),
      };
      if (isNew) {
        await window.W3J_API.apiFetch("/admin/roles", { method: "POST", body });
      } else {
        const { public_id, company_id, ...patch } = body;
        await window.W3J_API.apiFetch(`/admin/roles/${role.id}`, { method: "PATCH", body: patch });
      }
      onSaved(); onClose();
    } catch (ex) {
      setErr(ex.message || "Save failed");
    } finally {
      setBusy(false);
    }
  };

  const remove = async () => {
    if (!confirm("Delete this role? Applications will be deleted too.")) return;
    await window.W3J_API.apiFetch(`/admin/roles/${role.id}`, { method: "DELETE" });
    onSaved(); onClose();
  };

  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal modal--wide" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3 className="h3">{isNew ? "New role" : `Edit ${role.public_id}`}</h3>
          <button className="modal-close" onClick={onClose}><Icon.Close /></button>
        </div>
        <form className="modal-body" onSubmit={submit}>
          <div className="field-row">
            <label className="field"><span className="field-label">Public ID</span>
              <input value={form.public_id} onChange={set("public_id")} required disabled={!isNew} placeholder="W3J-0500" /></label>
            <label className="field"><span className="field-label">Status</span>
              <select value={form.status} onChange={set("status")}>
                {ROLE_STATUSES.map((s) => <option key={s} value={s}>{s}</option>)}
              </select></label>
          </div>
          <label className="field"><span className="field-label">Title</span>
            <input value={form.title} onChange={set("title")} required /></label>
          <label className="field"><span className="field-label">Company</span>
            <select value={form.company_id} onChange={set("company_id")} required disabled={!isNew}>
              {companies.map((c) => <option key={c.id} value={c.id}>{c.name} — {c.public_display}</option>)}
            </select></label>
          <div className="field-row three">
            <label className="field"><span className="field-label">Category</span>
              <input list="role-categories" value={form.category} onChange={set("category")} required placeholder="Pick one or type your own" />
              <datalist id="role-categories">
                {ROLE_CATEGORIES.map((c) => <option key={c} value={c} />)}
              </datalist></label>
            <label className="field"><span className="field-label">Chain (optional)</span>
              <select value={form.chain} onChange={set("chain")}>
                <option value="">—</option>
                {CHAINS.map((c) => <option key={c} value={c}>{c}</option>)}
              </select></label>
            <label className="field"><span className="field-label">Level</span>
              <select value={form.level} onChange={set("level")}>
                {LEVELS.map((c) => <option key={c} value={c}>{c}</option>)}
              </select></label>
          </div>
          <label className="field"><span className="field-label">Stack (comma-separated)</span>
            <input value={form.stack} onChange={set("stack")} placeholder="Rust, Anchor, SPL" /></label>
          <div className="field-row">
            <label className="field"><span className="field-label">Type</span>
              <input value={form.type} onChange={set("type")} /></label>
            <label className="field"><span className="field-label">Location</span>
              <input value={form.remote} onChange={set("remote")} placeholder="Remote · Global" /></label>
          </div>
          <div className="field-row">
            <label className="field"><span className="field-label">Min comp ($k)</span>
              <input type="number" min="0" value={form.min_comp_k} onChange={set("min_comp_k")} /></label>
            <label className="field"><span className="field-label">Max comp ($k)</span>
              <input type="number" min="0" value={form.max_comp_k} onChange={set("max_comp_k")} /></label>
          </div>
          <label className="field"><span className="field-label">Description</span>
            <textarea rows={4} value={form.description} onChange={set("description")} /></label>
          <label className="field"><span className="field-label">Requirements (one per line)</span>
            <textarea rows={4} value={form.requirements} onChange={set("requirements")} /></label>
          <label className="field"><span className="field-label">Offer (one per line)</span>
            <textarea rows={4} value={form.offer} onChange={set("offer")} /></label>

          <QuestionsBuilder questions={questions} onChange={setQuestions} />

          {err && <div className="form-error">{err}</div>}
          <div className="form-actions">
            <button type="submit" className="btn btn--primary" disabled={busy}>{busy ? "…" : "Save"} <Icon.Arrow /></button>
            {!isNew && <button type="button" className="btn btn--ghost" onClick={remove}>Delete</button>}
          </div>
        </form>
      </div>
    </div>
  );
}

function QuestionsBuilder({ questions, onChange }) {
  const add = () => onChange([...questions, {
    id: "q_" + Math.random().toString(36).slice(2, 10),
    label: "", type: "text", required: false,
  }]);
  const update = (i, patch) => onChange(questions.map((q, idx) => idx === i ? { ...q, ...patch } : q));
  const remove = (i) => onChange(questions.filter((_, idx) => idx !== i));

  return (
    <div className="qb">
      <div className="qb-head">
        <h5 className="form-h" style={{ margin: 0 }}>Custom application questions</h5>
        <button type="button" className="btn btn--ghost" onClick={add} style={{ padding: "6px 12px" }}>+ Add question</button>
      </div>
      <p className="body" style={{ margin: "4px 0 12px" }}>
        Default fields (name, email, LinkedIn, X, location, expected comp, CV) are always shown to candidates.
        Add any role-specific extras here.
      </p>
      {questions.length === 0 ? (
        <div className="qb-empty">No custom questions.</div>
      ) : (
        questions.map((q, i) => (
          <div key={q.id} className="qb-row">
            <input
              className="qb-label"
              value={q.label} placeholder="Question label"
              onChange={(e) => update(i, { label: e.target.value })}
            />
            <select className="jb-select" value={q.type} onChange={(e) => update(i, { type: e.target.value })}>
              <option value="text">Short text</option>
              <option value="textarea">Long text</option>
              <option value="url">URL</option>
              <option value="number">Number</option>
            </select>
            <label className="qb-req">
              <input type="checkbox" checked={q.required} onChange={(e) => update(i, { required: e.target.checked })} />
              Required
            </label>
            <button type="button" className="btn btn--quiet" onClick={() => remove(i)} title="Remove" style={{ padding: 6 }}>
              <Icon.Close />
            </button>
          </div>
        ))
      )}
    </div>
  );
}

// ---------- applications ----------

function AdminApplications() {
  const [apps, setApps] = React.useState([]);
  const [roles, setRoles] = React.useState({});
  const [statusFilter, setStatusFilter] = React.useState("");
  const [loading, setLoading] = React.useState(true);
  const [expanded, setExpanded] = React.useState(null);

  React.useEffect(() => {
    (async () => {
      const qs = statusFilter ? `?status=${statusFilter}` : "";
      const a = await window.W3J_API.apiFetch(`/admin/applications${qs}`);
      setApps(a);
      const ids = [...new Set(a.map((x) => x.role_id))];
      const fetched = await Promise.all(ids.map((id) => window.W3J_API.apiFetch(`/roles/${id}`).catch(() => null)));
      const map = {};
      fetched.forEach((r) => { if (r) map[r.id] = r; });
      setRoles(map);
      setLoading(false);
    })();
  }, [statusFilter]);

  const updateStatus = async (id, status) => {
    const updated = await window.W3J_API.apiFetch(`/admin/applications/${id}`, { method: "PATCH", body: { status } });
    setApps(apps.map((a) => (a.id === id ? updated : a)));
  };

  if (loading) return <p className="lede">Loading…</p>;

  return (
    <div>
      <div className="toolbar-row">
        <h4 className="form-h" style={{ margin: 0 }}>{apps.length} applications</h4>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <select value={statusFilter} onChange={(e) => setStatusFilter(e.target.value)} className="jb-select">
            <option value="">All statuses</option>
            {APP_STATUSES.map((s) => <option key={s} value={s}>{s}</option>)}
          </select>
          <DownloadCsvBtn path="/admin/applications/export.csv" label="Export CSV" />
        </div>
      </div>
      <div className="admin-table">
        <div className="admin-tr admin-tr--head">
          <div>Applied</div><div>Role</div><div>Candidate</div><div>Status</div><div></div>
        </div>
        {apps.map((a) => {
          const r = roles[a.role_id];
          const isOpen = expanded === a.id;
          return (
            <React.Fragment key={a.id}>
              <div className="admin-tr">
                <div className="mono small">{new Date(a.created_at).toLocaleDateString()}</div>
                <div>
                  <div>{r?.title || "—"}</div>
                  <div className="mono small">{r?.public_id} · {r?.company_display}</div>
                </div>
                <div>
                  <div>{a.full_name || "—"}</div>
                  <div className="mono small">{a.email || a.candidate_id.slice(0, 8) + "…"}</div>
                </div>
                <div>
                  <select value={a.status} onChange={(e) => updateStatus(a.id, e.target.value)} className="jb-select">
                    {APP_STATUSES.map((s) => <option key={s} value={s}>{s}</option>)}
                  </select>
                </div>
                <div>
                  <button className="btn btn--quiet" style={{ padding: 6 }} onClick={() => setExpanded(isOpen ? null : a.id)}>
                    {isOpen ? "Hide" : "Details"}
                  </button>
                </div>
              </div>
              {isOpen && <ApplicationDetail app={a} />}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

function ApplicationDetail({ app }) {
  const fields = [
    ["Location", app.location],
    ["Expected comp", app.expected_comp],
    ["LinkedIn", app.linkedin_url],
    ["X / Twitter", app.twitter_url],
  ].filter(([, v]) => v);

  const viewResume = async () => {
    try {
      const { download_url } = await window.W3J_API.apiFetch(`/uploads/application/${app.id}/resume/url`);
      window.open(download_url, "_blank", "noopener");
    } catch (ex) {
      alert(ex.message || "Resume not available");
    }
  };

  return (
    <div className="app-detail">
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
        <div className="form-h" style={{ margin: 0 }}>Application detail</div>
        <button type="button" className="btn btn--ghost" onClick={viewResume}>View resume <Icon.Arrow /></button>
      </div>
      {fields.length > 0 && (
        <div className="kv-grid">
          {fields.map(([k, v]) => (
            <div className="kv" key={k}>
              <div className="kv-key">{k}</div>
              <div className="kv-val" style={{ fontSize: 14, fontWeight: 400, wordBreak: "break-word" }}>
                {String(v).startsWith("http") ? <a href={v} target="_blank" rel="noopener noreferrer">{v}</a> : v}
              </div>
            </div>
          ))}
        </div>
      )}
      {Object.entries(app.answers || {}).length > 0 && (
        <div className="app-detail-long">
          <div className="form-h">Custom question answers</div>
          {Object.entries(app.answers || {}).map(([qid, ans]) => (
            <div key={qid} style={{ marginTop: 12 }}>
              <div className="mono small" style={{ color: "var(--fg-faint)" }}>{qid}</div>
              <p style={{ whiteSpace: "pre-wrap", color: "var(--fg-dim)", margin: "4px 0 0" }}>{ans}</p>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function DownloadCsvBtn({ path, label }) {
  const onClick = async () => {
    const url = (window.W3J_API.API_BASE || "/api") + path;
    const r = await fetch(url, { headers: { Authorization: `Bearer ${window.W3J_API.tokens.access}` } });
    if (!r.ok) { alert("Export failed"); return; }
    const blob = await r.blob();
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = path.split("/").pop().replace(".csv", "") + ".csv";
    a.click();
    URL.revokeObjectURL(a.href);
  };
  return <button type="button" className="btn btn--ghost" onClick={onClick}>{label} <Icon.Arrow /></button>;
}

// ---------- candidates ----------

function AdminCandidates() {
  const [rows, setRows] = React.useState([]);
  const [filter, setFilter] = React.useState("");
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    const qs = filter ? `?open_to_offers=${filter}` : "";
    window.W3J_API.apiFetch(`/admin/candidates${qs}`).then((r) => { setRows(r); setLoading(false); });
  }, [filter]);

  if (loading) return <p className="lede">Loading…</p>;

  const viewResume = async (user_id) => {
    try {
      const { download_url } = await window.W3J_API.apiFetch(`/uploads/resume/${user_id}/url`);
      window.open(download_url, "_blank", "noopener");
    } catch (ex) {
      alert(ex.message || "Resume not available");
    }
  };

  return (
    <div>
      <div className="toolbar-row">
        <h4 className="form-h" style={{ margin: 0 }}>{rows.length} candidates</h4>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <select value={filter} onChange={(e) => setFilter(e.target.value)} className="jb-select">
            <option value="">All statuses</option>
            <option value="actively_looking">Actively looking</option>
            <option value="open">Open to offers</option>
            <option value="passive">Passive</option>
            <option value="closed">Not looking</option>
          </select>
          <DownloadCsvBtn path="/admin/candidates/export.csv" label="Export CSV" />
        </div>
      </div>
      <div className="admin-table">
        <div className="admin-tr admin-tr--head">
          <div>Name</div><div>Headline</div><div>Seniority</div><div>Chains</div><div>Status</div>
        </div>
        {rows.map((r) => (
          <div className="admin-tr" key={r.user_id}>
            <div>
              <div>{r.full_name}</div>
              <button onClick={() => viewResume(r.user_id)} className="link-btn">View resume →</button>
            </div>
            <div className="mono small">{r.headline || "—"}</div>
            <div className="mono small">{r.seniority || "—"}</div>
            <div className="mono small">{(r.chains || []).join(", ") || "—"}</div>
            <div><span className="chip">{r.open_to_offers.replace(/_/g, " ")}</span></div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- companies ----------

function AdminCompanies() {
  const [rows, setRows] = React.useState([]);
  const [editing, setEditing] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  const reload = React.useCallback(() => {
    window.W3J_API.apiFetch("/admin/companies").then((r) => { setRows(r); setLoading(false); });
  }, []);

  React.useEffect(() => { reload(); }, [reload]);
  if (loading) return <p className="lede">Loading…</p>;

  return (
    <div>
      <div className="toolbar-row">
        <h4 className="form-h" style={{ margin: 0 }}>{rows.length} companies</h4>
        <button className="btn btn--primary" onClick={() => setEditing({})}>New company <Icon.Arrow /></button>
      </div>
      <div className="admin-table">
        <div className="admin-tr admin-tr--head">
          <div>Name</div><div>Public display</div><div>Category</div><div>Chain</div><div></div>
        </div>
        {rows.map((c) => (
          <div className="admin-tr admin-tr--clickable" key={c.id} onClick={() => setEditing(c)}>
            <div>{c.name}</div>
            <div className="mono small">{c.public_display}</div>
            <div className="mono small">{c.category || "—"}</div>
            <div className="mono small">{c.chain || "—"}</div>
            <div><Icon.Arrow size={12} /></div>
          </div>
        ))}
      </div>
      {editing && <CompanyEditor company={editing} onClose={() => setEditing(null)} onSaved={reload} />}
    </div>
  );
}

function CompanyEditor({ company, onClose, onSaved }) {
  const isNew = !company.id;
  const [form, setForm] = React.useState({
    name: company.name || "",
    public_display: company.public_display || "",
    category: company.category || "",
    chain: company.chain || "",
    description: company.description || "",
  });
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState("");
  const set = (k) => (e) => setForm((f) => ({ ...f, [k]: e.target.value }));

  const submit = async (e) => {
    e.preventDefault();
    setBusy(true); setErr("");
    try {
      if (isNew) await window.W3J_API.apiFetch("/admin/companies", { method: "POST", body: form });
      else await window.W3J_API.apiFetch(`/admin/companies/${company.id}`, { method: "PATCH", body: form });
      onSaved(); onClose();
    } catch (ex) {
      setErr(ex.message);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3 className="h3">{isNew ? "New company" : "Edit company"}</h3>
          <button className="modal-close" onClick={onClose}><Icon.Close /></button>
        </div>
        <form className="modal-body" onSubmit={submit}>
          <label className="field"><span className="field-label">Name (internal)</span>
            <input value={form.name} onChange={set("name")} required /></label>
          <label className="field"><span className="field-label">Public display (anonymized)</span>
            <input value={form.public_display} onChange={set("public_display")} required placeholder="Tier-1 DeFi protocol" /></label>
          <div className="field-row">
            <label className="field"><span className="field-label">Category</span>
              <input value={form.category} onChange={set("category")} /></label>
            <label className="field"><span className="field-label">Chain</span>
              <input value={form.chain} onChange={set("chain")} /></label>
          </div>
          <label className="field"><span className="field-label">Description (internal)</span>
            <textarea rows={4} value={form.description} onChange={set("description")} /></label>
          {err && <div className="form-error">{err}</div>}
          <button type="submit" className="btn btn--primary" disabled={busy}>{busy ? "…" : "Save"} <Icon.Arrow /></button>
        </form>
      </div>
    </div>
  );
}

function InviteModal({ onClose }) {
  const [email, setEmail] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [msg, setMsg] = React.useState("");
  const [err, setErr] = React.useState("");

  const submit = async (e) => {
    e.preventDefault();
    setBusy(true); setErr(""); setMsg("");
    try {
      await window.W3J_API.apiFetch("/auth/invite", { method: "POST", body: { email } });
      setMsg(`Invite sent to ${email}. Check the email (or the API server logs in dev mode) for the accept link.`);
      setEmail("");
    } catch (ex) {
      setErr(ex.message);
    } finally { setBusy(false); }
  };

  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3 className="h3">Invite recruiter</h3>
          <button className="modal-close" onClick={onClose}><Icon.Close /></button>
        </div>
        <form className="modal-body" onSubmit={submit}>
          <p className="body" style={{ margin: 0 }}>
            Send an invite to a new recruiter. They'll get an email with a one-time link to set their password.
          </p>
          <label className="field"><span className="field-label">Email</span>
            <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required autoFocus /></label>
          {err && <div className="form-error">{err}</div>}
          {msg && <div className="form-warn">{msg}</div>}
          <button type="submit" className="btn btn--primary" disabled={busy}>
            {busy ? "Sending…" : "Send invite"} <Icon.Arrow />
          </button>
        </form>
      </div>
    </div>
  );
}

window.RecruiterDashboard = RecruiterDashboard;
