THIS IS PDF GENERATED REPORT
THIS IS WHAT WEBSITE SHOWING
i have created an application of invoice generator where an functionality after filling all feilds you can just download pdf , i am using html2canvas and jsPDF library to convert my Form<div> into a canvas and the jsPDF convert that canvas to a pdf,
There is textarea feild in form when i fill the feild in webpage like 3 lines when text reaches to max width it automatically shift to next line and looks good, okay but the problem is when i am generating PDF the productname text only shows in single line and the rest of the text overflow i cant see that…. how to fix this i have tried eveything css changes textbox to input box nothing works …..
// THIS IS MAIN FILE HERE IS PDF GENERATION MECHANISM
import Head from "./components/Head/Head";
import "./index.css";
import Date from "./components/Datepart/Date";
import Btst from "./components/BtStpart/Btst";
import InvoiceItemForm from "./components/Items/InvoiceItemForm";
import Footer from "./components/Footer/Footer";
import { useState } from "react";
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
function App() {
const[loader,setLoader] = useState(false);
const downloadPDF = ()=>{
const capture = document.querySelector("#invoice");
setLoader(true);
html2canvas(capture).then((canvas)=>{
const imgData = canvas.toDataURL("img/png");
const doc = new jsPDF('p', 'mm', 'a4');
const componentWidth = doc.internal.pageSize.getWidth();
const componentHeight = doc.internal.pageSize.getHeight();
doc.addImage(imgData, 'PNG', 0, 0, componentWidth, componentHeight);
setLoader(false);
doc.save('receipt.pdf');
})
}
return (
<>
<button className="download-btn" id="download" disabled={!(loader === false)} onClick={downloadPDF} >
{loader?(<span>Downloading</span>):(<span>Download</span>)}
</button>
<div className="container" id="invoice">
<Head />
<Date />
<Btst />
<InvoiceItemForm />
<Footer />
</div>
</>
);
}
export default App;
// THIS IS FORM MAIN COMPONENT WHERE IS ALL TEXTFEILDS AVAILABLE
import React, { useState, useEffect } from "react";
import "./InvoiceItemForm.css";
function InvoiceItemForm({ onAddItem }) {
const [items, setItems] = useState([
{ sno: "1", productName: "", qty: "",unit:"Nos.", rate: "", gst: "", total: "" },
]);
const [totals, setTotals] = useState({
totalTaxable: 0,
totalGSTAmt: 0,
overallTotal: 0,
});
useEffect(() => {
updateTotals();
}, [items]);
const handleAddItem = () => {
const lastSno =
items.length > 0 ? parseInt(items[items.length - 1].sno) + 1 : 1;
setItems([
...items,
{
sno: lastSno.toString(),
productName: "",
qty: "",
rate: "",
gst: "",
total: "",
unit: "Nos."
},
]);
};
const handleRemoveItem = (index) => {
const updatedItems = [...items];
updatedItems.splice(index, 1);
setItems(updatedItems);
};
const handleChange = (index, e) => {
const { name, value } = e.target;
const updatedItems = [...items];
updatedItems[index][name] = value;
// Calculate TaxableValue
const qty = parseFloat(updatedItems[index].qty);
const rate = parseFloat(updatedItems[index].rate);
updatedItems[index].taxable = (qty * rate).toFixed(2);
// Calculate GST Amt
const gstPercent = parseFloat(updatedItems[index].gst);
updatedItems[index].gstAmt = (
(gstPercent / 100) *
updatedItems[index].taxable
).toFixed(2);
// Calculate Total
updatedItems[index].total = (
parseFloat(updatedItems[index].taxable) +
parseFloat(updatedItems[index].gstAmt)
).toFixed(2);
setItems(updatedItems);
};
const updateTotals = () => {
let totalTaxable = 0;
let totalGSTAmt = 0;
let overallTotal = 0;
items.forEach((item) => {
totalTaxable += parseFloat(item.taxable);
totalGSTAmt += parseFloat(item.gstAmt);
overallTotal += parseFloat(item.total);
});
setTotals({
totalTaxable: totalTaxable.toFixed(2),
totalGSTAmt: totalGSTAmt.toFixed(2),
overallTotal: overallTotal.toFixed(2),
});
};
return (
<div>
<form className="InvoiceItemForm">
<table>
<thead>
<tr>
<th>SNO</th>
<th>Product Name</th>
<th>HSN</th>
<th>Qty</th>
<th>Unit</th>
<th>Rate</th>
<th>Taxable Value</th>
<th>GST %</th>
<th>GST Amt</th>
<th>Total</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{items.map((item, index) => (
<tr key={index}>
<td>{item.sno}</td>
<td>
// THIS TEXTFEILD SUCKSS.............. IT IS OVERFLOWING IN PDF
<textarea
className="productName"
name="productName"
value={item.productName}
onChange={(e) => handleChange(index, e)}
placeholder="Enter Product Name"
/>
</td>
<td>
<input
type="text"
name={`hsn-${index}`}
value={item.hsn}
onChange={(e) => handleChange(index, e)}
placeholder="HSN"
/>
</td>
<td>
<input
type="number"
name="qty"
value={item.qty}
onChange={(e) => handleChange(index, e)}
placeholder="Qty"
/>
</td>
<td>
<input
type="text"
name="unit"
value={item.unit}
onChange={(e) => handleChange(index, e)}
placeholder="Unit"
/>
</td>
<td>
<input
type="number"
name="rate"
value={item.rate}
onChange={(e) => handleChange(index, e)}
placeholder="Rate"
/>
</td>
<td>
<input
type="number"
className="taxable"
name="taxable"
value={item.taxable}
readOnly
placeholder="Taxable"
/>
</td>
<td>
<input
type="number"
name="gst"
value={item.gst}
onChange={(e) => handleChange(index, e)}
placeholder="GST %"
/>
</td>
<td>
<input
type="number"
className="gstAmt"
name="gstAmt"
value={item.gstAmt}
readOnly
placeholder="GST Amt"
/>
</td>
<td>
{" "}
<input
type="number"
className="total"
name="total"
value={item.total}
readOnly
placeholder="Total"
/>
</td>
<td>
<button type="button" onClick={() => handleRemoveItem(index)}>
Remove
</button>
</td>
</tr>
))}
</tbody>
</table>
<button type="button" onClick={handleAddItem}>
Add Item
</button>
</form>
<div className="totals-container">
<div className="alphaTotal">
<div className="headtot">Total Proforma Invoice Amount In Words</div>
<input className="alpha_text" type="text"></input>
</div>
<table className="totals">
<thead>
<tr>
<th>Total Taxable</th>
<th>Total GST Amount</th>
<th>Overall Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>{`₹${totals.totalTaxable}`}</td>
<td>{`₹${totals.totalGSTAmt}`}</td>
<td>{`₹${totals.overallTotal}`}</td>
</tr>
</tbody>
</table>
</div>
</div>
);
}
export default InvoiceItemForm; .InvoiceItemForm {
margin: 0 auto;
padding: 1%;
font-size: large;
border: 1px solid black;
}
.InvoiceItemForm h2 {
text-align: center;
}
.InvoiceItemForm form {
display: flex;
flex-direction: column;
}
.InvoiceItemForm label {
font-weight: bold;
}
.InvoiceItemForm input,
.InvoiceItemForm button {
width: 5vw;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: large;
}
.InvoiceItemForm textarea{
font-size: large;
}
.InvoiceItemForm .productNamee {
width: 9vw;
}
.InvoiceItemForm button {
background-color: #007bff;
color: #fff;
border: none;
cursor: pointer;
}
.InvoiceItemForm button:hover {
background-color: #0056b3;
}
.totals-container {
width: 100%;
display: flex;
justify-content: flex-end;
}
.totals {
width: 50%;
border-collapse: collapse;
border-right: 1px solid black;
}
.totals th,
.totals td {
padding: 13px;
text-align: center;
}
.totals th {
background-color: #f2f2f2;
}
.alphaTotal {
width: 50%;
border-left: 1px solid black;
border-bottom: 1px solid black;
padding: 10px;
}
.headtot {
display: flex;
justify-content: center;
font-size: 1.4rem;
}
.alpha_text {
width: 99%;
font-size: 1.5rem;
}
.productName {
resize: vertical;
}
enter image description here