feat(forms): implement dynamic form builder for admin and company creation
continuous-integration/drone/push Build is passing

- Introduced DynamicFormBuilder component to streamline form creation for admin and company categories.
- Refactored CreateAdmin and CreateCompany components to utilize the new dynamic form structure.
- Added createAdminFormSections and createCompanyFormSections functions to define form fields and validation rules.
- Enhanced form handling with improved error management and dynamic field rendering.

This update enhances maintainability and scalability of forms across the application.
This commit is contained in:
AmirReza Jamali
2026-06-21 09:03:51 +03:30
parent 5a6a5346c6
commit 90a42b9fc5
22 changed files with 1717 additions and 1392 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ export * from "./useNotificationQueries";
export * from "./useProfileQueries";
export * from "./useTenders";
export * from "./useUsersQueries";
export * from "./useAdminListQuery";
export * from "./useAdminQueries";
export * from "./useSelectSearchQuery";
export * from "./useDashboardQueries";
export * from "./useFilesQueries";
-11
View File
@@ -1,11 +0,0 @@
import { API_ENDPOINTS, userService } from "@/lib/api";
import { useQuery } from "@tanstack/react-query";
import { useMemo } from "react";
export const useGetAdminListQuery = (params?: Record<string, any>) => {
const queryKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, params], [params]);
return useQuery({
queryKey,
queryFn: () => userService.adminsList(params),
});
};
+163
View File
@@ -0,0 +1,163 @@
import { API_ENDPOINTS, userService } from "@/lib/api";
import {
useInfiniteQuery,
useMutation,
useQuery,
useQueryClient,
} from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { useMemo } from "react";
import { toast } from "react-toastify";
export const useDeleteAdmin = (onSuccessCallback: () => void) => {
const queryClient = useQueryClient();
const mutationKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, "delete"], []);
return useMutation({
mutationKey,
mutationFn: userService.deleteAdmin,
onSuccess: (response) => {
toast.info(response.data.message);
onSuccessCallback();
queryClient.invalidateQueries({
queryKey: [API_ENDPOINTS.USER.ADMINS],
});
},
});
};
export const useCreateAdmin = () => {
const queryClient = useQueryClient();
const router = useRouter();
const mutationKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, "create"], []);
return useMutation({
mutationKey,
mutationFn: userService.createAdmin,
onSuccess: (response) => {
toast.success(response);
queryClient.invalidateQueries({
queryKey: [API_ENDPOINTS.USER.ADMINS],
});
router.push("/admins");
},
});
};
export const useUpdateAdmin = (id: string) => {
const queryClient = useQueryClient();
const router = useRouter();
const mutationKey = useMemo(
() => [API_ENDPOINTS.USER.ADMINS, "update", id],
[id],
);
return useMutation({
mutationKey,
mutationFn: userService.updateAdmin,
onSuccess: (response) => {
toast.success(response);
queryClient.invalidateQueries({
queryKey: [API_ENDPOINTS.USER.ADMINS],
});
router.push("/admins");
},
});
};
export const useAdminDetails = (id: string) => {
const queryKey = useMemo(
() => [API_ENDPOINTS.USER.ADMINS, "details", id],
[id],
);
return useQuery({
queryKey,
queryFn: () => userService.adminDetails(id),
});
};
export const useAdminListInfiniteQuery = (
params?: Record<string, any>,
options?: { enabled?: boolean },
) => {
const enabled = options?.enabled ?? true;
const queryKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, params], [params]);
return useInfiniteQuery({
queryKey,
queryFn: ({ pageParam = 0 }) =>
userService.adminsList({ ...params, offset: pageParam }),
initialPageParam: 0,
enabled,
getNextPageParam: (lastPage) => {
if (!lastPage.meta) {
return undefined;
}
const { offset, limit, total } = lastPage.meta;
const nextOffset = offset + limit;
return nextOffset < total ? nextOffset : undefined;
},
});
};
export const useGetAdminListQuery = (params?: Record<string, any>) => {
const queryKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, params], [params]);
return useQuery({
queryKey,
queryFn: () => userService.adminsList(params),
});
};
export const useGetUsersQuery = (params?: Record<string, any>) => {
const queryKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, params], [params]);
return useQuery({
queryKey,
queryFn: () => userService.adminsList(params),
});
};
export const useResetAdminPassword = ({
successCallback,
}: {
successCallback?: (password: string) => void;
} = {}) => {
const mutationKey = useMemo(
() => [API_ENDPOINTS.USER.ADMINS, "reset-password"],
[],
);
return useMutation({
mutationKey,
mutationFn: userService.resetAdminPassword,
onSuccess: (response) => {
toast.success(response.message);
successCallback?.(response.data.password);
},
});
};
export const useChangeAdminStatus = ({
id,
successCallback,
}: {
id: string;
successCallback: () => void;
}) => {
const queryClient = useQueryClient();
const mutationKey = useMemo(
() => [API_ENDPOINTS.USER.CHANGE_ADMIN_STATUS(id)],
[id],
);
return useMutation({
mutationKey,
mutationFn: userService.changeAdminStatus,
onSuccess: ({ message }: { message: string }) => {
successCallback();
toast.success(message);
queryClient.invalidateQueries({
queryKey: [API_ENDPOINTS.USER.ADMINS],
});
},
});
};
+6 -152
View File
@@ -1,19 +1,11 @@
import { useUser } from "@/contexts";
import { API_ENDPOINTS, userService } from "@/lib/api";
import {
useInfiniteQuery,
useMutation,
useQuery,
useQueryClient,
} from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { useMutation } from "@tanstack/react-query";
import { useMemo } from "react";
import { toast } from "react-toastify";
export const useLoginQuery = (callback?: () => void) => {
const mutationKey = useMemo(() => [API_ENDPOINTS.USER.LOGIN], []);
const { setAuthState } = useUser();
const router = useRouter();
return useMutation({
mutationKey,
mutationFn: userService.login,
@@ -28,153 +20,15 @@ export const useLoginQuery = (callback?: () => void) => {
});
};
export const useDeleteAdmin = (onSuccessCallback: () => void) => {
const queryClient = useQueryClient();
const mutationKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, "delete"], []);
return useMutation({
mutationKey,
mutationFn: userService.deleteAdmin,
onSuccess: (response) => {
toast.info(response.data.message);
onSuccessCallback();
queryClient.invalidateQueries({
queryKey: [API_ENDPOINTS.USER.ADMINS],
});
},
});
};
export const useLogoutQuery = () => {
const queryKey = useMemo(() => [API_ENDPOINTS.USER.LOGOUT], []);
const { logout } = useUser();
const mutationKey = useMemo(() => [API_ENDPOINTS.USER.LOGOUT], []);
return useQuery({
queryKey,
queryFn: userService.logout,
});
};
export const useCreateAdmin = () => {
const queryClient = useQueryClient();
const router = useRouter();
const mutationKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, "create"], []);
return useMutation({
mutationKey,
mutationFn: userService.createAdmin,
onSuccess: (response) => {
toast.success(response);
queryClient.invalidateQueries({
queryKey: [API_ENDPOINTS.USER.ADMINS],
});
router.push("/admins");
},
});
};
export const useUpdateAdmin = (id: string) => {
const queryClient = useQueryClient();
const router = useRouter();
const mutationKey = useMemo(
() => [API_ENDPOINTS.USER.ADMINS, "update", id],
[id],
);
return useMutation({
mutationKey,
mutationFn: userService.updateAdmin,
onSuccess: (response) => {
toast.success(response);
queryClient.invalidateQueries({
queryKey: [API_ENDPOINTS.USER.ADMINS],
});
router.push("/admins");
},
});
};
export const useAdminDetails = (id: string) => {
const queryKey = useMemo(
() => [API_ENDPOINTS.USER.ADMINS, "details", id],
[id],
);
return useQuery({
queryKey,
queryFn: () => userService.adminDetails(id),
});
};
export const useAdminListInfiniteQuery = (
params?: Record<string, any>,
options?: { enabled?: boolean },
) => {
const enabled = options?.enabled ?? true;
const queryKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, params], [params]);
return useInfiniteQuery({
queryKey,
queryFn: ({ pageParam = 0 }) =>
userService.adminsList({ ...params, offset: pageParam }),
initialPageParam: 0,
enabled,
getNextPageParam: (lastPage) => {
if (!lastPage.meta) {
return undefined;
}
const { offset, limit, total } = lastPage.meta;
const nextOffset = offset + limit;
return nextOffset < total ? nextOffset : undefined;
},
});
};
export const useGetUsersQuery = (params?: Record<string, any>) => {
const queryKey = useMemo(() => [API_ENDPOINTS.USER.ADMINS, params], [params]);
return useQuery({
queryKey,
queryFn: () => userService.adminsList(params),
});
};
export const useResetAdminPassword = ({
successCallback,
}: {
successCallback?: (password: string) => void;
} = {}) => {
const mutationKey = useMemo(
() => [API_ENDPOINTS.USER.ADMINS, "reset-password"],
[],
);
return useMutation({
mutationKey,
mutationFn: userService.resetAdminPassword,
onSuccess: (response) => {
toast.success(response.message);
successCallback?.(response.data.password);
},
});
};
export const useChangeAdminStatus = ({
id,
successCallback,
}: {
id: string;
successCallback: () => void;
}) => {
const queryClient = useQueryClient();
const mutationKey = useMemo(
() => [API_ENDPOINTS.USER.CHANGE_ADMIN_STATUS(id)],
[id],
);
return useMutation({
mutationKey,
mutationFn: userService.changeAdminStatus,
onSuccess: ({ message }: { message: string }) => {
successCallback();
toast.success(message);
queryClient.invalidateQueries({
queryKey: [API_ENDPOINTS.USER.ADMINS],
});
mutationFn: () => userService.logout(),
onSuccess: () => {
logout();
},
});
};