import { Info, Lock, Mail, Plus, User, UsersRound } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { createOrgMember, createOrgSection, listOrgSections } from "../api"; const EMAIL_LOCAL_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,62}[A-Za-z0-9])?$/; function RequiredLabel({ children }) { return ( <> {children} ); } function SetupField({ label, error, children, hint }) { return (
{label && {label}} {children} {hint && {hint}} {error && {error}}
); } function InputWrap({ icon: Icon, children }) { return (
); } function validateForm(form, companyDomain) { const errors = {}; if (!form.first_name.trim()) errors.first_name = "Please enter a first name."; if (!form.last_name.trim()) errors.last_name = "Please enter a last name."; const local = form.email_local.trim(); if (!local) { errors.email_local = "Please enter a work email address."; } else if (!EMAIL_LOCAL_PATTERN.test(local)) { errors.email_local = "Enter a valid email address before @."; } if (!form.send_invitation && !form.password.trim()) { errors.password = "Please set an initial password."; } if (form.send_invitation) { const invite = form.invitation_email.trim(); if (!invite) { errors.invitation_email = "Please enter a personal email for the invitation."; } else if (invite.endsWith(`@${companyDomain}`)) { errors.invitation_email = "Use a personal email, not your company domain."; } } return errors; } export default function AddEmployeeForm({ companyDomain, platformDomain = "gentic.email", variant = "drawer", submitLabel = "Create user", onCreated, onCancel, }) { const token = sessionStorage.getItem("agmail_access_token"); const [sections, setSections] = useState([]); const [sectionsLoading, setSectionsLoading] = useState(true); const [showNewSection, setShowNewSection] = useState(false); const [newSectionName, setNewSectionName] = useState(""); const [sectionError, setSectionError] = useState(""); const [creatingSection, setCreatingSection] = useState(false); const [form, setForm] = useState({ first_name: "", last_name: "", email_local: "", invitation_email: "", org_role: "user", section_id: null, send_invitation: true, force_password_change: true, password: "", }); const [fieldErrors, setFieldErrors] = useState({}); const [submitAttempted, setSubmitAttempted] = useState(false); const [status, setStatus] = useState({ loading: false, error: "" }); useEffect(() => { let cancelled = false; setSectionsLoading(true); listOrgSections(token) .then((items) => { if (!cancelled) { setSections(items); } }) .catch(() => { if (!cancelled) { setSections([]); } }) .finally(() => { if (!cancelled) { setSectionsLoading(false); } }); return () => { cancelled = true; }; }, [token]); const formValid = useMemo( () => Object.keys(validateForm(form, companyDomain)).length === 0, [form, companyDomain], ); function updateField(field, value) { setForm((current) => { const next = { ...current, [field]: value }; if (submitAttempted || fieldErrors[field]) { const nextErrors = validateForm(next, companyDomain); setFieldErrors((errors) => ({ ...errors, [field]: nextErrors[field] })); } return next; }); } function selectSection(sectionId) { setForm((current) => ({ ...current, section_id: current.section_id === sectionId ? null : sectionId, })); } async function handleCreateSection() { const name = newSectionName.trim(); if (!name) { setSectionError("Enter a section name."); return; } setCreatingSection(true); setSectionError(""); try { const section = await createOrgSection({ name }, token); setSections((current) => [...current, section].sort((a, b) => a.name.localeCompare(b.name))); setForm((current) => ({ ...current, section_id: section.id })); setNewSectionName(""); setShowNewSection(false); } catch (error) { setSectionError(error.message); } finally { setCreatingSection(false); } } async function handleSubmit(event) { event.preventDefault(); setSubmitAttempted(true); const errors = validateForm(form, companyDomain); setFieldErrors(errors); if (Object.keys(errors).length > 0) { return; } setStatus({ loading: true, error: "" }); const email = `${form.email_local.trim().toLowerCase()}@${companyDomain}`; try { const member = await createOrgMember( { first_name: form.first_name.trim(), last_name: form.last_name.trim(), email, invitation_email: form.send_invitation ? form.invitation_email.trim().toLowerCase() : undefined, section_id: form.section_id || undefined, org_role: form.org_role, send_invitation: form.send_invitation, force_password_change: form.send_invitation ? false : form.force_password_change, password: form.send_invitation ? undefined : form.password, }, token, ); setForm({ first_name: "", last_name: "", email_local: "", invitation_email: "", org_role: "user", section_id: null, send_invitation: true, force_password_change: true, password: "", }); setFieldErrors({}); setSubmitAttempted(false); setStatus({ loading: false, error: "" }); onCreated?.(member); } catch (error) { setStatus({ loading: false, error: error.message }); } } const formClass = variant === "inline" ? "org-setup-form employee-add-form employee-add-form-inline" : "people-drawer-form employee-add-form"; return (
First name} error={fieldErrors.first_name} > updateField("first_name", event.target.value)} placeholder="Rahul" /> Last name} error={fieldErrors.last_name} > updateField("last_name", event.target.value)} placeholder="Sharma" />
Work email} error={fieldErrors.email_local} hint="This will be their login email address on your company domain." >
updateField("email_local", event.target.value)} placeholder="rahul" /> @{companyDomain}
Add to a department or team (optional). Group emails are managed under Groups.
{sectionsLoading ? ( Loading sections… ) : ( sections.map((section) => ( )) )}
{showNewSection && (
setNewSectionName(event.target.value)} placeholder="e.g. Marketing" />
)} {sectionError && {sectionError}}
); }