feat: complete MENTORING round config form (§A)
Surfaces every MentoringConfigSchema field on the round Config tab: - Adds "Mentoring Request Window" card with mentoringRequestDeadlineDays numeric input (1-90 days, default 14) and passThroughIfNoRequest toggle (default ON; OFF holds projects PENDING until manual mentor assignment). - Adds inline help-text for the Eligibility dropdown explaining each option's effect on auto-PASS behavior. - Hides the General Settings card on MENTORING rounds (it only renders Advancement Targets, which don't apply to a pass-through round). - Relaxes the Launch Readiness "File requirements set" gate for MENTORING rounds without filePromotionEnabled + a target window — file requirements only matter when files will be promoted to a downstream submission window. Spec: docs/superpowers/specs/2026-04-28-mentor-round-readiness-design.md §A Plan: docs/superpowers/plans/2026-04-28-pr3-mentoring-config-completeness.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
# PR 3 — MENTORING Round Config Completeness (§A)
|
||||||
|
|
||||||
|
> **For agentic workers:** Use superpowers:executing-plans for inline execution.
|
||||||
|
|
||||||
|
**Goal:** Surface every `MentoringConfigSchema` field on the round Config tab; hide the empty General Settings card on MENTORING rounds; relax the "File requirements set" Launch Readiness gate when no file promotion is configured.
|
||||||
|
|
||||||
|
**Architecture:** UI-only changes. No schema, no API. Three files touched.
|
||||||
|
|
||||||
|
**Spec:** `docs/superpowers/specs/2026-04-28-mentor-round-readiness-design.md` §A.
|
||||||
|
|
||||||
|
## File map
|
||||||
|
|
||||||
|
| File | Action | Why |
|
||||||
|
|------|--------|-----|
|
||||||
|
| `src/components/admin/rounds/config/mentoring-config.tsx` | Modify | Add `mentoringRequestDeadlineDays` numeric input + `passThroughIfNoRequest` toggle; add help-text to Eligibility |
|
||||||
|
| `src/app/(admin)/admin/rounds/[roundId]/page.tsx` | Modify | Hide General Settings card when `round.roundType === 'MENTORING'`; relax File-requirements readiness gate for MENTORING rounds without file promotion configured |
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
### Task 1: Add the two missing inputs to `mentoring-config.tsx`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Patch the file** — append a new "Mentoring Request Window" card BETWEEN the existing two cards, and add help-text to Eligibility. Code in execution.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Typecheck** — `npm run typecheck`. Expect 0 errors.
|
||||||
|
|
||||||
|
### Task 2: Hide General Settings card + relax readiness on MENTORING rounds
|
||||||
|
|
||||||
|
- [ ] **Step 1: Patch `(admin)/admin/rounds/[roundId]/page.tsx`** — wrap the General Settings card in `{!isMentoring && (...)}` and extend the file-requirements bypass condition.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Typecheck + build** — confirm clean.
|
||||||
|
|
||||||
|
### Task 3: Smoke + commit
|
||||||
|
|
||||||
|
- [ ] **Step 1: `npm run build`** — confirm clean.
|
||||||
|
- [ ] **Step 2: Commit** — message references §A.
|
||||||
|
|
||||||
|
## Out of scope
|
||||||
|
|
||||||
|
Form unit tests (heavy render setup; existing config-save mutation already verified by other PRs). Manual smoke covers the UI work.
|
||||||
@@ -514,6 +514,7 @@ export default function RoundDetailPage() {
|
|||||||
|
|
||||||
const isFiltering = round?.roundType === 'FILTERING'
|
const isFiltering = round?.roundType === 'FILTERING'
|
||||||
const isEvaluation = round?.roundType === 'EVALUATION'
|
const isEvaluation = round?.roundType === 'EVALUATION'
|
||||||
|
const isMentoring = round?.roundType === 'MENTORING'
|
||||||
const hasJury = ['EVALUATION', 'LIVE_FINAL', 'DELIBERATION'].includes(round?.roundType ?? '')
|
const hasJury = ['EVALUATION', 'LIVE_FINAL', 'DELIBERATION'].includes(round?.roundType ?? '')
|
||||||
const hasAwards = roundAwards.length > 0
|
const hasAwards = roundAwards.length > 0
|
||||||
const isSimpleAdvance = ['INTAKE', 'SUBMISSION', 'MENTORING'].includes(round?.roundType ?? '')
|
const isSimpleAdvance = ['INTAKE', 'SUBMISSION', 'MENTORING'].includes(round?.roundType ?? '')
|
||||||
@@ -589,7 +590,8 @@ export default function RoundDetailPage() {
|
|||||||
action: undefined as Route | undefined,
|
action: undefined as Route | undefined,
|
||||||
actionLabel: undefined as string | undefined,
|
actionLabel: undefined as string | undefined,
|
||||||
},
|
},
|
||||||
...((isEvaluation && !(config.requireDocumentUpload as boolean))
|
...((isEvaluation && !(config.requireDocumentUpload as boolean)) ||
|
||||||
|
(isMentoring && !(config.filePromotionEnabled as boolean) && !config.promotionTargetWindowId)
|
||||||
? []
|
? []
|
||||||
: [{
|
: [{
|
||||||
label: 'File requirements set',
|
label: 'File requirements set',
|
||||||
@@ -2198,7 +2200,8 @@ export default function RoundDetailPage() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* General Round Settings */}
|
{/* General Round Settings — hidden on MENTORING rounds (no advancement targets apply) */}
|
||||||
|
{!isMentoring && (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="border-b">
|
<CardHeader className="border-b">
|
||||||
<ConfigSectionHeader
|
<ConfigSectionHeader
|
||||||
@@ -2321,6 +2324,7 @@ export default function RoundDetailPage() {
|
|||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Round-type-specific config */}
|
{/* Round-type-specific config */}
|
||||||
<RoundConfigForm
|
<RoundConfigForm
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ export function MentoringConfig({ config, onChange }: MentoringConfigProps) {
|
|||||||
<SelectItem value="admin_selected">Admin Selected</SelectItem>
|
<SelectItem value="admin_selected">Admin Selected</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
<ul className="text-xs text-muted-foreground space-y-1 mt-2">
|
||||||
|
<li><strong>All Advancing Projects</strong> — every project that enters this round is paired with a mentor.</li>
|
||||||
|
<li><strong>Requested Only</strong> — only projects that explicitly request mentoring participate (default).</li>
|
||||||
|
<li><strong>Admin Selected</strong> — admin manually picks which projects get a mentor.</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@@ -56,6 +61,46 @@ export function MentoringConfig({ config, onChange }: MentoringConfigProps) {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-base">Mentoring Request Window</CardTitle>
|
||||||
|
<CardDescription>How long teams have to request a mentor, and what happens to non-requesters</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="mentoringRequestDeadlineDays">Request deadline (days from round opening)</Label>
|
||||||
|
<p className="text-xs text-muted-foreground">After this many days, teams can no longer submit a mentoring request. Default: 14.</p>
|
||||||
|
<Input
|
||||||
|
id="mentoringRequestDeadlineDays"
|
||||||
|
type="number"
|
||||||
|
min={1}
|
||||||
|
max={90}
|
||||||
|
className="w-32"
|
||||||
|
value={(config.mentoringRequestDeadlineDays as number) ?? 14}
|
||||||
|
onChange={(e) => {
|
||||||
|
const v = parseInt(e.target.value, 10)
|
||||||
|
if (!Number.isNaN(v) && v >= 1 && v <= 90) update('mentoringRequestDeadlineDays', v)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="passThroughIfNoRequest">Auto-pass non-requesters</Label>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
When ON, projects that don't request mentoring auto-PASS to the next round (default).
|
||||||
|
When OFF, all projects are held in PENDING until the admin decides — useful when mentoring is mandatory.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
id="passThroughIfNoRequest"
|
||||||
|
checked={(config.passThroughIfNoRequest as boolean | undefined) ?? true}
|
||||||
|
onCheckedChange={(v) => update('passThroughIfNoRequest', v)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-base">Communication & Files</CardTitle>
|
<CardTitle className="text-base">Communication & Files</CardTitle>
|
||||||
|
|||||||
Reference in New Issue
Block a user