297 lines
10 KiB
JavaScript
297 lines
10 KiB
JavaScript
import React, { useState } from "react";
|
|
import { useCollections } from "../../hooks/useCollections";
|
|
import {
|
|
ADDPAYMENT_COLLECTION,
|
|
ADMIN_COLLECTION,
|
|
CREATE_COLLECTION,
|
|
EDIT_COLLECTION,
|
|
ITEMS_PER_PAGE,
|
|
VIEW_COLLECTION,
|
|
} from "../../utils/constants";
|
|
import { formatFigure, localToUtc, useDebounce } from "../../utils/appUtils";
|
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
|
import Pagination from "../common/Pagination";
|
|
import { useCollectionContext } from "../../pages/collections/CollectionPage";
|
|
import { CollectionTableSkeleton } from "./CollectionSkeleton";
|
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
|
|
|
const CollectionList = ({ fromDate, toDate, isPending, searchString }) => {
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
|
|
const isAdmin = useHasUserPermission(ADMIN_COLLECTION);
|
|
const canAddPayment = useHasUserPermission(ADDPAYMENT_COLLECTION);
|
|
const canViewCollection = useHasUserPermission(VIEW_COLLECTION);
|
|
const canEditCollection = useHasUserPermission(EDIT_COLLECTION);
|
|
const canCreate = useHasUserPermission(CREATE_COLLECTION);
|
|
|
|
const selectedProject = useSelectedProject();
|
|
const searchDebounce = useDebounce(searchString, 500);
|
|
|
|
const { data, isLoading, isError, error } = useCollections(
|
|
selectedProject,
|
|
searchDebounce,
|
|
localToUtc(fromDate),
|
|
localToUtc(toDate),
|
|
ITEMS_PER_PAGE,
|
|
currentPage,
|
|
true,
|
|
isPending
|
|
);
|
|
const { setProcessedPayment, setAddPayment, setViewCollection } =
|
|
useCollectionContext();
|
|
|
|
const paginate = (page) => {
|
|
if (page >= 1 && page <= (data?.totalPages ?? 1)) {
|
|
setCurrentPage(page);
|
|
}
|
|
};
|
|
|
|
const collectionColumns = [
|
|
{
|
|
key: "invoiceDate",
|
|
label: "Invoice Date",
|
|
getValue: (col) => (
|
|
<span
|
|
className="text-truncate d-inline-block"
|
|
style={{ maxWidth: "200px" }}
|
|
>
|
|
{formatUTCToLocalTime(col.invoiceDate)}
|
|
</span>
|
|
),
|
|
align: "text-start",
|
|
},
|
|
{
|
|
key: "invoiceId",
|
|
label: "Invoice No",
|
|
getValue: (col) => (
|
|
<span
|
|
className="text-truncate d-inline-block"
|
|
style={{ maxWidth: "200px" }}
|
|
>
|
|
{col?.invoiceNumber ?? "-"}
|
|
</span>
|
|
),
|
|
align: "text-start",
|
|
},
|
|
{
|
|
key: "project",
|
|
label: "Project",
|
|
getValue: (col) => (
|
|
<span
|
|
className="text-truncate d-inline-block"
|
|
style={{ maxWidth: "200px" }}
|
|
>
|
|
{col?.project?.name ?? "-"}
|
|
</span>
|
|
),
|
|
align: "text-start",
|
|
},
|
|
{
|
|
key: "submittedDate",
|
|
label: "Submission Date",
|
|
getValue: (col) => (
|
|
<span
|
|
className="text-truncate d-inline-block"
|
|
style={{ maxWidth: "200px" }}
|
|
>
|
|
{formatUTCToLocalTime(col.createdAt)}
|
|
</span>
|
|
),
|
|
align: "text-center",
|
|
},
|
|
{
|
|
key: "expectedSubmittedDate",
|
|
label: "Expected Payment Date",
|
|
getValue: (col) => (
|
|
<span
|
|
className="text-truncate d-inline-block"
|
|
style={{ maxWidth: "200px" }}
|
|
>
|
|
{formatUTCToLocalTime(col.exceptedPaymentDate) ?? "-"}
|
|
</span>
|
|
),
|
|
align: "text-center",
|
|
},
|
|
{
|
|
key: "amount",
|
|
label: "Total Amount",
|
|
getValue: (col) => (
|
|
<span
|
|
className="text-truncate d-inline-block"
|
|
style={{ maxWidth: "200px" }}
|
|
>
|
|
{formatFigure(col?.basicAmount + col?.taxAmount, {
|
|
type: "currency",
|
|
currency: "INR",
|
|
}) ?? 0}
|
|
</span>
|
|
),
|
|
align: "text-end",
|
|
},
|
|
{
|
|
key: "balance",
|
|
label: "Balance",
|
|
getValue: (col) => (
|
|
<span
|
|
className="text-truncate d-inline-block py-3"
|
|
style={{ maxWidth: "200px" }}
|
|
>
|
|
{formatFigure(col?.balanceAmount, {
|
|
type: "currency",
|
|
currency: "INR",
|
|
}) ?? 0}
|
|
</span>
|
|
),
|
|
align: "text-end",
|
|
},
|
|
];
|
|
|
|
if (isLoading) return <CollectionTableSkeleton />;
|
|
if (isError) return <p>{error.message}</p>;
|
|
|
|
return (
|
|
<div className="card px-sm-4 px-0">
|
|
<div
|
|
className="card-datatable table-responsive page-min-h"
|
|
id="horizontal-example"
|
|
>
|
|
<div className="dataTables_wrapper no-footer mx-3 pb-2">
|
|
<table className="table dataTable text-nowrap">
|
|
<thead>
|
|
<tr className="table_header_border">
|
|
{collectionColumns.map((col) => (
|
|
<th key={col.key} className={col.align}>
|
|
{col.label}
|
|
</th>
|
|
))}
|
|
{(isAdmin ||
|
|
canAddPayment ||
|
|
canViewCollection ||
|
|
canEditCollection ||
|
|
canCreate) && <th>Action</th>}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{Array.isArray(data?.data) && data.data.length > 0 ? (
|
|
data.data.map((row, i) => (
|
|
<tr key={i}>
|
|
{collectionColumns.map((col) => (
|
|
<td key={col.key} className={col.align}>
|
|
{col.getValue(row)}
|
|
</td>
|
|
))}
|
|
{(isAdmin ||
|
|
canAddPayment ||
|
|
canViewCollection ||
|
|
canEditCollection ||
|
|
canCreate) && (
|
|
<td
|
|
className="sticky-action-column text-center"
|
|
style={{ padding: "12px 8px" }}
|
|
>
|
|
<div className="dropdown z-2">
|
|
<button
|
|
type="button"
|
|
className="btn btn-icon btn-text-secondary rounded-pill dropdown-toggle hide-arrow p-0"
|
|
data-bs-toggle="dropdown"
|
|
aria-expanded="false"
|
|
>
|
|
<i
|
|
className="bx bx-dots-vertical-rounded bx-sm text-muted"
|
|
data-bs-toggle="tooltip"
|
|
data-bs-offset="0,8"
|
|
data-bs-placement="top"
|
|
data-bs-custom-class="tooltip-dark"
|
|
title="More Action"
|
|
></i>
|
|
</button>
|
|
|
|
<ul className="dropdown-menu dropdown-menu-end">
|
|
{/* View */}
|
|
|
|
<li>
|
|
<a
|
|
className="dropdown-item cursor-pointer"
|
|
onClick={() => setViewCollection(row.id)}
|
|
>
|
|
<i className="bx bx-show me-2 text-primary"></i>
|
|
<span>View</span>
|
|
</a>
|
|
</li>
|
|
|
|
{/* Only if not completed */}
|
|
{!row?.markAsCompleted && (
|
|
<>
|
|
{/* Add Payment */}
|
|
{(isAdmin || canAddPayment) && (
|
|
<li>
|
|
<a
|
|
className="dropdown-item cursor-pointer"
|
|
onClick={() =>
|
|
setAddPayment({
|
|
isOpen: true,
|
|
invoiceId: row.id,
|
|
})
|
|
}
|
|
>
|
|
<i className="bx bx-wallet me-2 text-warning"></i>
|
|
<span>Add Payment</span>
|
|
</a>
|
|
</li>
|
|
)}
|
|
|
|
{/* Mark Payment */}
|
|
{isAdmin && (
|
|
<li>
|
|
<a
|
|
className="dropdown-item cursor-pointer"
|
|
onClick={() =>
|
|
setProcessedPayment({
|
|
isOpen: true,
|
|
invoiceId: row.id,
|
|
})
|
|
}
|
|
>
|
|
<i className="bx bx-check-circle me-2 text-success"></i>
|
|
<span>Mark Payment</span>
|
|
</a>
|
|
</li>
|
|
)}
|
|
</>
|
|
)}
|
|
</ul>
|
|
</div>
|
|
</td>
|
|
)}
|
|
</tr>
|
|
))
|
|
) : (
|
|
<tr style={{ height: "200px" }}>
|
|
<td
|
|
colSpan={collectionColumns.length + 1}
|
|
className="text-center border-0 align-middle"
|
|
>
|
|
No Collections Found
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
{data?.data?.length > 0 && (
|
|
<div className="d-flex justify-content-start mt-2">
|
|
<Pagination
|
|
currentPage={currentPage}
|
|
totalPages={data?.totalPages}
|
|
onPageChange={paginate}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CollectionList;
|