Adding Date picker chips in Expense and
This commit is contained in:
parent
153ffcdc3e
commit
0f43c877c4
@ -94,6 +94,14 @@ const ExpenseFilterPanel = forwardRef(
|
|||||||
reset({ ...methods.getValues(), [name]: defaultFilter[name] });
|
reset({ ...methods.getValues(), [name]: defaultFilter[name] });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// --- START FIX: Add resetDateRange method ---
|
||||||
|
resetDateRange: () => {
|
||||||
|
setValue("startDate", null);
|
||||||
|
setValue("endDate", null);
|
||||||
|
// Trigger re-render/reset of the DateRangePicker component
|
||||||
|
setResetKey((prev) => prev + 1);
|
||||||
|
},
|
||||||
|
// --- END FIX ---
|
||||||
getValues: methods.getValues, // optional, to read current filter state
|
getValues: methods.getValues, // optional, to read current filter state
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -137,13 +145,13 @@ const ExpenseFilterPanel = forwardRef(
|
|||||||
: dynamicDefaultFilter.projectIds || [],
|
: dynamicDefaultFilter.projectIds || [],
|
||||||
startDate: dynamicDefaultFilter.startDate
|
startDate: dynamicDefaultFilter.startDate
|
||||||
? moment
|
? moment
|
||||||
.utc(dynamicDefaultFilter.startDate, "DD-MM-YYYY")
|
.utc(dynamicDefaultFilter.startDate, "DD-MM-YYYY")
|
||||||
.toISOString()
|
.toISOString()
|
||||||
: undefined,
|
: undefined,
|
||||||
endDate: dynamicDefaultFilter.endDate
|
endDate: dynamicDefaultFilter.endDate
|
||||||
? moment
|
? moment
|
||||||
.utc(dynamicDefaultFilter.endDate, "DD-MM-YYYY")
|
.utc(dynamicDefaultFilter.endDate, "DD-MM-YYYY")
|
||||||
.toISOString()
|
.toISOString()
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -176,18 +184,16 @@ const ExpenseFilterPanel = forwardRef(
|
|||||||
<div className="d-inline-flex border rounded-pill mb-1 overflow-hidden shadow-none">
|
<div className="d-inline-flex border rounded-pill mb-1 overflow-hidden shadow-none">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`btn px-2 py-1 rounded-0 text-tiny ${
|
className={`btn px-2 py-1 rounded-0 text-tiny ${isTransactionDate ? "active btn-primary text-white" : ""
|
||||||
isTransactionDate ? "active btn-primary text-white" : ""
|
}`}
|
||||||
}`}
|
|
||||||
onClick={() => setValue("isTransactionDate", true)}
|
onClick={() => setValue("isTransactionDate", true)}
|
||||||
>
|
>
|
||||||
Transaction Date
|
Transaction Date
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`btn px-2 py-1 rounded-0 text-tiny ${
|
className={`btn px-2 py-1 rounded-0 text-tiny ${!isTransactionDate ? "active btn-primary text-white" : ""
|
||||||
!isTransactionDate ? "active btn-primary text-white" : ""
|
}`}
|
||||||
}`}
|
|
||||||
onClick={() => setValue("isTransactionDate", false)}
|
onClick={() => setValue("isTransactionDate", false)}
|
||||||
>
|
>
|
||||||
Submitted Date
|
Submitted Date
|
||||||
|
|||||||
@ -83,64 +83,64 @@ const ExpenseList = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const groupByField = (items, field) => {
|
const groupByField = (items, field) => {
|
||||||
if (!field || field === "none") {
|
if (!field || field === "none") {
|
||||||
return {
|
return {
|
||||||
All: {
|
All: {
|
||||||
key: "All",
|
key: "All",
|
||||||
displayField: "All",
|
displayField: "All",
|
||||||
items: items || []
|
items: items || []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return items.reduce((acc, item) => {
|
||||||
|
let key;
|
||||||
|
let displayField;
|
||||||
|
|
||||||
|
switch (field) {
|
||||||
|
case "transactionDate":
|
||||||
|
key = formatUTCToLocalTime(item?.transactionDate);
|
||||||
|
displayField = "Transaction Date";
|
||||||
|
break;
|
||||||
|
case "status":
|
||||||
|
key = item?.status?.displayName || "Unknown";
|
||||||
|
displayField = "Status";
|
||||||
|
break;
|
||||||
|
case "submittedBy":
|
||||||
|
key = `${item?.createdBy?.firstName ?? ""} ${item?.createdBy?.lastName ?? ""}`.trim();
|
||||||
|
displayField = "Submitted By";
|
||||||
|
break;
|
||||||
|
case "project":
|
||||||
|
key = item?.project?.name || "Unknown Project";
|
||||||
|
displayField = "Project";
|
||||||
|
break;
|
||||||
|
case "paymentMode":
|
||||||
|
key = item?.paymentMode?.name || "Unknown Mode";
|
||||||
|
displayField = "Payment Mode";
|
||||||
|
break;
|
||||||
|
case "expenseCategory":
|
||||||
|
key = item?.expenseCategory?.name || "Unknown Type";
|
||||||
|
displayField = "Expense Category";
|
||||||
|
break;
|
||||||
|
case "createdAt":
|
||||||
|
key = item?.createdAt?.split("T")[0] || "Unknown Date";
|
||||||
|
displayField = "Created Date";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
key = "Others";
|
||||||
|
displayField = "Others";
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return items.reduce((acc, item) => {
|
const groupKey = `${field}_${key}`;
|
||||||
let key;
|
if (!acc[groupKey]) {
|
||||||
let displayField;
|
acc[groupKey] = { key, displayField, items: [] };
|
||||||
|
}
|
||||||
|
|
||||||
switch (field) {
|
acc[groupKey].items.push(item);
|
||||||
case "transactionDate":
|
return acc;
|
||||||
key = formatUTCToLocalTime(item?.transactionDate);
|
}, {});
|
||||||
displayField = "Transaction Date";
|
};
|
||||||
break;
|
|
||||||
case "status":
|
|
||||||
key = item?.status?.displayName || "Unknown";
|
|
||||||
displayField = "Status";
|
|
||||||
break;
|
|
||||||
case "submittedBy":
|
|
||||||
key = `${item?.createdBy?.firstName ?? ""} ${item?.createdBy?.lastName ?? ""}`.trim();
|
|
||||||
displayField = "Submitted By";
|
|
||||||
break;
|
|
||||||
case "project":
|
|
||||||
key = item?.project?.name || "Unknown Project";
|
|
||||||
displayField = "Project";
|
|
||||||
break;
|
|
||||||
case "paymentMode":
|
|
||||||
key = item?.paymentMode?.name || "Unknown Mode";
|
|
||||||
displayField = "Payment Mode";
|
|
||||||
break;
|
|
||||||
case "expenseCategory":
|
|
||||||
key = item?.expenseCategory?.name || "Unknown Type";
|
|
||||||
displayField = "Expense Category";
|
|
||||||
break;
|
|
||||||
case "createdAt":
|
|
||||||
key = item?.createdAt?.split("T")[0] || "Unknown Date";
|
|
||||||
displayField = "Created Date";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
key = "Others";
|
|
||||||
displayField = "Others";
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupKey = `${field}_${key}`;
|
|
||||||
if (!acc[groupKey]) {
|
|
||||||
acc[groupKey] = { key, displayField, items: [] };
|
|
||||||
}
|
|
||||||
|
|
||||||
acc[groupKey].items.push(item);
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const expenseColumns = [
|
const expenseColumns = [
|
||||||
@ -167,9 +167,8 @@ const groupByField = (items, field) => {
|
|||||||
label: "Submitted By",
|
label: "Submitted By",
|
||||||
align: "text-start",
|
align: "text-start",
|
||||||
getValue: (e) =>
|
getValue: (e) =>
|
||||||
`${e.createdBy?.firstName ?? ""} ${
|
`${e.createdBy?.firstName ?? ""} ${e.createdBy?.lastName ?? ""
|
||||||
e.createdBy?.lastName ?? ""
|
}`.trim() || "N/A",
|
||||||
}`.trim() || "N/A",
|
|
||||||
customRender: (e) => (
|
customRender: (e) => (
|
||||||
<div
|
<div
|
||||||
className="d-flex align-items-center cursor-pointer"
|
className="d-flex align-items-center cursor-pointer"
|
||||||
@ -182,9 +181,8 @@ const groupByField = (items, field) => {
|
|||||||
lastName={e.createdBy?.lastName}
|
lastName={e.createdBy?.lastName}
|
||||||
/>
|
/>
|
||||||
<span className="text-truncate">
|
<span className="text-truncate">
|
||||||
{`${e.createdBy?.firstName ?? ""} ${
|
{`${e.createdBy?.firstName ?? ""} ${e.createdBy?.lastName ?? ""
|
||||||
e.createdBy?.lastName ?? ""
|
}`.trim() || "N/A"}
|
||||||
}`.trim() || "N/A"}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@ -216,9 +214,8 @@ const groupByField = (items, field) => {
|
|||||||
align: "text-center",
|
align: "text-center",
|
||||||
getValue: (e) => (
|
getValue: (e) => (
|
||||||
<span
|
<span
|
||||||
className={`badge bg-label-${
|
className={`badge bg-label-${getColorNameFromHex(e?.status?.color) || "secondary"
|
||||||
getColorNameFromHex(e?.status?.color) || "secondary"
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{e.status?.name || "Unknown"}
|
{e.status?.name || "Unknown"}
|
||||||
</span>
|
</span>
|
||||||
@ -238,16 +235,16 @@ const groupByField = (items, field) => {
|
|||||||
return <ExpenseTableSkeleton headers={headers} />;
|
return <ExpenseTableSkeleton headers={headers} />;
|
||||||
if (isError) return <div>{error?.message}</div>;
|
if (isError) return <div>{error?.message}</div>;
|
||||||
|
|
||||||
const isNoGrouping = !groupBy || groupBy === "none";
|
const isNoGrouping = !groupBy || groupBy === "none";
|
||||||
const grouped = isNoGrouping
|
const grouped = isNoGrouping
|
||||||
? { All: { key: "All", displayField: "All", items: data?.data ?? [] } }
|
? { All: { key: "All", displayField: "All", items: data?.data ?? [] } }
|
||||||
: groupByField(data?.data ?? [], groupBy);
|
: groupByField(data?.data ?? [], groupBy);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const IsGroupedByDate = [
|
const IsGroupedByDate = [
|
||||||
{key:"none",displayField:"None"},
|
{ key: "none", displayField: "None" },
|
||||||
{ key: "transactionDate", displayField: "Transaction Date" },
|
{ key: "transactionDate", displayField: "Transaction Date" },
|
||||||
{ key: "createdAt", displayField: "created Date", },
|
{ key: "createdAt", displayField: "created Date", },
|
||||||
]?.includes(groupBy);
|
]?.includes(groupBy);
|
||||||
@ -343,26 +340,22 @@ const grouped = isNoGrouping
|
|||||||
(col.isAlwaysVisible || groupBy !== col.key) && (
|
(col.isAlwaysVisible || groupBy !== col.key) && (
|
||||||
<td
|
<td
|
||||||
key={col.key}
|
key={col.key}
|
||||||
className={`d-table-cell ml-2 ${
|
className={`d-table-cell ml-2 ${col.align ?? ""
|
||||||
col.align ?? ""
|
} `}
|
||||||
} `}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`d-flex px-2 ${
|
className={`d-flex px-2 ${col.key === "status"
|
||||||
col.key === "status"
|
|
||||||
? "justify-content-center"
|
? "justify-content-center"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
${
|
${col.key === "amount"
|
||||||
col.key === "amount"
|
? "justify-content-end"
|
||||||
? "justify-content-end"
|
: ""
|
||||||
: ""
|
}
|
||||||
}
|
${col.key === "submitted"
|
||||||
${
|
? "justify-content-center"
|
||||||
col.key === "submitted"
|
: ""
|
||||||
? "justify-content-center"
|
}
|
||||||
: ""
|
|
||||||
}
|
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{col.customRender
|
{col.customRender
|
||||||
@ -445,7 +438,18 @@ const grouped = isNoGrouping
|
|||||||
<tr>
|
<tr>
|
||||||
<td colSpan={8} className="text-center border-0 ">
|
<td colSpan={8} className="text-center border-0 ">
|
||||||
<div className="py-8">
|
<div className="py-8">
|
||||||
<p>No Expense Found</p>
|
<p
|
||||||
|
className="text-center"
|
||||||
|
style={{
|
||||||
|
height: "250px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
No Expense found
|
||||||
|
</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import moment from "moment";
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
|
|
||||||
const PaymentRequestFilterChips = ({ filters, filterData, removeFilterChip, clearFilter }) => {
|
const PaymentRequestFilterChips = ({ filters, filterData, removeFilterChip, clearFilter }) => {
|
||||||
@ -22,6 +23,21 @@ const PaymentRequestFilterChips = ({ filters, filterData, removeFilterChip, clea
|
|||||||
addGroup(filters.projectIds, data.projects, "Projects", "projectIds");
|
addGroup(filters.projectIds, data.projects, "Projects", "projectIds");
|
||||||
addGroup(filters.statusIds, data.status, "Status", "statusIds");
|
addGroup(filters.statusIds, data.status, "Status", "statusIds");
|
||||||
|
|
||||||
|
if (filters.startDate || filters.endDate) {
|
||||||
|
const start = filters.startDate ? moment(filters.startDate).format("DD MMM YYYY") : "";
|
||||||
|
const end = filters.endDate ? moment(filters.endDate).format("DD MMM YYYY") : "";
|
||||||
|
chips.push({
|
||||||
|
key: "dateRange",
|
||||||
|
label: "Date",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: "dateRange",
|
||||||
|
name: start && end ? `${start} to ${end}` : start || end,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return chips;
|
return chips;
|
||||||
}, [filters, filterData]);
|
}, [filters, filterData]);
|
||||||
|
|
||||||
|
|||||||
@ -76,9 +76,18 @@ const PaymentRequestFilterPanel = forwardRef(({ onApply, handleGroupBy, setFilte
|
|||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
setValue(name, value);
|
setValue(name, value);
|
||||||
} else {
|
} else {
|
||||||
reset({ ...methods.getValues(), [name]: defaultFilter[name] });
|
// NOTE: Using defaultPaymentRequestFilter for clear functionality
|
||||||
|
reset({ ...methods.getValues(), [name]: defaultPaymentRequestFilter[name] });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// --- START FIX: Add resetDateRange method ---
|
||||||
|
resetDateRange: () => {
|
||||||
|
setValue("startDate", null);
|
||||||
|
setValue("endDate", null);
|
||||||
|
// Trigger re-render/reset of the DateRangePicker component
|
||||||
|
setResetKey((prev) => prev + 1);
|
||||||
|
},
|
||||||
|
// --- END FIX ---
|
||||||
getValues: methods.getValues, // optional, to read current filter state
|
getValues: methods.getValues, // optional, to read current filter state
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -94,7 +103,7 @@ const PaymentRequestFilterPanel = forwardRef(({ onApply, handleGroupBy, setFilte
|
|||||||
startDate: moment.utc(formData.startDate, "DD-MM-YYYY").toISOString(),
|
startDate: moment.utc(formData.startDate, "DD-MM-YYYY").toISOString(),
|
||||||
endDate: moment.utc(formData.endDate, "DD-MM-YYYY").toISOString(),
|
endDate: moment.utc(formData.endDate, "DD-MM-YYYY").toISOString(),
|
||||||
});
|
});
|
||||||
handleGroupBy(selectedGroup.id);
|
// handleGroupBy(selectedGroup.id);
|
||||||
// closePanel();
|
// closePanel();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -355,8 +355,18 @@ const PaymentRequestList = ({ filters, filterData, removeFilterChip, clearFilter
|
|||||||
) : (
|
) : (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={8} className="text-center border-0 ">
|
<td colSpan={8} className="text-center border-0 ">
|
||||||
<div className="py-8">
|
<div >
|
||||||
<p>No Request Found</p>
|
<p
|
||||||
|
className="text-center"
|
||||||
|
style={{
|
||||||
|
height: "250px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
No data found
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -106,10 +106,13 @@ const ExpensePage = () => {
|
|||||||
updated[key] = updated[key].filter((v) => v !== id);
|
updated[key] = updated[key].filter((v) => v !== id);
|
||||||
filterPanelRef.current?.resetFieldValue(key, updated[key]);
|
filterPanelRef.current?.resetFieldValue(key, updated[key]);
|
||||||
} else if (key === "dateRange") {
|
} else if (key === "dateRange") {
|
||||||
|
// --- START FIX: Use a dedicated function to reset the date range ---
|
||||||
updated.startDate = null;
|
updated.startDate = null;
|
||||||
updated.endDate = null;
|
updated.endDate = null;
|
||||||
filterPanelRef.current?.resetFieldValue("startDate", null);
|
|
||||||
filterPanelRef.current?.resetFieldValue("endDate", null);
|
// Call the new resetDateRange method on the ref
|
||||||
|
filterPanelRef.current?.resetDateRange();
|
||||||
|
// --- END FIX ---
|
||||||
}
|
}
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -71,6 +71,11 @@ const PaymentRequestPage = () => {
|
|||||||
if (Array.isArray(updated[key])) {
|
if (Array.isArray(updated[key])) {
|
||||||
updated[key] = updated[key].filter((v) => v !== id);
|
updated[key] = updated[key].filter((v) => v !== id);
|
||||||
setTimeout(() => updatedRef.current?.resetFieldValue(key, updated[key]), 0);
|
setTimeout(() => updatedRef.current?.resetFieldValue(key, updated[key]), 0);
|
||||||
|
} else if (key === "dateRange") { // Handle date range reset
|
||||||
|
updated.startDate = null;
|
||||||
|
updated.endDate = null;
|
||||||
|
// Call the new resetDateRange method on the ref
|
||||||
|
updatedRef.current?.resetDateRange();
|
||||||
} else {
|
} else {
|
||||||
updated[key] = null;
|
updated[key] = null;
|
||||||
setTimeout(() => updatedRef.current?.resetFieldValue(key, null), 0);
|
setTimeout(() => updatedRef.current?.resetFieldValue(key, null), 0);
|
||||||
@ -80,9 +85,9 @@ const PaymentRequestPage = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExport = (type) => {
|
const handleExport = (type) => {
|
||||||
HandlePaymentRequestExport(type, filters, search, tableRef, setExportLoading);
|
HandlePaymentRequestExport(type, filters, search, tableRef, setExportLoading);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PaymentRequestContext.Provider value={contextValue}>
|
<PaymentRequestContext.Provider value={contextValue}>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user