2026-01-27 18:27:29 +05:30
|
|
|
|
import { useState, useRef } from 'react';
|
|
|
|
|
|
import { Emailsend } from '../../../../Features/PurchaseOrder/PurchaseOrder';
|
|
|
|
|
|
import {
|
|
|
|
|
|
blobToBase64,
|
|
|
|
|
|
encryptObject,
|
|
|
|
|
|
pdfDiv,
|
|
|
|
|
|
} from '../../../../Services/Others';
|
|
|
|
|
|
import { PrintStyleFunction } from '../../../paymentpdfPage/PrintStyleFunction';
|
|
|
|
|
|
import { PDFDocument } from 'pdf-lib';
|
|
|
|
|
|
import { PublicQrCodepost } from '../../../../Features/ConfigMasterPage/ConfigMasterPage';
|
|
|
|
|
|
import { renderToStaticMarkup } from 'react-dom/server';
|
2026-03-27 16:54:37 +05:30
|
|
|
|
import { downloadFile } from '../../../../utils/downloadFile';
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
|
|
const MainHomeUrl = import.meta.env.ENV_MAIN_BASE_URL;
|
2026-02-16 14:34:29 +05:30
|
|
|
|
const uploadApiUrl = import.meta.env.ENV_IMAGE_UPLOAD_API_URL;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
|
|
// Create a secure blob URL creator that works in all environments
|
|
|
|
|
|
const createSecureBlobUrl = (blob) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
return URL.createObjectURL(blob);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.warn(
|
|
|
|
|
|
'Standard blob URL creation failed, using alternative approach'
|
|
|
|
|
|
);
|
|
|
|
|
|
return window.URL.createObjectURL(blob);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Revoke blob URL safely
|
|
|
|
|
|
const revokeSecureBlobUrl = (url) => {
|
|
|
|
|
|
if (url && url.startsWith('blob:')) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
URL.revokeObjectURL(url);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.warn('Failed to revoke blob URL:', error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Merge multiple pdf blobs into one
|
|
|
|
|
|
const mergePdfBlobs = async (blobs) => {
|
|
|
|
|
|
const mergedPdf = await PDFDocument.create();
|
|
|
|
|
|
|
|
|
|
|
|
for (const blob of blobs) {
|
|
|
|
|
|
const pdfBytes = await blob.arrayBuffer();
|
|
|
|
|
|
const pdf = await PDFDocument.load(pdfBytes);
|
|
|
|
|
|
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
|
|
|
|
|
|
copiedPages.forEach((page) => mergedPdf.addPage(page));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const mergedBytes = await mergedPdf.save();
|
|
|
|
|
|
return new Blob([mergedBytes], { type: 'application/pdf' });
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const MobileMultiPdfPrint = async ({
|
|
|
|
|
|
printerTemplateStyle = 'Style 13',
|
|
|
|
|
|
printDatas = {},
|
|
|
|
|
|
PrintOrderDetails = [],
|
2026-03-27 16:54:37 +05:30
|
|
|
|
setPrintOrderDetails = () => { },
|
2026-01-27 18:27:29 +05:30
|
|
|
|
PrintComing = '',
|
|
|
|
|
|
emailId = '',
|
|
|
|
|
|
dispatch,
|
|
|
|
|
|
UserId = '',
|
2026-03-27 16:54:37 +05:30
|
|
|
|
onProgress = () => { },
|
2026-02-16 14:34:29 +05:30
|
|
|
|
returnBlob = false,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const style = await PrintStyleFunction(printerTemplateStyle, 'Sales');
|
2026-03-23 16:08:11 +05:30
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const stylesMap = {
|
|
|
|
|
|
'Style 1': 'PrintStyle1',
|
|
|
|
|
|
'Style 2': 'PrintStyle2',
|
|
|
|
|
|
'Style 3': 'PrintStyle3',
|
|
|
|
|
|
'Style 4': 'PrintStyle4',
|
|
|
|
|
|
'Style 5': 'PrintStyle5',
|
|
|
|
|
|
'Style 6': 'PrintStyle6',
|
|
|
|
|
|
'Style 7': 'PrintStyle7',
|
|
|
|
|
|
'Style 8': 'PrintStyle8',
|
|
|
|
|
|
'Style 9': 'PrintStyle9',
|
|
|
|
|
|
'Style 10': 'PrintStyle10',
|
|
|
|
|
|
'Style 11': 'PrintStyle11',
|
|
|
|
|
|
'Style 12': 'PrintStyle12',
|
|
|
|
|
|
'Style 13': 'RePrint',
|
|
|
|
|
|
A4: 'PrintStyleA4',
|
|
|
|
|
|
A5: 'PrintStyleA5',
|
|
|
|
|
|
A4Standard: 'A4Standard',
|
|
|
|
|
|
TaxInvoice: 'TaxInvoice',
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const selectedStyle = stylesMap[printerTemplateStyle] || 'RePrint';
|
|
|
|
|
|
const Printsize = printDatas?.PageSize || 'A4';
|
|
|
|
|
|
|
|
|
|
|
|
const totalOrders = PrintOrderDetails.length;
|
|
|
|
|
|
let allBlobs = [];
|
|
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// 🔥 LOOP EACH INVOICE (MAIN FIX)
|
|
|
|
|
|
for (let i = 0; i < totalOrders; i++) {
|
|
|
|
|
|
const element = document.getElementById(
|
|
|
|
|
|
`${selectedStyle}-${i}`
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (!element) {
|
|
|
|
|
|
console.warn('⚠️ Element not found:', `${selectedStyle}-${i}`);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 🔥 TEMP WRAPPER (IMPORTANT)
|
|
|
|
|
|
const wrapper = document.createElement('div');
|
|
|
|
|
|
wrapper.id = `temp-${i}`;
|
|
|
|
|
|
wrapper.style.width = '794px';
|
|
|
|
|
|
wrapper.style.background = '#fff';
|
|
|
|
|
|
|
|
|
|
|
|
wrapper.innerHTML = `
|
|
|
|
|
|
${style}
|
|
|
|
|
|
${element.innerHTML}
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
document.body.appendChild(wrapper);
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
try {
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// 👉 ONE invoice → ONE PDF
|
|
|
|
|
|
const blob = await pdfDiv(wrapper.id);
|
|
|
|
|
|
|
|
|
|
|
|
allBlobs.push(blob);
|
|
|
|
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('PDF error:', err);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}
|
2026-03-23 16:08:11 +05:30
|
|
|
|
|
|
|
|
|
|
document.body.removeChild(wrapper);
|
|
|
|
|
|
|
|
|
|
|
|
// 🔥 Progress update
|
|
|
|
|
|
const progress = Math.round(((i + 1) / totalOrders) * 100);
|
|
|
|
|
|
onProgress(progress);
|
|
|
|
|
|
|
|
|
|
|
|
// 🔥 small delay for stability (important for large data)
|
|
|
|
|
|
await new Promise((r) => setTimeout(r, 5));
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 16:54:37 +05:30
|
|
|
|
// // 🔥 MERGE ALL PDFs
|
|
|
|
|
|
// const combinedPdfBlob = await mergePdfBlobs(allBlobs);
|
|
|
|
|
|
// const base64Pdf = await blobToBase64(combinedPdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
// // 🔥 DOWNLOAD
|
|
|
|
|
|
// if (PrintComing === 'download') {
|
|
|
|
|
|
// const blobUrl = createSecureBlobUrl(combinedPdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
// const link = document.createElement('a');
|
|
|
|
|
|
// link.href = blobUrl;
|
|
|
|
|
|
// link.download = 'Receipts.pdf';
|
|
|
|
|
|
// document.body.appendChild(link);
|
|
|
|
|
|
// link.click();
|
|
|
|
|
|
|
|
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
|
// document.body.removeChild(link);
|
|
|
|
|
|
// revokeSecureBlobUrl(blobUrl);
|
|
|
|
|
|
// }, 100);
|
|
|
|
|
|
// }
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const combinedPdfBlob = await mergePdfBlobs(allBlobs);
|
|
|
|
|
|
const base64Pdf = await blobToBase64(combinedPdfBlob);
|
|
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// 🔥 DOWNLOAD
|
2026-03-27 16:54:37 +05:30
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (PrintComing === 'download') {
|
2026-03-27 16:54:37 +05:30
|
|
|
|
// ✅ Convert Blob → ArrayBuffer for downloadFile
|
|
|
|
|
|
const buffer = await combinedPdfBlob.arrayBuffer();
|
2026-03-23 16:08:11 +05:30
|
|
|
|
|
2026-03-27 16:54:37 +05:30
|
|
|
|
downloadFile(
|
|
|
|
|
|
buffer,
|
|
|
|
|
|
"Receipts.pdf",
|
|
|
|
|
|
"application/pdf",
|
|
|
|
|
|
(success) => {
|
|
|
|
|
|
if (!success) {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-03-27 16:54:37 +05:30
|
|
|
|
console.error('Failed to download the file. Please try again.');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}
|
2026-03-23 16:08:11 +05:30
|
|
|
|
|
|
|
|
|
|
// 🔥 RETURN BLOB
|
2026-02-16 14:34:29 +05:30
|
|
|
|
if (returnBlob && PrintComing === 'download') {
|
|
|
|
|
|
setPrintOrderDetails([]);
|
|
|
|
|
|
return { success: true, pdfBlob: combinedPdfBlob };
|
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// 🔥 WHATSAPP
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (PrintComing === 'whatsapp') {
|
2026-03-23 16:08:11 +05:30
|
|
|
|
const orderIdsArray = PrintOrderDetails.map((row) => row?.OrderId).filter(Boolean);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
if (orderIdsArray.length === 0) return;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
|
|
const encrypted = encryptObject(orderIdsArray);
|
|
|
|
|
|
|
|
|
|
|
|
const postData = {
|
|
|
|
|
|
Url: encrypted,
|
2026-03-23 16:08:11 +05:30
|
|
|
|
CreatedBy: UserId,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await dispatch(PublicQrCodepost(postData)).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
const urlData = res?.data?.ReferenceNo || res?.ReferenceNo;
|
2026-03-23 16:08:11 +05:30
|
|
|
|
if (!urlData) return;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
|
|
const documentUrl = `${MainHomeUrl}viewbill?code=${urlData}`;
|
|
|
|
|
|
|
|
|
|
|
|
const waUrl =
|
|
|
|
|
|
'https://web.whatsapp.com/send?text=' +
|
|
|
|
|
|
encodeURIComponent('Here are your receipts 👉 ' + documentUrl);
|
|
|
|
|
|
|
|
|
|
|
|
window.open(waUrl, '_blank');
|
|
|
|
|
|
} catch (err) {
|
2026-03-23 16:08:11 +05:30
|
|
|
|
console.error('❌ WhatsApp error:', err);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// 🔥 EMAIL
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (PrintComing === 'email') {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const payload = {
|
|
|
|
|
|
fileBlob: combinedPdfBlob,
|
|
|
|
|
|
toEmail: emailId,
|
|
|
|
|
|
type: 'Sales',
|
|
|
|
|
|
messageTemplatesList: [],
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const res = await dispatch(Emailsend(payload))?.unwrap();
|
|
|
|
|
|
return res;
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('❌ Email error:', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// 🔥 PRINT VIEW
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (!['download', 'whatsapp', 'email'].includes(PrintComing)) {
|
|
|
|
|
|
const blobUrl = createSecureBlobUrl(combinedPdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
const newWindow = window.open('', '_blank');
|
|
|
|
|
|
if (newWindow) {
|
|
|
|
|
|
newWindow.document.write(`
|
|
|
|
|
|
<html>
|
2026-03-23 16:08:11 +05:30
|
|
|
|
<body style="margin:0">
|
|
|
|
|
|
<button onclick="window.print()"
|
|
|
|
|
|
style="position:fixed;top:10px;right:10px;">Print</button>
|
|
|
|
|
|
<iframe src="${blobUrl}" style="width:100%;height:100%;border:none"></iframe>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|
|
|
|
|
|
`);
|
|
|
|
|
|
newWindow.document.close();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
window.location.href = blobUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const intentUrl =
|
|
|
|
|
|
'intent://open?' +
|
2026-03-23 16:08:11 +05:30
|
|
|
|
'filename=' + encodeURIComponent('Receipts.pdf') +
|
|
|
|
|
|
'&size=' + combinedPdfBlob.size +
|
2026-01-27 18:27:29 +05:30
|
|
|
|
'&type=application/pdf' +
|
2026-03-23 16:08:11 +05:30
|
|
|
|
'&data=' + encodeURIComponent(base64Pdf) +
|
|
|
|
|
|
'&PrintTypeS=' + encodeURIComponent(Printsize) +
|
2026-01-27 18:27:29 +05:30
|
|
|
|
'#Intent;scheme=pozoprinter;package=com.example.pozoprinter;end';
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
window.location.href = intentUrl;
|
2026-03-27 16:54:37 +05:30
|
|
|
|
} catch { console.log("some errors") }
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}, 500);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// 🔥 CLEANUP
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setPrintOrderDetails([]);
|
|
|
|
|
|
|
|
|
|
|
|
return { success: true, message: 'PDF processed successfully' };
|
2026-03-23 16:08:11 +05:30
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('MobileMultiPdfPrint error:', error);
|
|
|
|
|
|
return { success: false, message: error.message };
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// export const MobileMultiPdfPrint = async ({
|
|
|
|
|
|
// printerTemplateStyle = 'Style 13',
|
|
|
|
|
|
// printDatas = {},
|
|
|
|
|
|
// PrintOrderDetails = [],
|
|
|
|
|
|
// setPrintOrderDetails = () => {},
|
|
|
|
|
|
// PrintComing = '',
|
|
|
|
|
|
// emailId = '',
|
|
|
|
|
|
// dispatch,
|
|
|
|
|
|
// UserId = '',
|
|
|
|
|
|
// onProgress = () => {},
|
|
|
|
|
|
// returnBlob = false,
|
|
|
|
|
|
// }) => {
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// const style = await PrintStyleFunction(printerTemplateStyle, 'Sales');
|
|
|
|
|
|
// const stylesMap = {
|
|
|
|
|
|
// 'Style 1': 'PrintStyle1',
|
|
|
|
|
|
// 'Style 2': 'PrintStyle2',
|
|
|
|
|
|
// 'Style 3': 'PrintStyle3',
|
|
|
|
|
|
// 'Style 4': 'PrintStyle4',
|
|
|
|
|
|
// 'Style 5': 'PrintStyle5',
|
|
|
|
|
|
// 'Style 6': 'PrintStyle6',
|
|
|
|
|
|
// 'Style 7': 'PrintStyle7',
|
|
|
|
|
|
// 'Style 8': 'PrintStyle8',
|
|
|
|
|
|
// 'Style 9': 'PrintStyle9',
|
|
|
|
|
|
// 'Style 10': 'PrintStyle10',
|
|
|
|
|
|
// 'Style 11': 'PrintStyle11',
|
|
|
|
|
|
// 'Style 12': 'PrintStyle12',
|
|
|
|
|
|
// 'Style 13': 'RePrint',
|
|
|
|
|
|
// A4: 'PrintStyleA4',
|
|
|
|
|
|
// A5: 'PrintStyleA5',
|
|
|
|
|
|
// A4Standard: 'A4Standard',
|
|
|
|
|
|
// TaxInvoice: 'TaxInvoice',
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
// const selectedStyle = stylesMap[printerTemplateStyle] || 'RePrint';
|
|
|
|
|
|
// const Printsize = printDatas?.PageSize || 'A4';
|
|
|
|
|
|
|
|
|
|
|
|
// // Create or clear the container
|
|
|
|
|
|
// let container = document.getElementById('print-merged');
|
|
|
|
|
|
// if (!container) {
|
|
|
|
|
|
// container = document.createElement('div');
|
|
|
|
|
|
// container.id = 'print-merged';
|
|
|
|
|
|
// container.style.display = 'none';
|
|
|
|
|
|
// document.body.appendChild(container);
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// container.innerHTML = '';
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // Process in batches for large files
|
|
|
|
|
|
// const BATCH_SIZE = 5;
|
|
|
|
|
|
// const totalOrders = PrintOrderDetails.length;
|
|
|
|
|
|
// let processedOrders = 0;
|
|
|
|
|
|
// let allBlobs = [];
|
|
|
|
|
|
|
|
|
|
|
|
// for (let i = 0; i < totalOrders; i += BATCH_SIZE) {
|
|
|
|
|
|
// const batch = PrintOrderDetails.slice(i, i + BATCH_SIZE);
|
|
|
|
|
|
|
|
|
|
|
|
// // Clear container for each batch
|
|
|
|
|
|
// container.innerHTML = '';
|
|
|
|
|
|
|
|
|
|
|
|
// // Process each order in the current batch
|
|
|
|
|
|
// batch.forEach((_, index) => {
|
|
|
|
|
|
// const globalIndex = i + index;
|
|
|
|
|
|
// const element = document.getElementById(
|
|
|
|
|
|
// `${selectedStyle}-${globalIndex}`
|
|
|
|
|
|
// );
|
|
|
|
|
|
// if (element) {
|
|
|
|
|
|
// const cloned = element.cloneNode(true);
|
|
|
|
|
|
|
|
|
|
|
|
// // Add page break between orders (except the last one)
|
|
|
|
|
|
// if (globalIndex < totalOrders - 1) {
|
|
|
|
|
|
// const pageBreak = document.createElement('div');
|
|
|
|
|
|
// pageBreak.style.pageBreakAfter = 'always';
|
|
|
|
|
|
// container.appendChild(cloned);
|
|
|
|
|
|
// container.appendChild(pageBreak);
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// container.appendChild(cloned);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// console.warn(
|
|
|
|
|
|
// '⚠️ Element not found:',
|
|
|
|
|
|
// `${selectedStyle}-${globalIndex}`
|
|
|
|
|
|
// );
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
// // Generate PDF for this batch
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// const pdfBlob = await pdfDiv('print-merged', style);
|
|
|
|
|
|
// allBlobs.push(pdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
// processedOrders += batch.length;
|
|
|
|
|
|
// const progress = Math.round((processedOrders / totalOrders) * 100);
|
|
|
|
|
|
// onProgress(progress);
|
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
|
// console.error('Error generating PDF batch:', error);
|
|
|
|
|
|
// throw new Error(
|
|
|
|
|
|
// `Failed to generate PDF for batch starting at index ${i}`
|
|
|
|
|
|
// );
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // ✅ Merge all PDF blobs into one
|
|
|
|
|
|
// const combinedPdfBlob = await mergePdfBlobs(allBlobs);
|
|
|
|
|
|
// const base64Pdf = await blobToBase64(combinedPdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
// // Handle different print actions
|
|
|
|
|
|
// if (PrintComing === 'download') {
|
|
|
|
|
|
// const blobUrl = createSecureBlobUrl(combinedPdfBlob);
|
|
|
|
|
|
// const link = document.createElement('a');
|
|
|
|
|
|
// link.href = blobUrl;
|
|
|
|
|
|
// link.download = 'Receipts.pdf';
|
|
|
|
|
|
// document.body.appendChild(link);
|
|
|
|
|
|
// link.click();
|
|
|
|
|
|
|
|
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
|
// document.body.removeChild(link);
|
|
|
|
|
|
// revokeSecureBlobUrl(blobUrl);
|
|
|
|
|
|
// }, 100);
|
|
|
|
|
|
// }
|
2026-03-27 16:54:37 +05:30
|
|
|
|
|
2026-03-23 16:08:11 +05:30
|
|
|
|
// // Return blob if requested (after download completes)
|
|
|
|
|
|
// if (returnBlob && PrintComing === 'download') {
|
|
|
|
|
|
// setPrintOrderDetails([]);
|
|
|
|
|
|
// if (container) {
|
|
|
|
|
|
// document.body.removeChild(container);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// return { success: true, pdfBlob: combinedPdfBlob };
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // if (PrintComing === "whatsapp") {
|
|
|
|
|
|
// // const orderIds = PrintOrderDetails.map((row) => row?.OrderId).filter(Boolean);
|
|
|
|
|
|
// // const documentUrl = `${MainHomeUrl}viewbill?code=${orderIds}`;
|
|
|
|
|
|
// // const waUrl =
|
|
|
|
|
|
// // "https://web.whatsapp.com/send?text=" +
|
|
|
|
|
|
// // encodeURIComponent("Here are your receipts 👉 " + documentUrl);
|
|
|
|
|
|
// // window.open(waUrl, "_blank");
|
|
|
|
|
|
// // }
|
|
|
|
|
|
|
|
|
|
|
|
// if (PrintComing === 'whatsapp') {
|
|
|
|
|
|
// const orderIdsArray = PrintOrderDetails.map((row) => row?.OrderId).filter(
|
|
|
|
|
|
// Boolean
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
|
|
// if (orderIdsArray.length === 0) {
|
|
|
|
|
|
// console.warn('⚠️ No order IDs found for WhatsApp sharing.');
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // 2️⃣ Encrypt order IDs
|
|
|
|
|
|
// const encrypted = encryptObject(orderIdsArray);
|
|
|
|
|
|
|
|
|
|
|
|
// // 3️⃣ Prepare payload for backend
|
|
|
|
|
|
// const postData = {
|
|
|
|
|
|
// Url: encrypted,
|
|
|
|
|
|
// CreatedBy: UserId, // Make sure UserId is passed correctly to your function
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// // 4️⃣ Call backend to get a ReferenceNo
|
|
|
|
|
|
// const res = await dispatch(PublicQrCodepost(postData)).unwrap();
|
|
|
|
|
|
// console.log('Backend response:', res);
|
|
|
|
|
|
|
|
|
|
|
|
// // 5️⃣ Extract ReferenceNo (adjust based on your backend response structure)
|
|
|
|
|
|
// // Example: it might be res.data.ReferenceNo or res.ReferenceNo
|
|
|
|
|
|
// const urlData = res?.data?.ReferenceNo || res?.ReferenceNo;
|
|
|
|
|
|
|
|
|
|
|
|
// if (!urlData) {
|
|
|
|
|
|
// console.error('❌ No ReferenceNo returned from backend');
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // 6️⃣ Build the shareable URL
|
|
|
|
|
|
// const documentUrl = `${MainHomeUrl}viewbill?code=${urlData}`;
|
|
|
|
|
|
|
|
|
|
|
|
// // 7️⃣ Open WhatsApp Web with URL
|
|
|
|
|
|
// const waUrl =
|
|
|
|
|
|
// 'https://web.whatsapp.com/send?text=' +
|
|
|
|
|
|
// encodeURIComponent('Here are your receipts 👉 ' + documentUrl);
|
|
|
|
|
|
|
|
|
|
|
|
// window.open(waUrl, '_blank');
|
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
|
// console.error('❌ WhatsApp sharing failed:', err);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// if (PrintComing === 'email') {
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// const payload = {
|
|
|
|
|
|
// fileBlob: combinedPdfBlob,
|
|
|
|
|
|
// toEmail: emailId,
|
|
|
|
|
|
// type: 'Sales',
|
|
|
|
|
|
// messageTemplatesList: [],
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
// const res = await dispatch(Emailsend(payload))?.unwrap();
|
|
|
|
|
|
// console.log('✅ Email sent response:', res?.data || res);
|
|
|
|
|
|
// return res;
|
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
|
// console.error('❌ Email error:', err);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// if (!['download', 'whatsapp', 'email'].includes(PrintComing)) {
|
|
|
|
|
|
// const blobUrl = createSecureBlobUrl(combinedPdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
// const newWindow = window.open('', '_blank');
|
|
|
|
|
|
// if (newWindow) {
|
|
|
|
|
|
// newWindow.document.write(`
|
|
|
|
|
|
// <html>
|
|
|
|
|
|
// <head>
|
|
|
|
|
|
// <title>Receipts</title>
|
|
|
|
|
|
// <style>
|
|
|
|
|
|
// body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background: #f0f0f0; }
|
|
|
|
|
|
// iframe { width: 100%; height: 100%; border: none; }
|
|
|
|
|
|
// .print-button { position: fixed; top: 20px; right: 20px; z-index: 1000; padding: 10px 15px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }
|
|
|
|
|
|
// </style>
|
|
|
|
|
|
// </head>
|
|
|
|
|
|
// <body>
|
|
|
|
|
|
// <button class="print-button" onclick="window.print()">Print</button>
|
|
|
|
|
|
// <iframe src="${blobUrl}" type="application/pdf"></iframe>
|
|
|
|
|
|
// </body>
|
|
|
|
|
|
// </html>
|
|
|
|
|
|
// `);
|
|
|
|
|
|
// newWindow.document.close();
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// window.location.href = blobUrl;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // For mobile intent URL
|
|
|
|
|
|
// const intentUrl =
|
|
|
|
|
|
// 'intent://open?' +
|
|
|
|
|
|
// 'filename=' +
|
|
|
|
|
|
// encodeURIComponent('Receipts.pdf') +
|
|
|
|
|
|
// '&size=' +
|
|
|
|
|
|
// combinedPdfBlob.size +
|
|
|
|
|
|
// '&type=application/pdf' +
|
|
|
|
|
|
// '&data=' +
|
|
|
|
|
|
// encodeURIComponent(base64Pdf) +
|
|
|
|
|
|
// '&PrintTypeS=' +
|
|
|
|
|
|
// encodeURIComponent(Printsize) +
|
|
|
|
|
|
// '&PrintTypeE' +
|
|
|
|
|
|
// '#Intent;scheme=pozoprinter;package=com.example.pozoprinter;end';
|
|
|
|
|
|
|
|
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// window.location.href = intentUrl;
|
|
|
|
|
|
// } catch (e) {
|
|
|
|
|
|
// console.warn('Could not open intent URL:', e);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }, 500);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // Clean up
|
|
|
|
|
|
// setPrintOrderDetails([]);
|
|
|
|
|
|
// if (container) {
|
|
|
|
|
|
// document.body.removeChild(container);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// return { success: true, message: 'PDF processed successfully' };
|
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
|
// console.error('MobileMultiPdfPrint error:', error);
|
|
|
|
|
|
// return { success: false, message: error.message };
|
|
|
|
|
|
// }
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
// Progress component to show processing status
|
|
|
|
|
|
export const PdfProcessingProgress = ({ progress, isProcessing }) => {
|
|
|
|
|
|
if (!isProcessing) return null;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
position: 'fixed',
|
|
|
|
|
|
top: 0,
|
|
|
|
|
|
left: 0,
|
|
|
|
|
|
right: 0,
|
|
|
|
|
|
bottom: 0,
|
|
|
|
|
|
backgroundColor: 'rgba(0,0,0,0.7)',
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
flexDirection: 'column',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
zIndex: 10999,
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
backgroundColor: 'white',
|
|
|
|
|
|
padding: '20px',
|
|
|
|
|
|
borderRadius: '8px',
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
minWidth: '300px',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<h3>Processing PDFs</h3>
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
backgroundColor: '#f0f0f0',
|
|
|
|
|
|
borderRadius: '4px',
|
|
|
|
|
|
margin: '15px 0',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
width: `${progress}%`,
|
|
|
|
|
|
height: '20px',
|
|
|
|
|
|
backgroundColor: '#4caf50',
|
|
|
|
|
|
borderRadius: '4px',
|
|
|
|
|
|
transition: 'width 0.3s',
|
|
|
|
|
|
}}
|
|
|
|
|
|
></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>{progress}% Complete</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const MobileMultiCreditPdfPrint = async ({
|
|
|
|
|
|
PrintOrderDetails = [],
|
|
|
|
|
|
BSCreditCustomerPrint,
|
|
|
|
|
|
style,
|
|
|
|
|
|
PrintComing = '',
|
|
|
|
|
|
emailId = '',
|
|
|
|
|
|
dispatch,
|
|
|
|
|
|
UserId = '',
|
2026-03-27 16:54:37 +05:30
|
|
|
|
onProgress = () => { },
|
2026-01-27 18:27:29 +05:30
|
|
|
|
BATCH_SIZE = 5,
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
if (!BSCreditCustomerPrint) {
|
|
|
|
|
|
throw new Error('BSCreditCustomerPrint component is required');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Helper: wait for images & fonts in a container
|
|
|
|
|
|
const waitForImagesAndFonts = (container, timeout = 7000) =>
|
|
|
|
|
|
new Promise((resolve) => {
|
|
|
|
|
|
// images
|
|
|
|
|
|
const imgs = Array.from(container.querySelectorAll('img'));
|
|
|
|
|
|
let remaining = imgs.length;
|
|
|
|
|
|
if (remaining === 0) {
|
|
|
|
|
|
// still ensure fonts ready
|
|
|
|
|
|
if (document.fonts && document.fonts.ready) {
|
|
|
|
|
|
document.fonts.ready.then(() => resolve()).catch(() => resolve());
|
|
|
|
|
|
} else resolve();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const timer = setTimeout(() => {
|
|
|
|
|
|
clearTimeout(timer);
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
}, timeout);
|
|
|
|
|
|
imgs.forEach((img) => {
|
|
|
|
|
|
if (img.complete) {
|
|
|
|
|
|
remaining--;
|
|
|
|
|
|
if (remaining === 0) {
|
|
|
|
|
|
clearTimeout(timer);
|
|
|
|
|
|
// fonts:
|
|
|
|
|
|
if (document.fonts && document.fonts.ready) {
|
|
|
|
|
|
document.fonts.ready.then(() => resolve()).catch(() => resolve());
|
|
|
|
|
|
} else resolve();
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
img.addEventListener(
|
|
|
|
|
|
'load',
|
|
|
|
|
|
() => {
|
|
|
|
|
|
remaining--;
|
|
|
|
|
|
if (remaining === 0) {
|
|
|
|
|
|
clearTimeout(timer);
|
|
|
|
|
|
if (document.fonts && document.fonts.ready) {
|
|
|
|
|
|
document.fonts.ready
|
|
|
|
|
|
.then(() => resolve())
|
|
|
|
|
|
.catch(() => resolve());
|
|
|
|
|
|
} else resolve();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{ once: true }
|
|
|
|
|
|
);
|
|
|
|
|
|
img.addEventListener(
|
|
|
|
|
|
'error',
|
|
|
|
|
|
() => {
|
|
|
|
|
|
remaining--;
|
|
|
|
|
|
if (remaining === 0) {
|
|
|
|
|
|
clearTimeout(timer);
|
|
|
|
|
|
if (document.fonts && document.fonts.ready) {
|
|
|
|
|
|
document.fonts.ready
|
|
|
|
|
|
.then(() => resolve())
|
|
|
|
|
|
.catch(() => resolve());
|
|
|
|
|
|
} else resolve();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{ once: true }
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Fallback mergePdfBlobs using pdf-lib (client-side)
|
|
|
|
|
|
const mergePdfBlobsFallback = async (blobs) => {
|
|
|
|
|
|
if (!blobs || blobs.length === 0) {
|
|
|
|
|
|
return new Blob([], { type: 'application/pdf' });
|
|
|
|
|
|
}
|
|
|
|
|
|
if (blobs.length === 1) return blobs[0];
|
|
|
|
|
|
|
|
|
|
|
|
const mergedPdf = await PDFDocument.create();
|
|
|
|
|
|
for (const blob of blobs) {
|
|
|
|
|
|
const arrayBuffer = await blob.arrayBuffer();
|
|
|
|
|
|
const donorPdf = await PDFDocument.load(arrayBuffer);
|
|
|
|
|
|
const copiedPages = await mergedPdf.copyPages(
|
|
|
|
|
|
donorPdf,
|
|
|
|
|
|
donorPdf.getPageIndices()
|
|
|
|
|
|
);
|
|
|
|
|
|
copiedPages.forEach((p) => mergedPdf.addPage(p));
|
|
|
|
|
|
}
|
|
|
|
|
|
const mergedBytes = await mergedPdf.save();
|
|
|
|
|
|
return new Blob([mergedBytes], { type: 'application/pdf' });
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const blobToBase64 = (blob) =>
|
|
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
|
reader.onloadend = () => resolve(reader.result.split(',')[1]); // base64 without prefix
|
|
|
|
|
|
reader.onerror = reject;
|
|
|
|
|
|
reader.readAsDataURL(blob);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// create container or ensure empty
|
|
|
|
|
|
let printRootContainer = document.getElementById('print-merged-react');
|
|
|
|
|
|
if (printRootContainer) {
|
|
|
|
|
|
printRootContainer.innerHTML = '';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
printRootContainer = document.createElement('div');
|
|
|
|
|
|
printRootContainer.id = 'print-merged-react';
|
|
|
|
|
|
printRootContainer.style.display = 'none';
|
|
|
|
|
|
document.body.appendChild(printRootContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const total = PrintOrderDetails.length;
|
|
|
|
|
|
let allBlobs = [];
|
|
|
|
|
|
let processedVisible = 0;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
for (let i = 0; i < total; i += BATCH_SIZE) {
|
|
|
|
|
|
const batch = PrintOrderDetails.slice(i, i + BATCH_SIZE);
|
|
|
|
|
|
|
|
|
|
|
|
// clear container for each batch
|
|
|
|
|
|
printRootContainer.innerHTML = '';
|
|
|
|
|
|
|
|
|
|
|
|
// Render each BSCreditCustomerPrint into its own div
|
|
|
|
|
|
const roots = [];
|
|
|
|
|
|
for (let idx = 0; idx < batch.length; idx++) {
|
|
|
|
|
|
const globalIndex = i + idx;
|
|
|
|
|
|
|
|
|
|
|
|
const wrapper = document.createElement('div');
|
|
|
|
|
|
wrapper.id = `Credit-customer-${globalIndex}`;
|
|
|
|
|
|
|
|
|
|
|
|
const html = renderToStaticMarkup(
|
|
|
|
|
|
<BSCreditCustomerPrint PrintDatas={batch[idx]} />
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
wrapper.innerHTML = html;
|
|
|
|
|
|
|
|
|
|
|
|
printRootContainer.appendChild(wrapper);
|
|
|
|
|
|
|
|
|
|
|
|
// add page break if needed
|
|
|
|
|
|
if (globalIndex < total - 1) {
|
|
|
|
|
|
const pb = document.createElement('div');
|
|
|
|
|
|
pb.style.pageBreakAfter = 'always';
|
|
|
|
|
|
printRootContainer.appendChild(pb);
|
|
|
|
|
|
}
|
|
|
|
|
|
roots.push(printRootContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await new Promise((res) => setTimeout(res, 120)); // small tick
|
|
|
|
|
|
|
|
|
|
|
|
await waitForImagesAndFonts(printRootContainer, 8000);
|
|
|
|
|
|
|
|
|
|
|
|
const batchContainerId = `print-merged-batch-${i}`;
|
|
|
|
|
|
let batchContainer = document.getElementById(batchContainerId);
|
|
|
|
|
|
if (!batchContainer) {
|
|
|
|
|
|
batchContainer = document.createElement('div');
|
|
|
|
|
|
batchContainer.id = batchContainerId;
|
|
|
|
|
|
batchContainer.style.display = 'none';
|
|
|
|
|
|
document.body.appendChild(batchContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
batchContainer.innerHTML = `${style}${printRootContainer.innerHTML}`;
|
|
|
|
|
|
|
|
|
|
|
|
const pdfBlob = await pdfDiv(batchContainerId, style);
|
|
|
|
|
|
allBlobs.push(pdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
roots.forEach((r) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
r.unmount();
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
// ignore
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// cleanup batch container
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (batchContainer && batchContainer.parentElement) {
|
|
|
|
|
|
batchContainer.parentElement.removeChild(batchContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
/* ignore */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// progress
|
|
|
|
|
|
processedVisible += batch.length;
|
|
|
|
|
|
onProgress(Math.round((processedVisible / total) * 100));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 16:54:37 +05:30
|
|
|
|
// // merge blobs - use existing merge function if available, otherwise fallback
|
|
|
|
|
|
// const combinedPdfBlob =
|
|
|
|
|
|
// typeof mergePdfBlobs === 'function'
|
|
|
|
|
|
// ? await mergePdfBlobs(allBlobs)
|
|
|
|
|
|
// : await mergePdfBlobsFallback(allBlobs);
|
|
|
|
|
|
|
|
|
|
|
|
// const base64Pdf = await blobToBase64(combinedPdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
// // Action handlers
|
|
|
|
|
|
// if (PrintComing === 'download') {
|
|
|
|
|
|
// const blobUrl =
|
|
|
|
|
|
// typeof createSecureBlobUrl === 'function'
|
|
|
|
|
|
// ? createSecureBlobUrl(combinedPdfBlob)
|
|
|
|
|
|
// : URL.createObjectURL(combinedPdfBlob);
|
|
|
|
|
|
// const link = document.createElement('a');
|
|
|
|
|
|
// link.href = blobUrl;
|
|
|
|
|
|
// link.download = 'Receipts.pdf';
|
|
|
|
|
|
// document.body.appendChild(link);
|
|
|
|
|
|
// link.click();
|
|
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
|
// document.body.removeChild(link);
|
|
|
|
|
|
// if (typeof revokeSecureBlobUrl === 'function')
|
|
|
|
|
|
// revokeSecureBlobUrl(blobUrl);
|
|
|
|
|
|
// else URL.revokeObjectURL(blobUrl);
|
|
|
|
|
|
// }, 300);
|
|
|
|
|
|
// return { success: true };
|
|
|
|
|
|
// }
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const combinedPdfBlob =
|
|
|
|
|
|
typeof mergePdfBlobs === 'function'
|
|
|
|
|
|
? await mergePdfBlobs(allBlobs)
|
|
|
|
|
|
: await mergePdfBlobsFallback(allBlobs);
|
|
|
|
|
|
|
|
|
|
|
|
const base64Pdf = await blobToBase64(combinedPdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
// Action handlers
|
|
|
|
|
|
if (PrintComing === 'download') {
|
2026-03-27 16:54:37 +05:30
|
|
|
|
// ✅ Convert Blob → ArrayBuffer for downloadFile
|
|
|
|
|
|
const buffer = await combinedPdfBlob.arrayBuffer();
|
|
|
|
|
|
|
|
|
|
|
|
downloadFile(
|
|
|
|
|
|
buffer,
|
|
|
|
|
|
"Receipts.pdf",
|
|
|
|
|
|
"application/pdf",
|
|
|
|
|
|
(success) => {
|
|
|
|
|
|
if (!success) {
|
|
|
|
|
|
console.error('Failed to download the file. Please try again.');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
return { success: true };
|
|
|
|
|
|
}
|
|
|
|
|
|
if (PrintComing === 'whatsapp') {
|
|
|
|
|
|
const orderIdsArray = PrintOrderDetails.map((r) => r?.receiptNo).filter(
|
|
|
|
|
|
Boolean
|
|
|
|
|
|
);
|
|
|
|
|
|
if (orderIdsArray.length === 0) {
|
|
|
|
|
|
console.warn('No order ids for whatsapp');
|
|
|
|
|
|
return { success: false, message: 'No orders' };
|
|
|
|
|
|
}
|
|
|
|
|
|
const encrypted = encryptObject(orderIdsArray);
|
|
|
|
|
|
const postData = { Url: encrypted, CreatedBy: UserId };
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await dispatch(PublicQrCodepost(postData)).unwrap();
|
|
|
|
|
|
const urlData = res?.data?.ReferenceNo || res?.ReferenceNo;
|
|
|
|
|
|
if (!urlData) throw new Error('No ReferenceNo from backend');
|
|
|
|
|
|
const documentUrl = `${MainHomeUrl}viewbill?code=${urlData}`;
|
|
|
|
|
|
const waUrl =
|
|
|
|
|
|
'https://web.whatsapp.com/send?text=' +
|
|
|
|
|
|
encodeURIComponent('Here are your receipts 👉 ' + documentUrl);
|
|
|
|
|
|
window.open(waUrl, '_blank');
|
|
|
|
|
|
return { success: true };
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('WhatsApp sharing failed', err);
|
|
|
|
|
|
return { success: false, message: err?.message || String(err) };
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (PrintComing === 'email') {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const payload = {
|
|
|
|
|
|
fileBlob: combinedPdfBlob,
|
|
|
|
|
|
toEmail: emailId,
|
|
|
|
|
|
type: 'CreditReceipt',
|
|
|
|
|
|
messageTemplatesList: [],
|
|
|
|
|
|
};
|
|
|
|
|
|
const res = await dispatch(Emailsend(payload)).unwrap();
|
|
|
|
|
|
return { success: true, data: res };
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('Email send failed', err);
|
|
|
|
|
|
return { success: false, message: err?.message || String(err) };
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// default: open viewer tab and attempt mobile intent
|
|
|
|
|
|
const blobUrl =
|
|
|
|
|
|
typeof createSecureBlobUrl === 'function'
|
|
|
|
|
|
? createSecureBlobUrl(combinedPdfBlob)
|
|
|
|
|
|
: URL.createObjectURL(combinedPdfBlob);
|
|
|
|
|
|
|
|
|
|
|
|
const newWindow = window.open('', '_blank');
|
|
|
|
|
|
if (newWindow) {
|
|
|
|
|
|
newWindow.document.write(`
|
|
|
|
|
|
<html>
|
|
|
|
|
|
<head><title>Receipts</title>
|
|
|
|
|
|
<style>
|
|
|
|
|
|
body{margin:0;background:#f0f0f0;height:100vh;display:flex;align-items:center;justify-content:center}
|
|
|
|
|
|
iframe{width:100%;height:100%;border:none}
|
|
|
|
|
|
.print-button{position:fixed;top:16px;right:16px;padding:10px 14px;background:#4CAF50;color:white;border:none;border-radius:6px;cursor:pointer;z-index:9999}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<button class="print-button" onclick="window.print()">Print</button>
|
|
|
|
|
|
<iframe src="${blobUrl}" type="application/pdf"></iframe>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|
|
|
|
|
|
`);
|
|
|
|
|
|
newWindow.document.close();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
window.location.href = blobUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// mobile intent (optional)
|
|
|
|
|
|
const intentUrl =
|
|
|
|
|
|
'intent://open?' +
|
|
|
|
|
|
'filename=' +
|
|
|
|
|
|
encodeURIComponent('Receipts.pdf') +
|
|
|
|
|
|
'&size=' +
|
|
|
|
|
|
combinedPdfBlob.size +
|
|
|
|
|
|
'&type=application/pdf' +
|
|
|
|
|
|
'&data=' +
|
|
|
|
|
|
encodeURIComponent(base64Pdf) +
|
|
|
|
|
|
'#Intent;scheme=pozoprinter;package=com.example.pozoprinter;end';
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
window.location.href = intentUrl;
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
/* ignore */
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
/* ignore */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return { success: true };
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('MobileMultiCreditPdfPrint error:', err);
|
|
|
|
|
|
return { success: false, message: err?.message || String(err) };
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
// final cleanup
|
|
|
|
|
|
try {
|
|
|
|
|
|
// remove printRootContainer and any leftover child batch containers
|
|
|
|
|
|
const root = document.getElementById('print-merged-react');
|
|
|
|
|
|
if (root && root.parentElement) root.parentElement.removeChild(root);
|
|
|
|
|
|
|
|
|
|
|
|
// remove any batch containers (ids starting with print-merged-batch-)
|
|
|
|
|
|
Array.from(
|
|
|
|
|
|
document.querySelectorAll("[id^='print-merged-batch-']")
|
|
|
|
|
|
).forEach((el) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
el.parentElement.removeChild(el);
|
2026-03-27 16:54:37 +05:30
|
|
|
|
} catch (e) { }
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.warn('Cleanup error', e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|