mirror of
https://github.com/open-reception/appointment-booking-software.git
synced 2026-08-17 21:25:52 +02:00
Added Cancellation Email template
This commit is contained in:
@@ -951,6 +951,11 @@
|
|||||||
"introduction": "Ihr Termin wurde abgelehnt.",
|
"introduction": "Ihr Termin wurde abgelehnt.",
|
||||||
"reason": "Sie erhalten diese E-Mail, weil jemand mit Ihrer E-Mail Adresse einen Termin bei angefragt hat."
|
"reason": "Sie erhalten diese E-Mail, weil jemand mit Ihrer E-Mail Adresse einen Termin bei angefragt hat."
|
||||||
},
|
},
|
||||||
|
"appointmentCancelled": {
|
||||||
|
"subject": "Ihr Termin für {channel} bei {tenant} wurde abgesagt",
|
||||||
|
"introduction": "Ihr Termin wurde abgesagt.",
|
||||||
|
"reason": "Sie erhalten diese E-Mail, weil jemand mit Ihrer E-Mail Adresse einen Termin bei angefragt hat."
|
||||||
|
},
|
||||||
"confirmation": {
|
"confirmation": {
|
||||||
"subject": "E-Mail Adresse bestätigen",
|
"subject": "E-Mail Adresse bestätigen",
|
||||||
"introduction": "willkommen bei unserem Terminbuchungsportal. Bitte bestätige Deine E-Mail Adresse.",
|
"introduction": "willkommen bei unserem Terminbuchungsportal. Bitte bestätige Deine E-Mail Adresse.",
|
||||||
|
|||||||
@@ -960,6 +960,11 @@
|
|||||||
"introduction": "your appointment was requested. You will be notified once it is confirmed.",
|
"introduction": "your appointment was requested. You will be notified once it is confirmed.",
|
||||||
"reason": "You are receiving this email because someone requested an appointment with your e-mail address."
|
"reason": "You are receiving this email because someone requested an appointment with your e-mail address."
|
||||||
},
|
},
|
||||||
|
"appointmentCancelled": {
|
||||||
|
"subject": "Your appointment for {channel} at {tenant} was cancelled",
|
||||||
|
"introduction": "Your appointment was cancelled.",
|
||||||
|
"reason": "You are receiving this email because someone booked an appointment with your e-mail address."
|
||||||
|
},
|
||||||
"confirmation": {
|
"confirmation": {
|
||||||
"subject": "Confirm your E-Mail Address",
|
"subject": "Confirm your E-Mail Address",
|
||||||
"introduction": "welcome our appointment booking platform. Please confirm your e-mail address.",
|
"introduction": "welcome our appointment booking platform. Please confirm your e-mail address.",
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { m } from "$i18n/messages";
|
||||||
|
import { setLocale } from "$i18n/runtime";
|
||||||
|
import type { SupportedLocale } from "$lib/const/locales";
|
||||||
|
import type { SelectTenant } from "$lib/server/db/central-schema";
|
||||||
|
import { type SelectAppointment } from "$lib/server/db/tenant-schema";
|
||||||
|
import type { SelectClient } from "$lib/server/email/email-service";
|
||||||
|
import EmailHeadline from "./components/EmailHeadline.svelte";
|
||||||
|
import EmailLayout from "./components/EmailLayout.svelte";
|
||||||
|
import EmailText from "./components/EmailText.svelte";
|
||||||
|
import { renderAppointmentDate, renderAppointmentTime } from "./utils";
|
||||||
|
|
||||||
|
let {
|
||||||
|
locale,
|
||||||
|
user,
|
||||||
|
tenant,
|
||||||
|
channel,
|
||||||
|
appointment,
|
||||||
|
address,
|
||||||
|
}: {
|
||||||
|
locale: SupportedLocale;
|
||||||
|
user: SelectClient;
|
||||||
|
tenant: SelectTenant;
|
||||||
|
channel: string;
|
||||||
|
appointment: SelectAppointment & { agentName: string };
|
||||||
|
address: {
|
||||||
|
street: string;
|
||||||
|
number: string;
|
||||||
|
additionalAddressInfo?: string;
|
||||||
|
zip: string;
|
||||||
|
city: string;
|
||||||
|
};
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
setLocale(locale);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<EmailLayout>
|
||||||
|
<EmailText variant="md">{m["emails.greeting"]({ name: user.email })}</EmailText>
|
||||||
|
<EmailText variant="md">
|
||||||
|
{m["emails.appointmentCancelled.introduction"]()}
|
||||||
|
</EmailText>
|
||||||
|
<EmailHeadline>{channel}</EmailHeadline>
|
||||||
|
<EmailText variant="md">
|
||||||
|
{appointment.agentName}<br />
|
||||||
|
{renderAppointmentDate(appointment.appointmentDate, locale)}<br />
|
||||||
|
{renderAppointmentTime(appointment.appointmentDate, locale)}
|
||||||
|
{m["emails.oclock"]()}
|
||||||
|
</EmailText>
|
||||||
|
<EmailHeadline>{tenant.longName}</EmailHeadline>
|
||||||
|
<EmailText variant="md">
|
||||||
|
{address.street}
|
||||||
|
{address.number}<br />
|
||||||
|
{#if address.additionalAddressInfo}{address.additionalAddressInfo}<br />{/if}
|
||||||
|
{address.zip}
|
||||||
|
{address.city}
|
||||||
|
</EmailText>
|
||||||
|
<EmailText variant="md" color="text-light">
|
||||||
|
{m["emails.appointmentCancelled.reason"]()}
|
||||||
|
</EmailText>
|
||||||
|
</EmailLayout>
|
||||||
@@ -15,6 +15,7 @@ import { m } from "$i18n/messages";
|
|||||||
import { render } from "svelte/server";
|
import { render } from "svelte/server";
|
||||||
import AppointmentBooked from "$lib/emails/AppointmentBooked.svelte";
|
import AppointmentBooked from "$lib/emails/AppointmentBooked.svelte";
|
||||||
import AppointmentRejected from "$lib/emails/AppointmentRejected.svelte";
|
import AppointmentRejected from "$lib/emails/AppointmentRejected.svelte";
|
||||||
|
import AppointmentCancelled from "$lib/emails/AppointmentCancelled.svelte";
|
||||||
import { htmlToText, renderOutputToHtml } from "$lib/emails/utils";
|
import { htmlToText, renderOutputToHtml } from "$lib/emails/utils";
|
||||||
import { AgentService } from "../services/agent-service";
|
import { AgentService } from "../services/agent-service";
|
||||||
import { TenantService } from "../db/tenant-service";
|
import { TenantService } from "../db/tenant-service";
|
||||||
@@ -529,17 +530,25 @@ export async function sendAppointmentCancelledEmail(
|
|||||||
channelTitle?: string,
|
channelTitle?: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Create recipient directly for SelectClient type, use helper for SelectUser
|
// Create recipient directly for SelectClient type, use helper for SelectUser
|
||||||
const recipient: EmailRecipient =
|
const { recipient, locale } = await getRecipient(user);
|
||||||
"email" in user && typeof user.email === "string" && "language" in user && !("name" in user)
|
// Generate email
|
||||||
? { email: user.email, language: user.language }
|
const subject = m["emails.appointmentCancelled.subject"]({
|
||||||
: createEmailRecipient(user);
|
channel: channelTitle || appointment.channelId,
|
||||||
|
tenant: tenant.longName,
|
||||||
const language = (recipient.language as Language) || "en";
|
|
||||||
const subject = language === "en" ? "Appointment Cancelled" : "Termin storniert";
|
|
||||||
|
|
||||||
await sendTemplatedEmail("appointment-cancelled", recipient, subject, language, tenant, {
|
|
||||||
appointment,
|
|
||||||
appointmentDate: appointment.appointmentDate,
|
|
||||||
title: channelTitle || appointment.channelId,
|
|
||||||
});
|
});
|
||||||
|
const emailRender = render(AppointmentCancelled, {
|
||||||
|
props: {
|
||||||
|
locale,
|
||||||
|
channel: channelTitle || appointment.channelId,
|
||||||
|
user,
|
||||||
|
tenant,
|
||||||
|
appointment: { ...appointment, agentName: "---" },
|
||||||
|
address: await getAddressFromTenant(tenant.id),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const html = renderOutputToHtml(emailRender);
|
||||||
|
const text = htmlToText(html);
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
await sendEmail(recipient as any, subject, html, text);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ export class AppointmentService {
|
|||||||
|
|
||||||
public async cancelAppointment(id: string): Promise<SelectAppointment> {
|
public async cancelAppointment(id: string): Promise<SelectAppointment> {
|
||||||
const log = logger.setContext("AppointmentService");
|
const log = logger.setContext("AppointmentService");
|
||||||
log.debug("Confirming appointment by ID", { appointmentId: id, tenantId: this.tenantId });
|
log.debug("Cancelling appointment by ID", { appointmentId: id, tenantId: this.tenantId });
|
||||||
const db = await this.getDb();
|
const db = await this.getDb();
|
||||||
|
|
||||||
const result = await db
|
const result = await db
|
||||||
|
|||||||
Reference in New Issue
Block a user