added attachement in invoice
This commit is contained in:
parent
9ce47a9232
commit
f0d21b14a2
@ -3,7 +3,6 @@ import { formatFileSize, getIconByFileType } from "../../utils/appUtils";
|
||||
import Tooltip from "../common/Tooltip";
|
||||
|
||||
const Filelist = ({ files, removeFile, expenseToEdit, sm = 6, md = 4 }) => {
|
||||
debugger
|
||||
return (
|
||||
<div className="d-flex flex-wrap gap-2 my-1">
|
||||
{files
|
||||
@ -23,15 +22,15 @@ const Filelist = ({ files, removeFile, expenseToEdit, sm = 6, md = 4 }) => {
|
||||
style={{ minWidth: "30px" }}
|
||||
></i>
|
||||
|
||||
<Tooltip text={file.fileName} >
|
||||
<Tooltip text={file.fileName}>
|
||||
<div className="d-flex flex-column text-truncate">
|
||||
<span className="fw-semibold small text-truncate">
|
||||
{file.fileName}
|
||||
</span>
|
||||
<span className="text-body-secondary small">
|
||||
{file.fileSize ? formatFileSize(file.fileSize) : ""}
|
||||
</span>
|
||||
</div>
|
||||
<span className="fw-semibold small text-truncate">
|
||||
{file.fileName}
|
||||
</span>
|
||||
<span className="text-body-secondary small">
|
||||
{file.fileSize ? formatFileSize(file.fileSize) : ""}
|
||||
</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@ -42,7 +41,7 @@ const Filelist = ({ files, removeFile, expenseToEdit, sm = 6, md = 4 }) => {
|
||||
role="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
removeFile(expenseToEdit ? file.documentId : idx);
|
||||
removeFile(expenseToEdit ? file.documentId ?? idx : idx);
|
||||
}}
|
||||
></i>
|
||||
</Tooltip>
|
||||
|
||||
16
src/components/InfoBlock/WarningBlock.jsx
Normal file
16
src/components/InfoBlock/WarningBlock.jsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
|
||||
const WarningBlock = ({content}) => {
|
||||
return (
|
||||
<div className="col-12 my-1">
|
||||
<div className="d-flex align-items-center gap-2 p-3 rounded bg-warning bg-opacity-10 border border-warning-subtle text-start align-item-start">
|
||||
<i className="bx bx-info-circle text-warning fs-5"></i>
|
||||
<p className="mb-0 small">
|
||||
{content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default WarningBlock
|
||||
@ -19,6 +19,8 @@ import SelectField from "../common/Forms/SelectField";
|
||||
import Filelist from "../Expenses/Filelist";
|
||||
import SingleFileUploader from "../common/SigleFileUploader";
|
||||
import { localToUtc } from "../../utils/appUtils";
|
||||
import WarningBlock from "../InfoBlock/WarningBlock";
|
||||
import { FILE_UPLOAD_INFO } from "../../utils/staticContent";
|
||||
|
||||
const DeliveryChallane = ({ purchaseId }) => {
|
||||
const [file, setFile] = useState(null);
|
||||
@ -178,15 +180,7 @@ const DeliveryChallane = ({ purchaseId }) => {
|
||||
</div>
|
||||
</form>
|
||||
{!isUploaded && (
|
||||
<div className="col-12 my-1">
|
||||
<div className="d-flex align-items-center gap-2 p-3 rounded bg-warning bg-opacity-10 border border-warning-subtle text-start align-item-start">
|
||||
<i className="bx bx-info-circle text-warning fs-5"></i>
|
||||
<p className="mb-0 small">
|
||||
If want upload document, Please select a document type before
|
||||
uploading the document.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<WarningBlock content={FILE_UPLOAD_INFO} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
||||
name: "Payment Details",
|
||||
icon: "bx bx-credit-card bx-md",
|
||||
subtitle: "Amount, tax & due date",
|
||||
component: <PurchasePaymentDetails purchaseId={purchaseId}/>,
|
||||
component: <PurchasePaymentDetails purchaseId={purchaseId} />,
|
||||
},
|
||||
];
|
||||
|
||||
@ -65,17 +65,18 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
||||
fileName: doc.fileName,
|
||||
base64Data: null,
|
||||
contentType: doc.contentType,
|
||||
documentId: doc.id,
|
||||
documentId: doc.documentId,
|
||||
invoiceAttachmentTypeId:doc.invoiceAttachmentTypeId ?? null,
|
||||
fileSize: 0,
|
||||
description: "",
|
||||
preSignedUrl: doc.preSignedUrl,
|
||||
isActive: doc.isActive ?? true,
|
||||
}))
|
||||
: []
|
||||
: [],
|
||||
});
|
||||
setCompletedTabs([0, 1, 2]);
|
||||
}
|
||||
}, [purchaseId, data, reset]);
|
||||
}, []);
|
||||
|
||||
const handleNext = async (e) => {
|
||||
e.preventDefault();
|
||||
@ -117,7 +118,8 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
||||
|
||||
if (purchaseId) {
|
||||
const changedData = Object.keys(dirtyFields).reduce((acc, key) => {
|
||||
if (dirtyFields[key]) {
|
||||
debugger;
|
||||
if (dirtyFields[key] && key !== "invoiceAttachmentTypeId") {
|
||||
acc.push({
|
||||
operationType: 0,
|
||||
path: `/${key}`,
|
||||
@ -128,15 +130,16 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
updatePurchase({
|
||||
purchaseId,
|
||||
payload: changedData,
|
||||
});
|
||||
console.log(changedData)
|
||||
// updatePurchase({
|
||||
// purchaseId,
|
||||
// payload: changedData,
|
||||
// });
|
||||
} else {
|
||||
CreateInvoice(formData);
|
||||
}
|
||||
};
|
||||
console.log(errors)
|
||||
return (
|
||||
<div
|
||||
id="wizard-property-listing"
|
||||
|
||||
@ -1,11 +1,21 @@
|
||||
import React, { useEffect } from "react";
|
||||
import Label from "../common/Label";
|
||||
import { useAppFormContext } from "../../hooks/appHooks/useAppForm";
|
||||
import {
|
||||
AppFormController,
|
||||
useAppFormContext,
|
||||
} from "../../hooks/appHooks/useAppForm";
|
||||
import DatePicker from "../common/DatePicker";
|
||||
import { useInvoiceAttachmentTypes } from "../../hooks/masterHook/useMaster";
|
||||
import Filelist from "../Expenses/Filelist";
|
||||
const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
import SelectField from "../common/Forms/SelectField";
|
||||
import { useWatch } from "react-hook-form";
|
||||
import WarningBlock from "../InfoBlock/WarningBlock";
|
||||
import { FILE_UPLOAD_INFO } from "../../utils/staticContent";
|
||||
|
||||
const PurchasePaymentDetails = ({ purchaseId = null }) => {
|
||||
const { data, isLoading, error, isError } = useInvoiceAttachmentTypes();
|
||||
const { data: InvoiceDocTypes, isLoading: invoiceDocLoading } =
|
||||
useInvoiceAttachmentTypes();
|
||||
const {
|
||||
register,
|
||||
watch,
|
||||
@ -25,7 +35,7 @@ const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
setValue("totalAmount", (base + tax).toFixed(2));
|
||||
}
|
||||
}, [baseAmount, taxAmount, setValue]);
|
||||
|
||||
const invoiceAttachmentType = watch("invoiceAttachmentTypeId");
|
||||
const files = watch("attachments");
|
||||
const onFileChange = async (e) => {
|
||||
const newFiles = Array.from(e.target.files);
|
||||
@ -43,6 +53,7 @@ const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
fileSize: file.size,
|
||||
description: "",
|
||||
isActive: true,
|
||||
invoiceAttachmentTypeId: invoiceAttachmentType,
|
||||
};
|
||||
})
|
||||
);
|
||||
@ -72,16 +83,24 @@ const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
reader.onerror = (error) => reject(error);
|
||||
});
|
||||
const removeFile = (index) => {
|
||||
debugger
|
||||
|
||||
|
||||
if (purchaseId) {
|
||||
const newFiles = files.map((file, i) => {
|
||||
if (file.documentId !== index) return file;
|
||||
if (i !== index) return file;
|
||||
|
||||
return {
|
||||
...file,
|
||||
isActive: false,
|
||||
};
|
||||
});
|
||||
setValue("attachments", newFiles, { shouldValidate: true });
|
||||
|
||||
console.log("OLD:", files);
|
||||
console.log("NEW:", newFiles);
|
||||
|
||||
// setValue("attachments", newFiles, { shouldValidate: true });
|
||||
const new_Files = files.filter((_, i) => i !== index);
|
||||
setValue("attachments", new_Files, { shouldValidate: true });
|
||||
} else {
|
||||
const newFiles = files.filter((_, i) => i !== index);
|
||||
setValue("attachments", newFiles, { shouldValidate: true });
|
||||
@ -89,7 +108,7 @@ const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="row g-3 text-start">
|
||||
<div className="row g-1 text-start">
|
||||
<div className="col-12 col-md-4">
|
||||
<Label htmlFor="baseAmount" required>
|
||||
Base Amount
|
||||
@ -200,6 +219,31 @@ const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<AppFormController
|
||||
name="invoiceAttachmentTypeId"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<SelectField
|
||||
label="Select Document Type"
|
||||
options={InvoiceDocTypes ?? []}
|
||||
placeholder="Choose Type"
|
||||
labelKeyKey="name"
|
||||
valueKeyKey="id"
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
isLoading={invoiceDocLoading}
|
||||
className="m-0"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{errors?.invoiceAttachmentTypeId && (
|
||||
<small className="danger-text">
|
||||
{errors.invoiceAttachmentTypeId.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="text-start">
|
||||
<div className="col-md-12">
|
||||
@ -223,6 +267,7 @@ const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
id="attachments"
|
||||
accept=".pdf,.jpg,.jpeg,.png"
|
||||
multiple
|
||||
disabled={!invoiceAttachmentType}
|
||||
style={{ display: "none" }}
|
||||
{...register("attachments")}
|
||||
onChange={(e) => {
|
||||
@ -232,9 +277,7 @@ const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
/>
|
||||
</div>
|
||||
{errors.attachments && (
|
||||
<small className="danger-text">
|
||||
{errors.attachments.message}
|
||||
</small>
|
||||
<small className="danger-text">{errors.attachments.message}</small>
|
||||
)}
|
||||
{files.length > 0 && (
|
||||
<Filelist
|
||||
@ -251,10 +294,13 @@ const PurchasePaymentDetails = ({purchaseId=null}) => {
|
||||
(fileError?.fileSize?.message ||
|
||||
fileError?.contentType?.message ||
|
||||
fileError?.base64Data?.message,
|
||||
fileError?.documentId?.message)
|
||||
fileError?.documentId?.message)
|
||||
}
|
||||
</div>
|
||||
))}
|
||||
{!invoiceAttachmentType && (
|
||||
<WarningBlock content={FILE_UPLOAD_INFO} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -10,10 +10,9 @@ const ALLOWED_TYPES = [
|
||||
];
|
||||
|
||||
export const AttachmentSchema = z.object({
|
||||
documentId: z.string().optional(),
|
||||
invoiceAttachmentTypeId: z.string().min(1, { message: "Attachment type is required" }),
|
||||
invoiceAttachmentTypeId: z.string().nullable(),
|
||||
fileName: z.string().min(1, { message: "Filename is required" }),
|
||||
base64Data: z.string().min(1, { message: "File data is required" }),
|
||||
base64Data: z.string().nullable(),
|
||||
contentType: z
|
||||
.string()
|
||||
.refine((val) => ALLOWED_TYPES.includes(val), {
|
||||
@ -25,39 +24,7 @@ export const AttachmentSchema = z.object({
|
||||
description: z.string().optional().default(""),
|
||||
isActive: z.boolean().default(true),
|
||||
});
|
||||
// export const AttachmentSchema = (allowedContentType, maxSizeAllowedInMB) => {
|
||||
// const allowedTypes = normalizeAllowedContentTypes(allowedContentType);
|
||||
|
||||
// return z.object({
|
||||
// fileName: z.string().min(1, { message: "File name is required" }),
|
||||
// base64Data: z.string().min(1, { message: "File data is required" }),
|
||||
// invoiceAttachmentTypeId: z
|
||||
// .string()
|
||||
// .min(1, { message: "File data is required" }),
|
||||
|
||||
// contentType: z
|
||||
// .string()
|
||||
// .min(1, { message: "MIME type is required" })
|
||||
// .refine(
|
||||
// (val) => (allowedTypes.length ? allowedTypes.includes(val) : true),
|
||||
// {
|
||||
// message: `File type must be one of: ${allowedTypes.join(", ")}`,
|
||||
// }
|
||||
// ),
|
||||
|
||||
// fileSize: z
|
||||
// .number()
|
||||
// .int()
|
||||
// .nonnegative("fileSize must be ≥ 0")
|
||||
// .max(
|
||||
// (maxSizeAllowedInMB ?? 25) * 1024 * 1024,
|
||||
// `fileSize must be ≤ ${maxSizeAllowedInMB ?? 25}MB`
|
||||
// ),
|
||||
|
||||
// description: z.string().optional().default(""),
|
||||
// isActive: z.boolean(),
|
||||
// });
|
||||
// };
|
||||
|
||||
export const PurchaseSchema = z.object({
|
||||
title: z.string().min(1, { message: "Title is required" }),
|
||||
@ -89,9 +56,10 @@ export const PurchaseSchema = z.object({
|
||||
paymentDueDate: z.coerce.date().nullable(),
|
||||
transportCharges: z.number().nullable(),
|
||||
description: z.string().min(1, { message: "Description is required" }),
|
||||
invoiceAttachmentTypeId:z.string().nullable(),
|
||||
attachments: z
|
||||
.array(AttachmentSchema)
|
||||
.nonempty({ message: "At least one file attachment is required" }),
|
||||
|
||||
|
||||
});
|
||||
|
||||
@ -130,9 +98,8 @@ export const defaultPurchaseValue = {
|
||||
paymentDueDate: null,
|
||||
transportCharges: null,
|
||||
description: "",
|
||||
invoiceAttachmentTypeId:null,
|
||||
attachments: [],
|
||||
|
||||
// attachments: [],
|
||||
};
|
||||
|
||||
export const getStepFields = (stepIndex) => {
|
||||
@ -165,7 +132,9 @@ export const getStepFields = (stepIndex) => {
|
||||
"totalAmount",
|
||||
"transportCharges",
|
||||
"paymentDueDate",
|
||||
"invoiceAttachmentTypeId",
|
||||
"description",
|
||||
"attachments"
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
4
src/utils/staticContent.jsx
Normal file
4
src/utils/staticContent.jsx
Normal file
@ -0,0 +1,4 @@
|
||||
export const FILE_UPLOAD_INFO = `
|
||||
If you want to upload a document, please select a document type
|
||||
before uploading the document.
|
||||
`;
|
||||
Loading…
x
Reference in New Issue
Block a user