Fix criteria validation using wrong form + fix reports page null crash
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m38s
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m38s
1. Evaluation submit: The requireAllCriteriaScored validation was
querying findFirst({ roundId, isActive: true }) to get the form
criteria, instead of using the evaluation's stored formId. If an
admin ever re-saved the evaluation form (creating a new version
with new criterion IDs), jurors who started evaluating before the
re-save had scores keyed to old IDs that didn't match the new
form. Now uses evaluation.form (the form assigned at start time).
2. Observer reports page: Two .map() calls on p.stages lacked null
guards, causing "Cannot read properties of null (reading 'map')"
crash. Added (p.stages || []) guards matching the pattern already
used in CrossStageTab.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -77,7 +77,7 @@ function OverviewTab({ selectedValue }: { selectedValue: string | null }) {
|
|||||||
const { data: programs, isLoading } = trpc.program.list.useQuery({ includeStages: true })
|
const { data: programs, isLoading } = trpc.program.list.useQuery({ includeStages: true })
|
||||||
|
|
||||||
const stages = programs?.flatMap(p =>
|
const stages = programs?.flatMap(p =>
|
||||||
(p.stages as { id: string; name: string; status: string; roundType: string; windowCloseAt: Date | null; _count: { projects: number; assignments: number } }[]).map(s => ({
|
((p.stages || []) as { id: string; name: string; status: string; roundType: string; windowCloseAt: Date | null; _count: { projects: number; assignments: number } }[]).map(s => ({
|
||||||
...s,
|
...s,
|
||||||
programName: `${p.year} Edition`,
|
programName: `${p.year} Edition`,
|
||||||
}))
|
}))
|
||||||
@@ -598,7 +598,7 @@ export default function ObserverReportsPage() {
|
|||||||
const { data: programs, isLoading: stagesLoading } = trpc.program.list.useQuery({ includeStages: true })
|
const { data: programs, isLoading: stagesLoading } = trpc.program.list.useQuery({ includeStages: true })
|
||||||
|
|
||||||
const stages = programs?.flatMap(p =>
|
const stages = programs?.flatMap(p =>
|
||||||
(p.stages as { id: string; name: string; status: string; roundType: string; windowCloseAt: Date | null; _count: { projects: number; assignments: number } }[]).map(s => ({
|
((p.stages || []) as { id: string; name: string; status: string; roundType: string; windowCloseAt: Date | null; _count: { projects: number; assignments: number } }[]).map(s => ({
|
||||||
...s,
|
...s,
|
||||||
programId: p.id,
|
programId: p.id,
|
||||||
programName: `${p.year} Edition`,
|
programName: `${p.year} Edition`,
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ export const evaluationRouter = router({
|
|||||||
where: { id },
|
where: { id },
|
||||||
include: {
|
include: {
|
||||||
assignment: true,
|
assignment: true,
|
||||||
|
form: { select: { criteriaJson: true } },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -231,11 +232,11 @@ export const evaluationRouter = router({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fix 5: requireAllCriteriaScored validation
|
// Fix 5: requireAllCriteriaScored validation
|
||||||
|
// Use the form the juror was assigned (evaluation.form), NOT the current active form.
|
||||||
|
// If the admin re-saves the form, criterion IDs change — jurors who started before
|
||||||
|
// the re-save would have scores keyed to old IDs that don't match the new form.
|
||||||
if (config.requireAllCriteriaScored && scoringMode === 'criteria') {
|
if (config.requireAllCriteriaScored && scoringMode === 'criteria') {
|
||||||
const evalForm = await ctx.prisma.evaluationForm.findFirst({
|
const evalForm = evaluation.form
|
||||||
where: { roundId: round.id, isActive: true },
|
|
||||||
select: { criteriaJson: true },
|
|
||||||
})
|
|
||||||
if (evalForm?.criteriaJson) {
|
if (evalForm?.criteriaJson) {
|
||||||
const criteria = evalForm.criteriaJson as Array<{ id: string; label?: string; type?: string; required?: boolean }>
|
const criteria = evalForm.criteriaJson as Array<{ id: string; label?: string; type?: string; required?: boolean }>
|
||||||
const scorableCriteria = criteria.filter(
|
const scorableCriteria = criteria.filter(
|
||||||
|
|||||||
Reference in New Issue
Block a user