modify view of PR

This commit is contained in:
pramod.mahajan 2025-11-10 12:40:29 +05:30
parent 30615e4bba
commit bc6a935e95
9 changed files with 326 additions and 418 deletions

View File

@ -256,7 +256,10 @@ font-weight: normal;
.h-48 { height: 12rem; } /* 192px */ .h-48 { height: 12rem; } /* 192px */
.h-56 { height: 14rem; } /* 224px */ .h-56 { height: 14rem; } /* 224px */
.h-64 { height: 16rem; } /* 256px */ .h-64 { height: 16rem; } /* 256px */
.h-70 { height: 20rem; } /* 256px */
.h-74 { max-height: 35rem; } /* 256px */
.h-full { height: 100%; } .h-full { height: 100%; }
.h-screen{ height: 100vh; } .h-screen{ height: 100vh; }
/* ========================== /* ==========================

View File

@ -154,7 +154,7 @@ export const ExpenseTableSkeleton = ({ groups = 3, rowsPerGroup = 3 }) => {
<thead> <thead>
<tr> <tr>
<th className="d-none d-sm-table-cell"> <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>
<th className="d-none d-sm-table-cell"> <th className="d-none d-sm-table-cell">
<div className="text-start ms-5">Payment Mode</div> <div className="text-start ms-5">Payment Mode</div>

View File

@ -2,7 +2,7 @@ import React from "react";
import { formatFileSize, getIconByFileType } from "../../utils/appUtils"; import { formatFileSize, getIconByFileType } from "../../utils/appUtils";
import Tooltip from "../common/Tooltip"; import Tooltip from "../common/Tooltip";
const Filelist = ({ files, removeFile, expenseToEdit }) => { const Filelist = ({ files, removeFile, expenseToEdit,sm=6,md=4 }) => {
return ( return (
<div className="d-flex flex-wrap gap-2 my-1"> <div className="d-flex flex-wrap gap-2 my-1">
{files {files
@ -13,7 +13,7 @@ const Filelist = ({ files, removeFile, expenseToEdit }) => {
return true; return true;
}) })
.map((file, idx) => ( .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"> <div className="d-flex align-items-center justify-content-between bg-white border rounded p-1">
{/* File icon and info */} {/* File icon and info */}
<div className="d-flex align-items-center flex-grow-1 gap-2 overflow-hidden"> <div className="d-flex align-items-center flex-grow-1 gap-2 overflow-hidden">

View File

@ -171,126 +171,151 @@ const ActionPaymentRequest = ({ requestId }) => {
{IsPaymentProcess && nextStatusWithPermission?.length > 0 && ( {IsPaymentProcess && nextStatusWithPermission?.length > 0 && (
<> <>
{isProccesed ? ( {isProccesed ? (
<div className="row text-start mt-3"> <div class="accordion-item active shadow-none">
{/* Expense Making */} <h2 class="accordion-header d-flex align-items-center">
<div className="col-md-6 mb-2"> <button
<Label htmlFor="paymentModeId" className="form-label" required> type="button"
Payment Mode class="accordion-button"
</Label> data-bs-toggle="collapse"
<select data-bs-target="#accordionWithIcon-1"
className="form-select form-select-sm" aria-expanded="true"
id="paymentModeId"
{...register("paymentModeId")}
> >
<option value="" disabled> <i class="icon-base bx bx-receipt me-2"></i>
Select Mode Make Expense
</option> </button>
{PaymentModeLoading ? ( </h2>
<option disabled>Loading...</option>
) : ( <div
PaymentModes?.map((payment) => ( id="accordionWithIcon-1"
<option key={payment.id} value={payment.id}> className="accordion-collapse collapse show"
{payment.name} >
<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> </option>
)) {PaymentModeLoading ? (
)} <option disabled>Loading...</option>
</select> ) : (
{errors.paymentModeId && ( PaymentModes?.map((payment) => (
<small className="danger-text"> <option key={payment.id} value={payment.id}>
{errors.paymentModeId.message} {payment.name}
</small> </option>
)} ))
</div> )}
</select>
<div className="col-md-6"> {errors.paymentModeId && (
<label htmlFor="statusId" className="form-label "> <small className="danger-text">
GST Number {errors.paymentModeId.message}
</label> </small>
<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 = "";
}}
/>
</div> </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) && <div className="col-md-6">
errors.billAttachments.map((fileError, index) => ( <label htmlFor="statusId" className="form-label ">
<div key={index} className="danger-text small mt-1"> GST Number
{ </label>
(fileError?.fileSize?.message || <input
fileError?.contentType?.message || type="text"
fileError?.base64Data?.message, id="gstNumber"
fileError?.documentId?.message) 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 && (
</div> <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>
</div> </div>
) : ( ) : (
@ -321,11 +346,12 @@ const ActionPaymentRequest = ({ requestId }) => {
<small className="danger-text">{errors.paidAt.message}</small> <small className="danger-text">{errors.paidAt.message}</small>
)} )}
</div> </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> <label className="form-label">Paid By </label>
<EmployeeSearchInput <EmployeeSearchInput
control={control} control={control}
name="paidById" name="paidById"
placeholder="Enter Employee Name"
projectId={null} projectId={null}
/> />
</div> </div>
@ -380,6 +406,7 @@ const ActionPaymentRequest = ({ requestId }) => {
{((nextStatusWithPermission?.length > 0 && !isRejectedRequest) || {((nextStatusWithPermission?.length > 0 && !isRejectedRequest) ||
(isRejectedRequest && isCreatedBy)) && ( (isRejectedRequest && isCreatedBy)) && (
<> <>
<Label className="form-label me-2 mb-0" required> <Label className="form-label me-2 mb-0" required>
Comment Comment
</Label> </Label>

View File

@ -1,8 +1,11 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import { useProjectName } from "../../hooks/useProjects"; import { useProjectName } from "../../hooks/useProjects";
import Label from "../common/Label"; import Label from "../common/Label";
import { Controller, useForm } from "react-hook-form"; 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 DatePicker from "../common/DatePicker";
import { import {
useCreatePaymentRequest, useCreatePaymentRequest,
@ -17,10 +20,15 @@ import {
defaultPaymentRequest, defaultPaymentRequest,
PaymentRequestSchema, PaymentRequestSchema,
} from "./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 Filelist from "../Expenses/Filelist";
import InputSuggestions from "../common/InputSuggestion"; import InputSuggestions from "../common/InputSuggestion";
import { useProfile } from "../../hooks/useProfile"; import { useProfile } from "../../hooks/useProfile";
import { blockUI } from "../../utils/blockUI";
function ManagePaymentRequest({ closeModal, requestToEdit = null }) { function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
const { const {
@ -71,7 +79,14 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
}); });
const [isItself, setisItself] = useState(false); 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 files = watch("billAttachments");
const onFileChange = async (e) => { const onFileChange = async (e) => {
const newFiles = Array.from(e.target.files); const newFiles = Array.from(e.target.files);
@ -211,7 +226,7 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
setValue("payee", name); setValue("payee", name);
}; };
return ( return (
<div className="container p-3"> <div className="container p-3 ">
<h5 className="m-0"> <h5 className="m-0">
{requestToEdit ? "Update Payment Request " : "Create Payment Request"} {requestToEdit ? "Update Payment Request " : "Create Payment Request"}
</h5> </h5>
@ -225,6 +240,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
<select <select
className="form-select form-select-sm" className="form-select form-select-sm"
{...register("projectId")} {...register("projectId")}
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
> >
<option value="">Select Project</option> <option value="">Select Project</option>
{projectLoading ? ( {projectLoading ? (
@ -250,6 +268,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
className="form-select form-select-sm" className="form-select form-select-sm"
id="expenseCategoryId" id="expenseCategoryId"
{...register("expenseCategoryId")} {...register("expenseCategoryId")}
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
> >
<option value="" disabled> <option value="" disabled>
Select Category Select Category
@ -283,6 +304,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
id="title" id="title"
className="form-control form-control-sm" className="form-control form-control-sm"
{...register("title")} {...register("title")}
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
/> />
{errors.title && ( {errors.title && (
<small className="danger-text">{errors.title.message}</small> <small className="danger-text">{errors.title.message}</small>
@ -298,6 +322,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
name="isAdvancePayment" name="isAdvancePayment"
control={control} control={control}
defaultValue={defaultPaymentRequest.isAdvancePayment ?? false} defaultValue={defaultPaymentRequest.isAdvancePayment ?? false}
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
render={({ field }) => ( render={({ field }) => (
<div className="d-flex align-items-center gap-3"> <div className="d-flex align-items-center gap-3">
<div className="form-check d-flex flex-row m-0 gap-2"> <div className="form-check d-flex flex-row m-0 gap-2">
@ -343,6 +370,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
control={control} control={control}
minDate={new Date()} minDate={new Date()}
className="w-100" className="w-100"
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
/> />
{errors.dueDate && ( {errors.dueDate && (
@ -382,6 +412,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
setValue("payee", val, { shouldValidate: true }) setValue("payee", val, { shouldValidate: true })
} }
error={errors.payee?.message} error={errors.payee?.message}
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
/> />
{/* Checkbox below input */} {/* Checkbox below input */}
@ -392,6 +425,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
className="form-check-input" className="form-check-input"
value={isItself} value={isItself}
onChange={handleSetItSelf} onChange={handleSetItSelf}
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
/> />
<Label htmlFor="sameAsSupplier" className="form-check-label"> <Label htmlFor="sameAsSupplier" className="form-check-label">
It self It self
@ -407,6 +443,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
id="currencyId" id="currencyId"
className="form-select form-select-sm" className="form-select form-select-sm"
{...register("currencyId")} {...register("currencyId")}
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
> >
<option value="">Select Currency</option> <option value="">Select Currency</option>
@ -437,6 +476,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
className="form-control form-control-sm" className="form-control form-control-sm"
{...register("description")} {...register("description")}
rows="2" rows="2"
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
></textarea> ></textarea>
{errors.description && ( {errors.description && (
<small className="danger-text"> <small className="danger-text">
@ -473,6 +515,9 @@ function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
onFileChange(e); onFileChange(e);
e.target.value = ""; e.target.value = "";
}} }}
disabled={
data?.recurringPayment?.isVariable && !isDraft && !isProcessed
}
/> />
</div> </div>
{errors.billAttachments && ( {errors.billAttachments && (

View File

@ -199,7 +199,7 @@ const PaymentRequestList = ({ filters, groupBy = "submittedBy", search }) => {
}; };
const canEditExpense = (paymentRequest) => { const canEditExpense = (paymentRequest) => {
return ( return (
(paymentRequest?.expenseStatus?.id === EXPENSE_DRAFT || (paymentRequest?.expenseStatus?.id === EXPENSE_DRAFT || paymentRequest?.recurringPayment?.isVariable === true ||
EXPENSE_REJECTEDBY.includes(paymentRequest?.expenseStatus.id)) && EXPENSE_REJECTEDBY.includes(paymentRequest?.expenseStatus.id)) &&
paymentRequest?.createdBy?.id === SelfId paymentRequest?.createdBy?.id === SelfId
); );

View File

@ -5,7 +5,6 @@ import Timeline from "../common/TimeLine";
import moment from "moment"; import moment from "moment";
import { getColorNameFromHex } from "../../utils/appUtils"; import { getColorNameFromHex } from "../../utils/appUtils";
const PaymentStatusLogs = ({ data }) => { const PaymentStatusLogs = ({ data }) => {
const sortedLogs = useMemo(() => { const sortedLogs = useMemo(() => {
if (!data?.updateLogs) return []; if (!data?.updateLogs) return [];
return [...data.updateLogs].sort( return [...data.updateLogs].sort(
@ -13,8 +12,6 @@ const PaymentStatusLogs = ({ data }) => {
); );
}, [data?.updateLogs]); }, [data?.updateLogs]);
const timelineData = useMemo(() => { const timelineData = useMemo(() => {
return sortedLogs.map((log, index) => ({ return sortedLogs.map((log, index) => ({
id: log.id, id: log.id,
@ -22,7 +19,7 @@ const PaymentStatusLogs = ({ data }) => {
description: log.nextStatus?.description || "", description: log.nextStatus?.description || "",
timeAgo: log.updatedAt, timeAgo: log.updatedAt,
color: getColorNameFromHex(log.nextStatus?.color) || "primary", color: getColorNameFromHex(log.nextStatus?.color) || "primary",
userComment:log.comment, userComment: log.comment,
users: log.updatedBy users: log.updatedBy
? [ ? [
{ {
@ -40,48 +37,14 @@ const PaymentStatusLogs = ({ data }) => {
setVisibleCount((prev) => prev + 4); setVisibleCount((prev) => prev + 4);
}; };
return ( return (
<div className="page-min-h overflow-auto h-56 py-1" > <div className="">
{/* <div className="row g-2"> <div className="d-flex mb-2 py-1">
{logsToShow.map((log) => ( <i className="bx bx-time-five me-2 "></i>{" "}
<div key={log.id} className="col-12 d-flex align-items-start mb-1"> <p className="fw-medium">TimeLine</p>
<Avatar </div>
size="xs" <div className="row h-74 overflow-auto px-3">
firstName={log.updatedBy.firstName} <Timeline items={timelineData} />
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> </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> </div>
); );
}; };

View File

@ -132,9 +132,9 @@ const ViewPaymentRequest = ({ requestId }) => {
<h5 className="fw-semibold m-0">Payment Request Details</h5> <h5 className="fw-semibold m-0">Payment Request Details</h5>
<hr /> <hr />
</div> </div>
<div className="row mb-1"> <div className="row mb-1 ">
<div className="col-12 col-sm-6 col-md-7"> <div className="col-12 col-sm-6 ">
<div className="row"> <div className="row ">
<div className="col-12 d-flex justify-content-between mb-6"> <div className="col-12 d-flex justify-content-between mb-6">
<span> {data?.paymentRequestUID}</span> <span> {data?.paymentRequestUID}</span>
<span <span
@ -145,111 +145,107 @@ const ViewPaymentRequest = ({ requestId }) => {
{data?.expenseStatus?.name} {data?.expenseStatus?.name}
</span> </span>
</div> </div>
<div className="col-md-8 mb-3"> <div className="row">
<div className="d-flex"> <div className="col-6 mb-3 text-start ">
<label <label className="form-label me-2 mb-0 fw-semibold ">
className="form-label me-2 mb-0 fw-semibold text-start"
style={{ minWidth: "130px" }}
>
Project Name: Project Name:
</label> </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> </div>
<div className="col-md-4 mb-3"> <div className="row">
<div className="d-flex"> <div className="col-6 mb-3 text-start">
<label <label className="form-label me-2 mb-0 fw-semibold text-start">
className="form-label me-2 mb-0 fw-semibold text-start" Due Date:
style={{ minWidth: "100px" }}
>
Due Date :
</label> </label>
<div className="text-muted"> </div>
<div className="col-6 mb-3 text-start">
<small className="text-muted">
{formatUTCToLocalTime(data?.dueDate)} {formatUTCToLocalTime(data?.dueDate)}
</div> </small>
</div> </div>
</div> </div>
<div className="col-md-6 mb-3"> <div className="row">
<div className="d-flex"> <div className="col-6 mb-3 text-start">
<label <label className="form-label me-2 mb-0 fw-semibold ">
className="form-label me-2 mb-0 fw-semibold text-start" Expense Category:
style={{ minWidth: "130px" }}
>
Expense Category :
</label> </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>
</div> </div>
{/* Row 2 */} {/* Row 2 */}
<div className="col-md-6 mb-3"> <div className="row text-start">
<div className="d-flex"> <div className="col-6 mb-3">
<label <label className="form-label me-2 mb-0 fw-semibold text-start">
className="form-label me-2 mb-0 fw-semibold text-start" Supplier:
style={{ minWidth: "130px" }}
>
Supplier :
</label> </label>
</div>
<div className="col-6 mb-3">
<div className="text-muted">{data?.payee}</div> <div className="text-muted">{data?.payee}</div>
</div> </div>
</div> </div>
<div className="col-md-6 mb-3"> <div className="row text-start">
<div className="d-flex"> <div className="col-6 mb-3">
<label <label className="form-label me-2 mb-0 fw-semibold text-start">
className="form-label me-2 mb-0 fw-semibold text-start" Amount:
style={{ minWidth: "130px" }}
>
Amount :
</label> </label>
<div className="text-muted"> </div>
<div className="col-6 mb-3">
<small className="text-muted">
{formatFigure(data?.amount, { {formatFigure(data?.amount, {
type: "currency", type: "currency",
currency: data?.currency?.currencyCode, currency: data?.currency?.currencyCode,
})} })}
</div> </small>
</div> </div>
</div> </div>
{data?.gstNumber && ( {data?.gstNumber && (
<div className="col-md-6 mb-3"> <div className="row text-start">
<div className="d-flex"> <div className="col-6 mb-3">
<label <label className="form-label me-2 mb-0 fw-semibold text-start">
className="form-label me-2 mb-0 fw-semibold text-start" GST Number:
style={{ minWidth: "130px" }}
>
GST Number :
</label> </label>
</div>
<div className="col-6 mb-3">
<div className="text-muted">{data?.gstNumber}</div> <div className="text-muted">{data?.gstNumber}</div>
</div> </div>
</div> </div>
)} )}
<div className="col-md-6 mb-3"> <div className="row text-start">
<div className="d-flex"> <div className="col-6 mb-3">
<label <label className="form-label me-2 mb-0 fw-semibold text-start">
className="form-label me-2 mb-0 fw-semibold text-start" Created At:
style={{ minWidth: "130px" }}
>
Created At :
</label> </label>
<div className="text-muted"> </div>
<div className="col-6 mb-3">
<small className="text-muted">
{formatUTCToLocalTime(data?.createdAt, true)} {formatUTCToLocalTime(data?.createdAt, true)}
</div> </small>
</div> </div>
</div> </div>
{/* Row 6 */} {/* Row 6 */}
{data?.createdBy && ( {data?.createdBy && (
<div className="col-md-6 text-start"> <div className="row">
<div className="d-flex align-items-center"> <div className="col-6 text-start">
<label <label className="form-label me-2 mb-0 fw-semibold">
className="form-label me-2 mb-0 fw-semibold" Created By:
style={{ minWidth: "130px" }}
>
Created By :
</label> </label>
</div>
<div className="col-6 text-start">
<div className="d-flex align-items-center"> <div className="d-flex align-items-center">
<Avatar <Avatar
size="xs" size="xs"
@ -267,13 +263,10 @@ const ViewPaymentRequest = ({ requestId }) => {
</div> </div>
)} )}
{data?.paidBy && ( {data?.paidBy && (
<div className="col-md-6 text-start"> <div className="col-6 text-start">
<div className="d-flex align-items-center"> <div className="d-flex flex-column gap-2 text-start">
<label <label className="form-label me-2 mb-0 fw-semibold">
className="form-label me-2 mb-0 fw-semibold" Paid By:
style={{ minWidth: "130px" }}
>
Paid By :
</label> </label>
<div className="d-flex align-items-center "> <div className="d-flex align-items-center ">
<Avatar <Avatar
@ -292,13 +285,60 @@ const ViewPaymentRequest = ({ requestId }) => {
</div> </div>
)} )}
<div className="text-start my-1"> <div className="text-start my-2">
<label className="fw-semibold form-label">Description : </label> <label className="fw-semibold form-label">Description : </label>
<div className="text-muted">{data?.description}</div> <div className="text-muted">{data?.description}</div>
</div> </div>
<div className="col-6 text-start">
<label className="form-label me-2 mb-2 fw-semibold"> {data?.paidTransactionId && (
Attachment : <>
<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> </label>
<div className="d-flex flex-wrap gap-2"> <div className="d-flex flex-wrap gap-2">
@ -312,180 +352,10 @@ const ViewPaymentRequest = ({ requestId }) => {
)} )}
</div> </div>
</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} /> <ActionPaymentRequest requestId={requestId} />
</div> </div>
</div> </div>
<div className=" col-sm-12 my-md-0 border-top border-md-none col-md-5"> <div className=" col-sm-12 my-md-0 border-top border-md-none col-md-6 ">
<div className="d-flex mb-2 py-1">
<i className="bx bx-time-five me-2 "></i>{" "}
<p className="fw-medium">TimeLine</p>
</div>
<PaymentStatusLogs data={data} /> <PaymentStatusLogs data={data} />
</div> </div>
</div> </div>

View File

@ -132,7 +132,7 @@ const PaymentRequestPage = () => {
{ViewRequest.view && ( {ViewRequest.view && (
<GlobalModel <GlobalModel
isOpen isOpen
size="xl" size="lg"
modalType="top" modalType="top"
closeModal={() => setVieRequest({ requestId: null, view: false })} closeModal={() => setVieRequest({ requestId: null, view: false })}
> >