Admin Portal Integration Guide

This guide is for the Admin UI team. It covers wiring the two new evaluation endpoints (team-match and compare) into existing admin flows: candidate review, role assignment, and side-by-side compare screens.

Backend service: evaluation (port 9103, gateway-proxied).
Auth: same Bearer JWT used for the rest of the admin app. Admin scopes already work — no new role required.


1. Endpoint Cheatsheet

A. Team Match (Combined Role + Workstyle)

POST /evaluation/{id}/team-match
Authorization: Bearer <token>
Content-Type: application/json

{
  "roleId": 1,                // optional; defaults to first role linked to evaluation team
  "algorithmUserId": 4,       // optional; defaults to bridged persona.user.id
  "roleWeight": 50            // optional; 0..100, default 50
}

Response:

{
  "evaluationId": "abc-123",
  "algorithmTeamId": 1,
  "roleId": 1,
  "algorithmUserId": 4,
  "workstyle": {
    "score": 72.5,
    "scoreCategory": "high",
    "dimensions": [ /* 16 dimension results */ ]
  },
  "roleMatch": {
    "roleId": 1,
    "score": 64.2,
    "scoreCategory": "medium",
    "experienceScore": 66.0,
    "goalScore": 30.0,
    "breakdown": [
      { "name": "industry", "priority": 1, "percentageMatch": 0.5, "points": 6.5, "maxPoints": 13, "source": "experience" }
      // …
    ]
  },
  "combined": {
    "score": 68.3,
    "scoreCategory": "high",
    "roleWeight": 50
  }
}

B. Evaluation Compare

POST /evaluation/compare
Authorization: Bearer <token>
Content-Type: application/json

{
  "evaluationIdA": "abc-123",
  "evaluationIdB": "def-456",
  "mode": "MUTUAL"   // PAIRWISE | SIMULATED_TEAM | MUTUAL
}

Response:

{
  "mode": "MUTUAL",
  "evaluationIdA": "abc-123",
  "evaluationIdB": "def-456",
  "score": 71.4,
  "scoreCategory": "high",
  "reverseScore": 68.9,
  "dimensions": [ /* per-dimension results A→B */ ],
  "reverseDimensions": [ /* per-dimension results B→A; only present for MUTUAL/SIMULATED_TEAM */ ]
}

2. Where to Surface in the Admin UI

Screen 1 — Candidate Detail

When viewing a single completed evaluation:

  • Add a “Team Match” card below the existing workstyle results.
  • On mount, call POST /evaluation/{id}/team-match with no body (defaults).
  • Render three rows:
    • Combined score (large) + category badge.
    • Workstyle score (with link to the existing 16-dimension chart).
    • Role match score (collapsible — show breakdown table when expanded).
  • Add a “Adjust weighting” slider (0–100). On change, debounce 400 ms and re-call team-match with the new roleWeight. Animate the combined score update.
  • If roleMatch === null, show “No role specification linked to this team — workstyle-only match”.

Screen 2 — Role / Team Browser

When viewing a Role or Team, list candidates ranked by combined score:

  1. List evaluations for this team via GET /evaluation?personaId=…&status=complete (existing).
  2. For each, fan-out POST /evaluation/{id}/team-match (limit concurrency to 5, e.g. via p-limit).
  3. Render a sortable table — columns: candidate name, combined, workstyle, role match, time taken.
  4. Persist the roleWeight selection in URL query so it can be shared.

Screen 3 — Side-by-side Compare

New page or modal, accessed from any candidate row’s overflow menu (“Compare with…”):

  1. Picker selects a second completed evaluation.
  2. Tab/segmented control for mode (PAIRWISE / MUTUAL / SIMULATED_TEAM).
  3. Call POST /evaluation/compare and render:
    • Big circular score with category color.
    • Tabs: “Dimensions” (default) and “Reverse Dimensions” (if returned).
    • Stacked bar chart per dimension showing both A→B and B→A percentages overlayed (for MUTUAL).
  4. Default mode: PAIRWISE for “how would B fit on A’s team” semantics; switch to MUTUAL for “how compatible are they”.

3. Score Category Color Legend

Use the same palette as the existing dimension charts:

Category Range Suggested color
low < 33 #e74c3c (red)
medium 33–65 #f39c12 (amber)
high ≥ 66 #27ae60 (green)

4. Error Handling Patterns

HTTP Meaning UI Behaviour
400 Evaluation has no answers / invalid params Disable the action; show “Evaluation not yet started”.
401 Token expired Redirect to login.
404 Evaluation not found Toast + go back.
500 Server error Toast “Match failed, retry” + retry button.

5. Tips & Gotchas

  • The endpoints don’t persist anything. Call them on demand. Cache on the client (e.g. SWR/react-query) keyed by (evaluationId, roleId, roleWeight) for compare/team-match; key by (idA, idB, mode) for compare.
  • algorithmUserId bridging: if the persona record on profile-service contains a numeric user.id, leave it blank — the API resolves it automatically. If you ever see roleMatch.error: "Cannot resolve algorithmUserId for role match", it means that bridge wasn’t set; pass algorithmUserId explicitly from your candidate list.
  • No role spec? roleMatch will be null. The UI should still show the workstyle card.
  • Performance: team-match runs ~16 dimension calculators + role match (negligible). Expect <300 ms per call. Compare is similar; for MUTUAL it doubles the work.
  • Internationalisation: all text comes from your existing i18n keys; the API returns no UI copy.