SME-Web/src/components/process/processStepOne/ProcessStepOne.tsx

270 lines
9.6 KiB
TypeScript

import { IoMdClose } from "react-icons/io";
import RecipientAddCard from './RecipientAddCard';
import RecipientCards from './RecipientCards';
import SelectedDocuments from "./SelectedDocuments";
import api from "../../../config/api";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../../../store/store";
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { setImages } from "../../../store/slices/selectedDocsSlice";
import { addRecipient, addRecipientAsync, fetchRecipients, recipientType, resetRecipients, updateRecipientIds } from "../../../store/slices/selectedRecipientsSlice";
import { setTransactionId, TRANSACTION_STATUS_ENUMS, updateTransactionStatus } from "../../../store/slices/transactionSlice";
import { hideLoader, showLoader } from "../../../store/slices/loaderSlice";
import Loader from "../../dashboard/Loader";
import { Bounce, toast } from "react-toastify";
import { fetchDocuments, resetDocuments, setDocuments, uploadDocuments } from "../../../store/slices/documentSlice";
const ProcessStepOne = () => {
interface EmailDtls {
subject: string;
message: string;
}
const { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
if (!accountId || !transactionId) {
window.location.href = "/";
return null;
}
const navigate = useNavigate();
const dispatch = useDispatch();
// const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments)
// const { selectedDocuments, signType } = useSelector((state: RootState) => state.selectedDocuments)
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients)
useEffect(() => {
selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId }));
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
}, [])
// const signingOrder = useSelector((state: RootState) => state.selectedRecipients.signingOrder)
// const user = useSelector((state: RootState) => state.user)
const [emailDtls, setEmailDtls] = useState<EmailDtls>({ subject: "Documents for Signature", message: "" });
useEffect(() => {
dispatch(hideLoader());
}, [])
const handleNextClick = async (isSendNow: boolean) => {
let formError = {
documents: false,
recipients: false,
subject: false
}
if (!selectedDocuments.length) {
formError.documents = true
}
if (!selectedRecipients.length) {
formError.recipients = true
}
if (!emailDtls.subject.length) {
formError.subject = true
}
if (formError.documents || formError.recipients || formError.subject) {
console.log(selectedDocuments, 'line 193')
toast.dismiss();
toast.error(`${formError.documents ? "Add Document" : ""}
${(formError.documents && formError.recipients) ? " | " : ""}
${formError.recipients ? "Add Recipient" : ""}
${(formError.documents || formError.recipients) ? " | " : ""}
${formError.subject ? "Add Subject" : ""}`, {
position: "top-center",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: false,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
transition: Bounce,
});
return;
}
try {
dispatch(showLoader("Processing Documents..."));
const documentsData = selectedDocuments.map((doc, index) => ({
name: doc.name,
documentId: doc.id,
order: index,
}));
await api.patch(`/api/accounts/${accountId}/transactions/${transactionId}/documents`, { "documents": documentsData });
await api.get(`/api/accounts/${accountId}/transactions/${transactionId}/documents?include_images=true`).then(res => {
if (res.status === 200) {
dispatch(setDocuments(res.data));
}
}).catch((err) => {
console.error(err)
});
dispatch(showLoader("Processing Recipients..."));
const recipientsData = selectedRecipients.map((recipient, index) => ({
// index,
routingOrder: "routingOrder" in recipient && recipient.routingOrder ? recipient.routingOrder : 1,
type: recipient.type,
firstName: recipient.firstName,
lastName: recipient.lastName,
authType: "NONE",
deliveryMethod: "EMAIL",
email: recipient.email,
hostName: recipient.hostName,
hostEmail: recipient.hostEmail,
company: "",
title: "",
website: "",
phone: "",
accessCode: "",
accessCodeDelivery: true,
language: "en",
name: `${recipient.firstName} ${recipient.lastName}`
}));
dispatch(addRecipientAsync({ recipientsData, accountId, transactionId }));
dispatch(showLoader("Processing Message..."));
await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, { subject: emailDtls.subject, message: emailDtls.message, status: "CREATED" }).then((res) => {
console.log(res);
})
dispatch(hideLoader());
if (isSendNow) {
dispatch(updateTransactionStatus(TRANSACTION_STATUS_ENUMS.TRANSACTION_SEND_SUCCESS));
setTimeout(() => {
// navigate("/");
}, 1000);
} else {
setTimeout(() => {
dispatch(resetDocuments())
dispatch(resetRecipients())
dispatch(hideLoader());
navigate(`/process-step-two/${accountId}/${transactionId}`);
}, 1000);
}
} catch (error) {
dispatch(hideLoader());
console.error("Error submitting data step-by-step:", error);
toast.error("Something went wrong. Please try again.", {
position: "top-center",
autoClose: 5000,
theme: "light",
transition: Bounce,
});
}
};
useEffect(() => {
dispatch(updateTransactionStatus(TRANSACTION_STATUS_ENUMS.TRANSACTION_INITIATED))
}, [])
const handleClose = () => {
dispatch(resetDocuments())
navigate('/')
}
const globalLoader = useSelector((state: RootState) => state.loader)
return (
<>
<div className={`relative w-full bg-[var(--mainViewBg)] ${globalLoader.isLoading ? 'pointer-events-none h-screen overflow-hidden' : ''}`}>
{/* Top Navigation */}
<div className='fixed top-0 w-full flex items-center justify-between bg-white shadow z-50 px-4 py-3'>
<div className='flex items-center gap-2'>
<IoMdClose
onClick={handleClose}
className='text-2xl text-slate-500 cursor-pointer hover:text-[var(--primary)] transition'
/>
<p className="text-base font-normal text-gray-700 border-l pl-4">Add Recipient and Message</p>
</div>
<div className='flex items-center gap-3'>
<button
onClick={() => handleNextClick(true)}
className="text-sm px-4 py-2 rounded border border-gray-300 hover:bg-gray-100 transition"
>
Send Now
</button>
<button
onClick={() => handleNextClick(false)}
className="text-sm px-4 py-2 rounded bg-[var(--primary)] text-white shadow hover:bg-[var(--primaryLight2)] transition"
>
Add Tags
</button>
</div>
</div>
{/* Main Content */}
<div className="relative max-w-4xl mx-auto pt-[80px] px-4 pb-10">
{/* Documents */}
<section>
<h2 className="text-lg font-medium mb-4 text-[var(--processStepOneTextHead)]">Documents</h2>
<SelectedDocuments />
</section>
{/* Recipients */}
<section className="mt-8">
<h2 className="text-lg font-medium mb-4 pt-6 border-t text-[var(--processStepOneTextHead)]">Signers</h2>
<div className="flex flex-col gap-4 align-start">
<RecipientCards />
{/* {signType !== "self-sign" && <RecipientAddCard />} */}
<RecipientAddCard />
</div>
</section>
{/* Email */}
<section className="mt-8">
<h2 className="text-lg font-medium mb-4 pt-6 border-t text-[var(--processStepOneTextHead)]">Email</h2>
{/* Subject */}
<div className='flex flex-col mb-4'>
<label className='text-sm font-medium text-[var(--greyTextCol)] mb-1'>Subject</label>
<input
type="text"
required
value={emailDtls.subject}
onChange={(e) => setEmailDtls({ ...emailDtls, subject: e.target.value })}
placeholder="Email Subject"
className="w-full px-3 py-2 rounded border border-gray-300 focus:outline-none focus:ring-2 focus:ring-[var(--primary)]"
/>
</div>
{/* Message */}
<div className='flex flex-col'>
<label className='text-sm font-medium text-[var(--greyTextCol)] mb-1'>Message for Signers</label>
<textarea
rows={4}
value={emailDtls.message}
onChange={(e) => setEmailDtls({ ...emailDtls, message: e.target.value })}
placeholder="Message"
className="w-full px-3 py-2 rounded border border-gray-300 focus:outline-none focus:ring-2 focus:ring-[var(--primary)]"
/>
</div>
</section>
</div>
{globalLoader.isLoading && <Loader />}
</div>
</>
);
}
export default ProcessStepOne