65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
export const escapeHtml = (s: unknown): string =>
|
|
String(s ?? '')
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
|
|
export const formatEur = (n: unknown): string => {
|
|
const num = typeof n === 'number' ? n : Number(n ?? 0)
|
|
if (!Number.isFinite(num)) return '—'
|
|
return new Intl.NumberFormat('de-DE', {
|
|
style: 'currency',
|
|
currency: 'EUR',
|
|
}).format(num)
|
|
}
|
|
|
|
export const formatDateDe = (d: string | Date): string => {
|
|
const date = typeof d === 'string' ? new Date(d) : d
|
|
return new Intl.DateTimeFormat('de-DE', {
|
|
day: '2-digit',
|
|
month: 'long',
|
|
year: 'numeric',
|
|
}).format(date)
|
|
}
|
|
|
|
export const baseDocument = (title: string, body: string): string => `<!doctype html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>${escapeHtml(title)}</title>
|
|
<style>
|
|
@page { size: A4; margin: 24mm 20mm; }
|
|
body { font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 11pt; color: #111; line-height: 1.5; }
|
|
h1 { font-size: 16pt; margin: 0 0 4mm 0; }
|
|
h2 { font-size: 13pt; margin: 8mm 0 2mm 0; }
|
|
.meta { color: #555; font-size: 10pt; margin-bottom: 8mm; }
|
|
.section { margin: 6mm 0; }
|
|
ul { margin: 2mm 0; padding-left: 6mm; }
|
|
table { border-collapse: collapse; width: 100%; }
|
|
td, th { border: 1px solid #ddd; padding: 2mm 3mm; text-align: left; vertical-align: top; }
|
|
.signature { margin-top: 16mm; display: flex; gap: 12mm; }
|
|
.signature .line { flex: 1; border-top: 1px solid #333; padding-top: 2mm; font-size: 10pt; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
${body}
|
|
</body>
|
|
</html>`
|
|
|
|
export const renderMembers = (
|
|
members: Array<{ displayName: string; role: string; shares: number | null }>,
|
|
): string => {
|
|
const rows = members
|
|
.map(
|
|
(m) =>
|
|
`<tr><td>${escapeHtml(m.displayName)}</td><td>${escapeHtml(m.role)}</td><td>${m.shares ?? '—'}</td></tr>`,
|
|
)
|
|
.join('')
|
|
return `<table>
|
|
<thead><tr><th>Name</th><th>Rolle</th><th>Anteile</th></tr></thead>
|
|
<tbody>${rows}</tbody>
|
|
</table>`
|
|
}
|