'use client'; import { useMemo, useRef, type ComponentProps } from 'react'; import { Controller, type Control, type FieldErrors, type UseFormRegister, } from 'react-hook-form'; import { Loader2 } from 'lucide-react'; import { FormField, PhoneInput, SelectPopover } from '@/components/form'; import { Button } from '@/components/ui/button'; import { Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import type { Client, Plan } from '@/types'; import type { TenantAdminFieldLocks, TenantFormValues, } from '../hooks/useTenantForm'; interface TenantSheetProps { open: boolean; onOpenChange: (open: boolean) => void; tenantId?: number; isEditMode: boolean; register: UseFormRegister; control: Control; errors: FieldErrors; isSubmitted: boolean; onSubmit: ComponentProps<'form'>['onSubmit']; canSubmit: boolean; clientId: string; planId: string; onClientChange: (clientId: string) => void; onPlanChange: (planId: string) => void; onNameChange: (name: string) => void; clients: Client[]; plans: Plan[]; isLookupsLoading: boolean; isSaving: boolean; adminEmail?: string; adminFieldLocks: TenantAdminFieldLocks; } export function TenantSheet({ open, onOpenChange, tenantId, isEditMode, register, control, errors, isSubmitted, onSubmit, canSubmit, clientId, planId, onClientChange, onPlanChange, onNameChange, clients, plans, isLookupsLoading, isSaving, adminEmail, adminFieldLocks, }: TenantSheetProps) { const dropdownPortalRef = useRef(null); const fieldError = (field: keyof TenantFormValues) => isSubmitted ? errors[field]?.message : undefined; const clientOptions = useMemo( () => clients.map((client) => ({ value: String(client.id), label: [client.first_name, client.last_name].filter(Boolean).join(' '), })), [clients], ); const planOptions = useMemo( () => plans.map((plan) => ({ value: String(plan.id), label: plan.name, })), [plans], ); return ( {tenantId ? 'Edit Tenant' : 'Create Tenant'} Bind a client and subscription plan, then invite the tenant administrator.

Basic Information

Tenant identity and subscription binding.

onNameChange(event.target.value), })} />