initial commit
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# PDF Generation Pagination
|
||||
|
||||
Source: `src/lib/pdf.ts`
|
||||
|
||||
## Page-break logic
|
||||
|
||||
Each service calculates its height before rendering. Page break triggers when `y + serviceHeight > CONTENT_BOTTOM - FOOTER_HEIGHT`.
|
||||
|
||||
Key constants:
|
||||
- `CONTENT_BOTTOM = PAGE_H - MARGIN` (772)
|
||||
- `FOOTER_HEIGHT = 35` (reserved for separator + footer text + page number)
|
||||
|
||||
## Height calculation (must match rendering yPos increments)
|
||||
|
||||
```
|
||||
svcH = 0
|
||||
if hasDecision: svcH += 5 // badge
|
||||
svcH += 6 // name + price
|
||||
if priority: svcH += 16 // priority label + reason
|
||||
if recommendation: svcH += 8
|
||||
if explanation: svcH += lines * 5 + 2
|
||||
if partsNotInStock: svcH += 8 + (deliveryTime ? 8 : 0)
|
||||
if aftermarket: svcH += 8 + (partsList ? 8 : 0)
|
||||
svcH += 6 // separator + spacing
|
||||
```
|
||||
|
||||
## After page break
|
||||
|
||||
- Call `doc.addPage()` then set `yPos = MARGIN`
|
||||
- **Redraw current section header** (SERVICES APPROVED / POSTPONED SERVICES) so new page has context
|
||||
- Summary box uses same FOOTER_HEIGHT check before rendering
|
||||
|
||||
## Footer
|
||||
|
||||
Drawn on EVERY page via post-render loop:
|
||||
```ts
|
||||
const totalPages = doc.getNumberOfPages();
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
drawFooter(doc, i, totalPages, settings, shopChargeAmount);
|
||||
}
|
||||
```
|
||||
Footer includes: separator line, shop message, validity note, "Page N of M"
|
||||
|
||||
## String rendering (jspdf 4.x)
|
||||
|
||||
NEVER pass arrays to `doc.text()` — jspdf 4.x uses different internal line spacing than manual yPos tracking, causing cascading desync and text overlap. Always render `splitTextToSize()` results per-line:
|
||||
```ts
|
||||
doc.splitTextToSize(text, CW).forEach((line) => {
|
||||
doc.text(line, MARGIN, y);
|
||||
y += 5;
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user