'use client'; import { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Loader2 } from 'lucide-react'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Textarea } from '@/components/ui/textarea'; import { ClientPicker } from '@/components/shared/client-picker'; import { apiFetch } from '@/lib/api/client'; import { ROLES } from '@/lib/validators/company-memberships'; type RoleEnum = (typeof ROLES)[number]; type FormValues = { clientId: string | null; role: RoleEnum; roleDetail?: string; startDate: string; // YYYY-MM-DD isPrimary: boolean; notes?: string; }; interface AddMembershipDialogProps { open: boolean; onOpenChange: (open: boolean) => void; companyId: string; } const todayIso = (): string => new Date().toISOString().slice(0, 10); const ROLE_LABEL: Record = { director: 'Director', officer: 'Officer', broker: 'Broker', representative: 'Representative', legal_counsel: 'Legal counsel', employee: 'Employee', shareholder: 'Shareholder', other: 'Other', }; export function AddMembershipDialog({ open, onOpenChange, companyId }: AddMembershipDialogProps) { const queryClient = useQueryClient(); const [formError, setFormError] = useState(null); const { register, handleSubmit, watch, setValue, reset, formState: { errors, isSubmitting }, } = useForm({ defaultValues: { clientId: null, role: 'director', roleDetail: '', startDate: todayIso(), isPrimary: false, notes: '', }, }); useEffect(() => { if (open) { setFormError(null); reset({ clientId: null, role: 'director', roleDetail: '', startDate: todayIso(), isPrimary: false, notes: '', }); } }, [open, reset]); const clientId = watch('clientId'); const role = watch('role'); const isPrimary = watch('isPrimary'); const mutation = useMutation({ mutationFn: async (data: FormValues) => { if (!data.clientId) { throw new Error('Please select a client'); } await apiFetch(`/api/v1/companies/${companyId}/members`, { method: 'POST', body: { clientId: data.clientId, role: data.role, roleDetail: data.roleDetail?.trim() || undefined, startDate: data.startDate, isPrimary: data.isPrimary, notes: data.notes?.trim() || undefined, }, }); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['companies', companyId, 'members'] }); onOpenChange(false); }, onError: (err: unknown) => { let msg = err instanceof Error ? err.message : 'Failed to add membership'; // Detect 409 — service returns a "membership already exists" message if (/already exists/i.test(msg)) { msg = 'This membership already exists (same client + role + start date).'; } setFormError(msg); }, }); return ( Add member Associate a client with this company in a specific role.
{ setFormError(null); mutation.mutate(data); })} className="space-y-4" >
setValue('clientId', id)} /> {!clientId && errors.clientId &&

Required

}
{errors.startDate &&

Required

}
setValue('isPrimary', v === true)} />