marco.pms.web/src/pages/PaymentRequest/PaymentRequestPage.jsx

240 lines
8.5 KiB
JavaScript

import React, { createContext, useState, useEffect, useContext, useRef } from "react";
import Breadcrumb from "../../components/common/Breadcrumb";
import GlobalModel from "../../components/common/GlobalModel";
import ManagePaymentRequest from "../../components/PaymentRequest/ManagePaymentRequest";
import { useFab } from "../../Context/FabContext";
import PaymentRequestList from "../../components/PaymentRequest/PaymentRequestList";
import PaymentRequestFilterPanel from "../../components/PaymentRequest/PaymentRequestFilterPanel";
import { defaultPaymentRequestFilter } from "../../components/PaymentRequest/PaymentRequestSchema";
import ViewPaymentRequest from "../../components/PaymentRequest/ViewPaymentRequest";
import PreviewDocument from "../../components/Expenses/PreviewDocument";
import MakeExpense from "../../components/PaymentRequest/MakeExpense";
import handlePaymentRequestExport from "../../components/PaymentRequest/handlePaymentRequestExport";
export const PaymentRequestContext = createContext();
export const usePaymentRequestContext = () => {
const context = useContext(PaymentRequestContext);
if (!context) {
throw new Error("usePaymentRequestContext must be used within PaymentRequestContext.Provider");
}
return context;
};
const PaymentRequestPage = () => {
const [ManageRequest, setManageRequest] = useState({ IsOpen: null, RequestId: null });
const [ViewRequest, setVieRequest] = useState({ view: false, requestId: null });
const [filters, setFilters] = useState(defaultPaymentRequestFilter);
const [filterData, setFilterdata] = useState(null);
const [ViewDocument, setDocumentView] = useState({ IsOpen: false, Image: null });
const [searchText, setSearchText] = useState("");
const [isExpenseGenerate, setIsExpenseGenerate] = useState({ IsOpen: null, RequestId: null });
const [modalSize, setModalSize] = useState("md");
const [search, setSearch] = useState("");
const updatedRef = useRef();
const { setOffcanvasContent, setShowTrigger } = useFab();
const [exportLoading, setExportLoading] = useState(false);
const tableRef = useRef(null);
const [filteredData, setFilteredData] = useState([]);
const contextValue = {
setManageRequest,
setVieRequest,
setDocumentView,
setModalSize,
setIsExpenseGenerate,
isExpenseGenerate,
};
const clearFilter = () => setFilters(defaultPaymentRequestFilter);
useEffect(() => {
setShowTrigger(true);
setOffcanvasContent(
"Payment Request Filters",
<PaymentRequestFilterPanel
onApply={setFilters}
ref={updatedRef}
clearFilter={clearFilter}
setFilterdata={setFilterdata}
/>
);
return () => {
setShowTrigger(false);
setOffcanvasContent("", null);
};
}, []);
const handleRemoveChip = (key, id) => {
setFilters((prev) => {
const updated = { ...prev };
if (Array.isArray(updated[key])) {
updated[key] = updated[key].filter((v) => v !== id);
setTimeout(() => updatedRef.current?.resetFieldValue(key, updated[key]), 0);
} else {
updated[key] = null;
setTimeout(() => updatedRef.current?.resetFieldValue(key, null), 0);
}
return updated;
});
};
const handleExport = (type) => {
handlePaymentRequestExport(type, filters, search, tableRef, setExportLoading);
};
return (
<PaymentRequestContext.Provider value={contextValue}>
<div className="container-fluid">
{/* Breadcrumb */}
<Breadcrumb
data={[
{ label: "Home", link: "/dashboard" },
{ label: "Finance", link: "/Payment Request" },
{ label: "Payment Request" },
]}
/>
{/* Top Bar */}
<div className="card my-3 px-sm-4 px-0">
<div className="card-body py-2 px-0 mx-2">
<div className="row align-items-center">
<div className="col-md-8 col-sm-12 mb-2 mb-md-0">
<div className="d-flex align-items-center flex-wrap gap-0">
<input
type="search"
className="form-control form-control-sm w-auto"
placeholder="Search Payment Request"
value={search}
style={{ minWidth: "200px" }}
onChange={(e) => setSearch(e.target.value)}
/>
</div>
</div>
<div className="col-md-4 col-sm-12 text-md-end text-end d-flex justify-content-end align-items-center gap-0">
<button
className="btn btn-sm btn-primary"
type="button"
onClick={() =>
setManageRequest({
IsOpen: true,
expenseId: null,
})
}
>
<i className="bx bx-plus-circle me-2"></i>
<span className="d-none d-md-inline-block">
Add Payment Request
</span>
</button>
{/* 3-Dots Dropdown */}
<div className="dropdown">
<button
className="btn btn-icon"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<i className="bx bx-dots-vertical-rounded bx-md"></i>
</button>
<ul className="dropdown-menu dropdown-menu-end shadow-sm" style={{ minWidth: "220px" }}>
<li>
<button className="dropdown-item" onClick={() => handleExport("print")}>
<i className="bx bx-printer me-2"></i> Print
</button>
</li>
<li><hr className="dropdown-divider" /></li>
<li>
<button className="dropdown-item" onClick={() => handleExport("csv")}>
<i className="bx bx-file me-2"></i> CSV
</button>
</li>
<li>
<button className="dropdown-item" onClick={() => handleExport("excel")}>
<i className="bx bxs-file-export me-2"></i> Excel
</button>
</li>
<li>
<button className="dropdown-item" onClick={() => handleExport("pdf")}>
<i className="bx bxs-file-pdf me-2"></i> PDF
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<PaymentRequestList
search={search}
filters={filters}
filterData={filterData}
removeFilterChip={handleRemoveChip}
clearFilter={clearFilter}
tableRef={tableRef}
onDataFiltered={setFilteredData}
/>
{/* Add/Edit Modal */}
{ManageRequest.IsOpen && (
<GlobalModel
isOpen
size="lg"
closeModal={() => setManageRequest({ IsOpen: null, expenseId: null })}
>
<ManagePaymentRequest
key={ManageRequest.RequestId ?? "new"}
requestToEdit={ManageRequest.RequestId}
closeModal={() => setManageRequest({ IsOpen: null, RequestId: null })}
/>
</GlobalModel>
)}
{ViewRequest.view && (
<GlobalModel
isOpen
size="xl"
modalType="top"
closeModal={() => setVieRequest({ requestId: null, view: false })}
>
<ViewPaymentRequest requestId={ViewRequest?.requestId} />
</GlobalModel>
)}
{isExpenseGenerate.IsOpen && (
<GlobalModel
isOpen
size="md"
closeModal={() => setIsExpenseGenerate({ IsOpen: false, requestId: null })}
>
<MakeExpense
onClose={() => setIsExpenseGenerate({ IsOpen: false, requestId: null })}
/>
</GlobalModel>
)}
{ViewDocument.IsOpen && (
<GlobalModel
isOpen
size="md"
key={ViewDocument.Image ?? "doc"}
closeModal={() => setDocumentView({ IsOpen: false, Image: null })}
>
<PreviewDocument imageUrl={ViewDocument.Image} />
</GlobalModel>
)}
</div>
</PaymentRequestContext.Provider>
);
};
export default PaymentRequestPage;