import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { X, Copy, Check, Trash2 } from 'lucide-react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Button, Input, Loading } from '../common'; import { guestsService, GuestInvite } from '../../services/guests.service'; import { toast } from 'react-toastify'; interface GuestInviteDialogProps { eventId: number; eventName?: string; onClose: () => void; } /** * Admin dialog to create pre-minted invite tokens and list existing ones. * Each invite generates a unique URL that the admin can send to a specific * guest. Opening the URL auto-registers that guest (single use). */ export const GuestInviteDialog: React.FC = ({ eventId, onClose }) => { const { t } = useTranslation(); const queryClient = useQueryClient(); const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [copiedId, setCopiedId] = useState(null); const { data, isLoading } = useQuery({ queryKey: ['admin-guest-invites', eventId], queryFn: () => guestsService.listInvites(eventId), }); const createMutation = useMutation({ mutationFn: () => guestsService.createInvite(eventId, { name, email: email || undefined }), onSuccess: () => { setName(''); setEmail(''); toast.success(t('admin.guests.inviteCreated', 'Invite created')); queryClient.invalidateQueries({ queryKey: ['admin-guest-invites', eventId] }); queryClient.invalidateQueries({ queryKey: ['admin-guests', eventId] }); }, onError: () => toast.error(t('admin.guests.inviteCreateError', 'Failed to create invite')), }); const revokeMutation = useMutation({ mutationFn: (inviteId: number) => guestsService.revokeInvite(eventId, inviteId), onSuccess: () => { toast.success(t('admin.guests.inviteRevoked', 'Invite revoked')); queryClient.invalidateQueries({ queryKey: ['admin-guest-invites', eventId] }); }, onError: () => toast.error(t('admin.guests.inviteRevokeError', 'Failed to revoke invite')), }); const copy = (invite: GuestInvite) => { navigator.clipboard.writeText(invite.url).then(() => { setCopiedId(invite.id); setTimeout(() => setCopiedId(null), 1500); }); }; const invites = data?.invites || []; return (

{t('admin.guests.invitesTitle', 'Guest invites')}

{/* Create form */}

{t('admin.guests.createInvite', 'Create invite')}

setName(e.target.value)} placeholder="e.g. Alice" required /> setEmail(e.target.value)} placeholder="alice@example.com" />
{/* Existing invites */}

{t('admin.guests.existingInvites', 'Existing invites')}

{isLoading ? ( ) : invites.length === 0 ? (
{t('admin.guests.noInvites', 'No invites yet')}
) : (
{invites.map((invite) => (
{invite.guest.name} {invite.guest.email && ( ยท {invite.guest.email} )}
{t(`admin.guests.inviteStatus.${invite.status}`, invite.status)}
{invite.url}
{invite.status === 'pending' && ( <> )}
))}
)}
); };