Fix jury reminders, add notify jurors button, fix checkbox borders, widen assignment modal
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m32s
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m32s
- Send Reminders button now works: added sendManualReminders() that bypasses cron-specific window/deadline/dedup guards so admin can send immediately - Added Notify Jurors button that sends direct BATCH_ASSIGNED emails to all jurors with assignments (not dependent on NotificationEmailSetting config) - Fixed checkbox component: default border is now neutral grey (border-input), red border (border-primary) only applied when checked - Widened Add Assignment dialog from max-w-2xl to max-w-3xl to prevent overflow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -85,6 +85,7 @@ import {
|
||||
ShieldAlert,
|
||||
Eye,
|
||||
Pencil,
|
||||
Mail,
|
||||
} from 'lucide-react'
|
||||
import {
|
||||
Command,
|
||||
@@ -1784,9 +1785,10 @@ export default function RoundDetailPage() {
|
||||
<ScoreDistribution roundId={roundId} />
|
||||
</div>
|
||||
|
||||
{/* Actions: Send Reminders + Export */}
|
||||
{/* Actions: Send Reminders + Notify + Export */}
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<SendRemindersButton roundId={roundId} />
|
||||
<NotifyJurorsButton roundId={roundId} />
|
||||
<Button variant="outline" size="sm" onClick={() => setExportOpen(true)}>
|
||||
<Download className="h-4 w-4 mr-1.5" />
|
||||
Export Evaluations
|
||||
@@ -2356,6 +2358,48 @@ function SendRemindersButton({ roundId }: { roundId: string }) {
|
||||
)
|
||||
}
|
||||
|
||||
// ── Notify Jurors of Assignments Button ──────────────────────────────────
|
||||
|
||||
function NotifyJurorsButton({ roundId }: { roundId: string }) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const mutation = trpc.assignment.notifyJurorsOfAssignments.useMutation({
|
||||
onSuccess: (data) => {
|
||||
toast.success(`Notified ${data.jurorCount} juror(s) — ${data.emailsSent} email(s) sent`)
|
||||
setOpen(false)
|
||||
},
|
||||
onError: (err) => toast.error(err.message),
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant="outline" size="sm" onClick={() => setOpen(true)}>
|
||||
<Mail className="h-4 w-4 mr-1.5" />
|
||||
Notify Jurors
|
||||
</Button>
|
||||
<AlertDialog open={open} onOpenChange={setOpen}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Notify jurors of their assignments?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will send an email to every juror assigned to this round, reminding them of how many projects they need to evaluate.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={() => mutation.mutate({ roundId })}
|
||||
disabled={mutation.isPending}
|
||||
>
|
||||
{mutation.isPending && <Loader2 className="h-4 w-4 mr-1.5 animate-spin" />}
|
||||
Notify Jurors
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// ── Export Evaluations Dialog ─────────────────────────────────────────────
|
||||
|
||||
function ExportEvaluationsDialog({
|
||||
@@ -2640,7 +2684,7 @@ function IndividualAssignmentsTable({
|
||||
if (!open) resetDialog()
|
||||
else setAddDialogOpen(true)
|
||||
}}>
|
||||
<DialogContent className="sm:max-w-[540px]">
|
||||
<DialogContent className="max-w-3xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Assignment</DialogTitle>
|
||||
<DialogDescription>
|
||||
@@ -2674,7 +2718,7 @@ function IndividualAssignmentsTable({
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[480px] p-0" align="start">
|
||||
<PopoverContent className="w-[var(--radix-popover-trigger-width)] p-0" align="start">
|
||||
<Command>
|
||||
<CommandInput placeholder="Search by name or email..." />
|
||||
<CommandList>
|
||||
@@ -2775,7 +2819,7 @@ function IndividualAssignmentsTable({
|
||||
</div>
|
||||
|
||||
{/* Project checklist */}
|
||||
<ScrollArea className="h-[240px] rounded-md border">
|
||||
<ScrollArea className="h-[320px] rounded-md border">
|
||||
<div className="p-2 space-y-0.5">
|
||||
{!selectedJurorId ? (
|
||||
<p className="text-sm text-muted-foreground text-center py-8">
|
||||
|
||||
Reference in New Issue
Block a user