import { EditFilled, SyncOutlined } from "@ant-design/icons"; import { Button, Card, Checkbox, Input, Space, Table, Typography } from "antd"; import { useQuery } from "@apollo/client"; import axios from "axios"; import queryString from "query-string"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useLocation, useNavigate } from "react-router-dom"; import BillDeleteButton from "../../components/bill-delete-button/bill-delete-button.component"; import PartsOrderModalContainer from "../../components/parts-order-modal/parts-order-modal.container"; import PrintWrapperComponent from "../../components/print-wrapper/print-wrapper.component"; import { setModalContext } from "../../redux/modals/modals.actions"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { DateFormatter } from "../../utils/DateFormatter"; import { TemplateList } from "../../utils/TemplateConstants"; import { pageLimit } from "../../utils/config"; import { alphaSort, dateSort } from "../../utils/sorters"; import { QUERY_ALL_VENDORS } from "../../graphql/vendors.queries"; import { logImEXEvent } from "../../firebase/firebase.utils"; const mapDispatchToProps = (dispatch) => ({ setBillEnterContext: (context) => dispatch(setModalContext({ context: context, modal: "billEnter" })) }); export function BillsListPage({ loading, data, refetch, total, setBillEnterContext, handleTableChange, sortedInfo }) { const search = queryString.parse(useLocation().search); const [openSearchResults, setOpenSearchResults] = useState([]); const [searchLoading, setSearchLoading] = useState(false); const { page } = search; const history = useNavigate(); const Templates = TemplateList("bill"); const { t } = useTranslation(); const { data: vendorsData } = useQuery(QUERY_ALL_VENDORS); const columns = [ { title: t("bills.fields.vendorname"), dataIndex: "vendorname", key: "vendorname", sorter: (a, b) => alphaSort(a.vendor.name, b.vendor.name), sortObject: (order) => ({ vendor: { name: order === "descend" ? "desc" : "asc" } }), filters: (vendorsData?.vendors || []).map((v) => ({ text: v.name, value: v.id })), filteredValue: search.vendorIds ? search.vendorIds.split(",") : null, sortOrder: sortedInfo.columnKey === "vendorname" && sortedInfo.order, render: (text, record) => {record.vendor.name} }, { title: t("bills.fields.invoice_number"), dataIndex: "invoice_number", key: "invoice_number", sorter: (a, b) => alphaSort(a.invoice_number, b.invoice_number), sortOrder: sortedInfo.columnKey === "invoice_number" && sortedInfo.order }, { title: t("jobs.fields.ro_number"), dataIndex: "ro_number", key: "ro_number", sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number), sortObject: (order) => ({ job: { ro_number: order === "descend" ? "desc" : "asc" } }), sortOrder: sortedInfo.columnKey === "ro_number" && sortedInfo.order, render: (text, record) => record.job && {record.job.ro_number} }, { title: t("bills.fields.date"), dataIndex: "date", key: "date", sorter: (a, b) => dateSort(a.date, b.date), sortOrder: sortedInfo.columnKey === "date" && sortedInfo.order, render: (text, record) => {record.date} }, { title: t("bills.fields.total"), dataIndex: "total", key: "total", sorter: (a, b) => a.total - b.total, sortOrder: sortedInfo.columnKey === "total" && sortedInfo.order, render: (text, record) => {record.total} }, { title: t("bills.fields.is_credit_memo"), dataIndex: "is_credit_memo", key: "is_credit_memo", sorter: (a, b) => a.is_credit_memo - b.is_credit_memo, sortOrder: sortedInfo.columnKey === "is_credit_memo" && sortedInfo.order, render: (text, record) => }, { title: t("bills.fields.exported"), dataIndex: "exported", key: "exported", sorter: (a, b) => a.exported - b.exported, sortOrder: sortedInfo.columnKey === "exported" && sortedInfo.order, render: (text, record) => }, { title: t("general.labels.actions"), dataIndex: "actions", key: "actions", render: (text, record) => ( { // } { //Filter out the state and set it again. setOpenSearchResults((currentResults) => currentResults.filter((bill) => bill.id !== deletedBillid)); }} /> {record.isinhouse && ( )} ) } ]; // (State & URL handling moved to container - Option C) useEffect(() => { if (search.search && search.search.trim() !== "") { searchBills(); } }, []); async function searchBills(value) { try { setSearchLoading(true); const searchData = await axios.post("/search", { search: value || search.search, index: "bills" }); logImEXEvent("bills_search", { search: value || search.search, results: searchData?.data?.hits?.hits?.length }); setOpenSearchResults(searchData.data.hits.hits.map((s) => s._source)); } catch (error) { console.log("Error while fetching search results", error); } finally { setSearchLoading(false); } } return ( {search.search && ( {t("general.labels.searchresults", { search: search.search })} )} { search.search = value; history({ search: queryString.stringify(search) }); searchBills(value); }} loading={loading || searchLoading} enterButton /> } > ); } export default connect(null, mapDispatchToProps)(BillsListPage);