added mark as completd api operation

This commit is contained in:
pramod.mahajan 2025-10-15 12:35:07 +05:30
parent 76df08e921
commit 962286a4da
10 changed files with 578 additions and 260 deletions

View File

@ -11,12 +11,19 @@ import { formatFigure, localToUtc } from "../../utils/appUtils";
import { formatUTCToLocalTime } from "../../utils/dateUtils";
import Avatar from "../common/Avatar";
import { PaymentHistorySkeleton } from "./CollectionSkeleton";
import { usePaymentType } from "../../hooks/masterHook/useMaster";
const AddPayment = ({ onClose }) => {
const { addPayment } = useCollectionContext();
const { data, isLoading, isError, error } = useCollection(
addPayment?.invoiceId
);
const {
data: paymentTypes,
isLoading: isPaymentTypeLoading,
isError: isPaymentTypeError,
error: paymentError,
} = usePaymentType(true);
const methods = useForm({
resolver: zodResolver(paymentSchema),
defaultValues: defaultPayment,
@ -37,7 +44,6 @@ const AddPayment = ({ onClose }) => {
paymentReceivedDate: localToUtc(formData.paymentReceivedDate),
invoiceId: addPayment.invoiceId,
};
AddPayment(payload);
};
const handleClose = (formData) => {
@ -78,6 +84,38 @@ const AddPayment = ({ onClose }) => {
)}
</div>
<div className="col-12 col-md-6 mb-2">
<Label
htmlFor="paymentAdjustmentHeadId"
className="form-label"
required
>
Payment Adjustment Head
</Label>
<select
className="form-select form-select-sm "
{...register("paymentAdjustmentHeadId")}
>
{isPaymentTypeLoading ? (
<option>Loading..</option>
) : (
<>
<option value="" >Select Payment Head</option>
{paymentTypes?.data?.sort((a, b) => a.name.localeCompare(b.name))?.map((type) => (
<option key={type.id} value={type.id}>
{type.name}
</option>
))}
</>
)}
</select>
{errors.paymentAdjustmentHeadId && (
<small className="danger-text">
{errors.paymentAdjustmentHeadId.message}
</small>
)}
</div>
<div className="col-12 col-md-6 mb-2">
<Label htmlFor="amount" className="form-label" required>
Amount
@ -114,8 +152,11 @@ const AddPayment = ({ onClose }) => {
<button
type="reset"
className="btn btn-label-secondary btn-sm mt-3"
onClick={handleClose}
// disabled={isPending}
onClick={()=>{
handleClose()
onClose()
}}
disabled={isPending}
>
Cancel
</button>
@ -141,7 +182,9 @@ const AddPayment = ({ onClose }) => {
</div>
<div className="row text-start mx-2">
{data.receivedInvoicePayments.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)).map((payment, index) => (
{data.receivedInvoicePayments
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
.map((payment, index) => (
<div className="col-12 mb-2" key={payment.id}>
<div className=" p-2 border-start border-warning">
<div className="row">
@ -161,7 +204,9 @@ const AddPayment = ({ onClose }) => {
</div>
<div className="col-12 col-md-6 mb-0 d-flex align-items-center m-0">
<small className="fw-semibold me-2">Received By:</small>{" "}
<small className="fw-semibold me-2">
Updated By:
</small>{" "}
<Avatar
size="xs"
firstName={payment?.createdBy?.firstName}
@ -175,18 +220,25 @@ const AddPayment = ({ onClose }) => {
<div className="row">
<div className="col-12 col-md-6">
<p className="mb-1">
<small className="fw-semibold">Transaction ID:</small>{" "}
<small className="fw-semibold">
Transaction ID:
</small>{" "}
{payment.transactionId}
</p>
</div>
<div className="col-12 ">
<div className="d-flex justify-content-between">
<span>{payment?.paymentAdjustmentHead?.name}</span>
<span className="fs-semibold d-none d-md-block">
{formatFigure(payment.amount, {
type: "currency",
currency: "INR",
})}
</span>
<p className="text-tiny m-0 mt-1">{payment?.comment}</p>
</div>
<p className="text-tiny m-0 mt-1">
{payment?.comment}
</p>
</div>
</div>
</div>

View File

@ -5,6 +5,7 @@ import { formatFigure, localToUtc, useDebounce } from "../../utils/appUtils";
import { formatUTCToLocalTime } from "../../utils/dateUtils";
import Pagination from "../common/Pagination";
import { useCollectionContext } from "../../pages/collections/CollectionPage";
import { CollectionTableSkeleton } from "./CollectionSkeleton";
const CollectionList = ({ fromDate, toDate, isPending, searchString }) => {
const [currentPage, setCurrentPage] = useState(1);
@ -19,7 +20,8 @@ const CollectionList = ({ fromDate, toDate, isPending, searchString }) => {
true,
searchDebounce
);
const {setProcessedPayment,setAddPayment,setViewCollection} = useCollectionContext()
const { setProcessedPayment, setAddPayment, setViewCollection } =
useCollectionContext();
const paginate = (page) => {
if (page >= 1 && page <= (data?.totalPages ?? 1)) {
@ -127,7 +129,7 @@ const CollectionList = ({ fromDate, toDate, isPending, searchString }) => {
},
];
if (isLoading) return <p>Loading...</p>;
if (isLoading) return <CollectionTableSkeleton />;
if (isError) return <p>{error.message}</p>;
return (
@ -183,15 +185,28 @@ const CollectionList = ({ fromDate, toDate, isPending, searchString }) => {
<ul className="dropdown-menu dropdown-menu-end">
{/* View */}
<li>
<a className="dropdown-item cursor-pointer" onClick={()=>setViewCollection(row.id)}>
<a
className="dropdown-item cursor-pointer"
onClick={() => setViewCollection(row.id)}
>
<i className="bx bx-show me-2 text-primary"></i>
<span>View</span>
</a>
</li>
{!row?.markAsCompleted && (
<>
{/* Add Payment */}
<li>
<a className="dropdown-item cursor-pointer" onClick={()=>setAddPayment({isOpen:true,invoiceId:row.id})}>
<a
className="dropdown-item cursor-pointer"
onClick={() =>
setAddPayment({
isOpen: true,
invoiceId: row.id,
})
}
>
<i className="bx bx-wallet me-2 text-warning"></i>
<span>Add Payment</span>
</a>
@ -199,11 +214,21 @@ const CollectionList = ({ fromDate, toDate, isPending, searchString }) => {
{/* Mark Payment */}
<li>
<a className="dropdown-item cursor-pointer" onClick={()=>setProcessedPayment({isOpen:true,invoiceId:row})}>
<a
className="dropdown-item cursor-pointer"
onClick={() =>
setProcessedPayment({
isOpen: true,
invoiceId: row.id,
})
}
>
<i className="bx bx-check-circle me-2 text-success"></i>
<span>Mark Payment</span>
</a>
</li>
</>
)}
</ul>
</div>
</td>

View File

@ -30,7 +30,12 @@ export const PaymentHistorySkeleton = ({ count = 2 }) => {
{/* Received By (Avatar + Name) */}
<div className="col-12 col-md-6 d-flex align-items-center gap-2">
<SkeletonLine width="30px" height={30} className="rounded-circle" /> {/* Avatar */}
<SkeletonLine
width="30px"
height={30}
className="rounded-circle"
/>{" "}
{/* Avatar */}
<SkeletonLine width="120px" height={16} /> {/* Name */}
</div>
</div>
@ -41,3 +46,166 @@ export const PaymentHistorySkeleton = ({ count = 2 }) => {
);
};
export const CollectionDetailsSkeleton = () => {
return (
<div className="container p-3">
{/* Title */}
<SkeletonLine height={24} width="200px" className="mx-auto" />
{/* Header Row */}
<div className="row mb-3 px-1">
<div className="col-10">
<SkeletonLine height={20} />
</div>
<div className="col-2 d-flex justify-content-end">
<SkeletonLine height={20} width="60px" />
</div>
</div>
{/* Project */}
<div className="row mb-3">
<div className="col-md-6">
<SkeletonLine width="60%" />
</div>
</div>
{/* Invoice & E-Invoice */}
<div className="row mb-3">
<div className="col-md-6">
<SkeletonLine />
</div>
<div className="col-md-6">
<SkeletonLine />
</div>
</div>
{/* Invoice Date & Client Submitted */}
<div className="row mb-3">
<div className="col-md-6">
<SkeletonLine />
</div>
<div className="col-md-6">
<SkeletonLine />
</div>
</div>
{/* Expected Payment & Mark as Completed */}
<div className="row mb-3">
<div className="col-md-6">
<SkeletonLine />
</div>
<div className="col-md-6">
<SkeletonLine width="40%" />
</div>
</div>
{/* Basic & Tax Amount */}
<div className="row mb-3">
<div className="col-md-6">
<SkeletonLine />
</div>
<div className="col-md-6">
<SkeletonLine />
</div>
</div>
{/* Balance & Created At */}
<div className="row mb-3">
<div className="col-md-6">
<SkeletonLine />
</div>
<div className="col-md-6">
<SkeletonLine />
</div>
</div>
{/* Created By */}
<div className="row mb-3">
<div className="col-md-6 d-flex align-items-center">
<SkeletonLine
width="40px"
height={40}
className="me-2 rounded-circle"
/>
<SkeletonLine width="100px" />
</div>
</div>
{/* Description */}
<div className="row mb-3">
<div className="col-12">
<SkeletonLine height={50} />
</div>
</div>
{/* Attachments */}
<div className="row mb-3">
<div className="col-12 d-flex gap-2 flex-wrap">
{[...Array(3)].map((_, idx) => (
<SkeletonLine key={idx} height={60} width="80px" />
))}
</div>
</div>
{/* Tabs */}
<div className="row mb-2">
<div className="col-12 d-flex gap-2">
<SkeletonLine height={35} width="120px" />
<SkeletonLine height={35} width="150px" />
</div>
</div>
{/* Tab Content (Comments / Payments) */}
<SkeletonLine height={200} />
</div>
);
};
export const CollectionTableSkeleton = () => {
const columnCount = 8;
return (
<div className="card ">
<div
className="card-datatable table-responsive page-min-h"
id="horizontal-example"
>
<div className="dataTables_wrapper no-footer mx-5 pb-2">
<table className="table dataTable text-nowrap">
<thead>
<tr >
{[...Array(columnCount - 1)].map((_, i) => (
<th key={i}>
<SkeletonLine height={15} width="80px" />
</th>
))}
<th className="d-flex justify-content-center">
<SkeletonLine height={16} width="40px" />
</th>
</tr>
</thead>
<tbody>
{[...Array(8)].map((_, rowIdx) => (
<tr key={rowIdx}>
{[...Array(columnCount - 1)].map((_, colIdx) => (
<td key={colIdx}>
<SkeletonLine height={33} />
</td>
))}
<td className="d-flex justify-content-center">
<SkeletonLine height={16} width="20px" />
</td>
</tr>
))}
</tbody>
</table>
{/* Pagination Skeleton */}
<div className="d-flex justify-content-end mt-2">
<SkeletonLine height={30} width="200px" />
</div>
</div>
</div>
</div>
);
};

View File

@ -9,7 +9,8 @@ import moment from "moment";
const Comment = ({ invoice }) => {
const {
register,reset,
register,
reset,
handleSubmit,
formState: { errors },
} = useForm({
@ -17,45 +18,16 @@ const Comment = ({ invoice }) => {
defaultValues: { comment: "" },
});
const { mutate: AddComment, isPending } = useAddComment(() => {reset()});
const { mutate: AddComment, isPending } = useAddComment(() => {
reset();
});
const onSubmit = (formData) => {
const payload = { ...formData, invoiceId: invoice?.id };
debugger;
AddComment(payload);
};
return (
<div className="row">
{invoice?.comments?.length > 0 ? (
invoice.comments.map((comment, index) => (
<div
className="border-start border-primary ps-3 py-2 mb-3"
key={comment.id || index}
>
<div className="d-flex justify-content-between align-items-center mb-1">
<div className="d-flex align-items-center">
<Avatar
size="xs"
firstName={comment?.createdBy?.firstName}
lastName={comment?.createdBy?.lastName}
/>
<span className="ms-1 fw-semibold">
{comment?.createdBy?.firstName} {comment?.createdBy?.lastName}
</span>
</div>
<small className="text-secondary">
{moment.utc(comment?.createdAt).local().fromNow()}
</small>
</div>
<p className="mb-1">{comment?.comment}</p>
</div>
))
) : (
<p className="text-muted">No comments yet.</p>
)}
<div className="row pt-1">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="col-12">
<textarea
@ -77,6 +49,35 @@ const Comment = ({ invoice }) => {
</button>
</div>
</form>
{invoice?.comments?.length > 0 ? (
invoice.comments.map((comment, index) => (
<div
className="border-start border-primary ps-1 py-2 mb-3"
key={comment.id || index}
>
<div className="d-flex justify-content-between align-items-center mb-1">
<div className="d-flex align-items-center">
<Avatar
size="xs"
firstName={comment?.createdBy?.firstName}
lastName={comment?.createdBy?.lastName}
/>
<span className="ms-1 fw-semibold">
{comment?.createdBy?.firstName} {comment?.createdBy?.lastName}
</span>
</div>
<small className="text-secondary">
{moment.utc(comment?.createdAt).local().fromNow()}
</small>
</div>
<div className="ms-9"> <p className="mb-1">{comment?.comment}</p></div>
</div>
))
) : (
<p className="text-muted">No comments yet.</p>
)}
</div>
);
};

View File

@ -8,13 +8,14 @@ const PaymentHistoryTable = ({data}) => {
<div>
{data?.receivedInvoicePayments?.length > 0 && (
<div className="mt-4">
<table className="table table-bordered mt-2">
<div className="pt-1 data-tabe table-responsive">
<table className="table table-bordered table-responsive mt-2">
<thead className="table-light">
<tr>
<th className="text-center">Sr.No</th>
<th className="text-center">Transaction ID</th>
<th className="text-center"> Received Date</th>
<th className="text-center"> Payment Adjustment-Head</th>
<th className="text-center">Amount</th>
<th className="text-center">Updated By</th>
</tr>
@ -25,6 +26,7 @@ const PaymentHistoryTable = ({data}) => {
<td className="text-center">{index + 1}</td>
<td ><span className="mx-2">{payment.transactionId}</span></td>
<td className="text-center">{formatUTCToLocalTime(payment.paymentReceivedDate)}</td>
<td className="text-start">{payment?.paymentAdjustmentHead?.name ?? "--"}</td>
<td className="text-end">
<span className="px-1">{formatFigure(payment.amount, {
type: "currency",
@ -32,12 +34,8 @@ const PaymentHistoryTable = ({data}) => {
})}</span>
</td>
<td>
<div className="d-flex align-items-center mx-2">
<Avatar
size="xs"
firstName={payment.createdBy?.firstName}
lastName={payment.createdBy?.lastName}
/>
<div className="d-flex align-items-center mx-2 py-1">
{payment.createdBy?.firstName}{" "}
{payment.createdBy?.lastName}
</div>

View File

@ -6,9 +6,11 @@ import { formatFigure, getIconByFileType } from "../../utils/appUtils";
import Avatar from "../common/Avatar";
import PaymentHistoryTable from "./PaymentHistoryTable";
import Comment from "./Comment";
import { CollectionDetailsSkeleton } from "./CollectionSkeleton";
const ViewCollection = ({ onClose }) => {
const { viewCollection, setCollection , setDocumentView} = useCollectionContext();
const { viewCollection, setCollection, setDocumentView } =
useCollectionContext();
const { data, isLoading, isError, error } = useCollection(viewCollection);
const handleEdit = () => {
@ -16,18 +18,25 @@ const ViewCollection = ({ onClose }) => {
onClose();
};
if (isLoading) return <div>isLoading...</div>;
if (isLoading) return <CollectionDetailsSkeleton />;
if (isError) return <div>{error.message}</div>;
return (
<div className="container p-3">
<p className="fs-5 fw-semibold">Collection Details</p>
<div className="text-start ">
<div className="row mb-3 px-1">
<div className="col-10">
<p className="mb-1 fs-6">{data?.title}</p>
<div className="row text-start ">
<div className="col-12 mb-3 d-flex justify-content-between">
<div className="d-flex">
<label
className=" me-2 mb-0 fw-semibold"
style={{ minWidth: "130px" }}
>
Project :
</label>
<div className="text-muted">{data?.project?.name}</div>
</div>
<div className="col-2">
<div>
{" "}
<span
className={`badge bg-label-${
data?.isActive ? "primary" : "danger"
@ -35,101 +44,127 @@ const ViewCollection = ({ onClose }) => {
>
{data?.isActive ? "Active" : "Inactive"}
</span>
{!data?.receivedInvoicePayments && (<span onClick={handleEdit} className="ms-2 cursor-pointer">
{!data?.receivedInvoicePayments && (
<span onClick={handleEdit} className="ms-2 cursor-pointer">
<i className="bx bx-edit text-primary bx-sm"></i>
</span>)}
</span>
)}
</div>
</div>
<div className="row mb-3">
<div className="col-md-6 d-flex ">
<p className="m-0 fw-semibold me-1">Project:</p>{" "}
{data?.project?.name}
<div className="col-md-6">
<div className="row mb-2 text-wrap">
<div className="col-4 fw-semibold">Title :</div>
<div className="col-8 text-wrap">{data?.title}</div>
</div>
</div>
<div className="row mb-3">
<div className="col-md-6 mb-3 d-flex">
<p className="m-0 fw-semibold me-1">Invoice Number:</p>{" "}
{data?.invoiceNumber}
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Invoice Number:</div>
<div className="col-8">{data?.invoiceNumber}</div>
</div>
<div className="col-md-6 d-flex">
<p className="m-0 fw-semibold me-1">E-Invoice Number:</p>{" "}
{data?.eInvoiceNumber}
</div>
{/* Row 2: E-Invoice Number + Project */}
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">E-Invoice Number:</div>
<div className="col-8">{data?.eInvoiceNumber}</div>
</div>
</div>
<div className="row mb-3">
<div className="col-md-6 mb-3 d-flex">
<p className="m-0 fw-semibold me-1">Invoice Date:</p>{" "}
{/* Row 3: Invoice Date + Client Submitted Date */}
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Invoice Date:</div>
<div className="col-8">
{formatUTCToLocalTime(data?.invoiceDate)}
</div>
<div className="col-md-6 d-flex">
<p className="m-0 fw-semibold me-1">Client Submitted Date:</p>{" "}
</div>
</div>
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Client Submitted Date:</div>
<div className="col-8">
{formatUTCToLocalTime(data?.clientSubmitedDate)}
</div>
</div>
<div className="row mb-3">
<div className="col-md-6 mb-3 d-flex">
<p className="m-0 fw-semibold me-1">Expected Payment Date:</p>{" "}
</div>
{/* Row 4: Expected Payment Date + Mark as Completed */}
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Expected Payment Date:</div>
<div className="col-8">
{formatUTCToLocalTime(data?.exceptedPaymentDate)}
</div>
<div className="col-md-6 d-flex">
<p className="m-0 fw-semibold me-1">Mark as Completed:</p>{" "}
{data?.markAsCompleted ? "Yes" : "No"}
</div>
</div>
<div className="row mb-3">
<div className="col-md-6 mb-3 d-flex">
<p className="m-0 fw-semibold me-1">Basic Amount:</p>{" "}
{/* Row 5: Basic Amount + Tax Amount */}
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Basic Amount :</div>
<div className="col-8">
{formatFigure(data?.basicAmount, {
type: "currency",
currency: "INR",
})}
</div>
<div className="col-md-6 d-flex">
<p className="m-0 fw-semibold me-1">Tax Amount:</p>{" "}
</div>
</div>
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Tax Amount :</div>
<div className="col-8">
{formatFigure(data?.taxAmount, {
type: "currency",
currency: "INR",
})}
</div>
</div>
<div className="row mb-3">
<div className="col-md-6 mb-3 d-flex">
<p className="m-0 fw-semibold me-1">Balance Amount:</p>{" "}
</div>
{/* Row 6: Balance Amount + Created At */}
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Balance Amount :</div>
<div className="col-8">
{formatFigure(data?.balanceAmount, {
type: "currency",
currency: "INR",
})}
</div>
<div className="col-md-6 d-flex">
<p className="m-0 fw-semibold me-1">Created At:</p>{" "}
{formatUTCToLocalTime(data?.createdAt)}
</div>
</div>
<div className="row mb-3">
<div className="col-md-6 mb-3 d-flex align-items-center">
<p className="m-0 fw-semibold">Created By:</p>{" "}
<div className="d-flex align-items-center">
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Created At :</div>
<div className="col-8">{formatUTCToLocalTime(data?.createdAt)}</div>
</div>
</div>
{/* Row 7: Created By */}
<div className="col-md-6">
<div className="row mb-4 align-items-center">
<div className="col-4 fw-semibold">Created By :</div>
<div className="col-8 d-flex align-items-center">
<Avatar
size="xs"
firstName={data.createdBy?.firstName}
lastName={data.createdBy?.lastName}
/>
<span className="ms-1 text-muted">
{data?.createdBy?.firstName} {data?.createdBy?.lastName}
</div>{" "}
</span>
</div>
</div>
</div>
{/* Description */}
<div className="col-12 my-1 mb-2">
<div className=" me-2 mb-0 fw-semibold">
Description :
</div>
<div className="text-muted">{data?.description}</div>
</div>
<div className="col-12">
<p className="m-0 fw-semibold">Description : </p>
{data?.description}
</div>
</div>
<div className="col-12 text-start">
<label className="form-label me-2 mb-2 fw-semibold">
<label className=" me-2 mb-2 fw-semibold">
Attachment :
</label>
@ -166,27 +201,15 @@ const ViewCollection = ({ onClose }) => {
</small>
</div>
);
})}
}) ?? "No Attachment"}
</div>
</div>
<div className="container px-1 ">
{/* Tabs Navigation */}
<ul className="nav nav-tabs" role="tablist">
<li className="nav-item">
<button
className="nav-link active"
id="details-tab"
data-bs-toggle="tab"
data-bs-target="#details"
type="button"
role="tab"
>
<i className="bx bx-message-dots bx-sm me-2"></i> Comments (
{data?.comments?.length ?? "0"})
</button>
</li>
<li className="nav-item">
<li className="nav-item active">
<button
className="nav-link"
id="payments-tab"
@ -198,19 +221,32 @@ const ViewCollection = ({ onClose }) => {
<i className="bx bx-history bx-sm me-1"></i> Payments History
</button>
</li>
<li className="nav-item">
<button
className="nav-link "
id="details-tab"
data-bs-toggle="tab"
data-bs-target="#details"
type="button"
role="tab"
>
<i className="bx bx-message-dots bx-sm me-2"></i> Comments (
{data?.comments?.length ?? "0"})
</button>
</li>
</ul>
<div className="tab-content py-1 border-top-0 ">
<div
className="tab-pane fade show active"
id="details"
role="tabpanel"
>
<div className="tab-content px-1 py-0 border-top-0 ">
<div className="tab-pane fade " id="details" role="tabpanel">
<Comment invoice={data} />
</div>
{/* Payments History Tab Content */}
<div className="tab-pane fade" id="payments" role="tabpanel">
<div
className="tab-pane fade show active"
id="payments"
role="tabpanel"
>
<div className="row text-start">
<PaymentHistoryTable data={data} />
</div>

View File

@ -77,7 +77,8 @@ export const paymentSchema = z.object({
paymentReceivedDate: z.string().min(1, { message: "Date is required" }),
transactionId: z.string().min(1, "Transaction ID is required"),
amount: z.number().min(1, "Amount must be greater than zero"),
comment:z.string().min(1,{message:"Comment required"})
comment:z.string().min(1,{message:"Comment required"}),
paymentAdjustmentHeadId:z.string().min(1,{message:"Payment Type required"})
});
// Default Value
@ -85,7 +86,8 @@ export const defaultPayment = {
paymentReceivedDate: null,
transactionId: "",
amount: 0,
comment:""
comment:"",
paymentAdjustmentHeadId:""
};

View File

@ -10,6 +10,14 @@ import {
} from "@tanstack/react-query";
import showToast from "../../services/toastService";
export const usePaymentType = (isActive) => {
return useQuery({
queryKey: ["paymentType",isActive],
queryFn: async () => await MasterRespository.getPaymentType(isActive),
});
};
export const useServices = () => {
return useQuery({
queryKey: ["services"],
@ -30,7 +38,6 @@ export const useActivitiesByGroups = (groupId) => {
queryFn: async () => await MasterRespository.getActivitesByGroup(groupId),
enabled: !!groupId,
});
};
export const useGlobalServices = () => {
@ -448,8 +455,6 @@ export const useUpdateApplicationRole = (onSuccessCallback) => {
});
};
//-----Create work Category-------------------------------
export const useCreateWorkCategory = (onSuccessCallback) => {
const queryClient = useQueryClient();
@ -703,13 +708,11 @@ export const useCreateService = (onSuccessCallback) => {
return useMutation({
mutationFn: async (payload) => {
const resp = await MasterRespository.createService(payload);
return resp.data;
},
onSuccess: (data) => {
queryClient.invalidateQueries({ queryKey: ["masterData", "Services"] });
showToast(data?.message || "Service added successfully", "success");
@ -717,8 +720,12 @@ export const useCreateService = (onSuccessCallback) => {
if (onSuccessCallback) onSuccessCallback(data?.data);
},
onError: (error) => {
showToast( error?.response?.data?.message || error?.message || "Something went wrong", "error");
showToast(
error?.response?.data?.message ||
error?.message ||
"Something went wrong",
"error"
);
},
});
};
@ -741,7 +748,12 @@ export const useUpdateService = (onSuccessCallback) => {
if (onSuccessCallback) onSuccessCallback(data);
},
onError: (error) => {
showToast(error?.response?.data?.message || error?.message || "Something went wrong", "error");
showToast(
error?.response?.data?.message ||
error?.message ||
"Something went wrong",
"error"
);
},
});
};
@ -759,15 +771,22 @@ export const useCreateActivityGroup = (onSuccessCallback) => {
queryKey: ["groups"],
});
showToast( data?.message ||
data?.response?.data?.message || "Activity Group created successfully.",
showToast(
data?.message ||
data?.response?.data?.message ||
"Activity Group created successfully.",
"success"
);
if (onSuccessCallback) onSuccessCallback(data);
},
onError: (error) => {
showToast(error?.response?.data?.message || error?.message || "Something went wrong", "error");
showToast(
error?.response?.data?.message ||
error?.message ||
"Something went wrong",
"error"
);
},
});
};
@ -786,7 +805,8 @@ export const useUpdateActivityGroup = (onSuccessCallback) => {
showToast(
data?.message ||
data?.response?.data?.message|| "Activity Group Updated successfully.",
data?.response?.data?.message ||
"Activity Group Updated successfully.",
"success"
);
@ -812,7 +832,12 @@ export const useCreateActivity = (onSuccessCallback) => {
if (onSuccessCallback) onSuccessCallback(data);
},
onError: (error) => {
showToast(error?.response?.data?.message || error?.message || "Something went wrong", "error");
showToast(
error?.response?.data?.message ||
error?.message ||
"Something went wrong",
"error"
);
},
});
};
@ -834,7 +859,12 @@ export const useUpdateActivity = (onSuccessCallback) => {
if (onSuccessCallback) onSuccessCallback(data);
},
onError: (error) => {
showToast(error?.response?.data?.message || error?.message || "Something went wrong", "error");
showToast(
error?.response?.data?.message ||
error?.message ||
"Something went wrong",
"error"
);
},
});
};
@ -1001,14 +1031,12 @@ export const useDeleteMasterItem = () => {
});
};
export const useDeleteServiceGroup = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (id) => await MasterRespository.deleteActivityGroup(id),
onSuccess: ({ _, variable }) => {
queryClient.invalidateQueries({ queryKey: ["groups"] });
showToast(`Group deleted successfully.`, "success");
@ -1022,15 +1050,13 @@ export const useDeleteServiceGroup =()=>{
showToast(message, "error");
},
});
}
};
export const useDeleteActivity = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (id) => await MasterRespository.deleteActivity(id),
onSuccess: ({ _, variable }) => {
queryClient.invalidateQueries({ queryKey: ["activties"] });
showToast(`Acivity deleted successfully.`, "success");
@ -1044,4 +1070,4 @@ export const useDeleteActivity =()=>{
showToast(message, "error");
},
});
}
};

View File

@ -26,7 +26,7 @@ export const useCollectionContext = () => {
return context;
};
const CollectionPage = () => {
const [viewCollection,setViewCollection] = useState(null)
const [viewCollection, setViewCollection] = useState(null);
const [makeCollection, setCollection] = useState({
isOpen: false,
invoiceId: null,
@ -59,12 +59,14 @@ const CollectionPage = () => {
addPayment,
setViewCollection,
viewCollection,
setDocumentView
setDocumentView,
};
const { mutate: MarkedReceived, isPending } = useMarkedPaymentReceived(() => {
setProcessedPayment(null);
});
const handleMarkedPayment = () => {};
const handleMarkedPayment = (payload) => {
MarkedReceived(payload);
};
return (
<CollectionContext.Provider value={contextMassager}>
<div className="container-fluid">
@ -99,7 +101,7 @@ const CollectionPage = () => {
</div>
<div className="col-12 col-md-6 d-flex justify-content-end gap-4">
<div className="">
<div className=" w-md-auto">
{" "}
<input
type="search"
@ -156,7 +158,11 @@ const CollectionPage = () => {
)}
{viewCollection && (
<GlobalModel size="lg" isOpen={viewCollection} closeModal={()=>setViewCollection(null)}>
<GlobalModel
size="lg"
isOpen={viewCollection}
closeModal={() => setViewCollection(null)}
>
<ViewCollection onClose={() => setViewCollection(null)} />
</GlobalModel>
)}
@ -169,7 +175,8 @@ const CollectionPage = () => {
closeModal={() => setDocumentView({ IsOpen: false, Image: null })}
>
<PreviewDocument imageUrl={ViewDocument.Image} />
</GlobalModel>)}
</GlobalModel>
)}
<ConfirmModal
type="success"
@ -177,7 +184,7 @@ const CollectionPage = () => {
message="Your payment has been processed successfully. Do you want to continue?"
isOpen={processedPayment?.isOpen}
loading={isPending}
onSubmit={handleMarkedPayment}
onSubmit={() => handleMarkedPayment(processedPayment?.invoiceId)}
onClose={() => setProcessedPayment(null)}
/>
</div>

View File

@ -124,10 +124,13 @@ export const MasterRespository = {
api.put(`/api/Master/activity-group/edit/${serviceId}`, data),
getActivitesByGroup: (activityGroupId) =>
api.get(`api/master/activities?activityGroupId=${activityGroupId}`),
deleteActivityGroup:(id)=>api.delete(`/api/Master/activity-group/delete/${id}`),
deleteActivityGroup: (id) =>
api.delete(`/api/Master/activity-group/delete/${id}`),
deleteActivity: (id) => api.delete(`/api/Master/activity/delete/${id}`),
getOrganizationType: () => api.get("/api/Master/organization-type/list"),
getPaymentType: (isActive) =>
api.get(`/api/Master/payment-adjustment-head/list?isActive=${isActive}`),
};