feat(form): Add clearable functionality to Select component

This commit introduces a new `clearable` prop to the `Select` component, allowing users to easily reset its value.

When the `clearable` prop is set to true, a clear button (an 'X' icon) is displayed when an option is selected. Clicking this button resets the select input to its initial placeholder state and triggers an optional `onClear` callback.

To support this, the component's internal state management was refactored to control the input's value.

Additionally, the `AdminListFilters` component has been updated to:
- Utilize the new clearable select for the status filter.
- Consolidate multiple search fields (email, username, full_name) into a single generic "search" input.
- Add explicit "Reset" and "Apply" buttons for better filter management.
This commit is contained in:
AmirReza Jamali
2025-10-13 12:26:56 +03:30
parent 5b73389d64
commit f84c21f829
8 changed files with 257 additions and 116 deletions
@@ -2,12 +2,14 @@
import { apiDefaultParams } from "@/constants/Api_Params";
import { AdminStatus } from "@/constants/enums";
import { deleteEmptyKeys } from "@/utils/shared";
import {
useAdminListInfiniteQuery,
useChangeAdminStatus,
useDeleteAdmin,
useGetAdminListQuery,
} from "@/hooks/queries";
import { IUser, TChangeAdminStatusCredentials } from "@/lib/api";
import { API_ENDPOINTS, IUser, TChangeAdminStatusCredentials } from "@/lib/api";
import { useIsMutating, useQueryClient } from "@tanstack/react-query";
import { usePathname, useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
@@ -20,7 +22,12 @@ export const useAdminsPresenter = () => {
const [status, setStatus] = useState<string>(
currentUser?.status ?? AdminStatus.ACTIVE,
);
const isMutating = useIsMutating();
const router = useRouter();
const { register: filterRegister, handleSubmit: handleFilterSubmit } =
useForm();
const queryClient = useQueryClient();
const {
register,
formState: { errors },
@@ -33,9 +40,11 @@ export const useAdminsPresenter = () => {
});
const [params, setParams] = useState<Record<string, any>>({
...apiDefaultParams,
offset: 0,
limit: 10,
});
const pathName = usePathname();
const { data, isPending } = useAdminListInfiniteQuery(params);
const { data, isPending } = useGetAdminListQuery(params);
const { mutate: deleteAdmin } = useDeleteAdmin(() => {
setIsModalOpen(false);
});
@@ -51,7 +60,16 @@ export const useAdminsPresenter = () => {
setIsChangeStatusModalOpen(false);
},
});
const allUsers = data?.pages.flatMap((page) => page.data.users) ?? [];
const search = (data: any) => {
setParams((prevParams) => {
const newParams = { ...prevParams, ...data, offset: 0 };
return deleteEmptyKeys(newParams);
});
setIsFilterModalOpen(false);
};
const allUsers = data?.data?.users ?? [];
const metadata = data?.meta;
const columns = [
"row",
"full name",
@@ -63,11 +81,13 @@ export const useAdminsPresenter = () => {
];
return {
allUsers,
metadata,
columns,
isPending,
onConfirmDelete,
isModalOpen,
setIsModalOpen,
isMutating,
router,
setCurrentUser,
pathName,
@@ -82,5 +102,9 @@ export const useAdminsPresenter = () => {
handleSubmit,
isFilterModalOpen,
setIsFilterModalOpen,
setParams,
filterRegister,
handleFilterSubmit,
search,
};
};