Add consent paragraphs and formatting to fillable PDF; update signature section and save new version

This commit is contained in:
Torsten Schulz (local)
2025-10-23 01:41:37 +02:00
parent 7cd39bb452
commit ed25373b1c
2 changed files with 102 additions and 4 deletions

View File

@@ -323,10 +323,8 @@ async function create() {
page2.drawRectangle({ x: sepaLeft, y: signLineY - 2, width: signLineWidth, height: 1, color: rgb(0,0,0) }) page2.drawRectangle({ x: sepaLeft, y: signLineY - 2, width: signLineWidth, height: 1, color: rgb(0,0,0) })
page2.drawText('Unterschrift des Kontoinhabers', { x: sepaLeft, y: signLineY - 18, size: 11, font: helv }) page2.drawText('Unterschrift des Kontoinhabers', { x: sepaLeft, y: signLineY - 18, size: 11, font: helv })
// no form field for signature on page 2 (physical signature) // no form field for signature on page 2 (physical signature)
page2.drawText('Unterschrift des Kontoinhabers', { x: sepaLeft, y: signLineY - 18, size: 11, font: helv })
const pdfBytes = await pdfDoc.save() // no form field for signature on page 2 (physical signature)
fs.writeFileSync('server/templates/mitgliedschaft-fillable.pdf', pdfBytes)
console.log('Wrote server/templates/mitgliedschaft-fillable.pdf')
// --- Add a third page with same header/bar/footer and title 'Einwilligungserklärung' --- // --- Add a third page with same header/bar/footer and title 'Einwilligungserklärung' ---
const page3 = pdfDoc.addPage([595.28, 841.89]) const page3 = pdfDoc.addPage([595.28, 841.89])
@@ -349,6 +347,106 @@ async function create() {
const footerSize3 = 10 const footerSize3 = 10
const footerWidth3 = helv.widthOfTextAtSize(footerText3, footerSize3) const footerWidth3 = helv.widthOfTextAtSize(footerText3, footerSize3)
page3.drawText(footerText3, { x: width3 - footerWidth3 - leftX, y: 56.7, size: footerSize3, font: helv }) page3.drawText(footerText3, { x: width3 - footerWidth3 - leftX, y: 56.7, size: footerSize3, font: helv })
// --- consent paragraphs on page 3 (wrapped) ---
const consentText = `für die Veröffentlichung von Mitgliederdaten im Internet.
Der Vereinsvorstand weist hiermit darauf hin, dass ausreichende technische Maßnahmen zur Gewährleistung des Datenschutzes getroffen wurden. Dennoch kann bei einer Veröffentlichung von personenbezogenen Mitgliederdaten im Internet ein umfassender Datenschutz nicht garantiert werden.
Daher nimmt das Vereinsmitglied die Risiken für eine eventuelle Persönlichkeitsrechtsverletzung zur
Kenntnis und ist sich bewusst, dass:
• die personenbezogenen Daten auch in Staaten abrufbar sind, die keine der Bundesrepublik Deutschland vergleichbaren Datenschutzbestimmungen kennen,
• die Vertraulichkeit, die Integrität (Unverletzlichkeit), die Authentizität (Echtheit) und die Verfügbarkeit der personenbezogenen Daten nicht garantiert ist.
Das Vereinsmitglied trifft die Entscheidung zur Veröffentlichung seiner Daten im Internet freiwillig und kann seine Einwilligung gegenüber dem Vereinsvorstand jederzeit widerrufen.`
// helper for wrapped text on page3
const wrapMaxWidth3 = width3 - leftX - 48
function drawWrappedOnPage3(text, x, y, size, font) {
// handle bullet lines: split by newline to preserve existing bullet markers
const lines = text.split(/\r?\n/)
let curY = y
const indent = 14 // indent for text following bullet
for (const rawLine of lines) {
const line = rawLine.trim()
if (!line) { curY -= size + 4; continue }
if (line.startsWith('•')) {
// draw bullet circle and then wrap remainder with indentation
const after = line.replace(/^•\s?/, '')
// bullet position
const bx = x + 4
// place bullet aligned with the first text line (slightly above center)
const by = curY - size * 0.25
page3.drawCircle({ x: bx, y: by, size: 1.8, color: rgb(0,0,0) })
// wrap the 'after' text with indent
const words = after.replace(/\s+/g, ' ').trim().split(' ')
let curLine = ''
for (const w of words) {
const test = curLine ? curLine + ' ' + w : w
const testWidth = helv.widthOfTextAtSize(test, size)
if (testWidth > wrapMaxWidth3 - indent) {
page3.drawText(curLine, { x: x + indent, y: curY, size, font })
curLine = w
curY -= size + 4
} else {
curLine = test
}
}
if (curLine) {
page3.drawText(curLine, { x: x + indent, y: curY, size, font })
curY -= size + 4
}
} else {
// regular paragraph line: wrap normally
const words = line.replace(/\s+/g, ' ').trim().split(' ')
let curLine = ''
for (const w of words) {
const test = curLine ? curLine + ' ' + w : w
const testWidth = helv.widthOfTextAtSize(test, size)
if (testWidth > wrapMaxWidth3) {
page3.drawText(curLine, { x, y: curY, size, font })
curLine = w
curY -= size + 4
} else {
curLine = test
}
}
if (curLine) {
page3.drawText(curLine, { x, y: curY, size, font })
curY -= size + 4
}
}
}
return curY
}
// split into paragraphs and draw with 0.5cm (~14.17pt) paragraph spacing
const paras = consentText.split('\n\n')
let py = page3TitleY - 28
const paraSpacing = 14.17
const paraSize = 11
for (const p of paras) {
py = drawWrappedOnPage3(p.trim(), leftX, py, paraSize, helv)
py -= paraSpacing
}
// Additional confirmation block (formatted) with 0.4cm spacing
const blockSpacing = 11.34 // 0.4 cm
const boldSize = 12
const normalSize = 11
// ensure a bit of space before the block
py -= blockSpacing
py = drawWrappedOnPage3('Erklärung:', leftX, py, boldSize, helvBold)
py -= blockSpacing
py = drawWrappedOnPage3('Ich bestätige das Vorstehende zur Kenntnis genommen zu haben und willige ein, dass der', leftX, py, normalSize, helv)
py -= blockSpacing
py = drawWrappedOnPage3('Harheimer Tischtennis-Club 1954 e.V.', leftX, py, boldSize, helvBold)
py -= blockSpacing
py = drawWrappedOnPage3('folgende allgemeine Daten zu meiner Person:', leftX, py, normalSize, helv)
py -= blockSpacing
const pdfBytes = await pdfDoc.save()
fs.writeFileSync('server/templates/mitgliedschaft-fillable.pdf', pdfBytes)
console.log('Wrote server/templates/mitgliedschaft-fillable.pdf')
} }
create().catch(e => { create().catch(e => {