fixed Transaction details inside request payment

This commit is contained in:
pramod.mahajan 2025-11-04 19:31:05 +05:30
parent 0dc68eb20d
commit ecf34b499e
5 changed files with 69 additions and 84 deletions

View File

@ -24,7 +24,7 @@ const ExpenseStatusLogs = ({ data }) => {
id: index + 1,
title: log.nextStatus?.name || "Status Updated",
description: log.nextStatus?.description || "",
timeAgo: moment.utc(log?.updatedAt).local().fromNow(),
timeAgo: log.updatedAt,
color: getColorNameFromHex(log.nextStatus?.color) || "primary",
users: log.updatedBy
? [

View File

@ -90,16 +90,16 @@ export const PaymentRequestActionScheam = (
.object({
comment: z.string().min(1, { message: "Please leave comment" }),
statusId: z.string().min(1, { message: "Please select a status" }),
paymentRequestId: z.string().nullable().optional(),
paidTransactionId: z.string().nullable().optional(),
paidAt: z.string().nullable().optional(),
paidById: z.string().nullable().optional(),
})
.superRefine((data, ctx) => {
if (isTransaction) {
if (!data.paymentRequestId?.trim()) {
if (!data.paidTransactionId?.trim()) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["paymentRequestId"],
path: ["paidTransactionId"],
message: "Reimburse Transaction ID is required",
});
}
@ -110,15 +110,7 @@ export const PaymentRequestActionScheam = (
message: "Transacion Date is required",
});
}
// let reimburse_Date = localToUtc(data.reimburseDate);
// if (transactionDate > reimburse_Date) {
// ctx.addIssue({
// code: z.ZodIssueCode.custom,
// path: ["reimburseDate"],
// message:
// "Reimburse Date must be greater than or equal to Expense created Date",
// });
// }
if (!data.paidById) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
@ -130,7 +122,7 @@ export const PaymentRequestActionScheam = (
});
};
export const defaultActionValues = {
export const defaultPaymentRequestActionValues = {
comment: "",
statusId: "",

View File

@ -1,4 +1,4 @@
import { useMemo, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import {
useActionOnExpense,
useActionOnPaymentRequest,
@ -28,11 +28,16 @@ import { useNavigate } from "react-router-dom";
import { usePaymentRequestContext } from "../../pages/PaymentRequest/PaymentRequestPage";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import {
EXPENSE_DRAFT,
EXPENSE_REJECTEDBY,
PROCESS_EXPENSE,
REVIEW_EXPENSE,
} from "../../utils/constants";
import Label from "../common/Label";
import {
defaultPaymentRequestActionValues,
PaymentRequestActionScheam,
} from "./PaymentRequestSchema";
const ViewPaymentRequest = ({ requestId }) => {
const { data, isLoading, isError, error, isFetching } =
@ -42,9 +47,10 @@ const ViewPaymentRequest = ({ requestId }) => {
const IsReview = useHasUserPermission(REVIEW_EXPENSE);
const [imageLoaded, setImageLoaded] = useState({});
const { setDocumentView } = usePaymentRequestContext();
const { setDocumentView, setModalSize } = usePaymentRequestContext();
const ActionSchema =
ExpenseActionScheam(IsPaymentProcess, data?.createdAt) ?? z.object({});
PaymentRequestActionScheam(IsPaymentProcess, data?.createdAt) ??
z.object({});
const navigate = useNavigate();
const {
register,
@ -55,7 +61,7 @@ const ViewPaymentRequest = ({ requestId }) => {
formState: { errors },
} = useForm({
resolver: zodResolver(ActionSchema),
defaultValues: defaultActionValues,
defaultValues: defaultPaymentRequestActionValues,
});
const userPermissions = useSelector(
@ -97,7 +103,7 @@ const ViewPaymentRequest = ({ requestId }) => {
const onSubmit = (formData) => {
const Payload = {
...formData,
paidAt: localToUtc(formData.reimburseDate),
paidAt: localToUtc(formData.paidAt),
paymentRequestId: data.id,
comment: formData.comment,
};
@ -111,18 +117,25 @@ const ViewPaymentRequest = ({ requestId }) => {
};
return (
<form className="container-xl px-3" onSubmit={handleSubmit(onSubmit)}>
<div className="col-12 mb-1">
<form className="container px-3" onSubmit={handleSubmit(onSubmit)}>
<div className="col-12 mb-2 text-center ">
<h5 className="fw-semibold m-0">Payment Request Details</h5>
<hr />
</div>
<div className="row mb-1">
<div className="col-12 col-sm-6 col-md-8">
<div className="row text-start">
<div className=" col-sm-12 col-md-7 border-none border-md-end">
<div className="row">
<div className="col-12 text-start fw-semibold mb-2">
<div className="col-12 d-flex justify-content-between text-start fw-semibold mb-2">
{data?.paymentRequestUID}
<span
className={`badge bg-label-${
getColorNameFromHex(data?.expenseStatus?.color) || "secondary"
}`}
>
{data?.expenseStatus?.name}
</span>
</div>
<div className="col-md-6 mb-3">
<div className="col-md-12 mb-3">
<div className="d-block d-md-flex align-items-center">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
@ -134,7 +147,7 @@ const ViewPaymentRequest = ({ requestId }) => {
</div>
</div>
<div className="col-md-6 mb-3">
<div className="col-md-12 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
@ -147,7 +160,7 @@ const ViewPaymentRequest = ({ requestId }) => {
</div>
</div>
</div>
<div className="col-md-6 mb-3">
<div className="col-md-12 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
@ -160,7 +173,7 @@ const ViewPaymentRequest = ({ requestId }) => {
</div>
{/* Row 2 */}
<div className="col-md-6 mb-3">
<div className="col-md-12 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
@ -171,7 +184,7 @@ const ViewPaymentRequest = ({ requestId }) => {
<div className="text-muted">{data?.payee}</div>
</div>
</div>
<div className="col-md-6 mb-3">
<div className="col-md-1 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
@ -185,20 +198,8 @@ const ViewPaymentRequest = ({ requestId }) => {
</div>
</div>
{/* Row 3 */}
{/* <div className="col-md-6 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
style={{ minWidth: "130px" }}
>
Payment Mode :
</label>
<div className="text-muted">{data?.paymentMode?.name}</div>
</div>
</div> */}
{data?.gstNumber && (
<div className="col-md-6 mb-3">
<div className="col-md-12 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
@ -212,25 +213,8 @@ const ViewPaymentRequest = ({ requestId }) => {
)}
{/* Row 4 */}
<div className="col-md-6 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
style={{ minWidth: "130px" }}
>
Status :
</label>
<span
className={`badge bg-label-${
getColorNameFromHex(data?.expenseStatus?.color) ||
"secondary"
}`}
>
{data?.expenseStatus?.name}
</span>
</div>
</div>
<div className="col-md-6 mb-3">
<div className="col-md-12 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
@ -244,18 +228,7 @@ const ViewPaymentRequest = ({ requestId }) => {
</div>
</div>
<div className="col-md-6 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
style={{ minWidth: "130px" }}
>
Project :
</label>
<div className="text-muted">{data?.project?.name}</div>
</div>
</div>
<div className="col-md-6 mb-3">
<div className="col-md-12 mb-3">
<div className="d-flex">
<label
className="form-label me-2 mb-0 fw-semibold text-start"
@ -271,7 +244,7 @@ const ViewPaymentRequest = ({ requestId }) => {
{/* Row 6 */}
{data?.createdBy && (
<div className="col-md-6 text-start">
<div className="col-md-12 text-start">
<div className="d-flex align-items-center">
<label
className="form-label me-2 mb-0 fw-semibold"
@ -296,7 +269,7 @@ const ViewPaymentRequest = ({ requestId }) => {
</div>
)}
{data?.paidBy && (
<div className="col-md-6 text-start">
<div className="col-md-12 text-start">
<div className="d-flex align-items-center">
<label
className="form-label me-2 mb-0 fw-semibold"
@ -496,7 +469,11 @@ const ViewPaymentRequest = ({ requestId }) => {
)}
</div>
</div>
<div className="col-12 col-sm-6 col-md-4">
<div className=" col-sm-12 my-2 my-md-0 border-top border-md-none col-md-5">
<div className="d-flex my-2">
<i className="bx bx-time-five me-2 "></i>{" "}
<p className="fw-medium">TimeLine</p>
</div>
<ExpenseStatusLogs data={data} />
</div>
</div>

View File

@ -1,5 +1,8 @@
import React from "react";
import Avatar from "./Avatar";
import Tooltip from "./Tooltip";
import { formatUTCToLocalTime } from "../../utils/dateUtils";
import moment from "moment";
const Timeline = ({ items = [], transparent = true }) => {
return (
@ -8,7 +11,7 @@ const Timeline = ({ items = [], transparent = true }) => {
transparent ? "timeline-transparent text-start" : ""
}`}
>
{items.map((item) => (
{items && items?.map((item) => (
<li
key={item.id}
className={`timeline-item ${
@ -24,7 +27,7 @@ const Timeline = ({ items = [], transparent = true }) => {
<div className="timeline-event">
<div className="timeline-header mb-3 d-flex justify-content-between">
<h6 className="mb-0 text-body">{item.title}</h6>
<small className="text-body-secondary">{item.timeAgo}</small>
<small className="text-body-secondary"><Tooltip text={formatUTCToLocalTime(item.timeAgo,true)}>{moment.utc(item.timeAgo).local().fromNow()}</Tooltip></small>
</div>
{item.description && <p className="mb-2">{item.description}</p>}
@ -64,7 +67,8 @@ const Timeline = ({ items = [], transparent = true }) => {
height="32"
/>
) : (
<Avatar size="xs"
<Avatar
size="xs"
firstName={user.firstName}
lastName={user.lastName}
/>
@ -84,6 +88,16 @@ const Timeline = ({ items = [], transparent = true }) => {
</div>
</li>
))}
{!items || items.length == 0 && (
<li
className={`timeline-item text-center ${
transparent ? "timeline-item-transparent" : ""
}`}
>
Not action yet.
</li>
)}
</ul>
);
};

View File

@ -14,7 +14,7 @@ export const PaymentRequestContext = createContext();
export const usePaymentRequestContext = () => {
const context = useContext(PaymentRequestContext);
if (!context) {
throw new Error("usePaymentRequestContext must be used within an ExpenseProvider");
throw new Error("usePaymentRequestContext must be used within an RequestPaymentProvider");
}
return context;
};
@ -30,12 +30,14 @@ const PaymentRequestPage = () => {
IsOpen: false,
Image: null,
});
const [modalSize,setModalSize] = useState("md")
const [search, setSearch] = useState("");
const contextValue = {
setManageRequest,
setVieRequest,
setDocumentView
setDocumentView,
setModalSize
};
useEffect(() => {
@ -125,7 +127,7 @@ const PaymentRequestPage = () => {
{ViewRequest.view && (
<GlobalModel
isOpen
size="xl"
modalType="top"
closeModal={() => setVieRequest({ requestId: null, view: false })}
>