feat(tables): integrate EmptyListWrapper component for improved empty state handling

- Add EmptyListWrapper to various tables (Admins, Companies, Customers, Feedback, Notification History, Tenders) to provide a consistent empty state message when no data is available.
- Update phone number and status display logic in the Profile page to handle null values gracefully.
- Introduce worktree setup configuration in worktrees.json for easier project setup.
This commit is contained in:
AmirReza Jamali
2026-02-10 18:19:49 +03:30
parent 7755384d51
commit da82399d07
13 changed files with 240 additions and 202 deletions
+5
View File
@@ -0,0 +1,5 @@
{
"setup-worktree": [
"npm install"
]
}
+2 -2
View File
@@ -62,7 +62,7 @@ export default function Page() {
<div> <div>
<p className="font-medium text-dark dark:text-white">Phone</p> <p className="font-medium text-dark dark:text-white">Phone</p>
<p className="text-gray-600 dark:text-gray-300"> <p className="text-gray-600 dark:text-gray-300">
{formatPhoneNumber(data?.phone)} {data?.phone ? formatPhoneNumber(data?.phone) : "-"}
</p> </p>
</div> </div>
<div> <div>
@@ -84,7 +84,7 @@ export default function Page() {
<div> <div>
<p className="font-medium text-dark dark:text-white">Status</p> <p className="font-medium text-dark dark:text-white">Status</p>
<div className="w-fit"> <div className="w-fit">
<Status status={data?.status}>{data?.status}</Status> <Status status={data?.status ?? ""}>{data?.status ?? "-"}</Status>
</div> </div>
</div> </div>
</div> </div>
+74 -77
View File
@@ -1,6 +1,7 @@
"use client"; "use client";
import { PencilSquareIcon, TrashIcon, UserSettingIcon } from "@/assets/icons"; import { PencilSquareIcon, TrashIcon, UserSettingIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import ConfirmationModal from "@/components/ui/ConfirmationModal"; import ConfirmationModal from "@/components/ui/ConfirmationModal";
import ListHeader from "@/components/ui/ListHeader"; import ListHeader from "@/components/ui/ListHeader";
import Modal from "@/components/ui/modal"; import Modal from "@/components/ui/modal";
@@ -65,85 +66,81 @@ const AdminsTable = () => {
</TableHeader> </TableHeader>
{isPending && <TableSkeleton column={columns.length} />} {isPending && <TableSkeleton column={columns.length} />}
<TableBody> <TableBody>
{!allUsers.length ? ( <EmptyListWrapper
<TableRow> list={allUsers}
<TableCell> columns={columns}
<h2>No user</h2> emptyMessage="No admins were found"
</TableCell> >
</TableRow> {allUsers.map((item, index) => (
) : ( <TableRow
allUsers.map((item, index) => { key={item?.id || index}
return ( className="odd:bg-gray-2 dark:odd:bg-gray-7"
<TableRow >
key={item?.id || index} <TableCell className="text-start" colSpan={100}>
className="odd:bg-gray-2 dark:odd:bg-gray-7" {index + 1}
> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{index + 1} {item?.full_name}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{item?.full_name} {item?.email}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}>
{item?.email}
</TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
{item?.username} {item?.username}
</TableCell> </TableCell>
<TableCell className="text-start" colSpan={100}> <TableCell className="text-start" colSpan={100}>
<Status status={item?.status ?? ""}>{item?.status}</Status> <Status status={item?.status ?? ""}>{item?.status}</Status>
</TableCell> </TableCell>
<TableCell className="text-start xl:pr-7.5"> <TableCell className="text-start xl:pr-7.5">
<div className="flex items-center justify-start gap-x-3.5"> <div className="flex items-center justify-start gap-x-3.5">
<button <button
data-tooltip-id="delete" data-tooltip-id="delete"
data-tooltip-content="Delete" data-tooltip-content="Delete"
data-tooltip-place="top" data-tooltip-place="top"
className="hover:text-red-500" className="hover:text-red-500"
onClick={() => { onClick={() => {
setCurrentUser(item); setCurrentUser(item);
setIsModalOpen(true); setIsModalOpen(true);
}} }}
> >
<Tooltip {..._TooltipDefaultParams({ id: "delete" })} /> <Tooltip {..._TooltipDefaultParams({ id: "delete" })} />
<span className="sr-only">Delete Admin </span> <span className="sr-only">Delete Admin </span>
<TrashIcon /> <TrashIcon />
</button> </button>
<button <button
data-tooltip-id="change-status" data-tooltip-id="change-status"
data-tooltip-content="Change status" data-tooltip-content="Change status"
data-tooltip-place="top" data-tooltip-place="top"
className="hover:text-yellow-dark" className="hover:text-yellow-dark"
onClick={() => { onClick={() => {
setCurrentUser(item); setCurrentUser(item);
setIsChangeStatusModalOpen(true); setIsChangeStatusModalOpen(true);
}} }}
> >
<Tooltip <Tooltip
{..._TooltipDefaultParams({ id: "change-status" })} {..._TooltipDefaultParams({ id: "change-status" })}
/> />
<span className="sr-only">Change Admin Status</span> <span className="sr-only">Change Admin Status</span>
<UserSettingIcon /> <UserSettingIcon />
</button> </button>
<button <button
data-tooltip-id="edit" data-tooltip-id="edit"
data-tooltip-content="Edit" data-tooltip-content="Edit"
data-tooltip-place="top" data-tooltip-place="top"
className="hover:text-primary" className="hover:text-primary"
onClick={() => router.push(`/admins/edit/${item.id}`)} onClick={() => router.push(`/admins/edit/${item.id}`)}
> >
<Tooltip {..._TooltipDefaultParams({ id: "edit" })} /> <Tooltip {..._TooltipDefaultParams({ id: "edit" })} />
<span className="sr-only">Edit Admin </span> <span className="sr-only">Edit Admin </span>
<PencilSquareIcon /> <PencilSquareIcon />
</button> </button>
</div> </div>
</TableCell> </TableCell>
</TableRow> </TableRow>
); ))}
}) </EmptyListWrapper>
)}
</TableBody> </TableBody>
</Table> </Table>
<Modal <Modal
@@ -40,7 +40,7 @@ export const useAdminsPresenter = () => {
} = useForm<TChangeAdminStatusCredentials>({ } = useForm<TChangeAdminStatusCredentials>({
mode: "onChange", mode: "onChange",
defaultValues: { defaultValues: {
status: currentUser?.status, status: currentUser?.status ?? "",
}, },
}); });
const [params, setParams] = useState<Record<string, any>>({}); const [params, setParams] = useState<Record<string, any>>({});
@@ -1,6 +1,7 @@
"use client"; "use client";
import { PencilSquareIcon, TrashIcon } from "@/assets/icons"; import { PencilSquareIcon, TrashIcon } from "@/assets/icons";
import { Switch } from "@/components/FormElements/switch"; import { Switch } from "@/components/FormElements/switch";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import ConfirmationModal from "@/components/ui/ConfirmationModal"; import ConfirmationModal from "@/components/ui/ConfirmationModal";
import IsVisible from "@/components/ui/IsVisible"; import IsVisible from "@/components/ui/IsVisible";
import { import {
@@ -44,6 +45,15 @@ const CompanyCategoriesTable = () => {
isMutating, isMutating,
} = useCompanyCategoriesPresenter(); } = useCompanyCategoriesPresenter();
const columns = [
"Row",
"Title",
"Description",
"Created at",
"Published",
"Actions",
];
return ( return (
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card"> <div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
<ListHeader <ListHeader
@@ -61,77 +71,75 @@ const CompanyCategoriesTable = () => {
<TableHead colSpan={100}>Actions</TableHead> <TableHead colSpan={100}>Actions</TableHead>
</TableRow> </TableRow>
</TableHeader> </TableHeader>
{isLoading && <TableSkeleton column={6} />} {isLoading && <TableSkeleton column={columns.length} />}
<TableBody> <TableBody>
<IsVisible condition={!categories}> <EmptyListWrapper
<TableRow> list={categories ?? []}
<TableCell colSpan={400} className="text-center"> columns={columns}
<h6>No category found</h6> emptyMessage="No categories were found"
</TableCell> >
</TableRow> {(categories ?? []).map((category, index) => (
</IsVisible> <TableRow
<IsVisible condition={!!categories}> key={category.id}
{categories?.map((category, index) => { className="odd:bg-gray-2 dark:odd:bg-gray-7"
return ( >
<TableRow key={category.id}> <TableCell colSpan={100}>{index + 1}</TableCell>
<TableCell colSpan={100}>{index + 1}</TableCell> <TableCell colSpan={100}>{category.name}</TableCell>
<TableCell colSpan={100}>{category.name}</TableCell> <TableCell colSpan={100}>{category.description}</TableCell>
<TableCell colSpan={100}>{category.description}</TableCell> <TableCell colSpan={100}>
<TableCell colSpan={100}> {unixToDate({ unix: category.created_at, hasTime: true })}
{unixToDate({ unix: category.created_at, hasTime: true })} </TableCell>
</TableCell> <TableCell colSpan={100}>
<TableCell colSpan={100}> <IsVisible condition={isToggling}>
<IsVisible condition={isToggling}> <Skeleton className="h-8 bg-neutral-400 dark:bg-dark-4" />
<Skeleton className="h-8 bg-neutral-400 dark:bg-dark-4" /> </IsVisible>
</IsVisible> <IsVisible condition={!isToggling}>
<IsVisible condition={!isToggling}> <Switch
<Switch withIcon
withIcon onChange={(e) => {
onChange={(e) => { togglePublished(category.id);
togglePublished(category.id); }}
}} checked={category.published}
checked={category.published} onToggle={(e) => {
onToggle={(e) => { console.log(e);
console.log(e); }}
}} />
/> </IsVisible>
</IsVisible> </TableCell>
</TableCell> <TableCell className="text-start xl:pr-7.5">
<TableCell className="text-start xl:pr-7.5"> <div className="flex items-center justify-start gap-x-3.5">
<div className="flex items-center justify-start gap-x-3.5"> <button
<button data-tooltip-id="delete"
data-tooltip-id="delete" data-tooltip-content="Delete"
data-tooltip-content="Delete" data-tooltip-place="top"
data-tooltip-place="top" className="hover:text-red-500"
className="hover:text-red-500" onClick={() => {
onClick={() => { setCurrentCategory(category);
setCurrentCategory(category); setIsModalOpen(true);
setIsModalOpen(true); }}
}} >
> <Tooltip {..._TooltipDefaultParams({ id: "delete" })} />
<Tooltip {..._TooltipDefaultParams({ id: "delete" })} /> <span className="sr-only">Delete Admin </span>
<span className="sr-only">Delete Admin </span> <TrashIcon />
<TrashIcon /> </button>
</button> <button
<button data-tooltip-id="edit"
data-tooltip-id="edit" data-tooltip-content="Edit"
data-tooltip-content="Edit" data-tooltip-place="top"
data-tooltip-place="top" className="hover:text-primary"
className="hover:text-primary" onClick={() =>
onClick={() => router.push(`${pathName}/edit/${category.id}`)
router.push(`${pathName}/edit/${category.id}`) }
} >
> <Tooltip {..._TooltipDefaultParams({ id: "edit" })} />
<Tooltip {..._TooltipDefaultParams({ id: "edit" })} /> <span className="sr-only">Edit Category</span>
<span className="sr-only">Edit Category</span> <PencilSquareIcon />
<PencilSquareIcon /> </button>
</button> </div>
</div> </TableCell>
</TableCell> </TableRow>
</TableRow> ))}
); </EmptyListWrapper>
})}
</IsVisible>
</TableBody> </TableBody>
</Table> </Table>
<Modal <Modal
+12 -6
View File
@@ -5,6 +5,7 @@ import {
PencilSquareIcon, PencilSquareIcon,
TrashIcon, TrashIcon,
} from "@/assets/icons"; } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import ConfirmationModal from "@/components/ui/ConfirmationModal"; import ConfirmationModal from "@/components/ui/ConfirmationModal";
import { import {
Table, Table,
@@ -44,6 +45,9 @@ const CompaniesTable = () => {
setFilterValue, setFilterValue,
isMutating, isMutating,
} = useCompanyListPresenter(); } = useCompanyListPresenter();
const companies = allCompanies.filter(
(c): c is NonNullable<typeof c> => c != null,
);
return ( return (
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card"> <div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
<ListHeader <ListHeader
@@ -66,10 +70,12 @@ const CompaniesTable = () => {
</TableHeader> </TableHeader>
{isPending && <TableSkeleton column={columns.length} />} {isPending && <TableSkeleton column={columns.length} />}
<TableBody> <TableBody>
{allCompanies.map((company, index) => <EmptyListWrapper
!company ? ( list={companies}
<h6 key={index}>No Data was Found</h6> columns={columns}
) : ( emptyMessage="No companies were found"
>
{companies.map((company, index) => (
<TableRow <TableRow
key={company.id} key={company.id}
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
@@ -156,8 +162,8 @@ const CompaniesTable = () => {
</div> </div>
</TableCell> </TableCell>
</TableRow> </TableRow>
), ))}
)} </EmptyListWrapper>
</TableBody> </TableBody>
</Table> </Table>
<Modal <Modal
+14
View File
@@ -5,6 +5,7 @@ import { Building } from "@/components/Layouts/sidebar/icons";
import ConfirmationModal from "@/components/ui/ConfirmationModal"; import ConfirmationModal from "@/components/ui/ConfirmationModal";
import ListHeader from "@/components/ui/ListHeader"; import ListHeader from "@/components/ui/ListHeader";
import Modal from "@/components/ui/modal"; import Modal from "@/components/ui/modal";
import Pagination from "@/components/ui/pagination";
import Status from "@/components/ui/Status"; import Status from "@/components/ui/Status";
import { import {
Table, Table,
@@ -30,6 +31,7 @@ const CustomersTable = () => {
router, router,
columns, columns,
allCustomers, allCustomers,
metadata,
isModalOpen, isModalOpen,
assignSelectedCompanies, assignSelectedCompanies,
selectedCompanies, selectedCompanies,
@@ -48,6 +50,7 @@ const CustomersTable = () => {
watch, watch,
setFilterValue, setFilterValue,
isMutating, isMutating,
setParams,
} = useCustomerListPresenter(); } = useCustomerListPresenter();
return ( return (
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card"> <div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
@@ -170,6 +173,17 @@ const CustomersTable = () => {
</EmptyListWrapper> </EmptyListWrapper>
</TableBody> </TableBody>
</Table> </Table>
<Pagination
currentPage={metadata?.page ? metadata?.page - 1 : 0}
totalPages={metadata?.pages ?? 1}
onPageChange={(e) => {
setParams((currentParams) => ({
...currentParams,
offset: e.selected * (metadata?.limit ?? 10),
limit: metadata?.limit ?? 10,
}));
}}
/>
<Modal <Modal
isOpen={isFilterModalOpen} isOpen={isFilterModalOpen}
onClose={() => setIsFilterModalOpen(false)} onClose={() => setIsFilterModalOpen(false)}
@@ -2,14 +2,15 @@
import { import {
useAssignCompany, useAssignCompany,
useCustomersInfiniteQuery, useCustomersQuery,
useDeleteCustomerQuery, useDeleteCustomerQuery,
} from "@/hooks/queries"; } from "@/hooks/queries";
import { TAssignCustomerToCompanyCredentials, TCustomer } from "@/lib/api"; import { TAssignCustomerToCompanyCredentials, TCustomer } from "@/lib/api";
import { apiDefaultParams } from "@/constants/Api_Params";
import { deleteEmptyKeys } from "@/utils/shared"; import { deleteEmptyKeys } from "@/utils/shared";
import { useIsMutating } from "@tanstack/react-query"; import { useIsMutating } from "@tanstack/react-query";
import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { usePathname, useRouter } from "next/navigation";
import { useEffect, useState } from "react"; import { useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
const useCustomerListPresenter = () => { const useCustomerListPresenter = () => {
@@ -25,8 +26,9 @@ const useCustomerListPresenter = () => {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const pathName = usePathname(); const pathName = usePathname();
const searchParams = useSearchParams(); const [params, setParams] = useState<Record<string, any>>({
const [params, setParams] = useState<Record<string, any>>({}); ...apiDefaultParams,
});
const router = useRouter(); const router = useRouter();
const isMutating = useIsMutating(); const isMutating = useIsMutating();
@@ -38,18 +40,7 @@ const useCustomerListPresenter = () => {
setValue: setFilterValue, setValue: setFilterValue,
} = useForm(); } = useForm();
useEffect(() => { const { data, isPending } = useCustomersQuery(params);
const newParams: Record<string, any> = {
sort: "created_at",
};
for (const [key, value] of searchParams.entries()) {
newParams[key] = value;
}
setParams(newParams);
filterFormReset(newParams);
}, [searchParams, filterFormReset]);
const { data, isPending } = useCustomersInfiniteQuery(params);
const { mutate: deleteCustomer } = useDeleteCustomerQuery(() => const { mutate: deleteCustomer } = useDeleteCustomerQuery(() =>
setIsModalOpen(false), setIsModalOpen(false),
); );
@@ -61,8 +52,9 @@ const useCustomerListPresenter = () => {
); );
const search = (data: any) => { const search = (data: any) => {
const newParams = { ...params, ...data }; const newParams = { ...params, ...data, offset: 0 };
const cleanedParams = deleteEmptyKeys(newParams); const cleanedParams = deleteEmptyKeys(newParams);
setParams(cleanedParams);
const queryString = new URLSearchParams(cleanedParams).toString(); const queryString = new URLSearchParams(cleanedParams).toString();
router.push(`${pathName}?${queryString}`); router.push(`${pathName}?${queryString}`);
setIsFilterModalOpen(false); setIsFilterModalOpen(false);
@@ -85,9 +77,10 @@ const useCustomerListPresenter = () => {
} }
}; };
const customers = data?.pages.flatMap((page) => page.data.customers) ?? []; const customers = data?.data?.customers ?? [];
return { return {
allCustomers: customers, allCustomers: customers,
metadata: data?.meta,
currentCustomer, currentCustomer,
columns, columns,
isPending, isPending,
@@ -110,6 +103,7 @@ const useCustomerListPresenter = () => {
watch, watch,
setFilterValue, setFilterValue,
isMutating, isMutating,
setParams,
}; };
}; };
+9 -10
View File
@@ -1,4 +1,5 @@
import { ExclamationIcon } from "@/assets/icons"; import { ExclamationIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import { import {
Table, Table,
TableBody, TableBody,
@@ -48,14 +49,12 @@ const FeedbackTable = ({ id, paramKey }: IProps) => {
{isLoading && <TableSkeleton column={columns.length} />} {isLoading && <TableSkeleton column={columns.length} />}
<TableBody> <TableBody>
{!feedback?.length ? ( <EmptyListWrapper
<TableRow className="w-full"> list={feedback ?? []}
<TableCell colSpan={500} className="text-center"> columns={columns}
<h2>No feedback</h2> emptyMessage="No feedback were found"
</TableCell> >
</TableRow> {(feedback ?? []).map((item, index) => (
) : (
feedback?.map((item, index) => (
<TableRow <TableRow
key={item.id} key={item.id}
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
@@ -87,8 +86,8 @@ const FeedbackTable = ({ id, paramKey }: IProps) => {
</button> </button>
</TableCell> </TableCell>
</TableRow> </TableRow>
)) ))}
)} </EmptyListWrapper>
</TableBody> </TableBody>
</Table> </Table>
</ShowcaseSection> </ShowcaseSection>
@@ -1,5 +1,6 @@
"use client"; "use client";
import { EyeIcon } from "@/assets/icons"; import { EyeIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import { ShowcaseSection } from "@/components/Layouts/showcase-section"; import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import Pagination from "@/components/ui/pagination"; import Pagination from "@/components/ui/pagination";
import Status from "@/components/ui/Status"; import Status from "@/components/ui/Status";
@@ -60,14 +61,12 @@ const NotificationHistoryTable = () => {
</TableHeader> </TableHeader>
{isLoading && <TableSkeleton column={columns.length} />} {isLoading && <TableSkeleton column={columns.length} />}
<TableBody> <TableBody>
{!notificationHistory?.length ? ( <EmptyListWrapper
<TableRow> list={notificationHistory ?? []}
<TableCell> columns={columns}
<h2>No notifications</h2> emptyMessage="No notifications were found"
</TableCell> >
</TableRow> {(notificationHistory ?? []).map((item, index) => (
) : (
notificationHistory.map((item, index) => (
<TableRow key={item.id}> <TableRow key={item.id}>
<TableCell colSpan={100}>{index + 1}</TableCell> <TableCell colSpan={100}>{index + 1}</TableCell>
<TableCell colSpan={100}>{item.title}</TableCell> <TableCell colSpan={100}>{item.title}</TableCell>
@@ -114,8 +113,8 @@ const NotificationHistoryTable = () => {
</button> </button>
</TableCell> </TableCell>
</TableRow> </TableRow>
)) ))}
)} </EmptyListWrapper>
</TableBody> </TableBody>
</Table> </Table>
<Pagination <Pagination
+10 -6
View File
@@ -1,5 +1,6 @@
"use client"; "use client";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import Status from "@/components/ui/Status"; import Status from "@/components/ui/Status";
import { import {
Table, Table,
@@ -13,6 +14,7 @@ import { Tooltip } from "react-tooltip";
import useTenderListPresenter from "./useTenderListPresenter"; import useTenderListPresenter from "./useTenderListPresenter";
import { ExclamationIcon, EyeIcon } from "@/assets/icons"; import { ExclamationIcon, EyeIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import ListHeader from "@/components/ui/ListHeader"; import ListHeader from "@/components/ui/ListHeader";
import Modal from "@/components/ui/modal"; import Modal from "@/components/ui/modal";
import Pagination from "@/components/ui/pagination"; import Pagination from "@/components/ui/pagination";
@@ -58,10 +60,12 @@ const TendersTable = () => {
{isPending && <TableSkeleton column={columns.length} />} {isPending && <TableSkeleton column={columns.length} />}
<TableBody> <TableBody>
{allTenders?.data.tenders?.map((item, index) => <EmptyListWrapper
!item ? ( list={allTenders?.data.tenders ?? []}
<h6 key={index}>No tenders were found</h6> columns={columns}
) : ( emptyMessage="No tenders were found"
>
{(allTenders?.data.tenders ?? []).map((item, index) => (
<TableRow <TableRow
key={item.id} key={item.id}
className="odd:bg-gray-2 dark:odd:bg-gray-7" className="odd:bg-gray-2 dark:odd:bg-gray-7"
@@ -121,8 +125,8 @@ const TendersTable = () => {
</button> </button>
</TableCell> </TableCell>
</TableRow> </TableRow>
), ))}
)} </EmptyListWrapper>
</TableBody> </TableBody>
</Table> </Table>
<Modal <Modal
@@ -66,7 +66,7 @@ const useCreateNotificationFormPresenter = () => {
], ],
[NotificationTargetGroups.SPECIFIC_USERS]: [NotificationTargetGroups.SPECIFIC_USERS]:
users?.data.users?.map((user) => ({ users?.data.users?.map((user) => ({
label: user.full_name, label: user.full_name ?? "",
value: user.id, value: user.id,
})) ?? null, })) ?? null,
[NotificationTargetGroups.SPECIFIC_CUSTOMER]: [NotificationTargetGroups.SPECIFIC_CUSTOMER]:
+12
View File
@@ -36,6 +36,18 @@ export const useCustomersInfiniteQuery = (params?: Record<string, any>) => {
}, },
}); });
}; };
export const useCustomersQuery = (params?: Record<string, any>) => {
const queryKey = useMemo(
() => [API_ENDPOINTS.CUSTOMERS.READ_ALL, params],
[params],
);
return useQuery({
queryKey,
queryFn: () => customersService.getCustomers(params),
});
};
export const useGetAllCustomers = () => { export const useGetAllCustomers = () => {
const queryKey = useMemo(() => ["GET ALL CUSTOMERS"], []); const queryKey = useMemo(() => ["GET ALL CUSTOMERS"], []);
return useQuery({ return useQuery({