feat(companies): implement companies page with data table
This commit introduces a new "Companies" page to the dashboard, providing a comprehensive view of company data in a sortable and paginated table. Key changes include: - A new page at `/companies` to display the data table. - A new API route `/api/companies` that serves mock company data. - A `CompaniesTable` component built with `react-table` featuring sorting, pagination, and search functionality. - Reusable `TablePagination` and `TableActions` components to support the table. - The `moment` library has been added as a dependency to format dates within the table. - A new `CrossIcon` has been added for UI controls. - The `InputGroup` component is enhanced with an `autoComplete` prop. - A link to the new "Companies" page has been added to the sidebar navigation.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import {
|
||||
Dispatch,
|
||||
FC,
|
||||
RefObject,
|
||||
SetStateAction,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
import { useForm } from "react-hook-form";
|
||||
import { TAssignCustomerToCompanyCredentials } from "@/lib/api";
|
||||
import { useCompanyFullList } from "@/hooks/queries";
|
||||
import { ILabelValue } from "@/types/shared";
|
||||
import { Select } from "@/components/FormElements/select";
|
||||
import { Building } from "@/components/Layouts/sidebar/icons";
|
||||
import { FormErrorMessages } from "@/constants/Texts";
|
||||
|
||||
interface IProps {
|
||||
setCompanies: Dispatch<
|
||||
SetStateAction<TAssignCustomerToCompanyCredentials | null>
|
||||
>;
|
||||
}
|
||||
const AssignToCompanyModalContent: FC<IProps> = ({ setCompanies }) => {
|
||||
const [options, setOptions] = useState<ILabelValue[]>([]);
|
||||
|
||||
const { data, status, isSuccess } = useCompanyFullList();
|
||||
const { handleSubmit, register } =
|
||||
useForm<TAssignCustomerToCompanyCredentials>();
|
||||
|
||||
useEffect(() => {
|
||||
if (isSuccess) {
|
||||
setOptions(
|
||||
data.data.companies
|
||||
? data.data.companies?.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}))
|
||||
: [],
|
||||
);
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
const assignCompany = (data: TAssignCustomerToCompanyCredentials) => {
|
||||
setCompanies(data);
|
||||
};
|
||||
return (
|
||||
<form className="mt-5" onSubmit={handleSubmit(assignCompany)}>
|
||||
<Select
|
||||
{...register("company_ids", {
|
||||
required: { message: FormErrorMessages.required, value: true },
|
||||
onChange: (e) => {
|
||||
setCompanies({
|
||||
company_ids: [e.target.value],
|
||||
});
|
||||
},
|
||||
})}
|
||||
name="company_ids"
|
||||
label="Companies"
|
||||
items={options}
|
||||
prefixIcon={<Building />}
|
||||
placeholder="Please Select company"
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AssignToCompanyModalContent;
|
||||
@@ -10,8 +10,13 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { PencilSquareIcon, TrashIcon } from "@/assets/icons";
|
||||
import { PencilSquareIcon, TrashIcon, UserIcon } from "@/assets/icons";
|
||||
import ConfirmationModal from "@/components/ui/ConfirmationModal";
|
||||
|
||||
import AssignToCompanyModalContent from "./AssignToCompanyModalContent";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import { TAssignCustomerToCompanyCredentials } from "@/lib/api";
|
||||
import { toast } from "react-toastify";
|
||||
const CustomersTable = () => {
|
||||
const {
|
||||
isPending,
|
||||
@@ -21,15 +26,21 @@ const CustomersTable = () => {
|
||||
allCustomers,
|
||||
modalConfig,
|
||||
isModalOpen,
|
||||
assignSelectedCompanies,
|
||||
selectedCompanies,
|
||||
currentCustomer,
|
||||
setSelectedCompanies,
|
||||
setIsModalOpen,
|
||||
onConfirmDelete,
|
||||
setCurrentCustomer,
|
||||
isAssignCompanyModalOpen,
|
||||
setIsAssignCompanyModalOpen,
|
||||
} = useCustomerListPresenter();
|
||||
if (isPending) return <CustomersSkeleton />;
|
||||
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">
|
||||
<button className="mb-5 flex w-fit justify-center self-end rounded-lg bg-primary p-[13px] font-medium text-white hover:bg-opacity-90">
|
||||
<Link href={`${pathName}/create`}>Create Company</Link>
|
||||
<Link href={`${pathName}/create`}>Create Customer </Link>
|
||||
</button>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
@@ -83,12 +94,38 @@ const CustomersTable = () => {
|
||||
<span className="sr-only">Edit Company </span>
|
||||
<PencilSquareIcon />
|
||||
</button>
|
||||
<button
|
||||
className="hover:text-green-dark"
|
||||
onClick={() => {
|
||||
setCurrentCustomer(customer);
|
||||
setIsAssignCompanyModalOpen(true);
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Assign To Company </span>
|
||||
<UserIcon />
|
||||
</button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<Modal
|
||||
onConfirm={() => {
|
||||
if (!selectedCompanies || !currentCustomer) {
|
||||
toast.error("Invalid credentials");
|
||||
return;
|
||||
}
|
||||
assignSelectedCompanies({
|
||||
credentials: selectedCompanies,
|
||||
id: currentCustomer?.id ?? "",
|
||||
});
|
||||
}}
|
||||
isOpen={isAssignCompanyModalOpen}
|
||||
onClose={() => setIsAssignCompanyModalOpen(false)}
|
||||
>
|
||||
<AssignToCompanyModalContent setCompanies={setSelectedCompanies} />
|
||||
</Modal>
|
||||
{isModalOpen && (
|
||||
<ConfirmationModal
|
||||
isOpen={isModalOpen}
|
||||
|
||||
@@ -15,7 +15,8 @@ import { z } from "zod";
|
||||
|
||||
const useCustomerListPresenter = () => {
|
||||
const deleteModal = useRef<HTMLDialogElement | null>(null);
|
||||
const assignToCompanyModal = useRef<HTMLDialogElement | null>(null);
|
||||
const [isAssignCompanyModalOpen, setIsAssignCompanyModalOpen] =
|
||||
useState(false);
|
||||
const { inView } = useInView({ threshold: 0.5 });
|
||||
const [selectedCompanies, setSelectedCompanies] =
|
||||
useState<TAssignCustomerToCompanyCredentials | null>(null);
|
||||
@@ -53,7 +54,7 @@ const useCustomerListPresenter = () => {
|
||||
const { mutate: assignSelectedCompanies } = useAssignCompany(
|
||||
currentCustomer?.id ?? "",
|
||||
() => {
|
||||
assignToCompanyModal.current?.close();
|
||||
setIsAssignCompanyModalOpen(false);
|
||||
},
|
||||
);
|
||||
useEffect(() => {
|
||||
@@ -101,7 +102,8 @@ const useCustomerListPresenter = () => {
|
||||
selectedCompanies,
|
||||
setSelectedCompanies,
|
||||
onConfirmDelete,
|
||||
assignToCompanyModal,
|
||||
setIsAssignCompanyModalOpen,
|
||||
isAssignCompanyModalOpen,
|
||||
assignSelectedCompanies,
|
||||
pathName,
|
||||
router,
|
||||
|
||||
Reference in New Issue
Block a user