da82399d07
- 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.
244 lines
8.5 KiB
TypeScript
244 lines
8.5 KiB
TypeScript
"use client";
|
|
import { ExclamationIcon, PencilSquareIcon, TrashIcon } from "@/assets/icons";
|
|
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
|
|
import { Building } from "@/components/Layouts/sidebar/icons";
|
|
import ConfirmationModal from "@/components/ui/ConfirmationModal";
|
|
import ListHeader from "@/components/ui/ListHeader";
|
|
import Modal from "@/components/ui/modal";
|
|
import Pagination from "@/components/ui/pagination";
|
|
import Status from "@/components/ui/Status";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
import TableSkeleton from "@/components/ui/TableSkeleton";
|
|
import { _TooltipDefaultParams } from "@/constants/tooltip";
|
|
import { unixToDate } from "@/utils/shared";
|
|
import { toast } from "react-toastify";
|
|
import { Tooltip } from "react-tooltip";
|
|
import AssignToCompanyModalContent from "./AssignToCompanyModalContent";
|
|
import CustomerListFilters from "./CustomerListFilters";
|
|
import useCustomerListPresenter from "./useCustomerListPresenter";
|
|
|
|
const CustomersTable = () => {
|
|
const {
|
|
isPending,
|
|
pathName,
|
|
router,
|
|
columns,
|
|
allCustomers,
|
|
metadata,
|
|
isModalOpen,
|
|
assignSelectedCompanies,
|
|
selectedCompanies,
|
|
currentCustomer,
|
|
setSelectedCompanies,
|
|
setIsModalOpen,
|
|
onConfirmDelete,
|
|
setCurrentCustomer,
|
|
isAssignCompanyModalOpen,
|
|
setIsAssignCompanyModalOpen,
|
|
isFilterModalOpen,
|
|
setIsFilterModalOpen,
|
|
filterRegister,
|
|
handleFilterSubmit,
|
|
search,
|
|
watch,
|
|
setFilterValue,
|
|
isMutating,
|
|
setParams,
|
|
} = useCustomerListPresenter();
|
|
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">
|
|
<ListHeader
|
|
onFilter={() => setIsFilterModalOpen(true)}
|
|
createButtonText="Create Customer"
|
|
/>
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
{columns.map((columns) => (
|
|
<TableHead
|
|
colSpan={100}
|
|
className="text-start font-extrabold uppercase"
|
|
key={columns}
|
|
>
|
|
{columns}
|
|
</TableHead>
|
|
))}
|
|
</TableRow>
|
|
</TableHeader>
|
|
{isPending && <TableSkeleton column={columns.length} />}
|
|
<TableBody>
|
|
<EmptyListWrapper
|
|
list={allCustomers ?? []}
|
|
columns={columns}
|
|
emptyMessage="No Customers were found"
|
|
>
|
|
{allCustomers?.map((customer, index) => (
|
|
<TableRow key={customer?.id ?? index}>
|
|
<TableCell colSpan={100}>{index + 1}</TableCell>
|
|
<TableCell colSpan={100}>{customer?.full_name}</TableCell>
|
|
<TableCell colSpan={100}>{customer?.email}</TableCell>
|
|
<TableCell colSpan={100}>
|
|
{unixToDate({ unix: customer?.created_at, hasTime: true })}
|
|
</TableCell>
|
|
|
|
<TableCell colSpan={100} className="uppercase">
|
|
{customer?.type}
|
|
</TableCell>
|
|
<TableCell colSpan={100}>
|
|
<Status status={customer?.status}>{customer?.status}</Status>
|
|
</TableCell>
|
|
<TableCell colSpan={100}>
|
|
{customer?.companies?.length ? (
|
|
customer?.companies.map((c) => (
|
|
<span key={c.id}>{c.name}, </span>
|
|
))
|
|
) : (
|
|
<span>None</span>
|
|
)}
|
|
</TableCell>
|
|
<TableCell colSpan={100} className="uppercase">
|
|
{customer?.role ?? "-"}
|
|
</TableCell>
|
|
<TableCell className="text-start xl:pr-7.5">
|
|
<div className="flex items-center justify-start gap-x-3.5">
|
|
<button
|
|
data-tooltip-id="delete"
|
|
data-tooltip-content="Delete"
|
|
data-tooltip-place="top"
|
|
className="hover:text-red-500"
|
|
onClick={() => {
|
|
setCurrentCustomer(customer);
|
|
setIsModalOpen(true);
|
|
}}
|
|
>
|
|
<Tooltip {..._TooltipDefaultParams({ id: "delete" })} />
|
|
<span className="sr-only">Delete Company </span>
|
|
<TrashIcon />
|
|
</button>
|
|
<button
|
|
data-tooltip-id="edit"
|
|
data-tooltip-content="Edit"
|
|
data-tooltip-place="top"
|
|
className="hover:text-primary"
|
|
onClick={() =>
|
|
router.push(`${pathName}/edit/${customer.id}`)
|
|
}
|
|
>
|
|
<Tooltip {..._TooltipDefaultParams({ id: "edit" })} />
|
|
<span className="sr-only">Edit Company </span>
|
|
<PencilSquareIcon />
|
|
</button>
|
|
<button
|
|
data-tooltip-id="assign-company"
|
|
data-tooltip-content="Assign to company"
|
|
data-tooltip-place="top"
|
|
className="hover:text-green-dark"
|
|
onClick={() => {
|
|
setCurrentCustomer(customer);
|
|
setIsAssignCompanyModalOpen(true);
|
|
setSelectedCompanies({
|
|
company_ids: [customer?.companies?.[0]?.id ?? ""],
|
|
});
|
|
}}
|
|
>
|
|
<Tooltip
|
|
{..._TooltipDefaultParams({ id: "assign-company" })}
|
|
/>
|
|
<span className="sr-only">Assign To Company </span>
|
|
<Building />
|
|
</button>
|
|
<button
|
|
data-tooltip-id="feedback"
|
|
data-tooltip-content="Feedback"
|
|
data-tooltip-place="top"
|
|
className="text-gray-40 rounded-full bg-gray-dark bg-opacity-5 hover:text-green-dark dark:bg-gray dark:bg-opacity-5"
|
|
onClick={() => {
|
|
router.push(`${pathName}/feedback/${customer.id}`);
|
|
}}
|
|
>
|
|
<Tooltip {..._TooltipDefaultParams({ id: "feedback" })} />
|
|
<ExclamationIcon />
|
|
</button>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</EmptyListWrapper>
|
|
</TableBody>
|
|
</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
|
|
isOpen={isFilterModalOpen}
|
|
onClose={() => setIsFilterModalOpen(false)}
|
|
classNames="w-full xl:w-1/2"
|
|
showButtons={false}
|
|
>
|
|
<CustomerListFilters
|
|
setValue={setFilterValue}
|
|
filterRegister={filterRegister}
|
|
handleFilterSubmit={handleFilterSubmit}
|
|
isMutating={isMutating as number}
|
|
search={search}
|
|
setIsFilterModalOpen={setIsFilterModalOpen}
|
|
watch={watch}
|
|
/>
|
|
</Modal>
|
|
<div className="w-1/12">
|
|
<Modal
|
|
onConfirm={() => {
|
|
if (!selectedCompanies || !currentCustomer) {
|
|
toast.error("Invalid credentials");
|
|
return;
|
|
}
|
|
assignSelectedCompanies({
|
|
credentials: selectedCompanies,
|
|
id: currentCustomer?.id ?? "",
|
|
});
|
|
}}
|
|
isOpen={isAssignCompanyModalOpen}
|
|
onClose={() => setIsAssignCompanyModalOpen(false)}
|
|
>
|
|
<AssignToCompanyModalContent
|
|
setCompanies={setSelectedCompanies}
|
|
defaultValues={selectedCompanies}
|
|
/>
|
|
</Modal>
|
|
</div>
|
|
{isModalOpen && (
|
|
<ConfirmationModal
|
|
isOpen={isModalOpen}
|
|
title={"Confirm"}
|
|
message={"Are you sure?"}
|
|
variant={"default"}
|
|
size={"md"}
|
|
confirmText={"Confirm"}
|
|
cancelText={"Cancel"}
|
|
onConfirm={() => {
|
|
onConfirmDelete();
|
|
}}
|
|
onCancel={() => setIsModalOpen(false)}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CustomersTable;
|