Files
road-monitoring-ui/src/app/(modules)/plans/hooks/usePlanForm.ts

152 lines
3.5 KiB
TypeScript

'use client';
import {
collectDefaultPermissionIds,
collectPermissionIdsByKeys,
} from '@/components/permission-tree';
import type { PermissionTreeItem, Plan } from '@/types';
import { useCallback } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { toast } from 'sonner';
import { useSavePlanMutation } from './usePlanMutations';
export interface PlanFormValues {
id?: number;
name: string;
slug: string;
description: string;
price: string;
billing_cycle: string;
trial_days: number;
max_projects: number;
max_organizations: number;
max_users: number;
max_roles: number;
permission_ids: number[];
is_active: boolean;
is_custom: boolean;
}
const defaultValues: PlanFormValues = {
name: '',
slug: '',
description: '',
price: '',
billing_cycle: 'monthly',
trial_days: 0,
max_projects: 0,
max_organizations: 0,
max_users: 0,
max_roles: 0,
permission_ids: [],
is_active: true,
is_custom: false,
};
function toNumber(value: unknown) {
const numberValue = Number(value);
return Number.isFinite(numberValue) ? numberValue : 0;
}
export function usePlanForm({
permissionTree,
onSaved,
}: {
permissionTree: PermissionTreeItem[];
onSaved: () => void;
}) {
const {
control,
register,
handleSubmit,
reset,
setValue,
formState: { isSubmitting },
} = useForm<PlanFormValues>({
defaultValues,
});
const saveMutation = useSavePlanMutation({
onSaved: () => {
reset(defaultValues);
onSaved();
},
});
const planId = useWatch({ control, name: 'id' });
const permissionIds = useWatch({ control, name: 'permission_ids' }) || [];
const onSubmit = handleSubmit((values) => {
if (values.permission_ids.length === 0) {
toast.error('Select at least one permission');
return;
}
saveMutation.mutate({
...values,
name: values.name.trim(),
slug: values.slug.trim(),
description: values.description.trim(),
price: values.price.trim(),
trial_days: toNumber(values.trial_days),
max_projects: toNumber(values.max_projects),
max_organizations: toNumber(values.max_organizations),
max_users: toNumber(values.max_users),
max_roles: toNumber(values.max_roles),
});
});
const openCreate = useCallback(() => {
reset({
...defaultValues,
permission_ids: collectDefaultPermissionIds(permissionTree),
});
}, [permissionTree, reset]);
const openEdit = useCallback(
(plan: Plan) => {
reset({
id: plan.id,
name: plan.name || '',
slug: plan.slug || '',
description: plan.description || '',
price: plan.price || '',
billing_cycle: plan.billing_cycle || 'monthly',
trial_days: plan.trial_days ?? 0,
max_projects: plan.max_projects ?? 0,
max_organizations: plan.max_organizations ?? 0,
max_users: plan.max_users ?? 0,
max_roles: plan.max_roles ?? 0,
permission_ids: collectPermissionIdsByKeys(
permissionTree,
plan.permissions || [],
),
is_active: plan.is_active,
is_custom: plan.is_custom,
});
},
[permissionTree, reset],
);
const setPermissionIds = useCallback(
(ids: number[]) =>
setValue('permission_ids', ids, {
shouldDirty: true,
shouldValidate: true,
}),
[setValue],
);
return {
register,
control,
onSubmit,
openCreate,
openEdit,
planId,
permissionIds,
setPermissionIds,
isSaving: isSubmitting || saveMutation.isPending,
};
}