diff --git a/src/app/(admin)/admin/rounds/pipeline/[id]/edit/page.tsx b/src/app/(admin)/admin/rounds/pipeline/[id]/edit/page.tsx
index 9bd33e4..ceb5cf5 100644
--- a/src/app/(admin)/admin/rounds/pipeline/[id]/edit/page.tsx
+++ b/src/app/(admin)/admin/rounds/pipeline/[id]/edit/page.tsx
@@ -187,10 +187,10 @@ export default function EditPipelinePage() {
const evalStage = mainTrack?.stages.find((s) => s.stageType === 'EVALUATION')
const liveStage = mainTrack?.stages.find((s) => s.stageType === 'LIVE_FINAL')
- const intakeConfig = (intakeStage?.configJson ?? defaultIntakeConfig()) as unknown as IntakeConfig
- const filterConfig = (filterStage?.configJson ?? defaultFilterConfig()) as unknown as FilterConfig
- const evalConfig = (evalStage?.configJson ?? defaultEvaluationConfig()) as unknown as EvaluationConfig
- const liveConfig = (liveStage?.configJson ?? defaultLiveConfig()) as unknown as LiveFinalConfig
+ const intakeConfig = { ...defaultIntakeConfig(), ...(intakeStage?.configJson ?? {}) } as IntakeConfig
+ const filterConfig = { ...defaultFilterConfig(), ...(filterStage?.configJson ?? {}) } as FilterConfig
+ const evalConfig = { ...defaultEvaluationConfig(), ...(evalStage?.configJson ?? {}) } as EvaluationConfig
+ const liveConfig = { ...defaultLiveConfig(), ...(liveStage?.configJson ?? {}) } as LiveFinalConfig
const basicsValid = validateBasics(state).valid
const tracksValid = validateTracks(state.tracks).valid
diff --git a/src/components/admin/pipeline/sections/assignment-section.tsx b/src/components/admin/pipeline/sections/assignment-section.tsx
index e2b4c83..af68014 100644
--- a/src/components/admin/pipeline/sections/assignment-section.tsx
+++ b/src/components/admin/pipeline/sections/assignment-section.tsx
@@ -32,7 +32,7 @@ export function AssignmentSection({ config, onChange, isActive }: AssignmentSect
type="number"
min={1}
max={20}
- value={config.requiredReviews}
+ value={config.requiredReviews ?? 3}
disabled={isActive}
onChange={(e) =>
updateConfig({ requiredReviews: parseInt(e.target.value) || 3 })
@@ -49,7 +49,7 @@ export function AssignmentSection({ config, onChange, isActive }: AssignmentSect
type="number"
min={1}
max={100}
- value={config.maxLoadPerJuror}
+ value={config.maxLoadPerJuror ?? 20}
disabled={isActive}
onChange={(e) =>
updateConfig({ maxLoadPerJuror: parseInt(e.target.value) || 20 })
@@ -66,7 +66,7 @@ export function AssignmentSection({ config, onChange, isActive }: AssignmentSect
type="number"
min={0}
max={50}
- value={config.minLoadPerJuror}
+ value={config.minLoadPerJuror ?? 5}
disabled={isActive}
onChange={(e) =>
updateConfig({ minLoadPerJuror: parseInt(e.target.value) || 5 })
@@ -78,7 +78,7 @@ export function AssignmentSection({ config, onChange, isActive }: AssignmentSect
- {config.minLoadPerJuror > config.maxLoadPerJuror && (
+ {(config.minLoadPerJuror ?? 0) > (config.maxLoadPerJuror ?? 20) && (
Min load per juror cannot exceed max load per juror.
@@ -92,7 +92,7 @@ export function AssignmentSection({ config, onChange, isActive }: AssignmentSect
updateConfig({ availabilityWeighting: checked })
}
@@ -103,7 +103,7 @@ export function AssignmentSection({ config, onChange, isActive }: AssignmentSect
- {config.rules.map((rule, index) => (
+ {rules.map((rule, index) => (
@@ -116,7 +118,7 @@ export function FilteringSection({ config, onChange, isActive }: FilteringSectio
))}
- {config.rules.length === 0 && (
+ {rules.length === 0 && (
No gate rules configured. All projects will pass through.
@@ -145,11 +147,11 @@ export function FilteringSection({ config, onChange, isActive }: FilteringSectio
updateConfig({
aiConfidenceThresholds: {
- ...config.aiConfidenceThresholds,
+ ...(config.aiConfidenceThresholds ?? { high: 0.85, medium: 0.6, low: 0.4 }),
high: v / 100,
},
})
@@ -160,7 +162,7 @@ export function FilteringSection({ config, onChange, isActive }: FilteringSectio
className="flex-1"
/>
- {Math.round(config.aiConfidenceThresholds.high * 100)}%
+ {Math.round((config.aiConfidenceThresholds?.high ?? 0.85) * 100)}%
@@ -168,11 +170,11 @@ export function FilteringSection({ config, onChange, isActive }: FilteringSectio
updateConfig({
aiConfidenceThresholds: {
- ...config.aiConfidenceThresholds,
+ ...(config.aiConfidenceThresholds ?? { high: 0.85, medium: 0.6, low: 0.4 }),
medium: v / 100,
},
})
@@ -183,7 +185,7 @@ export function FilteringSection({ config, onChange, isActive }: FilteringSectio
className="flex-1"
/>
- {Math.round(config.aiConfidenceThresholds.medium * 100)}%
+ {Math.round((config.aiConfidenceThresholds?.medium ?? 0.6) * 100)}%
diff --git a/src/components/admin/pipeline/sections/intake-section.tsx b/src/components/admin/pipeline/sections/intake-section.tsx
index b28c137..e3ad915 100644
--- a/src/components/admin/pipeline/sections/intake-section.tsx
+++ b/src/components/admin/pipeline/sections/intake-section.tsx
@@ -26,8 +26,10 @@ export function IntakeSection({ config, onChange, isActive }: IntakeSectionProps
onChange({ ...config, ...updates })
}
+ const fileRequirements = config.fileRequirements ?? []
+
const updateFileReq = (index: number, updates: Partial) => {
- const updated = [...config.fileRequirements]
+ const updated = [...fileRequirements]
updated[index] = { ...updated[index], ...updates }
onChange({ ...config, fileRequirements: updated })
}
@@ -36,7 +38,7 @@ export function IntakeSection({ config, onChange, isActive }: IntakeSectionProps
onChange({
...config,
fileRequirements: [
- ...config.fileRequirements,
+ ...fileRequirements,
{
name: '',
description: '',
@@ -49,7 +51,7 @@ export function IntakeSection({ config, onChange, isActive }: IntakeSectionProps
}
const removeFileReq = (index: number) => {
- const updated = config.fileRequirements.filter((_, i) => i !== index)
+ const updated = fileRequirements.filter((_, i) => i !== index)
onChange({ ...config, fileRequirements: updated })
}
@@ -71,7 +73,7 @@ export function IntakeSection({ config, onChange, isActive }: IntakeSectionProps
updateConfig({ submissionWindowEnabled: checked })
}
@@ -85,7 +87,7 @@ export function IntakeSection({ config, onChange, isActive }: IntakeSectionProps
- {config.lateSubmissionPolicy === 'flag' && (
+ {(config.lateSubmissionPolicy ?? 'flag') === 'flag' && (
updateConfig({ lateGraceHours: parseInt(e.target.value) || 0 })
}
@@ -130,13 +132,13 @@ export function IntakeSection({ config, onChange, isActive }: IntakeSectionProps
- {config.fileRequirements.length === 0 && (
+ {fileRequirements.length === 0 && (
No file requirements configured. Projects can be submitted without files.
)}
- {config.fileRequirements.map((req, index) => (
+ {fileRequirements.map((req, index) => (
diff --git a/src/components/admin/pipeline/sections/live-finals-section.tsx b/src/components/admin/pipeline/sections/live-finals-section.tsx
index ae8ecba..7f14057 100644
--- a/src/components/admin/pipeline/sections/live-finals-section.tsx
+++ b/src/components/admin/pipeline/sections/live-finals-section.tsx
@@ -33,7 +33,7 @@ export function LiveFinalsSection({ config, onChange, isActive }: LiveFinalsSect
updateConfig({ juryVotingEnabled: checked })
}
@@ -50,7 +50,7 @@ export function LiveFinalsSection({ config, onChange, isActive }: LiveFinalsSect
updateConfig({ audienceVotingEnabled: checked })
}
@@ -58,13 +58,13 @@ export function LiveFinalsSection({ config, onChange, isActive }: LiveFinalsSect
/>
- {config.audienceVotingEnabled && (
+ {(config.audienceVotingEnabled ?? false) && (
updateConfig({ audienceVoteWeight: v / 100 })
}
@@ -74,7 +74,7 @@ export function LiveFinalsSection({ config, onChange, isActive }: LiveFinalsSect
className="flex-1"
/>
- {Math.round(config.audienceVoteWeight * 100)}%
+ {Math.round((config.audienceVoteWeight ?? 0) * 100)}%
@@ -88,7 +88,7 @@ export function LiveFinalsSection({ config, onChange, isActive }: LiveFinalsSect