265 lines
8.6 KiB
JavaScript

import React, { useState } from "react";
import { useActionOnExpense, useExpense } from "../../hooks/useExpense";
import { formatUTCToLocalTime } from "../../utils/dateUtils";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { ActionSchema } from "./ExpenseSchema";
import { useExpenseContext } from "../../pages/Expense/ExpensePage";
import { getColorNameFromHex } from "../../utils/appUtils";
import { ExpenseDetailsSkeleton } from "./ExpenseSkeleton";
const ViewExpense = ({ ExpenseId }) => {
const { data, isLoading, isError, error } = useExpense(ExpenseId);
const [imageLoaded, setImageLoaded] = useState({});
const { setDocumentView } = useExpenseContext();
const {
register,
handleSubmit,
setValue,
reset,
formState: { errors },
} = useForm({
resolver: zodResolver(ActionSchema),
defaultValues: {
comment: "",
selectedStatus: "",
},
});
const { mutate: MakeAction } = useActionOnExpense(() => reset());
const onSubmit = (formData) => {
const Payload = {
expenseId: ExpenseId,
statusId: formData.selectedStatus,
comment: formData.comment,
};
MakeAction(Payload);
};
if (isLoading) return <ExpenseDetailsSkeleton />;
const handleImageLoad = (id) => {
setImageLoaded((prev) => ({ ...prev, [id]: true }));
};
return (
<form className="container px-3" onSubmit={handleSubmit(onSubmit)}>
<div className="row mb-3">
<div className="col-12 mb-3">
<h5 className="fw-semibold">Expense Details</h5>
<hr />
</div>
{/* Expense Info Rows */}
<div className="col-12 col-md-6 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">
Transaction Date :
</label>
<div className="text-muted">
{formatUTCToLocalTime(data.transactionDate)}
</div>
</div>
</div>
<div className="col-12 col-md-6 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">
Expense Type :
</label>
<div className="text-muted">{data.expensesType.name}</div>
</div>
</div>
<div className="col-12 col-md-4 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">
Supplier :
</label>
<div className="text-muted">{data.supplerName}</div>
</div>
</div>
<div className="col-12 col-md-4 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">Amount :</label>
<div className="text-muted"> {data.amount}</div>
</div>
</div>
<div className="col-12 col-md-4 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">
Payment Mode :
</label>
<div className="text-muted">{data.paymentMode.name}</div>
</div>
</div>
<div className="col-12 col-md-4 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">
Paid By :
</label>
<div className="text-muted">
{data.paidBy.firstName} {data.paidBy.lastName}
</div>
</div>
</div>
<div className="col-12 text-start col-md-4 mb-3">
<label className="form-label me-2 mb-0 fw-semibold">Status :</label>
<span
className={`badge bg-label-${
getColorNameFromHex(data?.status?.color) || "secondary"
}`}
>
{data?.status?.displayName}
</span>
</div>
<div className="col-12 text-start d-flex col-md-4 mb-3">
<label className="form-label me-2 mb-0 fw-semibold">
Pre-Approved :
</label>
<div className="text-muted">{data.preApproved ? "Yes" : "No"}</div>
</div>
<div className="col-12 col-md-4 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">
Project :
</label>
<div className="text-muted text-start">{data?.project?.name}</div>
</div>
</div>
<div className="col-12 col-md-4 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">
Created By :
</label>
<div className="text-muted">
{data?.createdBy?.firstName} {data?.createdBy?.lastName}
</div>
</div>
</div>
<div className="col-12 col-md-4 mb-3">
<div className="d-flex">
<label className="form-label me-2 mb-0 fw-semibold">
Created At :
</label>
<div className="text-muted">
{formatUTCToLocalTime(data?.createdAt, true)}
</div>
</div>
</div>
</div>
<div className="text-start">
<label className="form-label me-2 mb-0 fw-semibold">Description:</label>
<div className="text-muted">{data?.description}</div>
</div>
<div className="col-12 my-2 text-start ">
<label className="form-label me-2 mb-0 fw-semibold">
Attachement :
</label>
{data?.documents &&
data?.documents?.map((doc) => (
<div
className="list-group-item list-group-item-action d-flex align-items-center"
key={doc.id}
>
<div
className="rounded me-1 d-flex align-items-center justify-content-center cursor-pointer"
style={{ height: "50px", width: "80px", position: "relative" }}
>
{doc.contentType === "application/pdf" ? (
<div>
<i
className="bx bxs-file-pdf"
style={{ fontSize: "45px" }}
></i>
</div>
) : (
<>
{!imageLoaded[doc.id] && (
<div className="position-absolute text-secondary">
Loading...
</div>
)}
<img
src={doc.thumbPreSignedUrl}
alt={doc.fileName}
className="img-fluid rounded"
style={{
maxHeight: "100%",
maxWidth: "100%",
objectFit: "cover",
opacity: imageLoaded[doc.id] ? 1 : 0,
transition: "opacity 0.3s ease-in-out",
}}
onLoad={() => handleImageLoad(doc.id)}
onClick={() =>
setDocumentView({
IsOpen: true,
Image: doc.preSignedUrl,
})
}
/>
</>
)}
</div>
<div className="w-100">
<small className="mb-0 small">{doc.fileName}</small>
<div className="d">
<i className="bx bx-cloud-download cursor-pointer"></i>
</div>
</div>
</div>
))}
</div>
<hr className="divider my-1" />
{Array.isArray(data.nextStatus) && data.nextStatus.length > 0 && (
<div className="col-12 mb-3 text-start">
<label className="form-label me-2 mb-0 fw-semibold">Comment:</label>
<textarea
className="form-control form-control-sm"
{...register("comment")}
rows="2"
/>
{errors.comment && (
<small className="danger-text">{errors.comment.message}</small>
)}
<input type="hidden" {...register("selectedStatus")} />
<div className="text-center flex-wrap gap-2 my-2">
{data.nextStatus.map((status, index) => (
<button
key={index}
type="button"
onClick={() => {
setValue("selectedStatus", status.id);
handleSubmit(onSubmit)();
}}
className="btn btn-primary btn-sm cursor-pointer mx-2 border-0"
>
{status.displayName || status.name}
</button>
))}
</div>
</div>
)}
</form>
);
};
export default ViewExpense;