diff --git a/src/modules/events/components/CreateEventDialog.vue b/src/modules/events/components/CreateEventDialog.vue index ee8f487..bb7f20e 100644 --- a/src/modules/events/components/CreateEventDialog.vue +++ b/src/modules/events/components/CreateEventDialog.vue @@ -71,6 +71,10 @@ interface Props { autoApprove?: boolean } +// Instance name used in the From display name of ticket emails +// (the LNbits site title on the backend; the standalone's brand here). +const siteName = (import.meta.env.VITE_APP_NAME as string) || 'Events' + const props = defineProps() const emit = defineEmits<{ 'update:open': [value: boolean] @@ -144,6 +148,12 @@ const formSchema = toTypedSchema( nostr_notifications: z.boolean().default(false), notification_subject: z.string().max(200).default(''), notification_body: z.string().max(2000).default(''), + organizer_name: z.string().trim().max(100).default(''), + reply_to_email: z + .string() + .trim() + .default('') + .refine((v) => v === '' || z.string().email().safeParse(v).success, 'Invalid email address'), }) .superRefine((v, ctx) => { // End must not precede start. Compare on the folded date+time @@ -193,6 +203,8 @@ const form = useForm({ nostr_notifications: false, notification_subject: '', notification_body: '', + organizer_name: '', + reply_to_email: '', } }) @@ -299,6 +311,8 @@ async function populateFromEvent(event: TicketedEvent) { nostr_notifications: event.extra?.nostr_notifications ?? false, notification_subject: event.extra?.notification_subject ?? '', notification_body: event.extra?.notification_body ?? '', + organizer_name: event.extra?.organizer_name ?? '', + reply_to_email: event.extra?.reply_to_email ?? '', }) selectedCategories.value = [...(event.categories ?? [])] if (event.banner) { @@ -425,6 +439,8 @@ const onSubmit = form.handleSubmit(async (formValues) => { nostr_notifications: formValues.nostr_notifications, notification_subject: formValues.notification_subject, notification_body: formValues.notification_body, + organizer_name: formValues.organizer_name, + reply_to_email: formValues.reply_to_email || null, } if (isEditMode.value) { @@ -851,6 +867,35 @@ const handleOpenChange = (open: boolean) => { + + + + + Organizer name + + + + + Ticket emails arrive from "Organizer name via {{ siteName }}". + + + + + + + + Reply-to email + + + + + Where attendee replies go. Leave blank to use your account email. + + + + diff --git a/src/modules/events/types/ticket.ts b/src/modules/events/types/ticket.ts index d42b3c2c..533db2f 100644 --- a/src/modules/events/types/ticket.ts +++ b/src/modules/events/types/ticket.ts @@ -26,6 +26,12 @@ export interface EventExtra { nostr_notifications: boolean notification_subject: string notification_body: string + /** Shown as " via " in the From line of ticket + * emails. Optional. */ + organizer_name?: string + /** Reply-To for ticket emails; null/absent = the organizer's LNbits + * account email. */ + reply_to_email?: string | null /** Rails the organizer enabled (`lightning`, `fiat`). Empty / absent * means the legacy rule: Lightning always, fiat iff `allow_fiat`. * Same shape as upstream v2's `extra.payment_methods`. */