268 lines
9.3 KiB
JavaScript

import React, { useState } from "react";
import { useCollectionContext } from "../../pages/collections/CollectionPage";
import { useCollection } from "../../hooks/useCollections";
import { formatUTCToLocalTime } from "../../utils/dateUtils";
import { formatFigure, getIconByFileType } from "../../utils/appUtils";
import Avatar from "../common/Avatar";
import PaymentHistoryTable from "./PaymentHistoryTable";
import Comment from "./Comment";
import { CollectionDetailsSkeleton } from "./CollectionSkeleton";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { ADMIN_COLLECTION, EDIT_COLLECTION } from "../../utils/constants";
const ViewCollection = ({ onClose }) => {
const [activeTab, setActiveTab] = useState("payments");
const isAdmin = useHasUserPermission(ADMIN_COLLECTION);
const canEditCollection = useHasUserPermission(EDIT_COLLECTION);
const { viewCollection, setCollection, setDocumentView } =
useCollectionContext();
const { data, isLoading, isError, error } = useCollection(viewCollection);
const handleEdit = () => {
setCollection({ isOpen: true, invoiceId: viewCollection });
onClose();
};
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="row text-start">
{/* Row 0: Balance Amount + Expected Payment Date */}
<div className="row mb-3 px-2">
{/* Balance Amount */}
<div className="col-md-6 d-flex align-items-center">
<div className="fw-bold fs-6 text-dark me-2 ms-1">Balance Amount :</div>
<div className="fw-bold fs-6 text-dark">
{formatFigure(data?.balanceAmount, {
type: "currency",
currency: "INR",
})}
</div>
</div>
{/* Expected Payment Date */}
<div className="col-md-6 d-flex align-items-center">
<div className="fw-bold fs-6 text-dark me-2 ms-3">Expected Payment Date :</div>
<div className="fw-bold fs-6 text-dark">
{formatUTCToLocalTime(data?.exceptedPaymentDate)}
</div>
</div>
</div>
{/* Project and Status */}
<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: "120px" }}
>
Project :
</label>
<div className="text-muted">{data?.project?.name}</div>
</div>
<div>
<span
className={`badge bg-label-${data?.markAsCompleted ? "primary" : "danger"}`}
>
{data?.markAsCompleted ? "Active" : "Inactive"}
</span>
{(isAdmin || canEditCollection) &&
!data?.receivedInvoicePayments &&
!data?.markAsCompleted && (
<span onClick={handleEdit} className="ms-2 cursor-pointer">
<i className="bx bx-edit text-primary bx-sm"></i>
</span>
)}
</div>
</div>
{/* Title */}
<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>
{/* Invoice Number */}
<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>
{/* E-Invoice Number */}
<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>
{/* Invoice 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>
</div>
{/* Client Submitted Date */}
<div className="col-md-6">
<div className="row mb-4 align-items-end">
<div className="col-4 fw-semibold">Client Submission Date:</div>
<div className="col-8">
{formatUTCToLocalTime(data?.clientSubmitedDate)}
</div>
</div>
</div>
{/* Basic 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>
</div>
{/* Tax Amount */}
<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>
{/* Created At */}
<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>
{/* 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}
</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>
{/* Attachments */}
<div className="col-12 text-start">
<label className="me-2 mb-2 fw-semibold">Attachment :</label>
<div className="d-flex flex-wrap gap-2">
{data?.attachments?.map((doc) => {
const isImage = doc.contentType?.includes("image");
return (
<div
key={doc.documentId}
className="border rounded hover-scale p-2 d-flex flex-column align-items-center"
style={{
width: "80px",
cursor: isImage ? "pointer" : "default",
}}
onClick={() => {
if (isImage) {
setDocumentView({
IsOpen: true,
Image: doc.preSignedUrl,
});
}
}}
>
<i
className={`bx ${getIconByFileType(doc.contentType)}`}
style={{ fontSize: "30px" }}
></i>
<small
className="text-center text-tiny text-truncate w-100"
title={doc.fileName}
>
{doc.fileName}
</small>
</div>
);
}) ?? "No Attachment"}
</div>
</div>
{/* Tabs Section */}
<div className="container px-1 mt-4">
<ul className="nav nav-tabs" role="tablist">
<li className="nav-item">
<button
className={`nav-link ${activeTab === "payments" ? "active" : ""}`}
onClick={() => setActiveTab("payments")}
type="button"
>
<i className="bx bx-history bx-sm me-1"></i> Payments History
</button>
</li>
<li className="nav-item">
<button
className={`nav-link ${activeTab === "details" ? "active" : ""}`}
onClick={() => setActiveTab("details")}
type="button"
>
<i className="bx bx-message-dots bx-sm me-2"></i> Comments (
{data?.comments?.length ?? "0"})
</button>
</li>
</ul>
<div className="tab-content px-1 py-0 border-top-0">
{activeTab === "payments" && (
<div className="tab-pane fade show active">
<PaymentHistoryTable data={data} />
</div>
)}
{activeTab === "details" && (
<div className="tab-pane fade show active">
<Comment invoice={data} />
</div>
)}
</div>
</div>
</div>
</div>
);
};
export default ViewCollection;