Add AI eligibility toggle and include-submitted filter for awards
- Add useAiEligibility boolean to SpecialAward schema (default true) - Toggle on creation form lets admins disable AI for feeling-based awards - Detail page shows "Load All Projects" when AI is off vs "Run AI Eligibility" - Include Submitted toggle lets admins include SUBMITTED-status projects - Fix perPage: 200 → 100 to match user.list validation max - Fix edition display on award detail page - Add migration for new column Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -76,7 +77,7 @@ export default function AwardDetailPage({
|
||||
trpc.specialAward.listJurors.useQuery({ awardId })
|
||||
const { data: voteResults } =
|
||||
trpc.specialAward.getVoteResults.useQuery({ awardId })
|
||||
const { data: allUsers } = trpc.user.list.useQuery({ page: 1, perPage: 200 })
|
||||
const { data: allUsers } = trpc.user.list.useQuery({ page: 1, perPage: 100 })
|
||||
|
||||
const updateStatus = trpc.specialAward.updateStatus.useMutation()
|
||||
const runEligibility = trpc.specialAward.runEligibility.useMutation()
|
||||
@@ -86,6 +87,7 @@ export default function AwardDetailPage({
|
||||
const setWinner = trpc.specialAward.setWinner.useMutation()
|
||||
|
||||
const [selectedJurorId, setSelectedJurorId] = useState('')
|
||||
const [includeSubmitted, setIncludeSubmitted] = useState(true)
|
||||
|
||||
const handleStatusChange = async (
|
||||
status: 'DRAFT' | 'NOMINATIONS_OPEN' | 'VOTING_OPEN' | 'CLOSED' | 'ARCHIVED'
|
||||
@@ -103,7 +105,7 @@ export default function AwardDetailPage({
|
||||
|
||||
const handleRunEligibility = async () => {
|
||||
try {
|
||||
const result = await runEligibility.mutateAsync({ awardId })
|
||||
const result = await runEligibility.mutateAsync({ awardId, includeSubmitted })
|
||||
toast.success(
|
||||
`Eligibility run: ${result.eligible} eligible, ${result.ineligible} ineligible`
|
||||
)
|
||||
@@ -201,7 +203,7 @@ export default function AwardDetailPage({
|
||||
{award.status.replace('_', ' ')}
|
||||
</Badge>
|
||||
<span className="text-muted-foreground">
|
||||
{award.program.name}
|
||||
{award.program.year} Edition
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -262,23 +264,55 @@ export default function AwardDetailPage({
|
||||
|
||||
{/* Eligibility Tab */}
|
||||
<TabsContent value="eligibility" className="space-y-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex flex-col gap-3 sm:flex-row sm:justify-between sm:items-center">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{award.eligibleCount} of {award._count.eligibilities} projects
|
||||
eligible
|
||||
</p>
|
||||
<Button
|
||||
onClick={handleRunEligibility}
|
||||
disabled={runEligibility.isPending}
|
||||
>
|
||||
{runEligibility.isPending ? (
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch
|
||||
id="include-submitted"
|
||||
checked={includeSubmitted}
|
||||
onCheckedChange={setIncludeSubmitted}
|
||||
/>
|
||||
<Label htmlFor="include-submitted" className="text-sm whitespace-nowrap">
|
||||
Include submitted
|
||||
</Label>
|
||||
</div>
|
||||
{award.useAiEligibility ? (
|
||||
<Button
|
||||
onClick={handleRunEligibility}
|
||||
disabled={runEligibility.isPending}
|
||||
>
|
||||
{runEligibility.isPending ? (
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<Brain className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
Run AI Eligibility
|
||||
</Button>
|
||||
) : (
|
||||
<Brain className="mr-2 h-4 w-4" />
|
||||
<Button
|
||||
onClick={handleRunEligibility}
|
||||
disabled={runEligibility.isPending}
|
||||
variant="outline"
|
||||
>
|
||||
{runEligibility.isPending ? (
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<CheckCircle2 className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
Load All Projects
|
||||
</Button>
|
||||
)}
|
||||
Run AI Eligibility
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{!award.useAiEligibility && (
|
||||
<p className="text-sm text-muted-foreground italic">
|
||||
AI eligibility is off for this award. Projects are loaded for manual selection.
|
||||
</p>
|
||||
)}
|
||||
|
||||
{eligibilityData && eligibilityData.eligibilities.length > 0 ? (
|
||||
<Card>
|
||||
|
||||
Reference in New Issue
Block a user