162 lines
4.0 KiB
TypeScript
162 lines
4.0 KiB
TypeScript
'use client';
|
|
|
|
import { useCallback } from 'react';
|
|
import { useForm, useWatch } from 'react-hook-form';
|
|
import { toast } from 'sonner';
|
|
|
|
import type { Tenant } from '@/types';
|
|
|
|
import { useSaveTenantMutation } from './useTenantMutations';
|
|
|
|
export interface TenantFormValues {
|
|
id?: number;
|
|
name: string;
|
|
slug: string;
|
|
client_id: string;
|
|
plan_id: string;
|
|
domain: string;
|
|
description: string;
|
|
admin_first_name: string;
|
|
admin_last_name: string;
|
|
admin_email: string;
|
|
admin_phone_number: string;
|
|
}
|
|
|
|
const defaultValues: TenantFormValues = {
|
|
name: '',
|
|
slug: '',
|
|
client_id: '',
|
|
plan_id: '',
|
|
domain: '',
|
|
description: '',
|
|
admin_first_name: '',
|
|
admin_last_name: '',
|
|
admin_email: '',
|
|
admin_phone_number: '',
|
|
};
|
|
|
|
function createSlug(value: string) {
|
|
return value
|
|
.trim()
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '');
|
|
}
|
|
|
|
function splitContactName(contactName: string) {
|
|
const parts = contactName.trim().split(/\s+/).filter(Boolean);
|
|
if (parts.length === 0) return { firstName: '', lastName: '' };
|
|
if (parts.length === 1) return { firstName: parts[0], lastName: '' };
|
|
return { firstName: parts[0], lastName: parts.slice(1).join(' ') };
|
|
}
|
|
|
|
export function useTenantForm({ onSaved }: { onSaved: () => void }) {
|
|
const {
|
|
register,
|
|
handleSubmit: submitForm,
|
|
reset,
|
|
control,
|
|
setValue,
|
|
formState: { isSubmitting },
|
|
} = useForm<TenantFormValues>({
|
|
defaultValues,
|
|
});
|
|
const saveMutation = useSaveTenantMutation({
|
|
onSaved: () => {
|
|
reset(defaultValues);
|
|
onSaved();
|
|
},
|
|
});
|
|
|
|
const tenantId = useWatch({ control, name: 'id' });
|
|
const clientId = useWatch({ control, name: 'client_id' }) || '';
|
|
const planId = useWatch({ control, name: 'plan_id' }) || '';
|
|
const adminEmail = useWatch({ control, name: 'admin_email' }) || '';
|
|
const isEditMode = Boolean(tenantId);
|
|
|
|
const handleSubmit = submitForm(
|
|
(values) => {
|
|
if (!values.client_id || !values.plan_id) {
|
|
toast.error('Select a client and plan');
|
|
return;
|
|
}
|
|
|
|
if (!isEditMode) {
|
|
if (
|
|
!values.admin_first_name.trim() ||
|
|
!values.admin_last_name.trim() ||
|
|
!values.admin_email.trim()
|
|
) {
|
|
toast.error('Complete all required admin fields');
|
|
return;
|
|
}
|
|
}
|
|
|
|
saveMutation.mutate(values);
|
|
},
|
|
() => toast.error('Complete all required tenant fields'),
|
|
);
|
|
|
|
const openCreate = useCallback(() => {
|
|
reset(defaultValues);
|
|
}, [reset]);
|
|
|
|
const openEdit = useCallback(
|
|
(tenant: Tenant) => {
|
|
reset({
|
|
id: tenant.id,
|
|
name: tenant.name || '',
|
|
slug: tenant.slug || '',
|
|
client_id: String(tenant.client_id ?? ''),
|
|
plan_id: String(tenant.plan_id ?? ''),
|
|
domain: tenant.domain || '',
|
|
description: tenant.description || '',
|
|
admin_first_name: '',
|
|
admin_last_name: '',
|
|
admin_email: tenant.admin_email || '',
|
|
admin_phone_number: '',
|
|
});
|
|
},
|
|
[reset],
|
|
);
|
|
|
|
const applyClientAdminDefaults = useCallback(
|
|
(contactName: string, contactEmail: string, contactPhone: string) => {
|
|
if (isEditMode) return;
|
|
|
|
const { firstName, lastName } = splitContactName(contactName);
|
|
setValue('admin_first_name', firstName, { shouldDirty: true });
|
|
setValue('admin_last_name', lastName, { shouldDirty: true });
|
|
setValue('admin_email', contactEmail, { shouldDirty: true });
|
|
setValue('admin_phone_number', contactPhone, { shouldDirty: true });
|
|
},
|
|
[isEditMode, setValue],
|
|
);
|
|
|
|
const syncSlugFromName = useCallback(
|
|
(name: string) => {
|
|
if (isEditMode) return;
|
|
setValue('slug', createSlug(name), { shouldDirty: true });
|
|
},
|
|
[isEditMode, setValue],
|
|
);
|
|
|
|
return {
|
|
register,
|
|
handleSubmit,
|
|
reset,
|
|
control,
|
|
setValue,
|
|
openCreate,
|
|
openEdit,
|
|
tenantId,
|
|
clientId,
|
|
planId,
|
|
adminEmail,
|
|
isEditMode,
|
|
applyClientAdminDefaults,
|
|
syncSlugFromName,
|
|
isSaving: isSubmitting || saveMutation.isPending,
|
|
};
|
|
}
|