Pipeline UX: clickable cards, wizard edit, routing rules redesign, category quotas
All checks were successful
Build and Push Docker Image / build (push) Successful in 18s
All checks were successful
Build and Push Docker Image / build (push) Successful in 18s
- Simplify pipeline list cards: whole card is clickable, remove clutter - Add wizard edit page for existing pipelines with full state pre-population - Extract toWizardTrackConfig to shared utility for reuse - Rewrite predicate builder with 3 modes: Simple (sentence-style), AI (NLP), Advanced (JSON) - Fix routing operators to match backend (eq/neq/in/contains/gt/lt) - Rewrite routing rules editor with collapsible cards and natural language summaries - Add parseNaturalLanguageRule AI procedure for routing rules - Add per-category quotas to SelectionConfig and EvaluationConfig - Add category quota UI toggles to selection and assignment sections - Add category breakdown display to selection panel - Add category-aware scoring to smart assignment (penalty/bonus) - Add category-aware filtering targets with excess demotion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
67
src/lib/pipeline-conversions.ts
Normal file
67
src/lib/pipeline-conversions.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { normalizeStageConfig } from '@/lib/stage-config-schema'
|
||||
import type { WizardTrackConfig } from '@/types/pipeline-wizard'
|
||||
|
||||
type TrackInput = {
|
||||
id: string
|
||||
name: string
|
||||
slug: string
|
||||
kind: 'MAIN' | 'AWARD' | 'SHOWCASE'
|
||||
sortOrder: number
|
||||
routingMode: 'PARALLEL' | 'EXCLUSIVE' | 'POST_MAIN' | null
|
||||
decisionMode:
|
||||
| 'JURY_VOTE'
|
||||
| 'AWARD_MASTER_DECISION'
|
||||
| 'ADMIN_DECISION'
|
||||
| null
|
||||
stages: Array<{
|
||||
id: string
|
||||
name: string
|
||||
slug: string
|
||||
stageType:
|
||||
| 'INTAKE'
|
||||
| 'FILTER'
|
||||
| 'EVALUATION'
|
||||
| 'SELECTION'
|
||||
| 'LIVE_FINAL'
|
||||
| 'RESULTS'
|
||||
sortOrder: number
|
||||
configJson: unknown
|
||||
}>
|
||||
specialAward?: {
|
||||
name: string
|
||||
description: string | null
|
||||
scoringMode: 'PICK_WINNER' | 'RANKED' | 'SCORED'
|
||||
} | null
|
||||
}
|
||||
|
||||
export function toWizardTrackConfig(track: TrackInput): WizardTrackConfig {
|
||||
return {
|
||||
id: track.id,
|
||||
name: track.name,
|
||||
slug: track.slug,
|
||||
kind: track.kind,
|
||||
sortOrder: track.sortOrder,
|
||||
routingModeDefault: track.routingMode ?? undefined,
|
||||
decisionMode: track.decisionMode ?? undefined,
|
||||
stages: track.stages
|
||||
.map((stage) => ({
|
||||
id: stage.id,
|
||||
name: stage.name,
|
||||
slug: stage.slug,
|
||||
stageType: stage.stageType,
|
||||
sortOrder: stage.sortOrder,
|
||||
configJson: normalizeStageConfig(
|
||||
stage.stageType,
|
||||
stage.configJson as Record<string, unknown> | null
|
||||
),
|
||||
}))
|
||||
.sort((a, b) => a.sortOrder - b.sortOrder),
|
||||
awardConfig: track.specialAward
|
||||
? {
|
||||
name: track.specialAward.name,
|
||||
description: track.specialAward.description ?? undefined,
|
||||
scoringMode: track.specialAward.scoringMode,
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,8 @@ export function defaultSelectionConfig(): SelectionConfig {
|
||||
finalistCount: undefined,
|
||||
rankingMethod: 'score_average',
|
||||
tieBreaker: 'admin_decides',
|
||||
categoryQuotasEnabled: false,
|
||||
categoryQuotas: { STARTUP: 3, BUSINESS_CONCEPT: 3 },
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user