2026-01-27 18:27:29 +05:30
|
|
|
// InvoiceDetail.jsx
|
|
|
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
|
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
|
|
|
import moment from 'moment';
|
|
|
|
|
import {
|
|
|
|
|
dateFormatChange1,
|
|
|
|
|
decryptToObject,
|
|
|
|
|
encryptObject,
|
|
|
|
|
extractLastNumber,
|
|
|
|
|
extractLastNumberOrderId,
|
|
|
|
|
getSession,
|
|
|
|
|
sessionStore,
|
|
|
|
|
} from '../../Services/Others';
|
|
|
|
|
import { ApplicationPreferences, getBranchDetail, getCommonAppPreference } from '../../Features/BrachLogin/BranchLogin';
|
|
|
|
|
import PrintStyle1 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle1';
|
|
|
|
|
import PrintStyle2 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle2';
|
|
|
|
|
import PrintStyle3 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle3';
|
|
|
|
|
import PrintStyle4 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle4';
|
|
|
|
|
import PrintStyle5 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle5';
|
|
|
|
|
import PrintStyle6 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle6';
|
|
|
|
|
import PrintStyle7 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle7';
|
|
|
|
|
import PrintStyle8 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle8';
|
|
|
|
|
import PrintStyle9 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle9';
|
|
|
|
|
import PrintStyle10 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle10';
|
|
|
|
|
import PrintStyle11 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle11';
|
|
|
|
|
import PrintStyle12 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle12';
|
|
|
|
|
import {
|
|
|
|
|
getPrintSelectionComponentData,
|
|
|
|
|
GloabalFieldDetails,
|
|
|
|
|
GlobalPricingAppPricingName,
|
|
|
|
|
GlobalprintDatas,
|
|
|
|
|
PricingAppPricingNameData,
|
|
|
|
|
SelectedPrintTemplate,
|
|
|
|
|
} from '../../Features/ThemeChange/ThemeChange';
|
|
|
|
|
import {
|
|
|
|
|
getPreferenceData,
|
|
|
|
|
PaymentGatewayGetdetail,
|
|
|
|
|
} from '../../Features/BookingScreen/BookingData/BookingData';
|
|
|
|
|
import axios from 'axios';
|
|
|
|
|
import { FiDownload, FiChevronLeft, FiChevronRight } from 'react-icons/fi';
|
|
|
|
|
import './PaymentPdfBooking.scss';
|
|
|
|
|
import TaxInvoice from '../BookingScreen/PrintTemplates/A4/TaxInvoice';
|
|
|
|
|
import A4Standard from '../PurchaseReturn/PrintReturn/A4purchaseReturn/A4Standard';
|
|
|
|
|
import { PublicQrCodeget, PublicQrCodepost } from '../../Features/ConfigMasterPage/ConfigMasterPage';
|
|
|
|
|
import PrintStyle13 from '../BookingScreen/PrintTemplates/ThermalPrinter/PrintStyle13';
|
|
|
|
|
import PrintA5Style11 from '../BookingScreen/PrintTemplates/A4/PrintStyleA5';
|
|
|
|
|
import InvoiceTemplate from '../BookingScreen/PrintTemplates/A4/A4Standard';
|
|
|
|
|
import PrintA4Style11 from '../BookingScreen/PrintTemplates/A4/PrintA4Style11';
|
2026-03-24 12:45:51 +05:30
|
|
|
import html2canvas from "html2canvas";
|
|
|
|
|
import jsPDF from "jspdf";
|
2026-01-27 18:27:29 +05:30
|
|
|
const apiUrlToken = import.meta.env.ENV_API_URL_TOKEN;
|
|
|
|
|
|
|
|
|
|
const LinkUrlCreate = () => {
|
|
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
const CreatedDate = '2023-10-01T12:00:00Z';
|
|
|
|
|
const printRef = useRef();
|
|
|
|
|
const containerRef = useRef();
|
|
|
|
|
const [currentPage, setCurrentPage] = useState(0);
|
|
|
|
|
const url_string = window.location.href;
|
|
|
|
|
const url = new URL(url_string);
|
|
|
|
|
const [PrintOrderDetails, setPrintOrderDetails] = useState([]);
|
|
|
|
|
const [printerTemplateStyle, setPrintSettingData] = useState('');
|
|
|
|
|
const [Preference, setPreferenceData] = useState([]);
|
|
|
|
|
const [base64Image, setBase64Image] = useState(null);
|
|
|
|
|
const [conversionError, setConversionError] = useState(null);
|
|
|
|
|
const [allData, setAllData] = useState(null);
|
|
|
|
|
const [table2Data, setTable2Data] = useState({});
|
|
|
|
|
const [branchDetails, setBranchDetails] = useState({});
|
|
|
|
|
const [ProdId, setProdId] = useState([]);
|
|
|
|
|
const [isDataLoading, setIsDataLoading] = useState(true);
|
|
|
|
|
const [allDataLoaded, setAllDataLoaded] = useState(false);
|
|
|
|
|
|
|
|
|
|
const codesParam = url.searchParams.get('code');
|
|
|
|
|
|
|
|
|
|
// Global selectors
|
|
|
|
|
const FieldDetails = useSelector(GloabalFieldDetails);
|
|
|
|
|
const pricingAppName = useSelector(GlobalPricingAppPricingName);
|
|
|
|
|
const printTemplate = useSelector(SelectedPrintTemplate); // This should get the PrintTemplate from global state
|
|
|
|
|
const globalPrintDatas = useSelector(GlobalprintDatas); // This should get printDatas from global state
|
|
|
|
|
const appPreferences = useSelector(ApplicationPreferences);
|
|
|
|
|
|
|
|
|
|
const commonModulePreference = appPreferences?.find(
|
|
|
|
|
(preference) => preference?.PreferredCatName === "Common Module"
|
|
|
|
|
)?.PreferenceCatDetails;
|
|
|
|
|
const sportsAppPreference = commonModulePreference?.find(
|
|
|
|
|
(preference) => preference?.PreferredSubCatName === "SportsApp" && preference?.PreferredStatus === "Y"
|
|
|
|
|
);
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
initializeData();
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const initializeData = async () => {
|
|
|
|
|
try {
|
|
|
|
|
setIsDataLoading(true);
|
|
|
|
|
setAllDataLoaded(false);
|
|
|
|
|
await addSession();
|
|
|
|
|
await getQrCode();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error initializing data:', error);
|
|
|
|
|
setIsDataLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getQrCode = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const getQrCodedata = await dispatch(PublicQrCodeget(codesParam)).unwrap();
|
|
|
|
|
const oldUrl = getQrCodedata.data.data?.[0]?.OldUrl;
|
|
|
|
|
const decrypted = decryptToObject(oldUrl);
|
|
|
|
|
|
|
|
|
|
// Normalize decrypted value into an array of OrderIds
|
|
|
|
|
let orderIds = [];
|
|
|
|
|
if (Array.isArray(decrypted)) {
|
|
|
|
|
orderIds = decrypted.map((v) => String(v).trim()).filter(Boolean);
|
|
|
|
|
} else if (typeof decrypted === 'string') {
|
|
|
|
|
orderIds = decrypted.split(',').map((v) => v.trim()).filter(Boolean);
|
|
|
|
|
} else if (decrypted && typeof decrypted === 'object') {
|
|
|
|
|
const possible = decrypted.OrderId || decrypted.orderId || decrypted.code || decrypted.id;
|
|
|
|
|
if (possible) orderIds = [String(possible).trim()];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setProdId(orderIds);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error getting QR code:', error);
|
|
|
|
|
setIsDataLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const addSession = async () => {
|
2026-03-24 12:45:51 +05:30
|
|
|
if (!getSession('auth')) {
|
2026-01-27 18:27:29 +05:30
|
|
|
try {
|
|
|
|
|
let data = {
|
|
|
|
|
username: '1000000001',
|
|
|
|
|
password: '1234',
|
|
|
|
|
};
|
|
|
|
|
const response = await axios.post(
|
|
|
|
|
`${apiUrlToken}/jwtTokenGenerator`,
|
|
|
|
|
data,
|
|
|
|
|
{
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
Accept: 'application/json',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const { token } = response?.data;
|
2026-03-24 12:45:51 +05:30
|
|
|
sessionStore('auth', token);
|
2026-01-27 18:27:29 +05:30
|
|
|
sessionStore('LoginType', 'Kiosk');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error adding session:', error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Fetch API data when ProdId is available
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (Array.isArray(ProdId) && ProdId.length > 0) {
|
|
|
|
|
fetchApiData(ProdId);
|
|
|
|
|
}
|
|
|
|
|
}, [ProdId]);
|
|
|
|
|
|
|
|
|
|
const fetchApiData = async (orderIds = []) => {
|
|
|
|
|
try {
|
|
|
|
|
const promises = orderIds.map((orderId) =>
|
|
|
|
|
dispatch(PaymentGatewayGetdetail(orderId))
|
|
|
|
|
.unwrap()
|
|
|
|
|
.then((response) => response?.data?.data?.[0] || null)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const results = await Promise.all(promises);
|
|
|
|
|
const validResults = results.filter(Boolean);
|
|
|
|
|
|
|
|
|
|
setPrintOrderDetails(validResults);
|
|
|
|
|
if (validResults.length > 0) {
|
|
|
|
|
await loadAllRequiredData(validResults[0]);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error fetching bill details:", error);
|
|
|
|
|
setIsDataLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const loadAllRequiredData = async (firstInvoice) => {
|
|
|
|
|
try {
|
2026-03-17 11:32:45 +05:30
|
|
|
const { AppId, CompId, BranchId,UserId } = firstInvoice;
|
2026-01-27 18:27:29 +05:30
|
|
|
const pricingData = {
|
|
|
|
|
appId: AppId,
|
|
|
|
|
compId: CompId,
|
|
|
|
|
branchId: BranchId,
|
2026-03-17 11:32:45 +05:30
|
|
|
UserId : UserId
|
2026-01-27 18:27:29 +05:30
|
|
|
};
|
2026-03-17 11:32:45 +05:30
|
|
|
const printData = { AppId, CompId, BranchId, UserId };
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
// Step 1: Call PricingAppPricingName to update global state
|
|
|
|
|
console.log("Step 1: Calling PricingAppPricingNameData...");
|
|
|
|
|
const pricingRes = await dispatch(PricingAppPricingNameData(pricingData)).unwrap();
|
|
|
|
|
console.log(pricingRes, "PricingAppPricingName response");
|
|
|
|
|
const commonapppreference = await dispatch(getCommonAppPreference({ appId: AppId})).unwrap();
|
|
|
|
|
// Step 2: Call getPrintSelectionComponentData to update global state with print template
|
|
|
|
|
console.log("Step 2: Calling getPrintSelectionComponentData...");
|
|
|
|
|
const printSettings = await dispatch(getPrintSelectionComponentData(printData)).unwrap();
|
|
|
|
|
console.log(printSettings,commonapppreference, "getPrintSelectionComponentData response");
|
|
|
|
|
|
|
|
|
|
// Step 3: Call getPreferenceData
|
|
|
|
|
console.log("Step 3: Calling getPreferenceData...");
|
|
|
|
|
const preferences = await dispatch(getPreferenceData(printData)).unwrap();
|
|
|
|
|
setPreferenceData(preferences?.data);
|
|
|
|
|
|
|
|
|
|
// Step 4: Fetch branch details
|
|
|
|
|
console.log("Step 4: Fetching branch details...");
|
|
|
|
|
const branchIds = [...new Set([BranchId])]; // Start with current branch
|
|
|
|
|
await Promise.all(branchIds.map(branchId => fetchBranchData(branchId)));
|
|
|
|
|
|
|
|
|
|
// All data loaded successfully
|
|
|
|
|
console.log("All data loaded successfully");
|
|
|
|
|
setAllDataLoaded(true);
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error loading required data:', error);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsDataLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Handle additional branch details after PrintOrderDetails is set
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (PrintOrderDetails?.length > 0 && allDataLoaded) {
|
|
|
|
|
// Get any additional unique branch IDs from all invoices
|
|
|
|
|
const allBranchIds = [...new Set(PrintOrderDetails.map(invoice => invoice.BranchId))];
|
|
|
|
|
const currentBranchIds = Object.keys(branchDetails);
|
|
|
|
|
const newBranchIds = allBranchIds.filter(id => !currentBranchIds.includes(String(id)));
|
|
|
|
|
|
|
|
|
|
// Fetch details for any new branches
|
|
|
|
|
newBranchIds.forEach(branchId => {
|
|
|
|
|
if (branchId) {
|
|
|
|
|
fetchBranchData(branchId);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}, [PrintOrderDetails, allDataLoaded]);
|
|
|
|
|
|
|
|
|
|
const fetchBranchData = async (BranchId) => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await dispatch(
|
|
|
|
|
getBranchDetail({ BrId: BranchId })
|
|
|
|
|
).unwrap();
|
|
|
|
|
if (response?.data?.statusCode === 1) {
|
|
|
|
|
setBranchDetails(prev => ({
|
|
|
|
|
...prev,
|
|
|
|
|
[BranchId]: {
|
|
|
|
|
address: response?.data?.data?.[0]?.Address1,
|
|
|
|
|
city: response?.data?.data?.[0]?.City,
|
|
|
|
|
zip: response?.data?.data?.[0]?.Zip,
|
|
|
|
|
logo: response?.data?.data?.[0]?.CompLogo
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error fetching branch data:', error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const imageUrlToBase64 = async (url) => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch(url);
|
|
|
|
|
const blob = await response.blob();
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
reader.onloadend = () => resolve(reader.result);
|
|
|
|
|
reader.onerror = reject;
|
|
|
|
|
reader.readAsDataURL(blob);
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error fetching or converting image:', error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Convert logos to base64
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
async function convertLogos() {
|
|
|
|
|
const newBase64Images = {};
|
|
|
|
|
|
|
|
|
|
for (const [branchId, details] of Object.entries(branchDetails)) {
|
|
|
|
|
if (details.logo) {
|
|
|
|
|
try {
|
|
|
|
|
const base64 = await imageUrlToBase64(details.logo);
|
|
|
|
|
newBase64Images[branchId] = base64;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(`Error converting image for branch ${branchId}:`, error);
|
|
|
|
|
newBase64Images[branchId] = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setBase64Image(newBase64Images);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Object.keys(branchDetails).length > 0) {
|
|
|
|
|
convertLogos();
|
|
|
|
|
}
|
|
|
|
|
}, [branchDetails]);
|
|
|
|
|
|
|
|
|
|
const CashierName = PrintOrderDetails?.[0]?.CashierName || null;
|
|
|
|
|
|
|
|
|
|
// const handleDownloadPDF = () => {
|
|
|
|
|
// html2pdf().from(printRef.current).save();
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
2026-03-24 12:45:51 +05:30
|
|
|
// const handleDownloadPDF = () => {
|
|
|
|
|
// const element = printRef.current;
|
|
|
|
|
// const options = {
|
|
|
|
|
// // margin: 0.5,
|
|
|
|
|
// margin: 0,
|
|
|
|
|
// filename: "document.pdf",
|
|
|
|
|
// image: { type: "jpeg", quality: 0.98 },
|
|
|
|
|
// html2canvas: { scale: 2, useCORS: true }, // makes CSS + images sharper
|
|
|
|
|
// // jsPDF: { unit: "in", format: "a4", orientation: "portrait" },
|
|
|
|
|
// jsPDF: { unit: "px", format: [element.offsetWidth, element.offsetHeight] },
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// html2pdf().set(options).from(element).save();
|
|
|
|
|
// };
|
|
|
|
|
const handleDownloadPDF = async () => {
|
|
|
|
|
const element = printRef.current;
|
|
|
|
|
|
|
|
|
|
const canvas = await html2canvas(element, {
|
|
|
|
|
scale: 2,
|
|
|
|
|
useCORS: true
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const imgData = canvas.toDataURL("image/jpeg", 0.98);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
2026-03-24 12:45:51 +05:30
|
|
|
const pdf = new jsPDF({
|
|
|
|
|
unit: "px",
|
|
|
|
|
format: [canvas.width, canvas.height],
|
|
|
|
|
});
|
2026-01-27 18:27:29 +05:30
|
|
|
|
2026-03-24 12:45:51 +05:30
|
|
|
pdf.addImage(imgData, "JPEG", 0, 0, canvas.width, canvas.height);
|
|
|
|
|
pdf.save("document.pdf");
|
|
|
|
|
};
|
2026-01-27 18:27:29 +05:30
|
|
|
const scrollToPage = (pageIndex) => {
|
|
|
|
|
const pages = containerRef.current?.children;
|
|
|
|
|
if (pages && pages[pageIndex]) {
|
|
|
|
|
pages[pageIndex].scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
|
|
|
setCurrentPage(pageIndex);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleNextPage = () => {
|
|
|
|
|
if (currentPage < PrintOrderDetails.length - 1) {
|
|
|
|
|
scrollToPage(currentPage + 1);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handlePrevPage = () => {
|
|
|
|
|
if (currentPage > 0) {
|
|
|
|
|
scrollToPage(currentPage - 1);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Get preference data
|
|
|
|
|
let SalesModePref = Preference?.[0]?.SettingDtlDetails?.filter(
|
|
|
|
|
(i) => i.SettingIdName === 'Sales Mode'
|
|
|
|
|
)?.[0];
|
|
|
|
|
|
|
|
|
|
let PrintLogo = Preference?.[0]?.SettingDtlDetails?.filter(
|
|
|
|
|
(i) => i.SettingIdName === 'PrintLogo'
|
|
|
|
|
)?.[0];
|
|
|
|
|
|
|
|
|
|
let PrintGreeting = Preference?.[0]?.SettingDtlDetails?.filter(
|
|
|
|
|
(i) => i.SettingIdName === 'PrintGreetings'
|
|
|
|
|
)?.[0];
|
|
|
|
|
|
|
|
|
|
const Date1 = dateFormatChange1(CreatedDate);
|
|
|
|
|
|
|
|
|
|
// Show loading state while data is being fetched
|
|
|
|
|
if (isDataLoading || !allDataLoaded) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="loading-container" style={{ padding: '20px', textAlign: 'center' }}>
|
|
|
|
|
<div>Loading invoice Bill...</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Show message if no data
|
|
|
|
|
if (!PrintOrderDetails || PrintOrderDetails.length === 0) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="no-data-container" style={{ padding: '20px', textAlign: 'center' }}>
|
|
|
|
|
<div>No invoice data found.</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Show message if print template is not loaded
|
|
|
|
|
if (!printTemplate) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="no-template-container" style={{ padding: '20px', textAlign: 'center' }}>
|
|
|
|
|
<div>Print template not available. Please check your configuration.</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div className="invoice-viewer-controls">
|
|
|
|
|
<button
|
|
|
|
|
onClick={handleDownloadPDF}
|
|
|
|
|
className="control-btn download-btn"
|
|
|
|
|
title="Download PDF"
|
|
|
|
|
>
|
|
|
|
|
<FiDownload size={20} />
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
{PrintOrderDetails.length > 1 && (
|
|
|
|
|
<div className="pagination-controls">
|
|
|
|
|
<button
|
|
|
|
|
onClick={handlePrevPage}
|
|
|
|
|
disabled={currentPage === 0}
|
|
|
|
|
className="control-btn nav-btn"
|
|
|
|
|
title="Previous Invoice"
|
|
|
|
|
>
|
|
|
|
|
<FiChevronLeft size={20} />
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<span className="page-indicator">
|
|
|
|
|
{currentPage + 1} / {PrintOrderDetails.length}
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
onClick={handleNextPage}
|
|
|
|
|
disabled={currentPage === PrintOrderDetails.length - 1}
|
|
|
|
|
className="control-btn nav-btn"
|
|
|
|
|
title="Next Invoice"
|
|
|
|
|
>
|
|
|
|
|
<FiChevronRight size={20} />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="invoice-container" ref={containerRef}>
|
|
|
|
|
<div ref={printRef}>
|
|
|
|
|
{PrintOrderDetails?.map((table2Data, index) => {
|
|
|
|
|
if (!table2Data) return null;
|
|
|
|
|
const { BranchId, SalesDate, CashierName, productDetails, TaxDetails,
|
|
|
|
|
ExtraChargeDetails, OrderOfferDetails, PaymentOrderDtl, OrderId, FYStatus } = table2Data;
|
|
|
|
|
|
|
|
|
|
const branchDetail = branchDetails[BranchId] || {};
|
|
|
|
|
const currentBase64Image = base64Image?.[BranchId] || null;
|
|
|
|
|
|
|
|
|
|
const Date1 = dateFormatChange1(SalesDate);
|
|
|
|
|
const PaymentStatusSuccess = PaymentOrderDtl?.filter(ps => ps.PaymentStatus === 'S');
|
|
|
|
|
|
|
|
|
|
const ExtraChargeTotal = ExtraChargeDetails?.reduce(
|
|
|
|
|
(accumulator, currentObject) => accumulator + currentObject.TotalAmt, 0
|
|
|
|
|
) || 0;
|
|
|
|
|
|
|
|
|
|
const productsData = productDetails || [];
|
|
|
|
|
const offers = OrderOfferDetails || [];
|
|
|
|
|
let TotalOfferAmount = 0;
|
|
|
|
|
|
|
|
|
|
// Calculate SalesWiseOffers total amount
|
|
|
|
|
offers.forEach((offer) => {
|
|
|
|
|
if (offer.TableName === 'SalesWiseOffers') {
|
|
|
|
|
TotalOfferAmount += offer.OfferAmount;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const hasMappedOffer = offers.some((offer) =>
|
|
|
|
|
['ItemWiseOffers', 'BundleOffers', 'QuantityWiseOffers'].includes(offer.TableName)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (hasMappedOffer) {
|
|
|
|
|
const productTotal = productsData?.reduce(
|
|
|
|
|
(acc, item) => acc + (item?.Type != 'C' ? item.OfferAmt : item.OfferValue || 0), 0
|
|
|
|
|
);
|
|
|
|
|
TotalOfferAmount += productTotal;
|
|
|
|
|
} else {
|
|
|
|
|
const Combothere = productsData?.filter((item) => item?.Type == 'C');
|
|
|
|
|
const CombothereTotal = Combothere?.reduce(
|
|
|
|
|
(acc, item) => acc + (item.OfferValue || 0), 0
|
|
|
|
|
);
|
|
|
|
|
TotalOfferAmount += CombothereTotal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let totalQuantityFilter = productsData?.map(
|
|
|
|
|
(item) => item?.SalesQty || item?.OrderQty
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const totalQuantity = totalQuantityFilter?.reduce(
|
|
|
|
|
(accumulator, currentValue) => accumulator + currentValue, 0
|
|
|
|
|
) || 0;
|
|
|
|
|
|
|
|
|
|
const OrderDetailGST = TaxDetails?.filter(
|
|
|
|
|
(item) => item.TaxIdName?.toLowerCase() === 'cgst,sgst'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const OrderDetailIGST = TaxDetails?.filter(
|
|
|
|
|
(item) => item.TaxIdName?.toLowerCase() === 'igst'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const OrderDetailVAT = TaxDetails?.filter(
|
|
|
|
|
(item) => item.TaxIdName?.toLowerCase() === 'vat'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const tokenGroups = (productsData || []).reduce(
|
|
|
|
|
(acc, item, idx) => {
|
|
|
|
|
if (item.TokenAvailable === 'Y') {
|
|
|
|
|
if (!item.CounterName) {
|
|
|
|
|
acc[`individual-${idx}`] = [item];
|
|
|
|
|
} else {
|
|
|
|
|
if (!acc[item.CounterName]) acc[item.CounterName] = [];
|
|
|
|
|
acc[item.CounterName].push(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return acc;
|
|
|
|
|
},
|
|
|
|
|
{}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Render print template based on global state
|
|
|
|
|
const renderPrintTemplate = () => {
|
|
|
|
|
const commonProps = {
|
|
|
|
|
index,
|
|
|
|
|
ExtraChargeTotal,
|
|
|
|
|
Date1,
|
|
|
|
|
base64Image: currentBase64Image,
|
|
|
|
|
BranchAddress: branchDetail.address,
|
|
|
|
|
BranchCity: branchDetail.city,
|
|
|
|
|
BranchZip: branchDetail.zip,
|
|
|
|
|
SalesModePref,
|
|
|
|
|
CashierName,
|
|
|
|
|
totalQuantity,
|
|
|
|
|
OrderDetailGST,
|
|
|
|
|
OrderDetailIGST,
|
|
|
|
|
OrderDetailVAT,
|
|
|
|
|
table2Data,
|
|
|
|
|
totalQuantityFilter,
|
|
|
|
|
PaymentStatus: PaymentOrderDtl,
|
|
|
|
|
PrintLogo,
|
|
|
|
|
PrintGreeting,
|
|
|
|
|
printDatas: globalPrintDatas,
|
|
|
|
|
sportsAppPreference:sportsAppPreference
|
|
|
|
|
};
|
|
|
|
|
console.log(printTemplate,"printTemplate")
|
|
|
|
|
switch (printTemplate) {
|
|
|
|
|
case 'Style 1':
|
|
|
|
|
return <PrintStyle1 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 2':
|
|
|
|
|
return <PrintStyle2 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 3':
|
|
|
|
|
return <PrintStyle3 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 4':
|
|
|
|
|
return <PrintStyle4 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 5':
|
|
|
|
|
return <PrintStyle5 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 6':
|
|
|
|
|
return <PrintStyle6 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 7':
|
|
|
|
|
return <PrintStyle7 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 8':
|
|
|
|
|
return <PrintStyle8 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 9':
|
|
|
|
|
return <PrintStyle9 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 10':
|
|
|
|
|
return <PrintStyle10 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 11':
|
|
|
|
|
return <PrintStyle11 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'Style 12':
|
|
|
|
|
// return <PrintStyle12 {...commonProps} isPdf={true}/>;
|
|
|
|
|
// case 'Style 13':
|
|
|
|
|
return <PrintStyle13 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'A4':
|
|
|
|
|
return <PrintA4Style11 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'A5':
|
|
|
|
|
return <PrintA5Style11 {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'A4Standard':
|
|
|
|
|
return <InvoiceTemplate {...commonProps} isPdf={true} />;
|
|
|
|
|
case 'TaxInvoice':
|
|
|
|
|
return <TaxInvoice {...commonProps} isPdf={true} />;
|
|
|
|
|
default:
|
|
|
|
|
return <PrintStyle1 {...commonProps} isPdf={true} />;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div key={index} className="invoice-page">
|
|
|
|
|
<div
|
|
|
|
|
className="Reprint-body"
|
|
|
|
|
id={`RePrint-${index}`}
|
|
|
|
|
style={{ width: '50%' }}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{renderPrintTemplate()}
|
|
|
|
|
|
|
|
|
|
{/* Token Print */}
|
|
|
|
|
{/* {Object.entries(tokenGroups).map(
|
|
|
|
|
([counterName, items], tokenIdx) => (
|
|
|
|
|
<div key={`token-${index}-${tokenIdx}`} className="token-page">
|
|
|
|
|
<div
|
|
|
|
|
className="Reprint-body"
|
|
|
|
|
id={`TakeawayToken${index}-${tokenIdx}-${counterName}`}
|
|
|
|
|
style={{ width: '50%' }}
|
|
|
|
|
>
|
|
|
|
|
<div className="Re-print-top">
|
|
|
|
|
<p className="Re-print-title">{items[0]?.BrName}</p>
|
|
|
|
|
<p className="Re-print-title">Token</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="Re-print-top2">
|
|
|
|
|
<p className="Re-print-bold">
|
|
|
|
|
BillNo:
|
|
|
|
|
{OrderId && extractLastNumberOrderId(OrderId, FYStatus)}
|
|
|
|
|
</p>
|
|
|
|
|
<p className="Re-print-bold">{Date1}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<table className="Re-print-Table">
|
|
|
|
|
<thead className="Re-print-th">
|
|
|
|
|
<tr>
|
|
|
|
|
<th className="Re-print-td">S.No</th>
|
|
|
|
|
<th className="Re-print-td">Item</th>
|
|
|
|
|
<th className="Re-print-td">Qty</th>
|
|
|
|
|
<th className="Re-print-td">Rate</th>
|
|
|
|
|
<th className="Re-print-td">Price</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
{items?.map((item, idx) => (
|
|
|
|
|
<tr className="Re-print-body-Tr" key={idx}>
|
|
|
|
|
<td className="Re-print-td">{idx + 1}</td>
|
|
|
|
|
<td className="Re-print-body-Product">
|
|
|
|
|
{item.ProdName}
|
|
|
|
|
</td>
|
|
|
|
|
<td className="Re-print-body-Rate">
|
|
|
|
|
{item.SalesQty}
|
|
|
|
|
</td>
|
|
|
|
|
<td className="Re-print-body-Rate">
|
|
|
|
|
{item.Rate}
|
|
|
|
|
</td>
|
|
|
|
|
<td className="Re-print-body-Rate">
|
|
|
|
|
{item.TotalAmt}
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
))}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
)} */}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default LinkUrlCreate;
|