import React, { useState, useEffect } from 'react'; import api from '../utils/api'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from './ui/dialog'; import { Button } from './ui/button'; import { Input } from './ui/input'; import { Label } from './ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { toast } from 'sonner'; import { Loader2, Mail, Copy, Check } from 'lucide-react'; const InviteStaffDialog = ({ open, onOpenChange, onSuccess }) => { const [formData, setFormData] = useState({ email: '', first_name: '', last_name: '', phone: '', role: 'admin' }); const [loading, setLoading] = useState(false); const [errors, setErrors] = useState({}); const [invitationUrl, setInvitationUrl] = useState(null); const [copied, setCopied] = useState(false); const [roles, setRoles] = useState([]); const [loadingRoles, setLoadingRoles] = useState(false); // Fetch roles when dialog opens useEffect(() => { if (open) { fetchRoles(); } }, [open]); const fetchRoles = async () => { setLoadingRoles(true); try { const response = await api.get('/admin/roles'); // Filter to show only admin-type roles (not guest or member) const staffRoles = response.data.filter(role => ['admin', 'superadmin', 'finance'].includes(role.code) || !role.is_system_role ); setRoles(staffRoles); } catch (error) { console.error('Failed to fetch roles:', error); toast.error('Failed to load roles'); } finally { setLoadingRoles(false); } }; const handleChange = (field, value) => { setFormData(prev => ({ ...prev, [field]: value })); // Clear error when user starts typing if (errors[field]) { setErrors(prev => ({ ...prev, [field]: null })); } }; const validate = () => { const newErrors = {}; if (!formData.email) { newErrors.email = 'Email is required'; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { newErrors.email = 'Invalid email format'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleSubmit = async (e) => { e.preventDefault(); if (!validate()) { return; } setLoading(true); try { const response = await api.post('/admin/users/invite', formData); toast.success('Invitation sent successfully'); // Show invitation URL setInvitationUrl(response.data.invitation_url); // Don't close dialog yet - show invitation URL first if (onSuccess) onSuccess(); } catch (error) { const errorMessage = error.response?.data?.detail || 'Failed to send invitation'; toast.error(errorMessage); } finally { setLoading(false); } }; const copyToClipboard = () => { navigator.clipboard.writeText(invitationUrl); setCopied(true); toast.success('Invitation link copied to clipboard'); setTimeout(() => setCopied(false), 2000); }; const handleClose = () => { // Reset form setFormData({ email: '', first_name: '', last_name: '', phone: '', role: 'admin' }); setInvitationUrl(null); setCopied(false); onOpenChange(false); }; return ( {invitationUrl ? 'Invitation Sent' : 'Invite Staff Member'} {invitationUrl ? 'The invitation has been sent via email. You can also copy the link below.' : 'Send an email invitation to join as staff. They will set their own password.'} {invitationUrl ? ( // Show invitation URL after successful send
) : ( // Show invitation form
{/* Email */}
handleChange('email', e.target.value)} className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]" placeholder="staff@example.com" /> {errors.email && (

{errors.email}

)}
{/* First Name (Optional) */}
handleChange('first_name', e.target.value)} className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]" placeholder="John" />
{/* Last Name (Optional) */}
handleChange('last_name', e.target.value)} className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]" placeholder="Doe" />
{/* Phone (Optional) */}
handleChange('phone', e.target.value)} className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]" placeholder="(555) 123-4567" />
{/* Role */}
{roles.length > 0 && (

{roles.find(r => r.code === formData.role)?.description || ''}

)}
)} {invitationUrl && ( )}
); }; export default InviteStaffDialog;