/* CTO peer-review widgets — interactive controls specific to the engineering track. Skill matrix, sortable priorities, code-diff rating, slider scales, tag picker, stack tags, "would you ship this" yes/no with explanation, etc. */ const { useState: ctoUseState, useRef: ctoUseRef, useEffect: ctoUseEffect } = React; // ─── Skill matrix: rate me on 5 axes (slider 1–5) ───────────────────── function SkillMatrix({ skills, value = {}, onChange }) { const labels = ['—', '1', '2', '3', '4', '5']; const captions = (n) => n === 0 ? '· · ·' : n === 1 ? 'junior' : n === 2 ? 'developing' : n === 3 ? 'solid' : n === 4 ? 'strong' : 'staff-level'; return (
{skills.map(s => { const v = value[s.key] ?? 0; return (
{s.label}
{s.hint}
{[1,2,3,4,5].map(n => (
); })}
); } // ─── Sortable priorities ────────────────────────────────────────────── function SortablePriorities({ items, value, onChange }) { const ordered = value && value.length === items.length ? value : items.slice(); const [drag, setDrag] = ctoUseState(null); const move = (from, to) => { if (from === to) return; const arr = ordered.slice(); const [m] = arr.splice(from, 1); arr.splice(to, 0, m); onChange(arr); }; return (
// drag to reorder · top = matters most
{ordered.map((item, idx) => (
setDrag(idx)} onDragEnd={() => setDrag(null)} onDragOver={(e) => { e.preventDefault(); }} onDrop={() => { if (drag != null) move(drag, idx); setDrag(null); }} >
{String(idx + 1).padStart(2, '0')}
⋮⋮
{item}
))}
); } // ─── Slider scale (1–10) with named ends ────────────────────────────── function SliderScale({ value, onChange, lowLabel, highLabel, leftWord, rightWord }) { const v = value ?? 5; return (
{leftWord}{rightWord}
onChange(Number(e.target.value))} />
{v}
1 — {lowLabel} {highLabel} — 10
); } // ─── Code diff: which version is better? ───────────────────────────── function CodeDiffPick({ samples, value, onChange, t }) { return (
{samples.map((s, i) => ( ))}
); } // ─── Yes / No with required reason ─────────────────────────────────── function YesNoWithReason({ value = {}, onChange, yesLabel, noLabel, reasonPlaceholder }) { return (
{value.choice && (