feat(final-docs): admin manual reminder button
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { trpc } from '@/lib/trpc/client'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/components/ui/dialog'
|
||||
import { EmailPreviewDialog } from '@/components/admin/round/email-preview-dialog'
|
||||
import { Eye, Mail, Send } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
const REMINDER_TYPE = 'GRAND_FINAL_DOCS_REMINDER'
|
||||
|
||||
export function FinalDocsReminderButton({ programId }: { programId: string }) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [previewOpen, setPreviewOpen] = useState(false)
|
||||
|
||||
const preview = trpc.notification.previewEmailTemplate.useQuery(
|
||||
{ notificationType: REMINDER_TYPE },
|
||||
{ enabled: previewOpen },
|
||||
)
|
||||
|
||||
const send = trpc.finalist.sendDocumentReminders.useMutation({
|
||||
onSuccess: (r) => {
|
||||
toast.success(`Reminder sent to ${r.sent} team${r.sent === 1 ? '' : 's'}`)
|
||||
setOpen(false)
|
||||
},
|
||||
onError: (e) => toast.error(e.message),
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" size="sm">
|
||||
<Mail className="mr-2 h-4 w-4" /> Remind teams to upload final documents
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Remind finalist teams</DialogTitle>
|
||||
<DialogDescription>
|
||||
Sends an in-app + email reminder to every finalist team with missing required
|
||||
documents.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter className="sm:justify-between">
|
||||
<Button variant="ghost" size="sm" onClick={() => setPreviewOpen(true)}>
|
||||
<Eye className="mr-2 h-4 w-4" /> Preview email
|
||||
</Button>
|
||||
<Button onClick={() => send.mutate({ programId })} disabled={send.isPending}>
|
||||
<Send className="mr-2 h-4 w-4" /> {send.isPending ? 'Sending…' : 'Send reminders'}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* Self-contained preview dialog — rendered as a sibling so it is not nested
|
||||
inside the confirm dialog's content. */}
|
||||
<EmailPreviewDialog
|
||||
open={previewOpen}
|
||||
onOpenChange={setPreviewOpen}
|
||||
title="Final Documents Reminder"
|
||||
description="Preview of the email finalist teams receive."
|
||||
recipientCount={0}
|
||||
previewHtml={preview.data?.html}
|
||||
isPreviewLoading={preview.isLoading}
|
||||
onSend={() => {}}
|
||||
isSending={false}
|
||||
previewOnly
|
||||
showCustomMessage={false}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user