import { useState } from "react"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { apiRequest } from "@/lib/queryClient"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { useToast } from "@/hooks/use-toast"; import { Mail, UserPlus, RotateCcw, Trash2 } from "lucide-react"; interface Invitation { id: number; email: string; token: string; expiresAt: string; isUsed: boolean; createdAt: string; } interface InvitationManagementProps { invitations: Invitation[]; } export function InvitationManagement({ invitations }: InvitationManagementProps) { const { toast } = useToast(); const queryClient = useQueryClient(); const [isResendOpen, setIsResendOpen] = useState(false); const [isManualCreateOpen, setIsManualCreateOpen] = useState(false); const [selectedInvitation, setSelectedInvitation] = useState(null); const [manualUserData, setManualUserData] = useState({ email: "", firstName: "", lastName: "", displayName: "", tempPassword: "" }); // Resend invitation mutation const resendInvitationMutation = useMutation({ mutationFn: async (invitationId: number) => { await apiRequest("POST", `/api/invitations/${invitationId}/resend`); }, onSuccess: () => { toast({ title: "Success", description: "Invitation resent successfully", }); queryClient.invalidateQueries({ queryKey: ['/api/invitations'] }); setIsResendOpen(false); }, onError: (error) => { toast({ title: "Error", description: `Failed to resend invitation: ${error.message}`, variant: "destructive", }); }, }); // Delete invitation mutation const deleteInvitationMutation = useMutation({ mutationFn: async (invitationId: number) => { await apiRequest("DELETE", `/api/invitations/${invitationId}`); }, onSuccess: () => { toast({ title: "Success", description: "Invitation deleted successfully", }); queryClient.invalidateQueries({ queryKey: ['/api/invitations'] }); }, onError: (error) => { toast({ title: "Error", description: `Failed to delete invitation: ${error.message}`, variant: "destructive", }); }, }); // Manual user creation mutation const createUserMutation = useMutation({ mutationFn: async (userData: typeof manualUserData) => { await apiRequest("POST", "/api/users/create-manual", userData); }, onSuccess: () => { toast({ title: "Success", description: "User created successfully. They can now log in with their temporary password.", }); queryClient.invalidateQueries({ queryKey: ['/api/users'] }); setIsManualCreateOpen(false); setManualUserData({ email: "", firstName: "", lastName: "", displayName: "", tempPassword: "" }); }, onError: (error) => { toast({ title: "Error", description: `Failed to create user: ${error.message}`, variant: "destructive", }); }, }); const handleResend = (invitation: Invitation) => { setSelectedInvitation(invitation); setIsResendOpen(true); }; const handleDelete = (invitation: Invitation) => { if (window.confirm(`Are you sure you want to delete the invitation for ${invitation.email}?`)) { deleteInvitationMutation.mutate(invitation.id); } }; const handleManualCreate = () => { setIsManualCreateOpen(true); }; const generateTempPassword = () => { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let password = ""; for (let i = 0; i < 12; i++) { password += chars.charAt(Math.floor(Math.random() * chars.length)); } setManualUserData(prev => ({ ...prev, tempPassword: password })); }; const isExpired = (expiresAt: string) => { return new Date(expiresAt) < new Date(); }; return (

Invitation Management

{invitations.map((invitation) => (
{invitation.email} {invitation.isUsed ? 'Used' : isExpired(invitation.expiresAt) ? 'Expired' : 'Pending'}

Created: {new Date(invitation.createdAt).toLocaleDateString()}

Expires: {new Date(invitation.expiresAt).toLocaleDateString()}

{!invitation.isUsed && ( )}
))}
{/* Resend Confirmation Dialog */} Resend Invitation

Are you sure you want to resend the invitation to {selectedInvitation?.email}?

This will generate a new invitation link and extend the expiration date by 7 days.

{/* Manual User Creation Dialog */} Manual User Activation
setManualUserData(prev => ({ ...prev, email: e.target.value }))} placeholder="dj@example.com" required />
setManualUserData(prev => ({ ...prev, firstName: e.target.value }))} placeholder="John" />
setManualUserData(prev => ({ ...prev, lastName: e.target.value }))} placeholder="Doe" />
setManualUserData(prev => ({ ...prev, displayName: e.target.value }))} placeholder="DJ John" />
setManualUserData(prev => ({ ...prev, tempPassword: e.target.value }))} placeholder="Enter temporary password" required />

The user will need to change this password on first login.

); }