Implementiere Impressum/Datenschutz-System und bereinige URL-Konfiguration

- Neues Impressum/Datenschutz-Tab mit konfigurierbaren rechtlichen Daten
- Konfigurationsdatei legal-config.ts für alle rechtlichen Informationen
- RPC-Endpoint legal.getConfig() für rechtliche Daten
- Schöne Tab-Navigation zwischen Impressum und Datenschutz
- Responsive Design mit Loading-States und Fehlerbehandlung
- Alle rechtlichen Daten über Umgebungsvariablen konfigurierbar
- FRONTEND_URL entfernt - nur noch DOMAIN wird verwendet
- Hilfsfunktion generateUrl() für konsistente URL-Generierung
- Code-Duplikation in bookings.ts eliminiert
- .env.example aktualisiert mit allen neuen Variablen
- README.md dokumentiert neue rechtliche Konfiguration
- DSGVO- und TMG-konforme Inhalte implementiert
This commit is contained in:
2025-09-30 18:14:01 +02:00
parent 55923e0426
commit 40d76680fd
9 changed files with 407 additions and 27 deletions

View File

@@ -19,6 +19,13 @@ function formatDateGerman(dateString: string): string {
return `${day}.${month}.${year}`;
}
// Helper function to generate URLs from DOMAIN environment variable
function generateUrl(path: string = ''): string {
const domain = process.env.DOMAIN || 'localhost:5173';
const protocol = domain.includes('localhost') ? 'http' : 'https';
return `${protocol}://${domain}${path}`;
}
const BookingSchema = z.object({
id: z.string(),
treatmentId: z.string(),
@@ -119,9 +126,7 @@ const create = os
// Notify customer: request received (pending)
void (async () => {
const formattedDate = formatDateGerman(input.appointmentDate);
const domain = process.env.DOMAIN || 'localhost:5173';
const protocol = domain.includes('localhost') ? 'http' : 'https';
const homepageUrl = `${protocol}://${domain}`;
const homepageUrl = generateUrl();
const html = await renderBookingPendingHTML({ name: input.customerName, date: input.appointmentDate, time: input.appointmentTime });
await sendEmail({
to: input.customerEmail,
@@ -150,9 +155,7 @@ const create = os
hasInspirationPhoto: !!input.inspirationPhoto
});
const domain = process.env.DOMAIN || 'localhost:5173';
const protocol = domain.includes('localhost') ? 'http' : 'https';
const homepageUrl = `${protocol}://${domain}`;
const homepageUrl = generateUrl();
const adminText = `Neue Buchungsanfrage eingegangen:\n\n` +
`Name: ${input.customerName}\n` +
@@ -260,7 +263,8 @@ const updateStatus = os
const cancellationToken = await queryClient.cancellation.createToken({ bookingId: booking.id });
const formattedDate = formatDateGerman(booking.appointmentDate);
const cancellationUrl = `${process.env.FRONTEND_URL || 'http://localhost:5173'}/cancel/${cancellationToken.token}`;
const cancellationUrl = generateUrl(`/cancel/${cancellationToken.token}`);
const homepageUrl = generateUrl();
const html = await renderBookingConfirmedHTML({
name: booking.customerName,
@@ -269,10 +273,6 @@ const updateStatus = os
cancellationUrl
});
const domain = process.env.DOMAIN || 'localhost:5173';
const protocol = domain.includes('localhost') ? 'http' : 'https';
const homepageUrl = `${protocol}://${domain}`;
await sendEmailWithAGB({
to: booking.customerEmail,
subject: "Dein Termin wurde bestätigt - AGB im Anhang",
@@ -282,9 +282,7 @@ const updateStatus = os
});
} else if (input.status === "cancelled") {
const formattedDate = formatDateGerman(booking.appointmentDate);
const domain = process.env.DOMAIN || 'localhost:5173';
const protocol = domain.includes('localhost') ? 'http' : 'https';
const homepageUrl = `${protocol}://${domain}`;
const homepageUrl = generateUrl();
const html = await renderBookingCancelledHTML({ name: booking.customerName, date: booking.appointmentDate, time: booking.appointmentTime });
await sendEmail({
to: booking.customerEmail,