Merge pull request 'Added Common Email Model Component' (#285) from Email-Loader into main

Reviewed-on: Pozomind/pozo-retail-app#285
This commit is contained in:
karthikalakshmi 2026-03-17 19:46:14 +05:30
commit 63a3cd47c6
18 changed files with 364 additions and 455 deletions

View File

@ -94,10 +94,12 @@ import { ChangeTotalAmount } from '../../../../../Features/ExteraCharges/ExtraCh
import { Radio } from 'antd'; import { Radio } from 'antd';
import ReprintPDFDataShare from './ReprintPDFDataShare.jsx'; import ReprintPDFDataShare from './ReprintPDFDataShare.jsx';
import { ImShare } from 'react-icons/im'; import { ImShare } from 'react-icons/im';
import EmailModel from '../../UtillComponents/EmailModel.jsx';
const RetailApiurl = import.meta.env.ENV_API_URL; const RetailApiurl = import.meta.env.ENV_API_URL;
function BSReprint({ setOpenModel = () => { } }) { function BSReprint({ setOpenModel = () => { } }) {
const [form] = Form.useForm();
const dispatch = useDispatch(); const dispatch = useDispatch();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const appPreferences = useSelector(ApplicationPreferences); const appPreferences = useSelector(ApplicationPreferences);
@ -1155,17 +1157,17 @@ function BSReprint({ setOpenModel = () => { } }) {
setEmailModalOpen(true); setEmailModalOpen(true);
}; };
const handleSendEmail = async () => { const handleSendEmail = async (value) => {
try { try {
const toEmail = value.email;
if (selectedRows.length === 0) { if (selectedRows.length === 0) {
setLoading(true); setLoading(true);
const result = await MobilePdfPrint({ const result = await MobilePdfPrint({
printerTemplateStyle, printerTemplateStyle,
printDatas, printDatas,
PrintOrderDetails: reprintData, PrintOrderDetails: reprintData,
PrintComing: 'email', PrintComing: 'email',
emailId: EmailId, emailId: toEmail,
dispatch, dispatch,
}); });
@ -1173,9 +1175,10 @@ function BSReprint({ setOpenModel = () => { } }) {
setEmailModalOpen(false); // Close modal setEmailModalOpen(false); // Close modal
setEmailId(''); // Reset email input (optional) setEmailId(''); // Reset email input (optional)
setLoading(false); setLoading(false);
form.resetFields();
} }
} else { } else {
mutiplePrint('email'); mutiplePrint('email',toEmail);
} }
} catch (err) { } catch (err) {
console.error('❌ Email error:', err); console.error('❌ Email error:', err);
@ -1196,7 +1199,7 @@ function BSReprint({ setOpenModel = () => { } }) {
const [processingProgress, setProcessingProgress] = useState(0); const [processingProgress, setProcessingProgress] = useState(0);
const [isProcessing, setIsProcessing] = useState(false); const [isProcessing, setIsProcessing] = useState(false);
const mutiplePrint = async (printType) => { const mutiplePrint = async (printType,toEmail) => {
setIsProcessing(true); setIsProcessing(true);
setProcessingProgress(0); setProcessingProgress(0);
@ -1206,25 +1209,27 @@ function BSReprint({ setOpenModel = () => { } }) {
PrintOrderDetails: selectedRows, PrintOrderDetails: selectedRows,
setPrintOrderDetails: setReprintData, setPrintOrderDetails: setReprintData,
PrintComing: printType, PrintComing: printType,
emailId: EmailId, emailId: EmailId || toEmail,
UserId: UserId, UserId: UserId,
dispatch, dispatch,
onProgress: (progress) => setProcessingProgress(progress), onProgress: (progress) => setProcessingProgress(progress),
}); });
setIsProcessing(false); setIsProcessing(false);
if (printType === 'email') { if (printType === 'email') {
if (result?.data?.status === 1) { if (result?.data?.status === 1) {
setMessage({ type: 'success', data: result?.data?.response });
setEmailModalOpen(false); setEmailModalOpen(false);
setEmailId(''); setEmailId('');
setSelectedRows([]); setSelectedRows([]);
setSelectAll(false); setSelectAll(false);
setBulkMode(false); setBulkMode(false);
form.resetFields();
} else { } else {
setSelectedRows([]); setSelectedRows([]);
setSelectAll(false); setSelectAll(false);
setBulkMode(false); setBulkMode(false);
form.resetFields();
} }
} else { } else {
setSelectedRows([]); setSelectedRows([]);
@ -1811,7 +1816,7 @@ function BSReprint({ setOpenModel = () => { } }) {
handleCancel={ReprintCancel} handleCancel={ReprintCancel}
/> />
<Modal {/* <Modal
title="Send Email" title="Send Email"
open={emailModalOpen} open={emailModalOpen}
onCancel={() => setEmailModalOpen(false)} onCancel={() => setEmailModalOpen(false)}
@ -1837,7 +1842,17 @@ function BSReprint({ setOpenModel = () => { } }) {
progress={processingProgress} progress={processingProgress}
isProcessing={isProcessing} isProcessing={isProcessing}
/> />
</Modal> </Modal> */}
{(emailModalOpen || isProcessing) && (
<EmailModel
open={emailModalOpen}
emailSending={isProcessing}
handleCancel={() => setEmailModalOpen(false)}
form={form}
handleSendEmailWithEnteredEmail={handleSendEmail}
/>)}
{!emailModalOpen && ( {!emailModalOpen && (
<PdfProcessingProgress <PdfProcessingProgress
progress={processingProgress} progress={processingProgress}

View File

@ -6,7 +6,7 @@ import { getConfigType, getCreditCustomerReprint } from "../../../../../Features
import { getSession, printDiv } from "../../../../../Services/Others"; import { getSession, printDiv } from "../../../../../Services/Others";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { AiFillPrinter, AiOutlineCheckSquare } from "react-icons/ai"; import { AiFillPrinter, AiOutlineCheckSquare } from "react-icons/ai";
import { Button, Checkbox, DatePicker, Form, Input, Modal, Switch, Tooltip } from "antd"; import { Button, Checkbox, DatePicker, Form, Switch, Tooltip } from "antd";
import moment from "moment"; import moment from "moment";
import { TbSettingsCog } from "react-icons/tb"; import { TbSettingsCog } from "react-icons/tb";
import { DefaultModal } from "../../../../../Components/Modal/DefaultModal"; import { DefaultModal } from "../../../../../Components/Modal/DefaultModal";
@ -25,6 +25,7 @@ import { GlobalprintDatas, GlobalPrinterMappingDtls, StoredSessionData } from ".
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import MobilePrintCreditCustomer from "../../UtillComponents/MobilePrintCreditCustomer"; import MobilePrintCreditCustomer from "../../UtillComponents/MobilePrintCreditCustomer";
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import EmailModel from "../../UtillComponents/EmailModel";
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
@ -56,7 +57,7 @@ const CreditCustomerReprint = () => {
const reprintReasonRef = useRef(null); const reprintReasonRef = useRef(null);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [form] = Form.useForm();
const AppId = getSession("AppId"); const AppId = getSession("AppId");
const CompId = getSession("CompId"); const CompId = getSession("CompId");
const BranchId = getSession("BranchId"); const BranchId = getSession("BranchId");
@ -444,7 +445,7 @@ const CreditCustomerReprint = () => {
const mutiplePrint = async (printType) => { const mutiplePrint = async (printType,toEmail) => {
setIsProcessing(true); setIsProcessing(true);
setProcessingProgress(0); setProcessingProgress(0);
@ -453,7 +454,7 @@ const CreditCustomerReprint = () => {
BSCreditCustomerPrint: BSCreditCustomerPrint, BSCreditCustomerPrint: BSCreditCustomerPrint,
PrintOrderDetails: selectedRows, PrintOrderDetails: selectedRows,
PrintComing: printType, PrintComing: printType,
emailId: EmailId, emailId: EmailId || toEmail,
UserId: UserId, UserId: UserId,
dispatch, dispatch,
onProgress: (progress) => setProcessingProgress(progress) onProgress: (progress) => setProcessingProgress(progress)
@ -484,8 +485,9 @@ const CreditCustomerReprint = () => {
} }
}; };
const handleSendEmail = async () => { const handleSendEmail = async (value) => {
try { try {
const toEmail = value.email;
if (selectedRows.length === 0) { if (selectedRows.length === 0) {
setLoading(true); setLoading(true);
@ -494,7 +496,7 @@ const CreditCustomerReprint = () => {
printDatas, printDatas,
PrintOrderDetails: reprintData, PrintOrderDetails: reprintData,
PrintComing: "email", PrintComing: "email",
emailId: EmailId, emailId: toEmail,
dispatch, dispatch,
}); });
@ -507,7 +509,7 @@ const CreditCustomerReprint = () => {
} }
} }
else { else {
mutiplePrint('email'); mutiplePrint('email',toEmail);
} }
} catch (err) { } catch (err) {
@ -664,7 +666,7 @@ const CreditCustomerReprint = () => {
</Form> </Form>
</>} </>}
/> />
<Modal {/* <Modal
title="Send Email" title="Send Email"
open={emailModalOpen} open={emailModalOpen}
onCancel={() => setEmailModalOpen(false)} onCancel={() => setEmailModalOpen(false)}
@ -691,7 +693,16 @@ const CreditCustomerReprint = () => {
progress={processingProgress} progress={processingProgress}
isProcessing={isProcessing} isProcessing={isProcessing}
/> />
</Modal> </Modal> */}
{(emailModalOpen || isProcessing) && (
<EmailModel
open={emailModalOpen}
emailSending={isProcessing}
handleCancel={() => setEmailModalOpen(false)}
form={form}
handleSendEmailWithEnteredEmail={handleSendEmail}
/>)}
{!emailModalOpen && {!emailModalOpen &&
<PdfProcessingProgress <PdfProcessingProgress
progress={processingProgress} progress={processingProgress}

View File

@ -0,0 +1,65 @@
import { Button, Form, Input, Spin } from "antd";
import { DefaultModal } from "../../../../Components/Modal/DefaultModal";
const EmailModel = ({
open,
emailSending,
handleCancel,
form,
handleSendEmailWithEnteredEmail,
}) => {
return (
<DefaultModal
width={400}
open={open || emailSending}
title={emailSending ? null : "User Mail"}
handleCancel={() => !emailSending && handleCancel()}
footer={false}
closable={!emailSending}
maskClosable={!emailSending}
children={
emailSending ? (
// 👇 Loader view
<div style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "30px",
gap: "16px"
}}>
<Spin size="large" />
<p style={{ margin: 0, fontSize: "16px", color: "#555" }}>
Sending email, please wait...
</p>
</div>
) :
(<div>
<Form
form={form}
layout="vertical"
onFinish={handleSendEmailWithEnteredEmail}
>
<Form.Item
label="Mail ID"
name="email"
rules={[
{ required: true, message: 'Email is required' },
{ type: 'email', message: 'Enter a valid email address' },
]}
>
<Input autoComplete="off" placeholder="Enter your email" />
</Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form>
</div>)
}
/>
);
};
export default EmailModel;

View File

@ -61,6 +61,7 @@ import { useSelector } from 'react-redux';
import { getPrintSelectionComponentData } from '../../Features/ThemeChange/ThemeChange.js'; import { getPrintSelectionComponentData } from '../../Features/ThemeChange/ThemeChange.js';
import { DCPDFMobilePrint } from './DCPDFMobilePrint.js'; import { DCPDFMobilePrint } from './DCPDFMobilePrint.js';
import { isMobile } from 'react-device-detect'; import { isMobile } from 'react-device-detect';
import EmailModel from '../BookingScreen/Components/UtillComponents/EmailModel.jsx';
const DeliveryChellanForm = () => { const DeliveryChellanForm = () => {
@ -114,6 +115,7 @@ const DeliveryChellanForm = () => {
const [segmentValue, setSegmentValue] = useState("N") const [segmentValue, setSegmentValue] = useState("N")
const [selectedOrder, setSelectedOrder] = useState(); const [selectedOrder, setSelectedOrder] = useState();
const [orderTableData, setOrderTableData] = useState([]); const [orderTableData, setOrderTableData] = useState([]);
const [emailSending, setEmailSending] = useState(false);
const items = [ const items = [
{ {
@ -1217,6 +1219,7 @@ const DeliveryChellanForm = () => {
// setPrintData(record); // setPrintData(record);
if (orderData?.CustMail) { if (orderData?.CustMail) {
setEmailSending(true);
setTimeout(async () => { setTimeout(async () => {
try { try {
const blob = await pdfDiv('DC-Default-Print', PurchaseOrderStyle); const blob = await pdfDiv('DC-Default-Print', PurchaseOrderStyle);
@ -1239,6 +1242,9 @@ const DeliveryChellanForm = () => {
setMessageData('Email failed to send'); setMessageData('Email failed to send');
setMessageType('error'); setMessageType('error');
} }
finally{
setEmailSending(false);
}
}, 300); }, 300);
} else { } else {
setPendingOrderDetails(ProductDetails); setPendingOrderDetails(ProductDetails);
@ -1683,7 +1689,7 @@ const DeliveryChellanForm = () => {
</div> </div>
</Form> </Form>
</div> </div>
<DefaultModal {/* <DefaultModal
width={400} width={400}
open={iSEmail} open={iSEmail}
title="User Mail" title="User Mail"
@ -1715,7 +1721,15 @@ const DeliveryChellanForm = () => {
</Form> </Form>
</div> </div>
} }
/> /> */}
{(iSEmail || emailSending )&& (
<EmailModel
open={iSEmail}
emailSending={emailSending}
handleCancel={() => setiSEmail(false)}
form={form}
handleSendEmailWithEnteredEmail={handleSendEmailWithEnteredEmail}
/>)}
{PrintingData?.length > 0 && {PrintingData?.length > 0 &&
<div <div

View File

@ -27,6 +27,7 @@ import { Emailsend } from '../../Features//PurchaseOrder/PurchaseOrder.js';
import { getPrintSelectionComponentData } from '../../Features/ThemeChange/ThemeChange.js'; import { getPrintSelectionComponentData } from '../../Features/ThemeChange/ThemeChange.js';
import { isMobile } from 'react-device-detect'; import { isMobile } from 'react-device-detect';
import { DCPDFMobilePrint } from './DCPDFMobilePrint.js'; import { DCPDFMobilePrint } from './DCPDFMobilePrint.js';
import EmailModel from '../BookingScreen/Components/UtillComponents/EmailModel.jsx';
const subDirectory = import.meta.env.ENV_BASE_URL; const subDirectory = import.meta.env.ENV_BASE_URL;
const items = [ const items = [
@ -75,6 +76,7 @@ const DeliveryChallanList = () => {
const [iSEmail, setiSEmail] = useState(false); const [iSEmail, setiSEmail] = useState(false);
const [enteredEmail, setEnteredEmail] = useState(''); const [enteredEmail, setEnteredEmail] = useState('');
const [pendingOrderDetails, setPendingOrderDetails] = useState(null); const [pendingOrderDetails, setPendingOrderDetails] = useState(null);
const [emailSending, setEmailSending] = useState(false);
const [pendingRecord, setPendingRecord] = useState(null); const [pendingRecord, setPendingRecord] = useState(null);
console.log(ProductDetails, 'ProductDetails'); console.log(ProductDetails, 'ProductDetails');
const PurchaseOrderStyle = `<style>@media print { const PurchaseOrderStyle = `<style>@media print {
@ -405,8 +407,8 @@ const DeliveryChallanList = () => {
}; };
setPrintingData([record]); setPrintingData([record]);
if (orderData?.CustMail) { if (orderData?.CustMail) {
setEmailSending(true);
setTimeout(async () => { setTimeout(async () => {
try { try {
const blob = await pdfDiv('DC-Default-Print', PurchaseOrderStyle); const blob = await pdfDiv('DC-Default-Print', PurchaseOrderStyle);
@ -429,6 +431,9 @@ const DeliveryChallanList = () => {
console.error('❌ Email send failed:', error); console.error('❌ Email send failed:', error);
setMessageData('Email failed to send'); setMessageData('Email failed to send');
setMessageType('error'); setMessageType('error');
}
finally {
setEmailSending(false); // 👈 Hide loader (success or error)
} }
}, 300); }, 300);
} else { } else {
@ -871,7 +876,7 @@ const DeliveryChallanList = () => {
setProductShow(false); setProductShow(false);
}} }}
/> />
<DefaultModal {/* <DefaultModal
width={400} width={400}
open={iSEmail} open={iSEmail}
title="User Mail" title="User Mail"
@ -903,7 +908,17 @@ const DeliveryChallanList = () => {
</Form> </Form>
</div> </div>
} }
/> /> */}
{(iSEmail || emailSending )&& (
<EmailModel
open={iSEmail}
emailSending={emailSending}
handleCancel={() => setiSEmail(false)}
form={form}
handleSendEmailWithEnteredEmail={handleSendEmailWithEnteredEmail}
/>)
}
<div <div
style={{ display: 'none' }} style={{ display: 'none' }}
> >

View File

@ -26,6 +26,7 @@ import { settingDataSelector } from "../../Features/PreferenceMaster/PreferenceM
import { printDCToInvoiceStyles } from "./PrintTemplates/printDCToInvoiceStyles.js"; import { printDCToInvoiceStyles } from "./PrintTemplates/printDCToInvoiceStyles.js";
import { getBranchDetail } from "../../Features/BrachLogin/BranchLogin.js"; import { getBranchDetail } from "../../Features/BrachLogin/BranchLogin.js";
import { PreferenceData } from "../../Features/BookingScreen/BookingData/BookingData.js"; import { PreferenceData } from "../../Features/BookingScreen/BookingData/BookingData.js";
import EmailModel from "../BookingScreen/Components/UtillComponents/EmailModel.jsx";
const subDirectory = import.meta.env.BASE_URL; const subDirectory = import.meta.env.BASE_URL;
@ -57,6 +58,7 @@ const DeliveryChallanToInvoiceForm = () => {
const [showShare, setShowShare] = useState(false); const [showShare, setShowShare] = useState(false);
const [defaultPrintStyle, setDefaultPrintStyle] = useState(null); const [defaultPrintStyle, setDefaultPrintStyle] = useState(null);
const [printTrue, setPrintTrue] = useState(false); const [printTrue, setPrintTrue] = useState(false);
const [emailSending, setEmailSending] = useState(false);
console.log(paymentOptions, "paymentOptions") console.log(paymentOptions, "paymentOptions")
@ -205,24 +207,21 @@ const DeliveryChallanToInvoiceForm = () => {
console.log("record", printingData) console.log("record", printingData)
// alert("This feature is not available yet. Please contact support for assistance.") // alert("This feature is not available yet. Please contact support for assistance.")
if (record?.CustEmail) { if (record?.CustEmail) {
setEmailSending(true)
setPrintTrue(true); setPrintTrue(true);
setTimeout(async () => { setTimeout(async () => {
try { try {
const style = getPrintStyle(); const style = getPrintStyle();
const blob = await pdfDiv('delivery-challan-to-invoice-print', style); const blob = await pdfDiv('delivery-challan-to-invoice-print', style);
console.log(blob, 'blobblob'); console.log(blob, 'blobblob');
const payload = { const payload = {
fileBlob: blob, fileBlob: blob,
toEmail: record?.CustEmail, toEmail: record?.CustEmail,
type: 'DeliveryChallantoInvoice', type: 'DeliveryChallantoInvoice',
messageTemplatesList: [], messageTemplatesList: [],
}; };
const res = await dispatch(Emailsend(payload))?.unwrap(); const res = await dispatch(Emailsend(payload))?.unwrap();
console.log('✅ API Response:', res?.data || res); console.log('✅ API Response:', res?.data || res);
setMessageData('Email sent successfully'); setMessageData('Email sent successfully');
setMessageType('success'); setMessageType('success');
} catch (error) { } catch (error) {
@ -231,6 +230,7 @@ const DeliveryChallanToInvoiceForm = () => {
setMessageType('error'); setMessageType('error');
} finally { } finally {
setPrintTrue(false); setPrintTrue(false);
setEmailSending(false)
} }
}, 300); }, 300);
} else { } else {
@ -448,39 +448,15 @@ const DeliveryChallanToInvoiceForm = () => {
</div> </div>
<DefaultModal
width={400}
open={emailModal}
title="User Mail"
handleCancel={() => setEmailModal(false)}
footer={false}
children={
<div>
<Form
form={form}
layout="vertical"
onFinish={handleSendEmailWithEnteredEmail}
>
<Form.Item
label="Mail ID"
name="email"
rules={[
{ required: true, message: 'Email is required' },
{ type: 'email', message: 'Enter a valid email address' },
]}
>
<Input
autoComplete="off"
placeholder="Enter your email" />
</Form.Item>
<Button type="primary" htmlType="submit"> {(emailModal || emailSending) && (
Submit <EmailModel
</Button> open={emailModal}
</Form> emailSending={emailSending}
</div> handleCancel={() => setEmailModal(false)}
} form={form}
/> handleSendEmailWithEnteredEmail={handleSendEmailWithEnteredEmail}
/>)}
{(printingData?.length > 0 && printTrue) && <div {(printingData?.length > 0 && printTrue) && <div
style={{ display: "none" }} style={{ display: "none" }}
id="delivery-challan-to-invoice-print" id="delivery-challan-to-invoice-print"

View File

@ -27,6 +27,7 @@ import { getPrintSelectionComponentData, GlobalDCtoInvoicePrint, GlobalprintData
import { printDCToInvoiceStyles } from "./PrintTemplates/printDCToInvoiceStyles"; import { printDCToInvoiceStyles } from "./PrintTemplates/printDCToInvoiceStyles";
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import { DCMobilePdfPrint } from "./PrintTemplates/DCMobilePdfPrint"; import { DCMobilePdfPrint } from "./PrintTemplates/DCMobilePdfPrint";
import EmailModel from "../BookingScreen/Components/UtillComponents/EmailModel";
const subDirectory = import.meta.env.BASE_URL; const subDirectory = import.meta.env.BASE_URL;
@ -60,6 +61,7 @@ const DeliveryChallanToInvoiceList = () => {
const [searchedText, setSearchedText] = useState(''); const [searchedText, setSearchedText] = useState('');
const [tableData, setTableData] = useState([]); const [tableData, setTableData] = useState([]);
const [emailModal, setEmailModal] = useState(false); const [emailModal, setEmailModal] = useState(false);
const [emailSending, setEmailSending] = useState(false);
const [printingData, setPrintingData] = useState([]); const [printingData, setPrintingData] = useState([]);
const [productDetails, setProductDetails] = useState([]); const [productDetails, setProductDetails] = useState([]);
const [productModal, setProductModal] = useState(false); const [productModal, setProductModal] = useState(false);
@ -263,6 +265,7 @@ const DeliveryChallanToInvoiceList = () => {
const handleEmailShare = async (record) => { const handleEmailShare = async (record) => {
const style = getPrintStyle(); const style = getPrintStyle();
if (record?.CustEmail) { if (record?.CustEmail) {
setEmailSending(true)
const { data: branchData } = await dispatch(getBranchDetail({ BrId: BranchId }))?.unwrap(); const { data: branchData } = await dispatch(getBranchDetail({ BrId: BranchId }))?.unwrap();
record.AddressDetails = branchData?.data; record.AddressDetails = branchData?.data;
setPrintingData([record]); setPrintingData([record]);
@ -290,6 +293,9 @@ const DeliveryChallanToInvoiceList = () => {
setMessageData('Email failed to send'); setMessageData('Email failed to send');
setMessageType('error'); setMessageType('error');
} }
finally {
setEmailSending(false)
}
}, 300); }, 300);
} else { } else {
setPendingRecord(record); setPendingRecord(record);
@ -427,39 +433,14 @@ const DeliveryChallanToInvoiceList = () => {
setProductModal(false); setProductModal(false);
}} }}
/> />
<DefaultModal {(emailModal || emailSending) && (
width={400} <EmailModel
open={emailModal} open={emailModal}
title="User Mail" emailSending={emailSending}
handleCancel={() => setEmailModal(false)} handleCancel={() => setEmailModal(false)}
footer={false}
children={
<div>
<Form
form={form} form={form}
layout="vertical" handleSendEmailWithEnteredEmail={handleSendEmailWithEnteredEmail}
onFinish={handleSendEmailWithEnteredEmail} />)}
>
<Form.Item
label="Mail ID"
name="email"
rules={[
{ required: true, message: 'Email is required' },
{ type: 'email', message: 'Enter a valid email address' },
]}
>
<Input
autoComplete="off"
placeholder="Enter your email" />
</Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form>
</div>
}
/>
</div> </div>
{printingData?.length > 0 && <div style={{ display: 'none' }} id="delivery-challan-to-invoice-print"> {printingData?.length > 0 && <div style={{ display: 'none' }} id="delivery-challan-to-invoice-print">
<DeliveryChallanToInvoicePrint <DeliveryChallanToInvoicePrint

View File

@ -193,7 +193,7 @@ const CatalogueTemplate1 = () => {
color: '#fff', color: '#fff',
}} }}
> >
{safeRound(item?.SellPrice)} {safeRound(item?.SellPrice || item?.MRP)}
</button> </button>
</div> </div>
</> </>

View File

@ -180,7 +180,7 @@ const Catalogues = () => {
color: '#fff', color: '#fff',
}} }}
> >
{safeRound(item?.SellPrice)} {safeRound(item?.SellPrice || item?.MRP)}
</button> </button>
</div> </div>
</> </>

View File

@ -76,7 +76,7 @@ const CatelogueTemplate3 = () => {
<img className="product-logo" src={item?.ProdLogo} alt={item?.ProdName} /> <img className="product-logo" src={item?.ProdLogo} alt={item?.ProdName} />
)} )}
<div className="product-price">{safeRound(item?.SellPrice)}</div> <div className="product-price">{safeRound(item?.SellPrice || item?.MRP)}</div>
</div> </div>
))} ))}
</div> </div>

View File

@ -113,7 +113,7 @@ const CatalogueTemplate4 = (props) => {
</div> </div>
<div className="product-price"> <div className="product-price">
{props?.cat === 'Catalogue 4' {props?.cat === 'Catalogue 4'
? `MRP: ₹${safeRound(item?.SellPrice)}` ? `MRP: ₹${safeRound(item?.SellPrice || item?.MRP)}`
: item?.OfferDtl?.[0]?.OfferName ? ( : item?.OfferDtl?.[0]?.OfferName ? (
<div className="product-original-price">{item?.OfferDtl?.[0]?.OfferName}</div>) : 'No Offer' <div className="product-original-price">{item?.OfferDtl?.[0]?.OfferName}</div>) : 'No Offer'
} }

View File

@ -292,7 +292,7 @@ const CatalogueTemplate5 = () => {
justifyContent: 'center', justifyContent: 'center',
}} }}
> >
{safeRound(item?.SellPrice)} {safeRound(item?.SellPrice || item?.MRP)}
<div> ONLY </div> <div> ONLY </div>
</div> </div>
</div> </div>

View File

@ -10,7 +10,7 @@ import {
WhatsAppOutlined, WhatsAppOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { changeBreadCrumb } from '../../Features/AppPage/CenterPage'; import { changeBreadCrumb } from '../../Features/AppPage/CenterPage';
import { useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { Skeleton, Form, Input, Button } from 'antd'; import { Skeleton, Form, Input, Button } from 'antd';
import './Productcatalogue.scss'; import './Productcatalogue.scss';
import FormHeader from '../PageComponents/FormHeader'; import FormHeader from '../PageComponents/FormHeader';
@ -30,6 +30,8 @@ import {
GetProductCatalogueByTypeData, GetProductCatalogueByTypeData,
ProductCatalogue, ProductCatalogue,
} from '../../Features/ProductCatlog/ProductCatlogue'; } from '../../Features/ProductCatlog/ProductCatlogue';
import EmailModel from '../BookingScreen/Components/UtillComponents/EmailModel';
import { Messages } from '../../Components/Notifications/Messages';
const subDirectory = import.meta.env.ENV_BASE_URL; const subDirectory = import.meta.env.ENV_BASE_URL;
const Productcatlogue = () => { const Productcatlogue = () => {
@ -44,6 +46,9 @@ const Productcatlogue = () => {
const [template, setTemplate] = useState(); const [template, setTemplate] = useState();
const [selectedTemplateData, setSelectedTemplateData] = useState(); const [selectedTemplateData, setSelectedTemplateData] = useState();
const [catelogueData, setCatelogueData] = useState(''); const [catelogueData, setCatelogueData] = useState('');
const [emailSending, setEmailSending] = useState(false);
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null)
const items = [ const items = [
{ {
@ -2803,6 +2808,7 @@ body {
const StyleId = StyleIDs[selectedTemplateData?.ConfigName]; const StyleId = StyleIDs[selectedTemplateData?.ConfigName];
const Style = StyleName[selectedTemplateData?.ConfigName]; const Style = StyleName[selectedTemplateData?.ConfigName];
if (toEmail) { if (toEmail) {
setEmailSending(true)
try { try {
const blob = await pdfDiv(StyleId, Style); const blob = await pdfDiv(StyleId, Style);
console.log(blob, 'blobblob'); console.log(blob, 'blobblob');
@ -2817,15 +2823,24 @@ body {
const res = await dispatch(Emailsend(payload))?.unwrap(); const res = await dispatch(Emailsend(payload))?.unwrap();
console.log('✅ API Response:', res?.data || res); console.log('✅ API Response:', res?.data || res);
setMessage({ type: 'success', data: 'Email sent successfully' }); setMessageType("success");
setMessageData(res.data?.response);
// setMessage({ type: 'success', data: 'Email sent successfully' });
} catch (error) { } catch (error) {
setMessage({ type: 'error', data: 'Email failed to send' }); setMessage({ type: 'error', data: 'Email failed to send' });
console.error('❌ Email send failed:', error); console.error('❌ Email send failed:', error);
} }
finally {
setEmailSending(false)
}
} else { } else {
setiSEmail(true); setiSEmail(true);
} }
}; };
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
const handleSendEmailWithEnteredEmail = async (values) => { const handleSendEmailWithEnteredEmail = async (values) => {
const recordWithEmail = { custEmail: values.email }; const recordWithEmail = { custEmail: values.email };
@ -2853,6 +2868,11 @@ body {
return ( return (
<div className="pc-wrapper"> <div className="pc-wrapper">
<div> <div>
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
<FormHeader title={'Product Catalogue'} /> <FormHeader title={'Product Catalogue'} />
</div> </div>
<div className="pc-header"> <div className="pc-header">
@ -3008,7 +3028,7 @@ body {
})()} })()}
</div> </div>
</div> </div>
<DefaultModal {/* <DefaultModal
width={400} width={400}
open={iSEmail} open={iSEmail}
title="User Mail" title="User Mail"
@ -3038,7 +3058,15 @@ body {
</Form> </Form>
</div> </div>
} }
/> /> */}
{(iSEmail || emailSending) && (
<EmailModel
open={iSEmail}
emailSending={emailSending}
handleCancel={() => setiSEmail(false)}
form={form}
handleSendEmailWithEnteredEmail={handleSendEmailWithEnteredEmail}
/>)}
</div> </div>
); );
}; };

View File

@ -8,7 +8,7 @@ import {
EditFilled, EditFilled,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { Messages } from '../../Components/Notifications/Messages'; import { Messages } from '../../Components/Notifications/Messages';
import { Form, Tooltip, Space, Input, Button, AutoComplete, Checkbox } from 'antd'; import { Form, Tooltip, Space, Input, Button, AutoComplete, Checkbox, Spin } from 'antd';
import { IoWarningOutline } from 'react-icons/io5'; import { IoWarningOutline } from 'react-icons/io5';
import { import {
getSession, getSession,
@ -53,6 +53,7 @@ import { PurchaseOrderMobilePrint } from './PurchsasePrintStyle/PurchaseOrderMob
import { isMobile } from 'react-device-detect'; import { isMobile } from 'react-device-detect';
import { CiEdit } from 'react-icons/ci'; import { CiEdit } from 'react-icons/ci';
import BarCodeScan from '../../Services/BarCodeScan.jsx'; import BarCodeScan from '../../Services/BarCodeScan.jsx';
import EmailModel from '../BookingScreen/Components/UtillComponents/EmailModel.jsx';
const subDirectory = import.meta.env.BASE_URL; const subDirectory = import.meta.env.BASE_URL;
const stylesMap = { const stylesMap = {
@ -108,6 +109,7 @@ const PurchaseOrder = () => {
const [printTrigger, setPrintTrigger] = useState(false); // <-- add this line const [printTrigger, setPrintTrigger] = useState(false); // <-- add this line
const [isSubmitted, setIsSubmitted] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false);
const [submittedOrderData, setSubmittedOrderData] = useState(null); const [submittedOrderData, setSubmittedOrderData] = useState(null);
const [emailSending, setEmailSending] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [isLowStockModel, setisLowStockModel] = useState(false); const [isLowStockModel, setisLowStockModel] = useState(false);
const [addressModel, setAddressModel] = useState(false); const [addressModel, setAddressModel] = useState(false);
@ -1124,8 +1126,8 @@ const PurchaseOrder = () => {
const handleEmailClick = async (ProductDetails, record) => { const handleEmailClick = async (ProductDetails, record) => {
const toEmail = record?.SuppEmail; const toEmail = record?.SuppEmail;
if (toEmail) { if (toEmail) {
setEmailSending(true); // 👈 Show loader
try { try {
const blob = await pdfDiv('Pur-Order-Print', PurchaseOrderStyle); const blob = await pdfDiv('Pur-Order-Print', PurchaseOrderStyle);
console.log(blob, 'blobblob'); console.log(blob, 'blobblob');
@ -1145,6 +1147,9 @@ const PurchaseOrder = () => {
setMessage({ type: 'error', data: 'Email failed to send' }); setMessage({ type: 'error', data: 'Email failed to send' });
console.error('❌ Email send failed:', error); console.error('❌ Email send failed:', error);
} }
finally {
setEmailSending(false); // 👈 Hide loader (success or error)
}
} else { } else {
setPendingOrderDetails(ProductDetails); setPendingOrderDetails(ProductDetails);
setPendingRecord(record); setPendingRecord(record);
@ -2174,14 +2179,32 @@ const PurchaseOrder = () => {
handleCancel={handleSupplier} handleCancel={handleSupplier}
></DefaultModal> ></DefaultModal>
<DefaultModal {/* <DefaultModal
width={400} width={400}
open={iSEmail} open={iSEmail || emailSending}
title="User Mail" title={emailSending ? null : "User Mail"}
handleCancel={() => setiSEmail(false)} handleCancel={() => !emailSending && setiSEmail(false)} // prevent close during sending
footer={false} footer={false}
closable={!emailSending}
maskClosable={!emailSending}
children={ children={
<div> emailSending ? (
// 👇 Loader view
<div style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "30px",
gap: "16px"
}}>
<Spin size="large" />
<p style={{ margin: 0, fontSize: "16px", color: "#555" }}>
Sending email, please wait...
</p>
</div>
) :
(<div>
<Form <Form
form={form} form={form}
layout="vertical" layout="vertical"
@ -2202,9 +2225,17 @@ const PurchaseOrder = () => {
Submit Submit
</Button> </Button>
</Form> </Form>
</div> </div>)
} }
/> /> */}
{(iSEmail || emailSending )&& (
<EmailModel
open={iSEmail}
emailSending={emailSending}
handleCancel={() => setiSEmail(false)}
form={form}
handleSendEmailWithEnteredEmail={handleSendEmailWithEnteredEmail}
/>)}
<DefaultModal <DefaultModal
width={600} width={600}
open={isLowStockModel} open={isLowStockModel}

View File

@ -1,7 +1,7 @@
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { Button, Form, Input, Table } from "antd"; import { Button, Form, Input, Spin, Table } from "antd";
import { IoEye } from "react-icons/io5"; import { IoEye } from "react-icons/io5";
import { Messages } from "../../Components/Notifications/Messages.jsx"; import { Messages } from "../../Components/Notifications/Messages.jsx";
import { Tables } from "../../Components/Tables/Table.jsx"; import { Tables } from "../../Components/Tables/Table.jsx";
@ -35,6 +35,7 @@ import { SelectedPrintTemplate, GlobalprintDatas, getPrintSelectionComponentData
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import { PurchaseQtMobilePrint } from "../PurchaseQuotation/PurchaseQtMobilePrint.js"; import { PurchaseQtMobilePrint } from "../PurchaseQuotation/PurchaseQtMobilePrint.js";
import { PurchaseOrderMobilePrint } from "./PurchsasePrintStyle/PurchaseOrderMobilePrint.js"; import { PurchaseOrderMobilePrint } from "./PurchsasePrintStyle/PurchaseOrderMobilePrint.js";
import EmailModel from "../BookingScreen/Components/UtillComponents/EmailModel.jsx";
const subDirectory = import.meta.env.BASE_URL; const subDirectory = import.meta.env.BASE_URL;
@ -71,7 +72,7 @@ const PurchaseOrderList = () => {
const [PrintData, setPrintData] = useState([]); const [PrintData, setPrintData] = useState([]);
const [printTrigger, setPrintTrigger] = useState(false); // <-- add this line const [printTrigger, setPrintTrigger] = useState(false); // <-- add this line
const [iSEmail, setiSEmail] = useState(false); const [iSEmail, setiSEmail] = useState(false);
const [enteredEmail, setEnteredEmail] = useState(''); const [emailSending, setEmailSending] = useState(false);
const [pendingOrderDetails, setPendingOrderDetails] = useState(null); const [pendingOrderDetails, setPendingOrderDetails] = useState(null);
const [pendingRecord, setPendingRecord] = useState(null); const [pendingRecord, setPendingRecord] = useState(null);
const printerTemplateStyle = useSelector(SelectedPrintTemplate); const printerTemplateStyle = useSelector(SelectedPrintTemplate);
@ -653,6 +654,7 @@ const PurchaseOrderList = () => {
setPrintData([orderDataEmail]); setPrintData([orderDataEmail]);
if (orderData?.CustMail) { if (orderData?.CustMail) {
setEmailSending(true); // 👈 Show loader
setTimeout(async () => { setTimeout(async () => {
try { try {
const blob = await pdfDiv('Pur-Order-Print', PurchaseOrderStyle); const blob = await pdfDiv('Pur-Order-Print', PurchaseOrderStyle);
@ -664,11 +666,8 @@ const PurchaseOrderList = () => {
type: 'PurchaseOrder', type: 'PurchaseOrder',
messageTemplatesList: [], messageTemplatesList: [],
}; };
const res = await dispatch(Emailsend(payload))?.unwrap(); const res = await dispatch(Emailsend(payload))?.unwrap();
console.log('✅ API Response:', res?.data || res); console.log('✅ API Response:', res?.data || res);
setMessageData('Email sent successfully'); setMessageData('Email sent successfully');
setMessageType('success'); setMessageType('success');
} catch (error) { } catch (error) {
@ -676,6 +675,9 @@ const PurchaseOrderList = () => {
setMessageData('Email failed to send'); setMessageData('Email failed to send');
setMessageType('error'); setMessageType('error');
} }
finally {
setEmailSending(false); // 👈 Hide loader (success or error)
}
}, 300); }, 300);
} else { } else {
setPendingOrderDetails(ProductDetails); setPendingOrderDetails(ProductDetails);
@ -714,8 +716,6 @@ const PurchaseOrderList = () => {
QrCode: item?.QrCode, QrCode: item?.QrCode,
})), })),
})); }));
console.log(formattedData, "formattedDataformattedDataformattedData")
let postDatas = { OrderDetails: [formattedData?.[0]] }; let postDatas = { OrderDetails: [formattedData?.[0]] };
console.log(postDatas, "postDatas") console.log(postDatas, "postDatas")
@ -841,7 +841,7 @@ const PurchaseOrderList = () => {
} }
/> />
<DefaultModal {/* <DefaultModal
width={400} width={400}
open={iSEmail} open={iSEmail}
title="User Mail" title="User Mail"
@ -873,7 +873,15 @@ const PurchaseOrderList = () => {
</Form> </Form>
</div> </div>
} }
/> /> */}
{(iSEmail || emailSending )&& (
<EmailModel
open={iSEmail}
emailSending={emailSending}
handleCancel={() => setiSEmail(false)}
form={form}
handleSendEmailWithEnteredEmail={handleSendEmailWithEnteredEmail}
/>)}
{(() => { {(() => {

View File

@ -61,6 +61,7 @@ import { PrintStyleFunction } from '../paymentpdfPage/PrintStyleFunction.js';
import { isMobile } from 'react-device-detect'; import { isMobile } from 'react-device-detect';
import { PurchaseQtMobilePrint } from './PurchaseQtMobilePrint.js'; import { PurchaseQtMobilePrint } from './PurchaseQtMobilePrint.js';
import BarCodeScan from '../../Services/BarCodeScan.jsx'; import BarCodeScan from '../../Services/BarCodeScan.jsx';
import EmailModel from '../BookingScreen/Components/UtillComponents/EmailModel.jsx';
const SalesQuotationForm = () => { const SalesQuotationForm = () => {
const { SadminuserAccess } = useAuth(); const { SadminuserAccess } = useAuth();
let SAAccessCommonMaster = SadminuserAccess?.find( let SAAccessCommonMaster = SadminuserAccess?.find(
@ -115,6 +116,7 @@ const SalesQuotationForm = () => {
const [usrMailDataModel, setusrMailDataModel] = useState(false); const [usrMailDataModel, setusrMailDataModel] = useState(false);
const [EnteredMailId, setEnteredMailId] = useState(null); const [EnteredMailId, setEnteredMailId] = useState(null);
const [PrintTempData, setPrintTempData] = useState([]); const [PrintTempData, setPrintTempData] = useState([]);
const [emailSending, setEmailSending] = useState(false);
console.log(TableData, 'TableData'); console.log(TableData, 'TableData');
const items = [ const items = [
{ {
@ -128,268 +130,6 @@ const SalesQuotationForm = () => {
}, },
]; ];
// const QuotationStylepdf = `<style>
// * {
// box-sizing: border-box;
// font-family: 'Poppins', sans-serif;
// }
// body {
// margin: 0;
// padding: 0;
// font-size: 12px;
// }
// .Quo-Print-Body {
// padding: 20px;
// width: 100%;
// }
// .Quo-Print-Content {
// border: 1px solid #aaa;
// padding: 16px;
// margin-bottom: 24px;
// page-break-after: always;
// }
// .Quo-print-Logo {
// width: 50px;
// height: 50px;
// margin: 10px;
// }
// .Quo-Print-Header {
// display: flex;
// justify-content: space-between;
// align-items: flex-start;
// }
// .Quo-Print-Company, .Quo-Print-Qno {
// font-size: 12px;
// }
// .Quo-Print-Cname {
// font-size: 16px;
// font-weight: bold;
// }
// .Quo-Print-address {
// font-size: 12px;
// }
// .Horizondal-line {
// border-bottom: 1px solid #aaa;
// margin: 8px 0;
// }
// .Quo-Print-Customer {
// font-size: 12px;
// margin-top: 8px;
// }
// .Quo-Print-Table {
// margin-top: 12px;
// overflow-x: auto;
// }
// .Quo-Print-ProTable {
// width: 100%;
// border-collapse: collapse;
// font-size: 11px;
// table-layout: fixed;
// }
// .Quo-Print-ProTable th,
// .Quo-Print-ProTable td {
// border: 1px solid #aaa;
// padding: 6px;
// word-wrap: break-word;
// }
// .Quo-Print-headingData {
// background-color: #f2f2f2;
// font-weight: bold;
// text-align: center;
// }
// .Quo-Print-TableDataSno,
// .Quo-Print-TableDataName,
// .Quo-Print-TableData,
// .Quo-Print-TableDataAmt {
// text-align: left;
// }
// .Quo-Print-TableDataAmt {
// text-align: right;
// }
// .Quo-Print-Summary {
// margin-top: 16px;
// display: flex;
// justify-content: flex-end;
// }
// .Quo-Print-Total {
// width: 280px;
// border: 1px solid #000;
// padding: 8px;
// font-size: 12px;
// }
// .Quo-Print-Total table {
// width: 100%;
// }
// .Quo-Print-SummTableData {
// text-align: right;
// padding: 4px 6px;
// }
// </style>`;
// const QuotationStyle = `<style>
// .Quo-Print-Body{
// height: 100%;
// margin: 0vw 0vh;
// }
// .page {
// page-break-after: always;
// page-break-inside: avoid;
// }
// .Quo-Print-Content{
// display:flex;
// flex-direction:column;
// height:95vh;
// width:93vw;
// border:0.5px solid rgb(170, 164, 164);
// margin:2rem 1rem 1rem 1rem;
// gap:1.5rem;
// page-break-after: always;
// }
// .Quo-print-Logo{
// width: 50px ;
// height: 50px;
// margin:10px 0 0 10px;
// }
// .Quo-Print-ComCus{
// display:flex;
// flex-direction:column;
// height:18vh;
// justify-content:space-between;
// }
// .Quo-Print-Tabsum{
// display:flex;
// flex-direction:column;
// justify-content:space-between;
// gap:1rem;
// height:60vh;
// }
// .Quo-Print-Header{
// display: flex;
// flex-direction: row;
// justify-content: space-between;
// }
// .Quo-Print-Company{
// display:flex;
// flex-direction:column;
// padding:10px;
// gap:0.1rem;
// }
// .Quo-Print-Cname{
// font-size:25px;
// }
// .Quo-Print-address{
// font-size:22px;
// display:flex;
// flex-wrap:wrap;
// }
// .Quo-Print-Qno{
// display:flex;
// flex-direction:column;
// padding:10px;
// gap:0.1rem;
// }
// .Quo-Print-Customer{
// display:flex;
// flex-direction:Column;
// padding-left:10px;
// gap:0.1rem;
// }
// .Horizondal-line{
// border-bottom: 0.5px solid rgb(170, 164, 164);
// }
// .Quo-Print-Table{
// display:flex;
// }
// .Quo-Print-ProTable{
// width:100%;
// border-collapse: collapse;
// }
// .Quo-Print-DataRow{
// line-height:2rem;
// }
// .Quo-Print-tableheader{
// border-top:0.5px solid rgb(170, 164, 164);
// border-bottom: 0.5px solid rgb(170, 164, 164);
// line-height:4rem;
// }
// .Quo-Print-TableData{
// text-align:right;
// padding:1px;
// font-size:22px;
// }
// .Quo-Print-TableDataSno{
// text-align:center;
// padding:1px;
// font-size:20px;
// }
// .Quo-Print-TableDataName{
// text-align:left;
// padding-left:1px;
// font-size:20px;
// }
// .Quo-Print-headingData{
// text-align:center;
// padding:1px;
// font-size:22px;
// }
// .Quo-Print-TableDataAmt{
// text-align:right;
// padding-right:5px;
// font-size:20px;
// }
// .Quo-Print-Summary{
// display:flex;
// flex-direction:row;
// justify-content: flex-end;
// }
// .Quo-Print-SummTableData{
// text-align:right;
// padding:1px;
// font-size:22px;
// }
// .Quo-Print-Total{
// display:flex;
// justify-content:flex-end;
// border:0.5px solid black;
// width:300px;
// margin-right: 10px;
// font-size:20px;
// }
// }
// </style>`;
const PurchaseOrderStyle = `<style> const PurchaseOrderStyle = `<style>
@media print { @media print {
@page { @page {
@ -1675,6 +1415,7 @@ const SalesQuotationForm = () => {
let record = mail == 'mail' ? data : PrintData?.[0]; let record = mail == 'mail' ? data : PrintData?.[0];
if (record?.Email) { if (record?.Email) {
setEmailSending(true)
setTimeout(async () => { setTimeout(async () => {
try { try {
const blob = await pdfDiv('Pur-Quot-Print', PurchaseOrderStyle); const blob = await pdfDiv('Pur-Quot-Print', PurchaseOrderStyle);
@ -1703,6 +1444,9 @@ const SalesQuotationForm = () => {
setMessageData('Email failed to send'); setMessageData('Email failed to send');
setMessageType('error'); setMessageType('error');
} }
finally{
setEmailSending(false)
}
}, 300); }, 300);
} else { } else {
setusrMailDataModel(true); setusrMailDataModel(true);
@ -1997,33 +1741,15 @@ const SalesQuotationForm = () => {
</div> </div>
)} )}
</div> </div>
<DefaultModal
width={400}
open={usrMailDataModel}
title="User Mail"
handleCancel={handleUserMailmodalCancel}
footer={false}
children={
<div>
<Form form={emailform} layout="vertical" onFinish={emailSubmit}>
<Form.Item
label="Mail ID"
name="email"
rules={[
{ required: true, message: 'Email is required' },
{ type: 'email', message: 'Enter a valid email address' },
]}
>
<Input autoComplete="off" placeholder="Enter your email" />
</Form.Item>
<Button type="primary" htmlType="submit"> {(usrMailDataModel || emailSending )&& (
Submit <EmailModel
</Button> open={usrMailDataModel}
</Form> emailSending={emailSending}
</div> handleCancel={() => setusrMailDataModel(false)}
} form={form}
/> handleSendEmailWithEnteredEmail={emailSubmit}
/>)}
<div style={{ display: 'none' }}> <div style={{ display: 'none' }}>
<PurchaseQuotationPrint <PurchaseQuotationPrint

View File

@ -36,6 +36,7 @@ import { PrintStyleFunction } from '../paymentpdfPage/PrintStyleFunction.js';
import { isMobile } from 'react-device-detect'; import { isMobile } from 'react-device-detect';
import { MobilePdfPrint } from '../BookingScreen/Components/BookingFunctionality/MobilePdfPrint.js'; import { MobilePdfPrint } from '../BookingScreen/Components/BookingFunctionality/MobilePdfPrint.js';
import { PurchaseQtMobilePrint } from './PurchaseQtMobilePrint.js'; import { PurchaseQtMobilePrint } from './PurchaseQtMobilePrint.js';
import EmailModel from '../BookingScreen/Components/UtillComponents/EmailModel.jsx';
const subDirectory = import.meta.env.BASE_URL; const subDirectory = import.meta.env.BASE_URL;
const PurchaseQuotationList = () => { const PurchaseQuotationList = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@ -57,6 +58,7 @@ const PurchaseQuotationList = () => {
const [AllCustomer, setAllCustomer] = useState(null); const [AllCustomer, setAllCustomer] = useState(null);
const [EnteredMailId, setEnteredMailId] = useState(null); const [EnteredMailId, setEnteredMailId] = useState(null);
const [PrintTempData, setPrintTempData] = useState(); const [PrintTempData, setPrintTempData] = useState();
const [emailSending, setEmailSending] = useState(false);
const [form] = Form.useForm(); const [form] = Form.useForm();
@ -698,6 +700,7 @@ const PurchaseQuotationList = () => {
setPrintData([orderData]); setPrintData([orderData]);
if (record?.Email) { if (record?.Email) {
setEmailSending(true);
setTimeout(async () => { setTimeout(async () => {
try { try {
const blob = await pdfDiv('Pur-Quot-Print', PurchaseOrderStyle); const blob = await pdfDiv('Pur-Quot-Print', PurchaseOrderStyle);
@ -726,6 +729,9 @@ const PurchaseQuotationList = () => {
setMessageData('Email failed to send'); setMessageData('Email failed to send');
setMessageType('error'); setMessageType('error');
} }
finally{
setEmailSending(false);
}
}, 300); }, 300);
} else { } else {
setusrMailDataModel(true); setusrMailDataModel(true);
@ -913,7 +919,7 @@ const PurchaseQuotationList = () => {
</div> </div>
} }
/> />
<DefaultModal {/* <DefaultModal
width={400} width={400}
open={usrMailDataModel} open={usrMailDataModel}
title="User Mail" title="User Mail"
@ -942,7 +948,16 @@ const PurchaseQuotationList = () => {
</Form> </Form>
</div> </div>
} }
/> /> */}
{(usrMailDataModel || emailSending )&& (
<EmailModel
open={usrMailDataModel}
emailSending={emailSending}
handleCancel={() => setusrMailDataModel(false)}
form={form}
handleSendEmailWithEnteredEmail={emailSubmit}
/>)}
</div> </div>
</div> </div>
<div> <div>

View File

@ -2,19 +2,21 @@ import { FaEnvelope, FaWhatsapp } from "react-icons/fa";
import { MdSms } from "react-icons/md"; import { MdSms } from "react-icons/md";
import "./PublicQrCodeShare.scss"; import "./PublicQrCodeShare.scss";
import { DefaultModal } from "../../../Components/Modal/DefaultModal"; import { DefaultModal } from "../../../Components/Modal/DefaultModal";
import { useState } from "react"; import { useCallback, useState } from "react";
import { Button, Table } from "antd"; import { Button, Form, Table } from "antd";
import { getSession } from "../../../Services/Others"; import { getSession } from "../../../Services/Others";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { getCustBasedOnCmpIdBrIdAppId } from "../../../Features/CustMaster/CustMaster"; import { getCustBasedOnCmpIdBrIdAppId } from "../../../Features/CustMaster/CustMaster";
import { SelfBookingEmailSendLink } from "../../../Features/ConfigMasterPage/ConfigMasterPage"; import { SelfBookingEmailSendLink } from "../../../Features/ConfigMasterPage/ConfigMasterPage";
import EmailModel from "../../BookingScreen/Components/UtillComponents/EmailModel";
import { Messages } from "../../../Components/Notifications/Messages";
const PublicQrCodeShare = (qrCodeUrl) => { const PublicQrCodeShare = (qrCodeUrl) => {
const URL = qrCodeUrl.qrCodeUrl const URL = qrCodeUrl.qrCodeUrl
const message = `Hello! You can view and confirm your booking using the link below: ${URL} \n\nThank you for choosing us!`; const message = `Hello! You can view and confirm your booking using the link below: ${URL} \n\nThank you for choosing us!`;
const whatsappShareUrl = `https://wa.me/?text=${encodeURIComponent(message)}`; const whatsappShareUrl = `https://wa.me/?text=${encodeURIComponent(message)}`;
const [form] = Form.useForm();
const AppId = getSession("AppId") const AppId = getSession("AppId")
const CompId = getSession('CompId'); const CompId = getSession('CompId');
const BranchId = getSession('BranchId'); const BranchId = getSession('BranchId');
@ -28,6 +30,7 @@ const PublicQrCodeShare = (qrCodeUrl) => {
const [selectedRows, setSelectedRows] = useState([]); const [selectedRows, setSelectedRows] = useState([]);
const [emailModal, setEmailModal] = useState({ open: false }); const [emailModal, setEmailModal] = useState({ open: false });
const [toEmail, setToEmail] = useState(""); const [toEmail, setToEmail] = useState("");
const [emailSending, setEmailSending] = useState(false);
@ -48,19 +51,20 @@ const PublicQrCodeShare = (qrCodeUrl) => {
setMessageData(err); setMessageData(err);
} }
}; };
const SendToEmailLink = async () => { const SendToEmailLink = async (values) => {
if (!toEmail) { const emailTo = values.email
if (!emailTo) {
setMessageType("error"); setMessageType("error");
setMessageData("Please enter a recipient email."); setMessageData("Please enter a recipient email.");
return; return;
} }
const data = { const data = {
toEmail: toEmail, toEmail: emailTo,
type: 'M', type: 'M',
fileUrl: qrCodeUrl.qrCodeUrl, fileUrl: qrCodeUrl.qrCodeUrl,
HeaderType: "SelfBooking" HeaderType: "SelfBooking"
}; };
setEmailSending(true)
try { try {
const res = await dispatch(SelfBookingEmailSendLink(data)).unwrap(); const res = await dispatch(SelfBookingEmailSendLink(data)).unwrap();
setMessageType("success"); setMessageType("success");
@ -71,9 +75,15 @@ const PublicQrCodeShare = (qrCodeUrl) => {
setMessageType("error"); setMessageType("error");
setMessageData("Failed to send email. Please try again."); setMessageData("Failed to send email. Please try again.");
} }
finally {
setEmailSending(false)
}
}; };
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
const columns = [ const columns = [
{ {
title: "S.No", title: "S.No",
@ -95,6 +105,11 @@ const PublicQrCodeShare = (qrCodeUrl) => {
]; ];
return ( return (
<div> <div>
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
<div className="icon-container"> <div className="icon-container">
<MdSms className="share-icon sms-icon" onClick={() => { <MdSms className="share-icon sms-icon" onClick={() => {
fetchCustomer(); fetchCustomer();
@ -171,7 +186,7 @@ const PublicQrCodeShare = (qrCodeUrl) => {
<DefaultModal {/* <DefaultModal
open={emailModal.open} open={emailModal.open}
title="Email Send" title="Email Send"
handleCancel={() => setEmailModal({ open: false })} handleCancel={() => setEmailModal({ open: false })}
@ -191,7 +206,16 @@ const PublicQrCodeShare = (qrCodeUrl) => {
Send Email Send Email
</button> </button>
</div> </div>
</DefaultModal> </DefaultModal> */}
{(emailModal.open || emailSending) && (
<EmailModel
open={emailModal.open}
emailSending={emailSending}
handleCancel={() => setEmailModal({ open: false })}
form={form}
handleSendEmailWithEnteredEmail={SendToEmailLink}
/>)}