feat: admin UX improvements — notify buttons, eval config, round finalization
Custom body support for advancement/rejection notification emails, evaluation config toggle fix, user actions improvements, round finalization with reorder support, project detail page enhancements, award pool duplicate prevention. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,8 @@ import { useState } from 'react'
|
||||
import { trpc } from '@/lib/trpc/client'
|
||||
import { toast } from 'sonner'
|
||||
import { Trophy } from 'lucide-react'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { EmailPreviewDialog } from './email-preview-dialog'
|
||||
|
||||
interface NotifyAdvancedButtonProps {
|
||||
@@ -14,9 +16,10 @@ interface NotifyAdvancedButtonProps {
|
||||
export function NotifyAdvancedButton({ roundId, targetRoundId }: NotifyAdvancedButtonProps) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [customMessage, setCustomMessage] = useState<string | undefined>()
|
||||
const [fullCustomBody, setFullCustomBody] = useState(false)
|
||||
|
||||
const preview = trpc.round.previewAdvancementEmail.useQuery(
|
||||
{ roundId, targetRoundId, customMessage },
|
||||
{ roundId, targetRoundId, customMessage, fullCustomBody },
|
||||
{ enabled: open }
|
||||
)
|
||||
|
||||
@@ -32,18 +35,31 @@ export function NotifyAdvancedButton({ roundId, targetRoundId }: NotifyAdvancedB
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() => setOpen(true)}
|
||||
className="flex items-start gap-3 p-4 rounded-lg border border-l-4 border-l-emerald-500 hover:-translate-y-0.5 hover:shadow-md transition-all text-left"
|
||||
>
|
||||
<Trophy className="h-5 w-5 text-emerald-600 mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<p className="text-sm font-medium">Notify Advanced Teams</p>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">
|
||||
Send advancement emails to passed projects
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
<button
|
||||
onClick={() => setOpen(true)}
|
||||
className="flex items-start gap-3 p-4 rounded-lg border border-l-4 border-l-emerald-500 hover:-translate-y-0.5 hover:shadow-md transition-all text-left w-full"
|
||||
>
|
||||
<Trophy className="h-5 w-5 text-emerald-600 mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<p className="text-sm font-medium">Notify Advanced Teams</p>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">
|
||||
Send advancement emails to passed projects
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<div className="flex items-center gap-2 px-1">
|
||||
<Switch
|
||||
id="advancement-full-custom-body"
|
||||
checked={fullCustomBody}
|
||||
onCheckedChange={setFullCustomBody}
|
||||
/>
|
||||
<Label htmlFor="advancement-full-custom-body" className="text-xs cursor-pointer">
|
||||
<span className="font-medium">Full custom body</span>
|
||||
<span className="text-muted-foreground ml-1">— only your message is sent (no standard text)</span>
|
||||
</Label>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<EmailPreviewDialog
|
||||
open={open}
|
||||
@@ -53,7 +69,7 @@ export function NotifyAdvancedButton({ roundId, targetRoundId }: NotifyAdvancedB
|
||||
recipientCount={preview.data?.recipientCount ?? 0}
|
||||
previewHtml={preview.data?.html}
|
||||
isPreviewLoading={preview.isLoading}
|
||||
onSend={(msg) => sendMutation.mutate({ roundId, targetRoundId, customMessage: msg })}
|
||||
onSend={(msg) => sendMutation.mutate({ roundId, targetRoundId, customMessage: msg, fullCustomBody })}
|
||||
isSending={sendMutation.isPending}
|
||||
onRefreshPreview={(msg) => setCustomMessage(msg)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user