added flatepicker for dates
This commit is contained in:
parent
6fbc0411db
commit
b864ed0529
@ -1,16 +1,16 @@
|
||||
// components/Expense/ExpenseFilterPanel.jsx
|
||||
import React, { useEffect } from "react";
|
||||
import { FormProvider, useForm, Controller } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { defaultFilter, SearchSchema } from "./ExpenseSchema";
|
||||
|
||||
import DateRangePicker from "../common/DateRangePicker";
|
||||
import DateRangePicker, { DateRangePicker1 } from "../common/DateRangePicker";
|
||||
import SelectMultiple from "../common/SelectMultiple";
|
||||
|
||||
import { useProjectName } from "../../hooks/useProjects";
|
||||
import { useExpenseStatus } from "../../hooks/masterHook/useMaster";
|
||||
import { useEmployeesAllOrByProjectId } from "../../hooks/useEmployees";
|
||||
import { useSelector } from "react-redux";
|
||||
import moment from "moment";
|
||||
|
||||
const ExpenseFilterPanel = ({ onApply }) => {
|
||||
const selectedProjectId = useSelector(
|
||||
@ -51,7 +51,11 @@ const ExpenseFilterPanel = ({ onApply }) => {
|
||||
};
|
||||
|
||||
const onSubmit = (data) => {
|
||||
onApply(data);
|
||||
onApply({
|
||||
...data,
|
||||
startDate: moment.utc(data.startDate, "DD-MM-YYYY").toISOString(),
|
||||
endDate: moment.utc(data.endDate, "DD-MM-YYYY").toISOString(),
|
||||
});
|
||||
closePanel();
|
||||
};
|
||||
|
||||
@ -66,11 +70,17 @@ const ExpenseFilterPanel = ({ onApply }) => {
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="p-2 text-start">
|
||||
<div className="mb-3 w-100">
|
||||
<label className="form-label">Created Date</label>
|
||||
<DateRangePicker
|
||||
{/* <DateRangePicker
|
||||
onRangeChange={setDateRange}
|
||||
endDateMode="today"
|
||||
DateDifference="6"
|
||||
dateFormat="DD-MM-YYYY"
|
||||
/> */}
|
||||
|
||||
<DateRangePicker1
|
||||
placeholder="DD-MM-YYYY To DD-MM-YYYY"
|
||||
startField="startDate"
|
||||
endField="endDate"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -11,8 +11,6 @@ import ConfirmModal from "../common/ConfirmModal";
|
||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
|
||||
|
||||
const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
const [deletingId, setDeletingId] = useState(null);
|
||||
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
@ -20,7 +18,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
const IsExpenseEditable = useHasUserPermission();
|
||||
const IsExpesneApprpve = useHasUserPermission(APPROVE_EXPENSE);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const pageSize = 10;
|
||||
const pageSize = 20;
|
||||
|
||||
const { mutate: DeleteExpense, isPending } = useDeleteExpense();
|
||||
const { data, isLoading, isError, isInitialLoading, error } = useExpenseList(
|
||||
@ -63,7 +61,9 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
key = item.status?.displayName || "Unknown";
|
||||
break;
|
||||
case "paidBy":
|
||||
key = `${item.paidBy?.firstName ?? ""} ${item.paidBy?.lastName ?? ""}`.trim();
|
||||
key = `${item.paidBy?.firstName ?? ""} ${
|
||||
item.paidBy?.lastName ?? ""
|
||||
}`.trim();
|
||||
break;
|
||||
case "project":
|
||||
key = item.project?.name || "Unknown Project";
|
||||
@ -88,20 +88,21 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
key: "expensesType",
|
||||
label: "Expense Type",
|
||||
getValue: (e) => e.expensesType?.name || "N/A",
|
||||
align:"text-start",
|
||||
align: "text-start",
|
||||
},
|
||||
{
|
||||
key: "paymentMode",
|
||||
label: "Payment Mode",
|
||||
getValue: (e) => e.paymentMode?.name || "N/A",
|
||||
align:"text-start"
|
||||
align: "text-start",
|
||||
},
|
||||
{
|
||||
key: "paidBy",
|
||||
label: "Paid By",
|
||||
align:"text-start",
|
||||
align: "text-start",
|
||||
getValue: (e) =>
|
||||
`${e.paidBy?.firstName ?? ""} ${e.paidBy?.lastName ?? ""}`.trim() || "N/A",
|
||||
`${e.paidBy?.firstName ?? ""} ${e.paidBy?.lastName ?? ""}`.trim() ||
|
||||
"N/A",
|
||||
customRender: (e) => (
|
||||
<div className="d-flex align-items-center">
|
||||
<Avatar
|
||||
@ -111,16 +112,18 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
lastName={e.paidBy?.lastName}
|
||||
/>
|
||||
<span>
|
||||
{`${e.paidBy?.firstName ?? ""} ${e.paidBy?.lastName ?? ""}`.trim() || "N/A"}
|
||||
{`${e.paidBy?.firstName ?? ""} ${
|
||||
e.paidBy?.lastName ?? ""
|
||||
}`.trim() || "N/A"}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "submitted",
|
||||
label: "Submitted",
|
||||
getValue: (e) => formatUTCToLocalTime(e?.createdAt),
|
||||
isAlwaysVisible: true
|
||||
isAlwaysVisible: true,
|
||||
},
|
||||
{
|
||||
key: "amount",
|
||||
@ -131,24 +134,30 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
</>
|
||||
),
|
||||
isAlwaysVisible: true,
|
||||
align: "text-end"
|
||||
align: "text-end",
|
||||
},
|
||||
{
|
||||
key: "status",
|
||||
label: "Status",
|
||||
align:"text-center",
|
||||
align: "text-center",
|
||||
getValue: (e) => (
|
||||
<span className={`badge bg-label-${getColorNameFromHex(e?.status?.color) || "secondary"}`}>
|
||||
<span
|
||||
className={`badge bg-label-${
|
||||
getColorNameFromHex(e?.status?.color) || "secondary"
|
||||
}`}
|
||||
>
|
||||
{e.status?.name || "Unknown"}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
if (isInitialLoading) return <ExpenseTableSkeleton />;
|
||||
if (isError) return <div>{error}</div>;
|
||||
|
||||
const grouped = groupBy ? groupByField(data?.data ?? [], groupBy) : { All: data?.data ?? [] };
|
||||
const grouped = groupBy
|
||||
? groupByField(data?.data ?? [], groupBy)
|
||||
: { All: data?.data ?? [] };
|
||||
const IsGroupedByDate = ["transactionDate", "createdAt"].includes(groupBy);
|
||||
|
||||
return (
|
||||
@ -160,7 +169,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
role="dialog"
|
||||
style={{
|
||||
display: "block",
|
||||
backgroundColor: "rgba(0,0,0,0.5)"
|
||||
backgroundColor: "rgba(0,0,0,0.5)",
|
||||
}}
|
||||
aria-hidden="false"
|
||||
>
|
||||
@ -177,8 +186,11 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
)}
|
||||
|
||||
<div className="card">
|
||||
<div className="card-datatable table-responsive">
|
||||
<div className="dataTables_wrapper no-footer px-2">
|
||||
<div
|
||||
className="card-datatable table-responsive "
|
||||
id="horizontal-example"
|
||||
>
|
||||
<div className="dataTables_wrapper no-footer px-2 ">
|
||||
<table className="table border-top dataTable text-nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -194,67 +206,80 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
</th>
|
||||
)
|
||||
)}
|
||||
<th>Action</th>
|
||||
<th className="sticky-action-column bg-white text-center">
|
||||
Action
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.entries(grouped).map(([group, expenses]) => (
|
||||
<React.Fragment key={group}>
|
||||
<tr className="tr-group text-dark">
|
||||
<td colSpan={8} className="text-start">
|
||||
<strong>{IsGroupedByDate ? formatUTCToLocalTime(group) : group}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
{expenses.map((expense) => (
|
||||
<tr key={expense.id}>
|
||||
{expenseColumns.map(
|
||||
(col) =>
|
||||
(col.isAlwaysVisible || groupBy !== col.key) && (
|
||||
<td key={col.key} className={`d-table-cell ${col.align ?? ""}`}>
|
||||
{col.customRender
|
||||
? col.customRender(expense)
|
||||
: col.getValue(expense)}
|
||||
</td>
|
||||
)
|
||||
)}
|
||||
<td>
|
||||
<div className="d-flex justify-content-center gap-2">
|
||||
<i
|
||||
className="bx bx-show text-primary cursor-pointer"
|
||||
onClick={() =>
|
||||
setViewExpense({ expenseId: expense.id, view: true })
|
||||
}
|
||||
></i>
|
||||
{(expense.status.name === "Draft" ||
|
||||
expense.status.name === "Rejected") &&
|
||||
expense.createdBy.id === SelfId && (
|
||||
<i
|
||||
className="bx bx-edit text-secondary cursor-pointer"
|
||||
onClick={() =>
|
||||
setManageExpenseModal({
|
||||
IsOpen: true,
|
||||
expenseId: expense.id
|
||||
})
|
||||
}
|
||||
></i>
|
||||
)}
|
||||
{expense.status.name === "Draft" &&
|
||||
expense?.createdBy?.id === SelfId && (
|
||||
<i
|
||||
className="bx bx-trash text-danger cursor-pointer"
|
||||
onClick={() => {
|
||||
setIsDeleteModalOpen(true);
|
||||
setDeletingId(expense.id);
|
||||
}}
|
||||
></i>
|
||||
)}
|
||||
</div>
|
||||
{Object.keys(grouped).length > 0 ? (
|
||||
Object.entries(grouped).map(([group, expenses]) => (
|
||||
<React.Fragment key={group}>
|
||||
<tr className="tr-group text-dark">
|
||||
<td colSpan={8} className="text-start">
|
||||
<strong>
|
||||
{IsGroupedByDate
|
||||
? formatUTCToLocalTime(group)
|
||||
: group}
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
{data?.data?.length === 0 && (
|
||||
{expenses.map((expense) => (
|
||||
<tr key={expense.id}>
|
||||
{expenseColumns.map(
|
||||
(col) =>
|
||||
(col.isAlwaysVisible || groupBy !== col.key) && (
|
||||
<td
|
||||
key={col.key}
|
||||
className={`d-table-cell ${col.align ?? ""}`}
|
||||
>
|
||||
{col.customRender
|
||||
? col.customRender(expense)
|
||||
: col.getValue(expense)}
|
||||
</td>
|
||||
)
|
||||
)}
|
||||
<td className="sticky-action-column bg-white">
|
||||
<div className="d-flex justify-content-center gap-2">
|
||||
<i
|
||||
className="bx bx-show text-primary cursor-pointer"
|
||||
onClick={() =>
|
||||
setViewExpense({
|
||||
expenseId: expense.id,
|
||||
view: true,
|
||||
})
|
||||
}
|
||||
></i>
|
||||
{(expense.status.name === "Draft" ||
|
||||
expense.status.name === "Rejected") &&
|
||||
expense.createdBy.id === SelfId && (
|
||||
<i
|
||||
className="bx bx-edit text-secondary cursor-pointer"
|
||||
onClick={() =>
|
||||
setManageExpenseModal({
|
||||
IsOpen: true,
|
||||
expenseId: expense.id,
|
||||
})
|
||||
}
|
||||
></i>
|
||||
)}
|
||||
{expense.status.name === "Draft" &&
|
||||
expense.createdBy.id === SelfId && (
|
||||
<i
|
||||
className="bx bx-trash text-danger cursor-pointer"
|
||||
onClick={() => {
|
||||
setIsDeleteModalOpen(true);
|
||||
setDeletingId(expense.id);
|
||||
}}
|
||||
></i>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan={8} className="text-center py-4">
|
||||
No Expense Found
|
||||
@ -278,4 +303,3 @@ const ExpenseList = ({ filters, groupBy = "transactionDate" }) => {
|
||||
};
|
||||
|
||||
export default ExpenseList;
|
||||
|
||||
|
@ -23,6 +23,7 @@ import {
|
||||
} from "../../hooks/useExpense";
|
||||
import ExpenseSkeleton from "./ExpenseSkeleton";
|
||||
import moment from "moment";
|
||||
import DatePicker from "../common/DatePicker";
|
||||
|
||||
const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
const {
|
||||
@ -44,6 +45,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
watch,
|
||||
setValue,
|
||||
reset,
|
||||
control,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: zodResolver(schema),
|
||||
@ -171,7 +173,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
}
|
||||
);
|
||||
const onSubmit = (fromdata) => {
|
||||
let payload = {...fromdata,transactionDate: moment.utc(fromdata.transactionDate, 'YYYY-MM-DD').toISOString()}
|
||||
let payload = {...fromdata,transactionDate: moment.utc(fromdata.transactionDate, 'DD-MM-YYYY').toISOString()}
|
||||
if (expenseToEdit) {
|
||||
const editPayload = { ...payload, id: data.id };
|
||||
ExpenseUpdate({ id: data.id, payload: editPayload });
|
||||
@ -321,13 +323,18 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
<label for="transactionDate" className="form-label ">
|
||||
Transaction Date
|
||||
</label>
|
||||
<input
|
||||
{/* <input
|
||||
type="date"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="YYYY-MM-DD"
|
||||
id="flatpickr-date"
|
||||
{...register("transactionDate")}
|
||||
/>
|
||||
/> */}
|
||||
<DatePicker
|
||||
name="transactionDate"
|
||||
control={control}
|
||||
/>
|
||||
|
||||
{errors.transactionDate && (
|
||||
<small className="danger-text">
|
||||
{errors.transactionDate.message}
|
||||
|
@ -1,39 +1,69 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useController } from "react-hook-form";
|
||||
|
||||
const DatePicker = ({ onDateChange }) => {
|
||||
|
||||
const DatePicker = ({
|
||||
name,
|
||||
control,
|
||||
placeholder = "DD-MM-YYYY",
|
||||
className = "",
|
||||
allowText = false,
|
||||
maxDate=new Date(),
|
||||
...rest
|
||||
}) => {
|
||||
const inputRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fp = flatpickr(inputRef.current, {
|
||||
dateFormat: "Y-m-d",
|
||||
defaultDate: new Date(),
|
||||
onChange: (selectedDates, dateStr) => {
|
||||
if (onDateChange) {
|
||||
onDateChange(dateStr); // Pass selected date to parent
|
||||
}
|
||||
}
|
||||
});
|
||||
const {
|
||||
field: { onChange, value, ref }
|
||||
} = useController({
|
||||
name,
|
||||
control
|
||||
});
|
||||
|
||||
return () => {
|
||||
// Cleanup flatpickr instance
|
||||
fp.destroy();
|
||||
};
|
||||
}, [onDateChange]);
|
||||
useEffect(() => {
|
||||
if (inputRef.current) {
|
||||
flatpickr(inputRef.current, {
|
||||
dateFormat: "d-m-Y",
|
||||
allowInput: allowText,
|
||||
defaultDate: value
|
||||
? flatpickr.parseDate(value, "Y-m-d")
|
||||
: null,
|
||||
maxDate:maxDate,
|
||||
onChange: function (selectedDates, dateStr) {
|
||||
onChange(dateStr);
|
||||
},
|
||||
...rest
|
||||
});
|
||||
}
|
||||
}, [inputRef]);
|
||||
|
||||
return (
|
||||
<div className="container mt-3">
|
||||
<div className="mb-3">
|
||||
{/* <label htmlFor="flatpickr-single" className="form-label">
|
||||
Select Date
|
||||
</label> */}
|
||||
<input
|
||||
type="text"
|
||||
id="flatpickr-single"
|
||||
className="form-control"
|
||||
placeholder="YYYY-MM-DD"
|
||||
ref={inputRef}
|
||||
/>
|
||||
</div>
|
||||
<div className={` position-relative ${className}`}>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm "
|
||||
placeholder={placeholder}
|
||||
defaultValue={
|
||||
value ? flatpickr.formatDate(flatpickr.parseDate(value, "Y-m-d"), "d-m-Y") : ""
|
||||
}
|
||||
ref={(el) => {
|
||||
inputRef.current = el;
|
||||
ref(el);
|
||||
}}
|
||||
readOnly={!allowText}
|
||||
autoComplete="off"
|
||||
/>
|
||||
|
||||
<span
|
||||
className="position-absolute top-50 end-0 pe-1 translate-middle-y cursor-pointer"
|
||||
onClick={() => {
|
||||
if (inputRef.current && inputRef.current._flatpickr) {
|
||||
inputRef.current._flatpickr.open();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<i className="bx bx-calendar bx-sm fs-5 text-muted"></i>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
|
||||
import { useController, useFormContext } from "react-hook-form";
|
||||
const DateRangePicker = ({
|
||||
md,
|
||||
sm,
|
||||
onRangeChange,
|
||||
DateDifference = 7,
|
||||
DateDifference = 7,
|
||||
endDateMode = "yesterday",
|
||||
}) => {
|
||||
const inputRef = useRef(null);
|
||||
@ -12,25 +12,25 @@ const DateRangePicker = ({
|
||||
useEffect(() => {
|
||||
const endDate = new Date();
|
||||
if (endDateMode === "yesterday") {
|
||||
endDate.setDate(endDate.getDate() - 1);
|
||||
endDate.setDate(endDate.getDate() - 1);
|
||||
}
|
||||
|
||||
endDate.setHours(0, 0, 0, 0);
|
||||
|
||||
const startDate = new Date(endDate);
|
||||
const startDate = new Date(endDate);
|
||||
startDate.setDate(endDate.getDate() - (DateDifference - 1));
|
||||
startDate.setHours(0, 0, 0, 0);
|
||||
|
||||
const fp = flatpickr(inputRef.current, {
|
||||
mode: "range",
|
||||
dateFormat: "Y-m-d",
|
||||
altInput: true,
|
||||
altFormat: "d-m-Y",
|
||||
defaultDate: [startDate, endDate],
|
||||
static: false,
|
||||
dateFormat: "Y-m-d",
|
||||
altInput: true,
|
||||
altFormat: "d-m-Y",
|
||||
defaultDate: [startDate, endDate],
|
||||
static: false,
|
||||
// appendTo: document.body,
|
||||
clickOpens: true,
|
||||
maxDate: endDate,
|
||||
maxDate: endDate,
|
||||
onChange: (selectedDates, dateStr) => {
|
||||
const [startDateString, endDateString] = dateStr.split(" To ");
|
||||
onRangeChange?.({ startDate: startDateString, endDate: endDateString });
|
||||
@ -38,8 +38,8 @@ const DateRangePicker = ({
|
||||
});
|
||||
|
||||
onRangeChange?.({
|
||||
startDate: startDate.toLocaleDateString("en-CA"),
|
||||
endDate: endDate.toLocaleDateString("en-CA"),
|
||||
startDate: startDate.toLocaleDateString("en-CA"),
|
||||
endDate: endDate.toLocaleDateString("en-CA"),
|
||||
});
|
||||
|
||||
return () => {
|
||||
@ -48,22 +48,99 @@ const DateRangePicker = ({
|
||||
}, [onRangeChange, DateDifference, endDateMode]);
|
||||
|
||||
return (
|
||||
<div className={`col-${sm} col-sm-${md} px-1 position-relative`}>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm ps-2 pe-5 me-4"
|
||||
placeholder="From to End"
|
||||
id="flatpickr-range"
|
||||
ref={inputRef}
|
||||
/>
|
||||
|
||||
<i
|
||||
className="bx bx-calendar calendar-icon cursor-pointer position-absolute top-50 translate-middle-y "
|
||||
style={{right:"12px"}}
|
||||
></i>
|
||||
</div>
|
||||
<div className={`col-${sm} col-sm-${md} px-1 position-relative`}>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm ps-2 pe-5 me-4"
|
||||
placeholder="From to End"
|
||||
id="flatpickr-range"
|
||||
ref={inputRef}
|
||||
/>
|
||||
|
||||
<i
|
||||
className="bx bx-calendar calendar-icon cursor-pointer position-absolute top-50 translate-middle-y "
|
||||
style={{ right: "12px" }}
|
||||
></i>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DateRangePicker;
|
||||
|
||||
export const DateRangePicker1 = ({
|
||||
startField = "startDate",
|
||||
endField = "endDate",
|
||||
label,
|
||||
placeholder = "Select date range",
|
||||
className = "",
|
||||
allowText = false,
|
||||
...rest
|
||||
}) => {
|
||||
const inputRef = useRef(null);
|
||||
const { control, setValue, getValues } = useFormContext();
|
||||
|
||||
const {
|
||||
field: { ref },
|
||||
} = useController({ name: startField, control });
|
||||
|
||||
useEffect(() => {
|
||||
if (!inputRef.current || inputRef.current._flatpickr) return;
|
||||
|
||||
const defaultStart = getValues(startField);
|
||||
const defaultEnd = getValues(endField);
|
||||
|
||||
const instance = flatpickr(inputRef.current, {
|
||||
mode: "range",
|
||||
dateFormat: "d-m-Y",
|
||||
allowInput: allowText,
|
||||
defaultDate:
|
||||
defaultStart && defaultEnd
|
||||
? [
|
||||
flatpickr.parseDate(defaultStart, "d-m-Y"),
|
||||
flatpickr.parseDate(defaultEnd, "d-m-Y"),
|
||||
]
|
||||
: null,
|
||||
onChange: (selectedDates, dateStr, fp) => {
|
||||
if (selectedDates.length === 2) {
|
||||
const [start, end] = selectedDates;
|
||||
const format = (d) => flatpickr.formatDate(d, "d-m-Y");
|
||||
setValue(startField, format(start));
|
||||
setValue(endField, format(end));
|
||||
} else {
|
||||
setValue(startField, "");
|
||||
setValue(endField, "");
|
||||
}
|
||||
},
|
||||
...rest,
|
||||
});
|
||||
|
||||
return () => instance.destroy();
|
||||
}, []);
|
||||
|
||||
const start = getValues(startField);
|
||||
const end = getValues(endField);
|
||||
const formattedValue = start && end ? `${start} To ${end}` : "";
|
||||
|
||||
return (
|
||||
<div className={` position-relative ${className}`}>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
placeholder={placeholder}
|
||||
defaultValue={formattedValue}
|
||||
ref={(el) => {
|
||||
inputRef.current = el;
|
||||
ref(el);
|
||||
}}
|
||||
readOnly={!allowText}
|
||||
autoComplete="off"
|
||||
/>
|
||||
<span
|
||||
className="position-absolute top-50 end-0 pe-1 translate-middle-y cursor-pointer"
|
||||
onClick={() => inputRef.current?._flatpickr?.open()}
|
||||
>
|
||||
<i className="bx bx-calendar bx-sm fs-5 text-muted"></i>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -81,47 +81,13 @@ const ExpensePage = () => {
|
||||
resolver: zodResolver(SearchSchema),
|
||||
defaultValues: defaultFilter,
|
||||
});
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
control,
|
||||
getValues,
|
||||
trigger,
|
||||
setValue,
|
||||
watch,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = methods;
|
||||
|
||||
const { projectNames, loading: projectLoading } = useProjectName();
|
||||
const { ExpenseStatus, loading: statusLoading, error } = useExpenseStatus();
|
||||
const { employees, loading: empLoading } = useEmployeesAllOrByProjectId(
|
||||
true,
|
||||
selectedProjectId,
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
const { setOffcanvasContent, setShowTrigger } = useFab();
|
||||
|
||||
const onSubmit = (data) => {
|
||||
setFilter(data);
|
||||
};
|
||||
const isValidDate = (date) => {
|
||||
return date instanceof Date && !isNaN(date);
|
||||
};
|
||||
|
||||
|
||||
const setDateRange = ({ startDate, endDate }) => {
|
||||
const parsedStart = new Date(startDate);
|
||||
const parsedEnd = new Date(endDate);
|
||||
|
||||
setValue(
|
||||
"startDate",
|
||||
isValidDate(parsedStart) ? parsedStart.toISOString().split("T")[0] : null
|
||||
);
|
||||
setValue(
|
||||
"endDate",
|
||||
isValidDate(parsedEnd) ? parsedEnd.toISOString().split("T")[0] : null
|
||||
);
|
||||
};
|
||||
|
||||
const clearFilter = () => {
|
||||
setFilter({
|
||||
|
Loading…
x
Reference in New Issue
Block a user