feat(admin): update B2B PDF, mail and admin table
- format PDF order number as AE- and add upgrade flags - style status emails with sleek modern dark theme - add badge counts to admin table status filter buttons - implement preiskorrektur inline editing inside admin detail modal - trigger DB and total price recalculations on snapshot changes
This commit is contained in:
@@ -99,31 +99,92 @@ export function getOrderEmailTemplate(
|
||||
return { text, html }
|
||||
}
|
||||
|
||||
export function getStatusEmailTemplate(orderNumber: string, oldLabel: string, newLabel: string) {
|
||||
const text = `Hallo,\n\nder Status deiner Anfrage ${orderNumber} hat sich geändert.\n\nStatus: ${newLabel} (vorher: ${oldLabel})\n\nViele Grüße,\nDein CASPOS Team`
|
||||
export function getStatusEmailTemplate(
|
||||
orderNumber: string,
|
||||
oldLabel: string,
|
||||
newLabel: string,
|
||||
statusKey?: string,
|
||||
rejectionReason?: string
|
||||
) {
|
||||
const formattedOrderNumber = orderNumber.replace(/^BE-/, 'AE-')
|
||||
|
||||
let title = 'Statusänderung'
|
||||
let intro = `der Status deiner Anfrage <strong>#${formattedOrderNumber}</strong> wurde aktualisiert.`
|
||||
let statusColor = '#f59e0b' // Amber default
|
||||
let showAttachmentBadge = false
|
||||
|
||||
if (statusKey === 'approved' || statusKey === 'active' || statusKey === 'completed') {
|
||||
title = 'Freigabebestätigung'
|
||||
intro = `Ihre Anfrage <strong>#${formattedOrderNumber}</strong> wurde erfolgreich freigegeben und ist nun aktiv. Die unterzeichnete Anfragebestätigung finden Sie im Anhang dieses Schreibens.`
|
||||
statusColor = '#10b981' // Emerald
|
||||
showAttachmentBadge = true
|
||||
} else if (statusKey === 'rejected') {
|
||||
title = 'Anfrage abgelehnt'
|
||||
intro = `Ihre Anfrage <strong>#${formattedOrderNumber}</strong> wurde vom Support geprüft und abgelehnt.`
|
||||
statusColor = '#ef4444' // Red
|
||||
} else if (statusKey === 'pending_approval' || statusKey === 'in_review' || statusKey === 'pending') {
|
||||
title = 'Eingangsbestätigung'
|
||||
intro = `Ihre Anfrage <strong>#${formattedOrderNumber}</strong> ist eingegangen und wird derzeit von unserem Support geprüft.`
|
||||
statusColor = '#f59e0b'
|
||||
}
|
||||
|
||||
const text = `Hallo,\n\n${title}\n\n${intro.replace(/<[^>]*>/g, '')}\n\nStatus: ${newLabel} (vorher: ${oldLabel})\n${rejectionReason ? `Grund: ${rejectionReason}\n` : ''}\nViele Grüße,\nDein CASPOS Team`
|
||||
|
||||
const reasonSection = rejectionReason
|
||||
? `
|
||||
<div style="margin-top: 20px; padding: 12px 16px; background-color: rgba(239, 68, 68, 0.1); border-left: 4px solid #ef4444; border-radius: 4px;">
|
||||
<p style="margin: 0; font-size: 11px; color: #ef4444; font-weight: bold; text-transform: uppercase; tracking-spacing: 0.05em;">Begründung:</p>
|
||||
<p style="margin: 4px 0 0 0; font-size: 14px; color: #f8fafc; font-style: italic;">"${rejectionReason}"</p>
|
||||
</div>
|
||||
`
|
||||
: ''
|
||||
|
||||
const footerActions = showAttachmentBadge
|
||||
? `
|
||||
<p style="text-align: center; margin: 32px 0 0 0;">
|
||||
<span style="display: inline-block; background-color: #1e293b; border: 1px solid #334155; border-radius: 6px; padding: 10px 20px; color: #3b82f6; font-size: 13px; font-weight: bold; letter-spacing: 0.025em;">
|
||||
📎 PDF im Anhang verfügbar
|
||||
</span>
|
||||
</p>
|
||||
`
|
||||
: ''
|
||||
|
||||
const html = `
|
||||
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e2e8f0; border-radius: 8px;">
|
||||
<h2 style="color: #0f172a; margin-bottom: 16px;">Statusänderung</h2>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5;">Hallo,</p>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5;">der Status deiner Anfrage <strong>${orderNumber}</strong> wurde aktualisiert.</p>
|
||||
<div style="background-color: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 16px; margin: 24px 0;">
|
||||
<table style="width: 100%; border-collapse: collapse; font-size: 14px; color: #475569;">
|
||||
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 32px; border: 1px solid #1e293b; border-radius: 12px; background-color: #0b0f19; color: #f8fafc;">
|
||||
<div style="text-align: center; margin-bottom: 32px;">
|
||||
<h1 style="color: #3b82f6; font-size: 26px; margin: 0; font-weight: 900; letter-spacing: -0.025em; text-transform: uppercase;">CASPOS</h1>
|
||||
<p style="color: #64748b; font-size: 10px; margin: 2px 0 0 0; text-transform: uppercase; letter-spacing: 0.2em; font-weight: bold;">Die Kasse</p>
|
||||
</div>
|
||||
|
||||
<div style="background-color: #111827; border: 1px solid #1e293b; border-radius: 8px; padding: 24px; margin-bottom: 24px;">
|
||||
<h2 style="color: #ffffff; font-size: 18px; margin-top: 0; margin-bottom: 12px; font-weight: 700;">${title}</h2>
|
||||
<p style="color: #cbd5e1; font-size: 14px; line-height: 1.6; margin-top: 0;">Hallo,</p>
|
||||
<p style="color: #cbd5e1; font-size: 14px; line-height: 1.6;">${intro}</p>
|
||||
|
||||
<table style="width: 100%; border-collapse: collapse; font-size: 13px; color: #cbd5e1; margin-top: 20px;">
|
||||
<tr>
|
||||
<td style="padding: 4px 0; font-weight: bold; width: 140px;">Nummer:</td>
|
||||
<td style="padding: 4px 0;">${orderNumber}</td>
|
||||
<td style="padding: 8px 0; border-bottom: 1px solid #1e293b; color: #64748b; width: 140px; font-weight: 600; text-transform: uppercase; font-size: 11px;">Anfragenummer:</td>
|
||||
<td style="padding: 8px 0; border-bottom: 1px solid #1e293b; font-family: monospace; font-weight: bold; color: #3b82f6; font-size: 14px;">#${formattedOrderNumber}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 4px 0; font-weight: bold;">Vorher:</td>
|
||||
<td style="padding: 4px 0; text-decoration: line-through; color: #94a3b8;">${oldLabel}</td>
|
||||
<td style="padding: 8px 0; border-bottom: 1px solid #1e293b; color: #64748b; font-weight: 600; text-transform: uppercase; font-size: 11px;">Vorher:</td>
|
||||
<td style="padding: 8px 0; border-bottom: 1px solid #1e293b; text-decoration: line-through; color: #475569;">${oldLabel}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 4px 0; font-weight: bold;">Aktuell:</td>
|
||||
<td style="padding: 4px 0; font-weight: bold; color: #3b82f6;">${newLabel}</td>
|
||||
<td style="padding: 8px 0; border-bottom: 1px solid #1e293b; color: #64748b; font-weight: 600; text-transform: uppercase; font-size: 11px;">Aktuell:</td>
|
||||
<td style="padding: 8px 0; border-bottom: 1px solid #1e293b; font-weight: bold; color: ${statusColor}; font-size: 14px;">${newLabel}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
${reasonSection}
|
||||
</div>
|
||||
|
||||
${footerActions}
|
||||
|
||||
<div style="text-align: center; margin-top: 32px; border-top: 1px solid #1e293b; padding-top: 20px; color: #475569; font-size: 11px; line-height: 1.5;">
|
||||
<p style="margin: 0; font-weight: 600;">CASPOS Computerabrechnungssysteme GmbH · Alte Bundesstraße 16 · 76846 Hauenstein</p>
|
||||
<p style="margin: 4px 0 0 0;">Dies ist eine automatisch generierte Systembenachrichtigung.</p>
|
||||
</div>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5;">Viele Grüße,<br>Dein CASPOS Team</p>
|
||||
</div>
|
||||
`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user