MOPC-App/src/components/admin/competition/round-config-form.tsx

249 lines
8.8 KiB
TypeScript
Raw Normal View History

'use client'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Switch } from '@/components/ui/switch'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
type RoundConfigFormProps = {
roundType: string
config: Record<string, unknown>
onChange: (config: Record<string, unknown>) => void
}
export function RoundConfigForm({ roundType, config, onChange }: RoundConfigFormProps) {
const updateConfig = (key: string, value: unknown) => {
onChange({ ...config, [key]: value })
}
if (roundType === 'INTAKE') {
return (
<Card>
<CardHeader>
<CardTitle className="text-base">Intake Configuration</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<Label htmlFor="allowDrafts">Allow Drafts</Label>
<Switch
id="allowDrafts"
checked={(config.allowDrafts as boolean) ?? true}
onCheckedChange={(checked) => updateConfig('allowDrafts', checked)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="draftExpiryDays">Draft Expiry (days)</Label>
<Input
id="draftExpiryDays"
type="number"
min={1}
value={(config.draftExpiryDays as number) ?? 30}
onChange={(e) => updateConfig('draftExpiryDays', parseInt(e.target.value, 10))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="maxFileSizeMB">Max File Size (MB)</Label>
<Input
id="maxFileSizeMB"
type="number"
min={1}
value={(config.maxFileSizeMB as number) ?? 50}
onChange={(e) => updateConfig('maxFileSizeMB', parseInt(e.target.value, 10))}
/>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="publicFormEnabled">Public Form Enabled</Label>
<Switch
id="publicFormEnabled"
checked={(config.publicFormEnabled as boolean) ?? false}
onCheckedChange={(checked) => updateConfig('publicFormEnabled', checked)}
/>
</div>
</CardContent>
</Card>
)
}
if (roundType === 'FILTERING') {
return (
<Card>
<CardHeader>
<CardTitle className="text-base">Filtering Configuration</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<Label htmlFor="aiScreeningEnabled">AI Screening</Label>
<Switch
id="aiScreeningEnabled"
checked={(config.aiScreeningEnabled as boolean) ?? true}
onCheckedChange={(checked) => updateConfig('aiScreeningEnabled', checked)}
/>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="duplicateDetectionEnabled">Duplicate Detection</Label>
<Switch
id="duplicateDetectionEnabled"
checked={(config.duplicateDetectionEnabled as boolean) ?? true}
onCheckedChange={(checked) => updateConfig('duplicateDetectionEnabled', checked)}
/>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="manualReviewEnabled">Manual Review</Label>
<Switch
id="manualReviewEnabled"
checked={(config.manualReviewEnabled as boolean) ?? true}
onCheckedChange={(checked) => updateConfig('manualReviewEnabled', checked)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="batchSize">Batch Size</Label>
<Input
id="batchSize"
type="number"
min={1}
value={(config.batchSize as number) ?? 20}
onChange={(e) => updateConfig('batchSize', parseInt(e.target.value, 10))}
/>
</div>
</CardContent>
</Card>
)
}
if (roundType === 'EVALUATION') {
return (
<Card>
<CardHeader>
<CardTitle className="text-base">Evaluation Configuration</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="requiredReviews">Required Reviews per Project</Label>
<Input
id="requiredReviews"
type="number"
min={1}
value={(config.requiredReviewsPerProject as number) ?? 3}
onChange={(e) => updateConfig('requiredReviewsPerProject', parseInt(e.target.value, 10))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="scoringMode">Scoring Mode</Label>
<Select
value={(config.scoringMode as string) ?? 'criteria'}
onValueChange={(value) => updateConfig('scoringMode', value)}
>
<SelectTrigger id="scoringMode">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="criteria">Criteria-based</SelectItem>
<SelectItem value="global">Global score</SelectItem>
<SelectItem value="binary">Binary (pass/fail)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="requireFeedback">Require Feedback</Label>
<Switch
id="requireFeedback"
checked={(config.requireFeedback as boolean) ?? true}
onCheckedChange={(checked) => updateConfig('requireFeedback', checked)}
/>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="coiRequired">COI Declaration Required</Label>
<Switch
id="coiRequired"
checked={(config.coiRequired as boolean) ?? true}
onCheckedChange={(checked) => updateConfig('coiRequired', checked)}
/>
</div>
</CardContent>
</Card>
)
}
if (roundType === 'LIVE_FINAL') {
return (
<Card>
<CardHeader>
<CardTitle className="text-base">Live Final Configuration</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<Label htmlFor="juryVotingEnabled">Jury Voting</Label>
<Switch
id="juryVotingEnabled"
checked={(config.juryVotingEnabled as boolean) ?? true}
onCheckedChange={(checked) => updateConfig('juryVotingEnabled', checked)}
/>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="audienceVotingEnabled">Audience Voting</Label>
<Switch
id="audienceVotingEnabled"
checked={(config.audienceVotingEnabled as boolean) ?? false}
onCheckedChange={(checked) => updateConfig('audienceVotingEnabled', checked)}
/>
</div>
{(config.audienceVotingEnabled as boolean) && (
<div className="space-y-2">
<Label htmlFor="audienceVoteWeight">Audience Vote Weight (0-1)</Label>
<Input
id="audienceVoteWeight"
type="number"
min={0}
max={1}
step={0.1}
value={(config.audienceVoteWeight as number) ?? 0}
onChange={(e) => updateConfig('audienceVoteWeight', parseFloat(e.target.value))}
/>
</div>
)}
<div className="space-y-2">
<Label htmlFor="presentationDuration">Presentation Duration (min)</Label>
<Input
id="presentationDuration"
type="number"
min={1}
value={(config.presentationDurationMinutes as number) ?? 15}
onChange={(e) => updateConfig('presentationDurationMinutes', parseInt(e.target.value, 10))}
/>
</div>
</CardContent>
</Card>
)
}
// Default view for other types
return (
<Card>
<CardHeader>
<CardTitle className="text-base">{roundType} Configuration</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Configuration UI for {roundType} rounds is not yet implemented.
</p>
<pre className="mt-4 p-3 bg-muted rounded text-xs overflow-auto">
{JSON.stringify(config, null, 2)}
</pre>
</CardContent>
</Card>
)
}