I just occur one problem that i want to create invoice but when invoice get item image than it break A4 size so i want to print that if item have image than i want to print a only single product per page so like if i have 3 products and two of them have item image than i want to print two pages with same header and footer of invoice but change in body
Here is my react component
import { useState, useEffect, useRef, useLayoutEffect } from 'react';
import "./invoiceDesign.css";
import image from "../assets/images/nk-header.png"
import footerImage from "../assets/images/nk-footer.png"
import { Row } from "react-bootstrap"
import { Col } from "react-bootstrap"
import { useParams } from 'react-router-dom';
import axios from 'axios'
import ReactLoading from 'react-loading'
import { useReactToPrint } from "react-to-print";
import { MdFileDownload } from 'react-icons/md'
import reactHtmlParser from "react-html-parser"
import converter from "number-to-words"
function IvoiceDesign() {
const { invoicenumber } = useParams()
const componentRef = useRef();
const [data, setData] = useState([])
const [formattedDate, setFormattedDate] = useState('')
const [isLoading, setIsLoading] = useState(true)
const [imageAppears, setImageAppears] = useState(false)
useEffect(() => {
axios({
method: "GET",
url: `http://localhost:3333/invoice/${invoicenumber}`,
headers: {
"Content-Type": 'application/json',
"Authorization": localStorage.getItem("token")
}
}).then((res) => {
setData(res.data)
console.log(res.data)
setIsLoading(false)
}).catch((err) => {
console.log(err)
setIsLoading(false)
})
}, []);
useEffect(() => {
if (data.invoiceDate) {
const oldDate = new Date(data.invoiceDate);
const newDate = oldDate.toLocaleString('en-GB');
setFormattedDate(newDate.split(',')[0])
}
}, [data]);
const handlePrint = useReactToPrint({
content: () => componentRef.current
});
return (
<>
{isLoading ? <ReactLoading type='spin' color='blue' height='3rem' width='3rem' className='text-center m-auto' /> :
<div className='container' >
<div ref={componentRef} className='sub-container'>
<div className='invoice-layout-header' >
<p className='text-center m-0'>Invoice</p>
<div className='invoice-header-image'>
<img src={image} alt="image" />
</div>
<div className='invoice-header-infomation'>
<Row className='invoice-header-row m-1'>
<Col sm={8} className='invoice-header-column '>
<Row className='invoice-header-subrows m-1 flex'><span className='p-0'><b>To:</b> {data.customerName}</span></Row>
<Row className='invoice-header-subrows m-1'><span className='p-0'><b>GST No: </b>{data.customerGstNo ? data.customerGstNo : ""}</span></Row>
</Col>
<Col sm={4} className='invoice-header-column'>
<Row className='invoice-header-subrows m-1'><span className='p-0'><b>Bill No :</b> {invoicenumber}</span></Row>
<Row className='invoice-header-subrows m-1'><span className='p-0'><b > Date :</b> {formattedDate.split(",")}</span></Row>
</Col>
</Row>
</div>
</div>
<div className='invoice-table-container' >
<table id="invoice-table">
<colgroup>
<col width="35mm" />
<col />
<col width="60mm" />
<col width="100mm" />
<col width="100mm" />
</colgroup>
<tr class="invoice_line ">
<th>sr.No</th>
<th>Particurals</th>
<th>Qty</th>
<th>Rate</th>
<th>Amount</th>
</tr>
{data.invoiceDetails.map((item, i) => {
return (
<tr class="invoice_line">
<td>{i + 1}</td>
<td class="site">
<span className='flex flex-column'>
<div className='text-black'>{item.title}</div>
{item.imageName ?
<img src={`http://localhost:3333/${item.imageName}`} alt="Image}" className='invoice-item-image' />
:
<div className='invoice-item-image'></div>
}
<div className='text-black'>{reactHtmlParser(item.description)}</div>
</span>
</td>
<td class="amount"><b>{item.quantity}</b></td>
<td class="amount"><b>{item.rate}</b></td>
<td class="amount"><b>{item.itemAmount}</b></td>
</tr>
)
})}
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tfoot>
<tr className='mt-5 '>
<td></td>
<td></td>
<td></td>
<td><tr className='t-foot-td'>TOTAL</tr></td>
<td><tr className='t-foot-td'><b>₹ {data.amount}</b></tr></td>
</tr>
{
data.IGST ? <tr className='mt-5 '>
<td></td>
<td></td>
<td></td>
<td className='p-3'><tr className='t-foot-td p-4'>IGST({data.GstRate[0].IGst}%)</tr></td>
<td><tr className='t-foot-td'><b>₹ {data.IGST}</b></tr></td>
</tr> :
<>
<tr className='mt-5 '>
<td></td>
<td></td>
<td></td>
<td className='p-3'><tr className='t-foot-td p-4'>CGST({data.GstRate[0].CGst}%)</tr></td>
<td><tr className='t-foot-td'><b>₹ {data.CGST}</b></tr></td>
</tr>
<tr className='mt-5 '>
<td></td>
<td></td>
<td></td>
<td className='p-3'><tr className='t-foot-td p-4'>SGST({data.GstRate[0].SGst}%)</tr></td>
<td><tr className='t-foot-td'><b>₹ {data.SGST}</b></tr></td>
</tr>
</>
}
<tr className='mt-5 '>
<td></td>
<td></td>
<td></td>
<td><tr className='t-foot-td'>TOTAL</tr></td>
<td><tr className='t-foot-td'><b>₹ {data.invoiceTotalPrice}</b></tr></td>
</tr>
<tr>
<td colSpan="5" className='price-in-words'><span className='p-0 text-black'><b>In words: {converter.toWords(data.invoiceTotalPrice)}</b></span></td>
</tr>
</tfoot>
</table>
</div >
<div className='invoice-footer-image'>
<img src={footerImage} alt="image" />
</div>
</div>
</div >
}
<botton className="print-btn" onClick={handlePrint}>{<MdFileDownload size={30} />}</botton >
</>
);
}
export default IvoiceDesign;
Here is my data that come from backend
{
"companyName": "LTIM",
"customerName": "Np builders",
"customerGstNo": "XPDS12344DESF",
"invoiceDetails": [
{
"title": "water cooler",
"description": "",
"imageName": "pngwing.com.png",
"imagePath": "../backend/media/pngwing.com.png",
"quantity": 1,
"rate": 12000,
"itemAmount": 12000,
"_id": "64dc481938309b30eb6abc5d"
},
{
"title": "router",
"description": "",
"imageName": "router.png",
"imagePath": "../backend/media/router.png",
"quantity": 1,
"rate": 12000,
"itemAmount": 12000,
"_id": "64dc481938309b30eb6abc5e"
}
],
"amount": 24000,
"invoiceTotalPrice": 26880,
"SGST": 1440,
"CGST": 1440,
"GstRate": [
{
"_id": "64b4d250ec83c5a4cebcd5bb",
"IGst": 5,
"CGst": 2.5,
"SGst": 2.5,
"__v": 0
}
],
"invoiceDate": "2023-08-16T03:52:57.766Z"
}
and here is my invoice route from backend
Router.get("/invoice/:invoicenumber", auth, async (req, res) => {
const { invoicenumber } = req.params;
const finalInvoice = {};
try {
const rawInvoice = await Invoice.findOne({ invoiceNumber: invoicenumber })
const company = await Company.findById(rawInvoice.companyID).exec()
const customer = await Client.findById(rawInvoice.customerID).exec()
const GSTrate = await GstModel.find({}).exec()
finalInvoice.companyName = company.companyName;
finalInvoice.customerName = customer.clientName;
finalInvoice.customerGstNo = customer.clientGstNo;
finalInvoice.invoiceDetails = rawInvoice.invoiceDetails;
finalInvoice.amount = rawInvoice.amount;
finalInvoice.invoiceTotalPrice = rawInvoice.totalAmount;
if (customer.state === 'Gujarat') {
finalInvoice.SGST = rawInvoice.SGST;
finalInvoice.CGST = rawInvoice.CGST;
} else {
finalInvoice.IGST = rawInvoice.IGST;
}
finalInvoice.GstRate = GSTrate;
finalInvoice.invoiceDate = rawInvoice.date;
res.status(200).send(finalInvoice)
} catch (err) {
res.send(err);
}
})
i got stuck into this problem from last three days i dont get and proper answer.
i just want to try print images on multiple pages