feat: add superadmin tenant module
This commit is contained in:
157
src/app/(modules)/tenants/hooks/useTenantForm.ts
Normal file
157
src/app/(modules)/tenants/hooks/useTenantForm.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
'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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user