user can not select reimburseDate before transaction date

This commit is contained in:
pramod mahajan 2025-08-01 18:39:03 +05:30
parent 28fb1c9387
commit e0f130e6a6
4 changed files with 107 additions and 87 deletions

View File

@ -57,7 +57,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
(store) => store.localVariables.projectId
);
const { projectNames, loading: projectLoading, error } = useProjectName();
debugger
const {
PaymentModes,
loading: PaymentModeLoading,

View File

@ -12,7 +12,11 @@ import { useExpenseContext } from "../../pages/Expense/ExpensePage";
import { getColorNameFromHex } from "../../utils/appUtils";
import { ExpenseDetailsSkeleton } from "./ExpenseSkeleton";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { EXPENSE_REJECTEDBY, PROCESS_EXPENSE, REVIEW_EXPENSE } from "../../utils/constants";
import {
EXPENSE_REJECTEDBY,
PROCESS_EXPENSE,
REVIEW_EXPENSE,
} from "../../utils/constants";
import { useProfile } from "../../hooks/useProfile";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
@ -69,22 +73,25 @@ const ViewExpense = ({ ExpenseId }) => {
});
}, [data, userPermissions]);
const IsRejectedExpense = useMemo(()=>{
return EXPENSE_REJECTEDBY.includes(data?.status?.id)
},[data])
const IsRejectedExpense = useMemo(() => {
return EXPENSE_REJECTEDBY.includes(data?.status?.id);
}, [data]);
const isCreatedBy = useMemo(() => {
return data?.createdBy.id === CurrentUser?.id;
}, [data, CurrentUser]);
return data?.createdBy.id === CurrentUser?.id;
}, [data, CurrentUser]);
const { mutate: MakeAction,isPending } = useActionOnExpense(() => {
const { mutate: MakeAction, isPending } = useActionOnExpense(() => {
setClickedStatusId(null);
reset()});
reset();
});
const onSubmit = (formData) => {
const Payload = {
...formData,
reimburseDate:moment.utc(formData.reimburseDate, "DD-MM-YYYY").toISOString(),
reimburseDate: moment
.utc(formData.reimburseDate, "DD-MM-YYYY")
.toISOString(),
expenseId: ExpenseId,
comment: formData.comment,
};
@ -340,42 +347,51 @@ const ViewExpense = ({ ExpenseId }) => {
</div>
)}
</div>
{data.expensesReimburse && (<div className="row text-start">
<div className="col-md-6 mb-3">
<strong>Transaction ID :</strong> {data.expensesReimburse.reimburseTransactionId || "N/A"}
</div>
<div className="col-md-6 mb-3">
<strong>Reimburse Date :</strong>{" "}
{ moment(data.expensesReimburse.reimburseDate).format("DD-MM-YYYY") }
</div>
{data.expensesReimburse && (
<div className="row text-start">
<div className="col-md-6 mb-3">
<label className="form-label me-2 mb-0 fw-semibold">
Transaction ID :
</label>
{data.expensesReimburse.reimburseTransactionId || "N/A"}
</div>
<div className="col-md-6 mb-3">
<label className="form-label me-2 mb-0 fw-semibold">
Reimburse Date :
</label>
{formatUTCToLocalTime(data.expensesReimburse.reimburseDate)}
</div>
{data.expensesReimburse && (
<>
<div className="col-md-6 mb-3 d-flex align-items-center">
<strong className="me-2">Reimburse By :</strong>
<Avatar
size="xs"
classAvatar="m-0 me-1"
firstName={data?.expensesReimburse?.reimburseBy?.firstName}
lastName={data?.expensesReimburse?.reimburseBy?.lastName}
/>
<span className="text-muted">
{`${data?.expensesReimburse?.reimburseBy?.firstName} ${data?.expensesReimburse?.reimburseBy?.lastName}`.trim()}
</span>
</div>
</>
)}
{data.expensesReimburse && (
<>
<div className="col-md-6 mb-3 d-flex align-items-center">
<label className="form-label me-2 mb-0 fw-semibold">
Reimburse By :
</label>
<Avatar
size="xs"
classAvatar="m-0 me-1"
firstName={data?.expensesReimburse?.reimburseBy?.firstName}
lastName={data?.expensesReimburse?.reimburseBy?.lastName}
/>
<span className="text-muted">
{`${data?.expensesReimburse?.reimburseBy?.firstName} ${data?.expensesReimburse?.reimburseBy?.lastName}`.trim()}
</span>
</div>
</>
)}
<div className="col-md-6 mb-3">
<strong>Note :</strong> {data.expensesReimburse.reimburseNote}
</div>
</div>)}
<div className="col-md-6 mb-3">
<label className="form-label me-2 mb-0 fw-semibold"> Note :</label>{" "}
{data.expensesReimburse.reimburseNote}
</div>
</div>
)}
<div className="text-start">
<label className="form-label me-2 mb-0 fw-semibold">Description :</label>
<label className="form-label me-2 mb-0 fw-semibold">
Description :
</label>
<div className="text-muted">{data?.description}</div>
</div>
<div className="col-12 my-2 text-start">
@ -443,7 +459,7 @@ const ViewExpense = ({ ExpenseId }) => {
{Array.isArray(data?.nextStatus) && data.nextStatus.length > 0 && (
<>
{(IsPaymentProcess && nextStatusWithPermission?.length > 0) && (
{IsPaymentProcess && nextStatusWithPermission?.length > 0 && (
<div className="row">
<div className="col-12 col-md-6 text-start">
<label className="form-label">Transaction Id </label>
@ -460,7 +476,11 @@ const ViewExpense = ({ ExpenseId }) => {
</div>
<div className="col-12 col-md-6 text-start">
<label className="form-label">Transaction Date </label>
<DatePicker name="reimburseDate" control={control} />
<DatePicker
name="reimburseDate"
control={control}
minDate={data?.transactionDate}
/>
{errors.reimburseDate && (
<small className="danger-text">
{errors.reimburseDate.message}
@ -477,49 +497,47 @@ const ViewExpense = ({ ExpenseId }) => {
</div>
</div>
)}
<div className="col-12 mb-3 text-start">
{(
(nextStatusWithPermission.length > 0 && !IsRejectedExpense) ||
(IsRejectedExpense && isCreatedBy)
) && (
<>
<label className="form-label me-2 mb-0">Comment:</label>
<textarea
className="form-control form-control-sm"
{...register("comment")}
rows="2"
/>
{errors.comment && (
<small className="danger-text">
{errors.comment.message}
</small>
)}
</>
)}
{(nextStatusWithPermission?.length > 0 && (!IsRejectedExpense || isCreatedBy)) && (
<div className="text-center flex-wrap gap-2 my-2">
{nextStatusWithPermission.map((status, index) => (
<button
key={status.id || index}
type="button"
onClick={() => {
setClickedStatusId(status.id);
setValue("statusId", status.id);
handleSubmit(onSubmit)();
}}
disabled={isPending}
className="btn btn-primary btn-sm cursor-pointer mx-2 border-0"
>
{isPending && clickedStatusId === status.id
? "Please Wait..."
: status.displayName || status.name}
</button>
))}
</div>
)}
</div>
<div className="col-12 mb-3 text-start">
{((nextStatusWithPermission.length > 0 && !IsRejectedExpense) ||
(IsRejectedExpense && isCreatedBy)) && (
<>
<label className="form-label me-2 mb-0">Comment:</label>
<textarea
className="form-control form-control-sm"
{...register("comment")}
rows="2"
/>
{errors.comment && (
<small className="danger-text">
{errors.comment.message}
</small>
)}
</>
)}
{nextStatusWithPermission?.length > 0 &&
(!IsRejectedExpense || isCreatedBy) && (
<div className="text-center flex-wrap gap-2 my-2">
{nextStatusWithPermission.map((status, index) => (
<button
key={status.id || index}
type="button"
onClick={() => {
setClickedStatusId(status.id);
setValue("statusId", status.id);
handleSubmit(onSubmit)();
}}
disabled={isPending}
className="btn btn-primary btn-sm cursor-pointer mx-2 border-0"
>
{isPending && clickedStatusId === status.id
? "Please Wait..."
: status.displayName || status.name}
</button>
))}
</div>
)}
</div>
</>
)}
</form>

View File

@ -9,6 +9,7 @@ const DatePicker = ({
className = "",
allowText = false,
maxDate=new Date(),
minDate,
...rest
}) => {
const inputRef = useRef(null);
@ -29,6 +30,7 @@ const DatePicker = ({
? flatpickr.parseDate(value, "Y-m-d")
: null,
maxDate:maxDate,
minDate:new Date(minDate?.split("T")[0]) ?? undefined,
onChange: function (selectedDates, dateStr) {
onChange(dateStr);
},

View File

@ -45,7 +45,7 @@ const EmployeeSearchInput = ({ control, name, projectId }) => {
onChange={(e) => {
setSearch(e.target.value);
setShowDropdown(true);
onChange(""); // Clear previous selection
onChange("");
}}
onFocus={() => {
if (search) setShowDropdown(true);