Rounds overhaul: full CRUD submission windows, scheduling UI, analytics, design refresh
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m40s

- Fix special award FK crash: replace 4x raw auditLog.create with logAudit() helper
- Add updateSubmissionWindow + deleteSubmissionWindow mutations to round router
- Add per-round analytics (_count, juryGroup) to competition.getById
- Remove redundant acceptedCategories from intake config
- Rewrite submission window manager with full CRUD, all fields, date pickers
- Add round scheduling card (open/close dates) to round detail page
- Add project count, assignment count, jury group to round list cards
- Visual redesign: pipeline view, brand colors, progress bars, enhanced cards

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 07:07:09 +01:00
parent 2fb26d4734
commit f572336781
8 changed files with 1208 additions and 414 deletions

View File

@@ -36,23 +36,11 @@ export function IntakeConfig({ config, onChange }: IntakeConfigProps) {
onChange({ ...config, [key]: value })
}
const acceptedCategories = (config.acceptedCategories as string[]) ?? ['STARTUP', 'BUSINESS_CONCEPT']
const allowedMimeTypes = (config.allowedMimeTypes as string[]) ?? ['application/pdf']
const customFields = (config.customFields as Array<{
id: string; label: string; type: string; required: boolean; options?: string[]
}>) ?? []
const toggleCategory = (cat: string) => {
const current = [...acceptedCategories]
const idx = current.indexOf(cat)
if (idx >= 0) {
current.splice(idx, 1)
} else {
current.push(cat)
}
update('acceptedCategories', current)
}
const toggleMime = (mime: string) => {
const current = [...allowedMimeTypes]
const idx = current.indexOf(mime)
@@ -141,28 +129,6 @@ export function IntakeConfig({ config, onChange }: IntakeConfigProps) {
</CardContent>
</Card>
{/* Categories */}
<Card>
<CardHeader>
<CardTitle className="text-base">Accepted Categories</CardTitle>
<CardDescription>Which project categories can submit in this round</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">
{['STARTUP', 'BUSINESS_CONCEPT'].map((cat) => (
<Badge
key={cat}
variant={acceptedCategories.includes(cat) ? 'default' : 'outline'}
className="cursor-pointer select-none"
onClick={() => toggleCategory(cat)}
>
{cat === 'STARTUP' ? 'Startup' : 'Business Concept'}
</Badge>
))}
</div>
</CardContent>
</Card>
{/* File Settings */}
<Card>
<CardHeader>