'use client' import { useState } from 'react' import { trpc } from '@/lib/trpc/client' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from '@/components/ui/dialog' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '@/components/ui/alert-dialog' import { Send, Eye, Bell } from 'lucide-react' import { toast } from 'sonner' export function LunchRecapActions({ programId, lunchEventId, recapSentAt, extraRecipientCount, }: { programId: string lunchEventId: string recapSentAt: Date | null extraRecipientCount: number }) { const utils = trpc.useUtils() const [previewOpen, setPreviewOpen] = useState(false) const send = trpc.lunch.sendRecap.useMutation({ onSuccess: () => { utils.lunch.getEvent.invalidate({ programId }) toast.success('Recap sent') }, onError: (e) => { if (e.data?.code === 'PRECONDITION_FAILED') { if ( confirm( "You've already sent a recap. Send updated version to all recipients?", ) ) { send.mutate({ programId, forceUpdate: true }) } } else { toast.error(e.message) } }, }) const sendReminders = trpc.lunch.sendReminders.useMutation({ onSuccess: (data) => { toast.success(`Reminders sent to ${data.sent} attendee${data.sent === 1 ? '' : 's'}`) }, onError: (e) => { toast.error(`Failed to send reminders: ${e.message}`) }, }) const { data: preview, isLoading: loadingPreview } = trpc.lunch.getRecapPreview.useQuery( { programId }, { enabled: previewOpen }, ) return ( Recap
Send lunch pick reminders? This will send a reminder email to all confirmed attendees who haven't picked a lunch dish yet. You can do this multiple times — it won't affect the automatic reminder window. Cancel sendReminders.mutate({ lunchEventId })} > Send reminders

{recapSentAt ? `Last sent: ${new Date(recapSentAt).toLocaleString()}. Recipients: edition admins${extraRecipientCount > 0 ? ` + ${extraRecipientCount} extra` : ''}.` : 'Recap has not been sent yet.'}

Recap preview {loadingPreview && (

Loading…

)} {preview && (

{preview.summary.picked}/{preview.summary.total} {' '} picked {preview.summary.missing > 0 ? ` · ${preview.summary.missing} missing` : ''}

{Object.keys(preview.dishCounts).length > 0 && (

Dishes

    {Object.entries(preview.dishCounts).map(([n, c]) => (
  • {c}× {n}
  • ))}
)} {Object.keys(preview.dietaryCounts).length > 0 && (

Dietary tags

    {Object.entries(preview.dietaryCounts).map(([n, c]) => (
  • {c}× {n.replace('_', ' ').toLowerCase()}
  • ))}
)}

Allergens

{Object.keys(preview.allergenCounts).length === 0 ? (

None reported.

) : (
    {Object.entries(preview.allergenCounts).map(([n, c]) => (
  • {c}× {n.replace('_', ' ').toLowerCase()}
  • ))}
)}
)}
) }