modify view of PR
This commit is contained in:
parent
30615e4bba
commit
bc6a935e95
@ -256,7 +256,10 @@ font-weight: normal;
|
||||
.h-48 { height: 12rem; } /* 192px */
|
||||
.h-56 { height: 14rem; } /* 224px */
|
||||
.h-64 { height: 16rem; } /* 256px */
|
||||
.h-70 { height: 20rem; } /* 256px */
|
||||
.h-74 { max-height: 35rem; } /* 256px */
|
||||
.h-full { height: 100%; }
|
||||
|
||||
.h-screen{ height: 100vh; }
|
||||
|
||||
/* ==========================
|
||||
|
||||
@ -154,7 +154,7 @@ export const ExpenseTableSkeleton = ({ groups = 3, rowsPerGroup = 3 }) => {
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="d-none d-sm-table-cell">
|
||||
<div className="text-start ms-5">Expense Type</div>
|
||||
<div className="text-start ms-5">Expense Categort</div>
|
||||
</th>
|
||||
<th className="d-none d-sm-table-cell">
|
||||
<div className="text-start ms-5">Payment Mode</div>
|
||||
|
||||
@ -2,7 +2,7 @@ import React from "react";
|
||||
import { formatFileSize, getIconByFileType } from "../../utils/appUtils";
|
||||
import Tooltip from "../common/Tooltip";
|
||||
|
||||
const Filelist = ({ files, removeFile, expenseToEdit }) => {
|
||||
const Filelist = ({ files, removeFile, expenseToEdit,sm=6,md=4 }) => {
|
||||
return (
|
||||
<div className="d-flex flex-wrap gap-2 my-1">
|
||||
{files
|
||||
@ -13,7 +13,7 @@ const Filelist = ({ files, removeFile, expenseToEdit }) => {
|
||||
return true;
|
||||
})
|
||||
.map((file, idx) => (
|
||||
<div className="col-12 col-sm-6 col-md-4 mb-2" key={idx}>
|
||||
<div className={`col-12 col-sm-${sm} col-md-${md} mb-2`} key={idx}>
|
||||
<div className="d-flex align-items-center justify-content-between bg-white border rounded p-1">
|
||||
{/* File icon and info */}
|
||||
<div className="d-flex align-items-center flex-grow-1 gap-2 overflow-hidden">
|
||||
|
||||
@ -171,126 +171,151 @@ const ActionPaymentRequest = ({ requestId }) => {
|
||||
{IsPaymentProcess && nextStatusWithPermission?.length > 0 && (
|
||||
<>
|
||||
{isProccesed ? (
|
||||
<div className="row text-start mt-3">
|
||||
{/* Expense Making */}
|
||||
<div className="col-md-6 mb-2">
|
||||
<Label htmlFor="paymentModeId" className="form-label" required>
|
||||
Payment Mode
|
||||
</Label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
id="paymentModeId"
|
||||
{...register("paymentModeId")}
|
||||
<div class="accordion-item active shadow-none">
|
||||
<h2 class="accordion-header d-flex align-items-center">
|
||||
<button
|
||||
type="button"
|
||||
class="accordion-button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#accordionWithIcon-1"
|
||||
aria-expanded="true"
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Mode
|
||||
</option>
|
||||
{PaymentModeLoading ? (
|
||||
<option disabled>Loading...</option>
|
||||
) : (
|
||||
PaymentModes?.map((payment) => (
|
||||
<option key={payment.id} value={payment.id}>
|
||||
{payment.name}
|
||||
<i class="icon-base bx bx-receipt me-2"></i>
|
||||
Make Expense
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div
|
||||
id="accordionWithIcon-1"
|
||||
className="accordion-collapse collapse show"
|
||||
>
|
||||
<div className="row text-start mt-3">
|
||||
{/* Expense Making */}
|
||||
<div className="col-md-6 mb-2">
|
||||
<Label
|
||||
htmlFor="paymentModeId"
|
||||
className="form-label"
|
||||
required
|
||||
>
|
||||
Payment Mode
|
||||
</Label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
id="paymentModeId"
|
||||
{...register("paymentModeId")}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Mode
|
||||
</option>
|
||||
))
|
||||
)}
|
||||
</select>
|
||||
{errors.paymentModeId && (
|
||||
<small className="danger-text">
|
||||
{errors.paymentModeId.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
<label htmlFor="statusId" className="form-label ">
|
||||
GST Number
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="gstNumber"
|
||||
className="form-control form-control-sm"
|
||||
min="1"
|
||||
{...register("gstNumber")}
|
||||
/>
|
||||
{errors.gstNumber && (
|
||||
<small className="danger-text">
|
||||
{errors.gstNumber.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start">
|
||||
<label className="form-label">Location </label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("location")}
|
||||
/>
|
||||
{errors.location && (
|
||||
<small className="danger-text">
|
||||
{errors.location.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="row my-2 text-start">
|
||||
<div className="col-md-12">
|
||||
<Label className="form-label" required>
|
||||
Upload Bill{" "}
|
||||
</Label>
|
||||
|
||||
<div
|
||||
className="border border-secondary border-dashed rounded p-4 text-center bg-textMuted position-relative"
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() =>
|
||||
document.getElementById("billAttachments").click()
|
||||
}
|
||||
>
|
||||
<i className="bx bx-cloud-upload d-block bx-lg"> </i>
|
||||
<span className="text-muted d-block">
|
||||
Click to select or click here to browse
|
||||
</span>
|
||||
<small className="text-muted">
|
||||
(PDF, JPG, PNG, max 5MB)
|
||||
</small>
|
||||
|
||||
<input
|
||||
type="file"
|
||||
id="billAttachments"
|
||||
accept=".pdf,.jpg,.jpeg,.png"
|
||||
multiple
|
||||
style={{ display: "none" }}
|
||||
{...register("billAttachments")}
|
||||
onChange={(e) => {
|
||||
onFileChange(e);
|
||||
e.target.value = "";
|
||||
}}
|
||||
/>
|
||||
{PaymentModeLoading ? (
|
||||
<option disabled>Loading...</option>
|
||||
) : (
|
||||
PaymentModes?.map((payment) => (
|
||||
<option key={payment.id} value={payment.id}>
|
||||
{payment.name}
|
||||
</option>
|
||||
))
|
||||
)}
|
||||
</select>
|
||||
{errors.paymentModeId && (
|
||||
<small className="danger-text">
|
||||
{errors.paymentModeId.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
{errors.billAttachments && (
|
||||
<small className="danger-text">
|
||||
{errors.billAttachments.message}
|
||||
</small>
|
||||
)}
|
||||
{files?.length > 0 && (
|
||||
<Filelist
|
||||
files={files}
|
||||
removeFile={removeFile}
|
||||
expenseToEdit={false}
|
||||
/>
|
||||
)}
|
||||
|
||||
{Array.isArray(errors.billAttachments) &&
|
||||
errors.billAttachments.map((fileError, index) => (
|
||||
<div key={index} className="danger-text small mt-1">
|
||||
{
|
||||
(fileError?.fileSize?.message ||
|
||||
fileError?.contentType?.message ||
|
||||
fileError?.base64Data?.message,
|
||||
fileError?.documentId?.message)
|
||||
<div className="col-md-6">
|
||||
<label htmlFor="statusId" className="form-label ">
|
||||
GST Number
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="gstNumber"
|
||||
className="form-control form-control-sm"
|
||||
min="1"
|
||||
{...register("gstNumber")}
|
||||
/>
|
||||
{errors.gstNumber && (
|
||||
<small className="danger-text">
|
||||
{errors.gstNumber.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start">
|
||||
<label className="form-label">Location </label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("location")}
|
||||
/>
|
||||
{errors.location && (
|
||||
<small className="danger-text">
|
||||
{errors.location.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<Label className="form-label" required>
|
||||
Upload Bill{" "}
|
||||
</Label>
|
||||
|
||||
<div
|
||||
className="border border-secondary border-dashed rounded p-4 text-center bg-textMuted position-relative"
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() =>
|
||||
document.getElementById("billAttachments").click()
|
||||
}
|
||||
>
|
||||
<i className="bx bx-cloud-upload d-block bx-lg"> </i>
|
||||
<span className="text-muted d-block">
|
||||
Click to select or click here to browse
|
||||
</span>
|
||||
<small className="text-muted">
|
||||
(PDF, JPG, PNG, max 5MB)
|
||||
</small>
|
||||
|
||||
<input
|
||||
type="file"
|
||||
id="billAttachments"
|
||||
accept=".pdf,.jpg,.jpeg,.png"
|
||||
multiple
|
||||
style={{ display: "none" }}
|
||||
{...register("billAttachments")}
|
||||
onChange={(e) => {
|
||||
onFileChange(e);
|
||||
e.target.value = "";
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{errors.billAttachments && (
|
||||
<small className="danger-text">
|
||||
{errors.billAttachments.message}
|
||||
</small>
|
||||
)}
|
||||
{files?.length > 0 && (
|
||||
<Filelist
|
||||
files={files}
|
||||
removeFile={removeFile}
|
||||
expenseToEdit={false}
|
||||
sm={12}
|
||||
md={12}
|
||||
/>
|
||||
)}
|
||||
|
||||
{Array.isArray(errors.billAttachments) &&
|
||||
errors.billAttachments.map((fileError, index) => (
|
||||
<div key={index} className="danger-text small mt-1">
|
||||
{
|
||||
(fileError?.fileSize?.message ||
|
||||
fileError?.contentType?.message ||
|
||||
fileError?.base64Data?.message,
|
||||
fileError?.documentId?.message)
|
||||
}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@ -321,11 +346,12 @@ const ActionPaymentRequest = ({ requestId }) => {
|
||||
<small className="danger-text">{errors.paidAt.message}</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start">
|
||||
<div className="col-12 text-start mb-2">
|
||||
<label className="form-label">Paid By </label>
|
||||
<EmployeeSearchInput
|
||||
control={control}
|
||||
name="paidById"
|
||||
placeholder="Enter Employee Name"
|
||||
projectId={null}
|
||||
/>
|
||||
</div>
|
||||
@ -380,6 +406,7 @@ const ActionPaymentRequest = ({ requestId }) => {
|
||||
{((nextStatusWithPermission?.length > 0 && !isRejectedRequest) ||
|
||||
(isRejectedRequest && isCreatedBy)) && (
|
||||
<>
|
||||
|
||||
<Label className="form-label me-2 mb-0" required>
|
||||
Comment
|
||||
</Label>
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { useProjectName } from "../../hooks/useProjects";
|
||||
import Label from "../common/Label";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useCurrencies, useExpenseCategory } from "../../hooks/masterHook/useMaster";
|
||||
import {
|
||||
useCurrencies,
|
||||
useExpenseCategory,
|
||||
} from "../../hooks/masterHook/useMaster";
|
||||
import DatePicker from "../common/DatePicker";
|
||||
import {
|
||||
useCreatePaymentRequest,
|
||||
@ -17,10 +20,15 @@ import {
|
||||
defaultPaymentRequest,
|
||||
PaymentRequestSchema,
|
||||
} from "./PaymentRequestSchema";
|
||||
import { INR_CURRENCY_CODE } from "../../utils/constants";
|
||||
import {
|
||||
EXPENSE_DRAFT,
|
||||
EXPENSE_STATUS,
|
||||
INR_CURRENCY_CODE,
|
||||
} from "../../utils/constants";
|
||||
import Filelist from "../Expenses/Filelist";
|
||||
import InputSuggestions from "../common/InputSuggestion";
|
||||
import { useProfile } from "../../hooks/useProfile";
|
||||
import { blockUI } from "../../utils/blockUI";
|
||||
|
||||
function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
const {
|
||||
@ -71,7 +79,14 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
});
|
||||
|
||||
const [isItself, setisItself] = useState(false);
|
||||
|
||||
const isDraft = useMemo(() => {
|
||||
if (!data) return false;
|
||||
return EXPENSE_STATUS.daft === data?.expenseStatus.id;
|
||||
}, [data]);
|
||||
const isProcessed = useMemo(() => {
|
||||
if (!data) return false;
|
||||
return EXPENSE_STATUS.payment_processed === data?.expenseStatus.id;
|
||||
}, [data]);
|
||||
const files = watch("billAttachments");
|
||||
const onFileChange = async (e) => {
|
||||
const newFiles = Array.from(e.target.files);
|
||||
@ -211,7 +226,7 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
setValue("payee", name);
|
||||
};
|
||||
return (
|
||||
<div className="container p-3">
|
||||
<div className="container p-3 ">
|
||||
<h5 className="m-0">
|
||||
{requestToEdit ? "Update Payment Request " : "Create Payment Request"}
|
||||
</h5>
|
||||
@ -225,6 +240,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
{...register("projectId")}
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
>
|
||||
<option value="">Select Project</option>
|
||||
{projectLoading ? (
|
||||
@ -250,6 +268,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
className="form-select form-select-sm"
|
||||
id="expenseCategoryId"
|
||||
{...register("expenseCategoryId")}
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Category
|
||||
@ -283,6 +304,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
id="title"
|
||||
className="form-control form-control-sm"
|
||||
{...register("title")}
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
/>
|
||||
{errors.title && (
|
||||
<small className="danger-text">{errors.title.message}</small>
|
||||
@ -298,6 +322,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
name="isAdvancePayment"
|
||||
control={control}
|
||||
defaultValue={defaultPaymentRequest.isAdvancePayment ?? false}
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
render={({ field }) => (
|
||||
<div className="d-flex align-items-center gap-3">
|
||||
<div className="form-check d-flex flex-row m-0 gap-2">
|
||||
@ -343,6 +370,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
control={control}
|
||||
minDate={new Date()}
|
||||
className="w-100"
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
/>
|
||||
|
||||
{errors.dueDate && (
|
||||
@ -382,6 +412,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
setValue("payee", val, { shouldValidate: true })
|
||||
}
|
||||
error={errors.payee?.message}
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Checkbox below input */}
|
||||
@ -392,6 +425,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
className="form-check-input"
|
||||
value={isItself}
|
||||
onChange={handleSetItSelf}
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
/>
|
||||
<Label htmlFor="sameAsSupplier" className="form-check-label">
|
||||
It self
|
||||
@ -407,6 +443,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
id="currencyId"
|
||||
className="form-select form-select-sm"
|
||||
{...register("currencyId")}
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
>
|
||||
<option value="">Select Currency</option>
|
||||
|
||||
@ -437,6 +476,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
className="form-control form-control-sm"
|
||||
{...register("description")}
|
||||
rows="2"
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
></textarea>
|
||||
{errors.description && (
|
||||
<small className="danger-text">
|
||||
@ -473,6 +515,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
|
||||
onFileChange(e);
|
||||
e.target.value = "";
|
||||
}}
|
||||
disabled={
|
||||
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{errors.billAttachments && (
|
||||
|
||||
@ -199,7 +199,7 @@ const PaymentRequestList = ({ filters, groupBy = "submittedBy", search }) => {
|
||||
};
|
||||
const canEditExpense = (paymentRequest) => {
|
||||
return (
|
||||
(paymentRequest?.expenseStatus?.id === EXPENSE_DRAFT ||
|
||||
(paymentRequest?.expenseStatus?.id === EXPENSE_DRAFT || paymentRequest?.recurringPayment?.isVariable === true ||
|
||||
EXPENSE_REJECTEDBY.includes(paymentRequest?.expenseStatus.id)) &&
|
||||
paymentRequest?.createdBy?.id === SelfId
|
||||
);
|
||||
|
||||
@ -5,7 +5,6 @@ import Timeline from "../common/TimeLine";
|
||||
import moment from "moment";
|
||||
import { getColorNameFromHex } from "../../utils/appUtils";
|
||||
const PaymentStatusLogs = ({ data }) => {
|
||||
|
||||
const sortedLogs = useMemo(() => {
|
||||
if (!data?.updateLogs) return [];
|
||||
return [...data.updateLogs].sort(
|
||||
@ -13,8 +12,6 @@ const PaymentStatusLogs = ({ data }) => {
|
||||
);
|
||||
}, [data?.updateLogs]);
|
||||
|
||||
|
||||
|
||||
const timelineData = useMemo(() => {
|
||||
return sortedLogs.map((log, index) => ({
|
||||
id: log.id,
|
||||
@ -22,7 +19,7 @@ const PaymentStatusLogs = ({ data }) => {
|
||||
description: log.nextStatus?.description || "",
|
||||
timeAgo: log.updatedAt,
|
||||
color: getColorNameFromHex(log.nextStatus?.color) || "primary",
|
||||
userComment:log.comment,
|
||||
userComment: log.comment,
|
||||
users: log.updatedBy
|
||||
? [
|
||||
{
|
||||
@ -40,48 +37,14 @@ const PaymentStatusLogs = ({ data }) => {
|
||||
setVisibleCount((prev) => prev + 4);
|
||||
};
|
||||
return (
|
||||
<div className="page-min-h overflow-auto h-56 py-1" >
|
||||
{/* <div className="row g-2">
|
||||
{logsToShow.map((log) => (
|
||||
<div key={log.id} className="col-12 d-flex align-items-start mb-1">
|
||||
<Avatar
|
||||
size="xs"
|
||||
firstName={log.updatedBy.firstName}
|
||||
lastName={log.updatedBy.lastName}
|
||||
/>
|
||||
|
||||
<div className="flex-grow-1">
|
||||
<div className="text-start">
|
||||
<div className="flex">
|
||||
<span>{`${log.updatedBy.firstName} ${log.updatedBy.lastName}`}</span>
|
||||
<small className="text-secondary text-tiny ms-2">
|
||||
<em>{log.action}</em>
|
||||
</small>
|
||||
<span className="text-tiny text-secondary d-block">
|
||||
{formatUTCToLocalTime(log.updateAt, true)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="d-flex align-items-center text-muted small mt-1">
|
||||
<span>{log.comment}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="">
|
||||
<div className="d-flex mb-2 py-1">
|
||||
<i className="bx bx-time-five me-2 "></i>{" "}
|
||||
<p className="fw-medium">TimeLine</p>
|
||||
</div>
|
||||
<div className="row h-74 overflow-auto px-3">
|
||||
<Timeline items={timelineData} />
|
||||
</div>
|
||||
|
||||
{sortedLogs.length > visibleCount && (
|
||||
<div className="text-center my-1">
|
||||
<button
|
||||
className="btn btn-xs btn-outline-primary"
|
||||
onClick={handleShowMore}
|
||||
>
|
||||
Show More
|
||||
</button>
|
||||
</div>
|
||||
)} */}
|
||||
|
||||
<Timeline items={timelineData} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -132,9 +132,9 @@ const ViewPaymentRequest = ({ requestId }) => {
|
||||
<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-7">
|
||||
<div className="row">
|
||||
<div className="row mb-1 ">
|
||||
<div className="col-12 col-sm-6 ">
|
||||
<div className="row ">
|
||||
<div className="col-12 d-flex justify-content-between mb-6">
|
||||
<span> {data?.paymentRequestUID}</span>
|
||||
<span
|
||||
@ -145,111 +145,107 @@ const ViewPaymentRequest = ({ requestId }) => {
|
||||
{data?.expenseStatus?.name}
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-8 mb-3">
|
||||
<div className="d-flex">
|
||||
<label
|
||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||
style={{ minWidth: "130px" }}
|
||||
>
|
||||
<div className="row">
|
||||
<div className="col-6 mb-3 text-start ">
|
||||
<label className="form-label me-2 mb-0 fw-semibold ">
|
||||
Project Name:
|
||||
</label>
|
||||
<div className="text-muted">{data?.project?.name || "—"}</div>
|
||||
</div>
|
||||
<div className="col-6 mb-3 text-start ">
|
||||
<small className="text-muted">
|
||||
{data?.project?.name || "—"}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-4 mb-3">
|
||||
<div className="d-flex">
|
||||
<label
|
||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||
style={{ minWidth: "100px" }}
|
||||
>
|
||||
Due Date :
|
||||
<div className="row">
|
||||
<div className="col-6 mb-3 text-start">
|
||||
<label className="form-label me-2 mb-0 fw-semibold text-start">
|
||||
Due Date:
|
||||
</label>
|
||||
<div className="text-muted">
|
||||
</div>
|
||||
<div className="col-6 mb-3 text-start">
|
||||
<small className="text-muted">
|
||||
{formatUTCToLocalTime(data?.dueDate)}
|
||||
</div>
|
||||
</small>
|
||||
</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" }}
|
||||
>
|
||||
Expense Category :
|
||||
<div className="row">
|
||||
<div className="col-6 mb-3 text-start">
|
||||
<label className="form-label me-2 mb-0 fw-semibold ">
|
||||
Expense Category:
|
||||
</label>
|
||||
<div className="text-muted">{data?.expenseCategory?.name}</div>
|
||||
</div>
|
||||
<div className="col-6 mb-3 text-start">
|
||||
<small className="text-muted">
|
||||
{data?.expenseCategory?.name}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<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" }}
|
||||
>
|
||||
Supplier :
|
||||
<div className="row text-start">
|
||||
<div className="col-6 mb-3">
|
||||
<label className="form-label me-2 mb-0 fw-semibold text-start">
|
||||
Supplier:
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-6 mb-3">
|
||||
<div className="text-muted">{data?.payee}</div>
|
||||
</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" }}
|
||||
>
|
||||
Amount :
|
||||
<div className="row text-start">
|
||||
<div className="col-6 mb-3">
|
||||
<label className="form-label me-2 mb-0 fw-semibold text-start">
|
||||
Amount:
|
||||
</label>
|
||||
<div className="text-muted">
|
||||
</div>
|
||||
<div className="col-6 mb-3">
|
||||
<small className="text-muted">
|
||||
{formatFigure(data?.amount, {
|
||||
type: "currency",
|
||||
currency: data?.currency?.currencyCode,
|
||||
})}
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{data?.gstNumber && (
|
||||
<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" }}
|
||||
>
|
||||
GST Number :
|
||||
<div className="row text-start">
|
||||
<div className="col-6 mb-3">
|
||||
<label className="form-label me-2 mb-0 fw-semibold text-start">
|
||||
GST Number:
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-6 mb-3">
|
||||
<div className="text-muted">{data?.gstNumber}</div>
|
||||
</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" }}
|
||||
>
|
||||
Created At :
|
||||
<div className="row text-start">
|
||||
<div className="col-6 mb-3">
|
||||
<label className="form-label me-2 mb-0 fw-semibold text-start">
|
||||
Created At:
|
||||
</label>
|
||||
<div className="text-muted">
|
||||
</div>
|
||||
<div className="col-6 mb-3">
|
||||
<small className="text-muted">
|
||||
{formatUTCToLocalTime(data?.createdAt, true)}
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 6 */}
|
||||
{data?.createdBy && (
|
||||
<div className="col-md-6 text-start">
|
||||
<div className="d-flex align-items-center">
|
||||
<label
|
||||
className="form-label me-2 mb-0 fw-semibold"
|
||||
style={{ minWidth: "130px" }}
|
||||
>
|
||||
Created By :
|
||||
<div className="row">
|
||||
<div className="col-6 text-start">
|
||||
<label className="form-label me-2 mb-0 fw-semibold">
|
||||
Created By:
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-6 text-start">
|
||||
<div className="d-flex align-items-center">
|
||||
<Avatar
|
||||
size="xs"
|
||||
@ -267,13 +263,10 @@ const ViewPaymentRequest = ({ requestId }) => {
|
||||
</div>
|
||||
)}
|
||||
{data?.paidBy && (
|
||||
<div className="col-md-6 text-start">
|
||||
<div className="d-flex align-items-center">
|
||||
<label
|
||||
className="form-label me-2 mb-0 fw-semibold"
|
||||
style={{ minWidth: "130px" }}
|
||||
>
|
||||
Paid By :
|
||||
<div className="col-6 text-start">
|
||||
<div className="d-flex flex-column gap-2 text-start">
|
||||
<label className="form-label me-2 mb-0 fw-semibold">
|
||||
Paid By:
|
||||
</label>
|
||||
<div className="d-flex align-items-center ">
|
||||
<Avatar
|
||||
@ -292,13 +285,60 @@ const ViewPaymentRequest = ({ requestId }) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="text-start my-1">
|
||||
<div className="text-start my-2">
|
||||
<label className="fw-semibold form-label">Description : </label>
|
||||
<div className="text-muted">{data?.description}</div>
|
||||
</div>
|
||||
<div className="col-6 text-start">
|
||||
<label className="form-label me-2 mb-2 fw-semibold">
|
||||
Attachment :
|
||||
|
||||
{data?.paidTransactionId && (
|
||||
<>
|
||||
<div className="row text-start mb-2">
|
||||
<div className="col-6 mb-sm-0 mb-2">
|
||||
<label className="form-label me-2 mb-0 fw-semibold">
|
||||
Transaction ID:
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-6 mb-sm-0 mb-2">
|
||||
<small>{data?.paidTransactionId}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row text-start mb-2">
|
||||
<div className="col-6 ">
|
||||
<label className="form-label me-2 mb-0 fw-semibold">
|
||||
Transaction Date :
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-6 ">
|
||||
{formatUTCToLocalTime(data?.paidAt)}
|
||||
<small></small>{" "}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{data?.paidBy && (
|
||||
<div className="row text-start mb-2">
|
||||
<div className="col-6 ">
|
||||
<label className="form-label me-2 mb-0 fw-semibold">
|
||||
Paid By :
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-6 d-flex align-items-center ">
|
||||
<Avatar
|
||||
size="xs"
|
||||
classAvatar="m-0 me-1"
|
||||
firstName={data?.paidBy?.firstName}
|
||||
lastName={data?.paidBy?.lastName}
|
||||
/>
|
||||
<span className="text-muted">
|
||||
{`${data?.paidBy?.firstName} ${data?.paidBy?.lastName}`.trim()}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<div className="col-6 text-start mt-2 mb-2">
|
||||
<label className="form-label me-2 mb-1 fw-semibold">
|
||||
Attachment:
|
||||
</label>
|
||||
|
||||
<div className="d-flex flex-wrap gap-2">
|
||||
@ -312,180 +352,10 @@ const ViewPaymentRequest = ({ requestId }) => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{data?.paidTransactionId && (
|
||||
<div className="row text-start mt-2">
|
||||
<div className="col-md-6 mb-sm-0 mb-2">
|
||||
<label className="form-label me-2 mb-0 fw-semibold">
|
||||
Transaction ID :
|
||||
</label>
|
||||
{data?.paidTransactionId}
|
||||
</div>
|
||||
<div className="col-md-6 ">
|
||||
<label className="form-label me-2 mb-0 fw-semibold">
|
||||
Transaction Date :
|
||||
</label>
|
||||
{formatUTCToLocalTime(data?.paidAt)}
|
||||
</div>
|
||||
|
||||
{data?.paidBy && (
|
||||
<>
|
||||
<div className="col-md-6 d-flex align-items-center">
|
||||
<label className="form-label me-2 mb-0 fw-semibold">
|
||||
Paid By :
|
||||
</label>
|
||||
<Avatar
|
||||
size="xs"
|
||||
classAvatar="m-0 me-1"
|
||||
firstName={data?.paidBy?.firstName}
|
||||
lastName={data?.paidBy?.lastName}
|
||||
/>
|
||||
<span className="text-muted">
|
||||
{`${data?.paidBy?.firstName} ${data?.paidBy?.lastName}`.trim()}
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* {Array.isArray(data?.nextStatus) && (data?.nextStatus?.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>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("paidTransactionId")}
|
||||
/>
|
||||
{errors.paidTransactionId && (
|
||||
<small className="danger-text">
|
||||
{errors.paidTransactionId.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start mb-1">
|
||||
<label className="form-label">Transaction Date </label>
|
||||
<DatePicker className="w-100"
|
||||
name="paidAt"
|
||||
control={control}
|
||||
minDate={data?.createdAt}
|
||||
/>
|
||||
{errors.paidAt && (
|
||||
<small className="danger-text">
|
||||
{errors.paidAt.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start">
|
||||
<label className="form-label">Paid By </label>
|
||||
<EmployeeSearchInput
|
||||
control={control}
|
||||
name="paidById"
|
||||
projectId={null}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start mb-1">
|
||||
<Label className="form-label">TDS Percentage</Label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("tdsPercentage")}
|
||||
/>
|
||||
{errors.tdsPercentage && (
|
||||
<small className="danger-text">
|
||||
{errors.tdsPercentage.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start mb-1">
|
||||
<Label className="form-label" required>
|
||||
Base Amount
|
||||
</Label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("baseAmount")}
|
||||
/>
|
||||
{errors.baseAmount && (
|
||||
<small className="danger-text">
|
||||
{errors.baseAmount.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start mb-1">
|
||||
<Label className="form-label" required>
|
||||
Tax Amount
|
||||
</Label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("taxAmount")}
|
||||
/>
|
||||
{errors.taxAmount && (
|
||||
<small className="danger-text">
|
||||
{errors.taxAmount.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="col-12 mb-3 text-start">
|
||||
{((nextStatusWithPermission?.length > 0 &&
|
||||
!isRejectedRequest) ||
|
||||
(isRejectedRequest && isCreatedBy)) && (
|
||||
<>
|
||||
<Label className="form-label me-2 mb-0" required>
|
||||
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 &&
|
||||
(!isRejectedRequest || isCreatedBy) && (
|
||||
<div className="text-end flex-wrap gap-2 my-2 mt-3">
|
||||
{nextStatusWithPermission?.map((status, index) => (
|
||||
<button
|
||||
key={status.id || index}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setClickedStatusId(status.id);
|
||||
setValue("statusId", status.id);
|
||||
handleSubmit(onSubmit)();
|
||||
}}
|
||||
disabled={isPending || isFetching}
|
||||
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>
|
||||
</>
|
||||
) } */}
|
||||
<ActionPaymentRequest requestId={requestId} />
|
||||
</div>
|
||||
</div>
|
||||
<div className=" col-sm-12 my-md-0 border-top border-md-none col-md-5">
|
||||
<div className="d-flex mb-2 py-1">
|
||||
<i className="bx bx-time-five me-2 "></i>{" "}
|
||||
<p className="fw-medium">TimeLine</p>
|
||||
</div>
|
||||
<div className=" col-sm-12 my-md-0 border-top border-md-none col-md-6 ">
|
||||
<PaymentStatusLogs data={data} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -132,7 +132,7 @@ const PaymentRequestPage = () => {
|
||||
{ViewRequest.view && (
|
||||
<GlobalModel
|
||||
isOpen
|
||||
size="xl"
|
||||
size="lg"
|
||||
modalType="top"
|
||||
closeModal={() => setVieRequest({ requestId: null, view: false })}
|
||||
>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user