diff --git a/src/modules/activities/components/CreateEventDialog.vue b/src/modules/activities/components/CreateEventDialog.vue index 739e300..5773200 100644 --- a/src/modules/activities/components/CreateEventDialog.vue +++ b/src/modules/activities/components/CreateEventDialog.vue @@ -24,6 +24,9 @@ import { Input } from '@/components/ui/input' import { Textarea } from '@/components/ui/textarea' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' +import { Switch } from '@/components/ui/switch' +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible' +import { Bell, ChevronDown } from 'lucide-vue-next' import { ScrollArea } from '@/components/ui/scroll-area' import { Select, @@ -125,6 +128,10 @@ const formSchema = toTypedSchema( fiat_currency: z.string().default("USD"), amount_tickets: z.number().min(0).max(100000).default(0), price_per_ticket: z.number().min(0).default(0), + email_notifications: z.boolean().default(false), + nostr_notifications: z.boolean().default(false), + notification_subject: z.string().max(200).default(''), + notification_body: z.string().max(2000).default(''), }) .superRefine((v, ctx) => { // End must not precede start. Compare on the folded date+time @@ -170,6 +177,10 @@ const form = useForm({ fiat_currency: 'USD', amount_tickets: 0, price_per_ticket: 0, + email_notifications: false, + nostr_notifications: false, + notification_subject: '', + notification_body: '', } }) @@ -192,6 +203,7 @@ function splitDateTime(value: string | null | undefined): { date: string; time: // When `true`, suppress the auto-mirror watcher so we don't clobber an // edit-mode population with start-date side effects mid-setValues. const isPopulating = ref(false) +const notificationsOpen = ref(false) // Auto-mirror end date to start: when the user picks a start date, // surface that same date in the end-date picker so a one-day event @@ -235,6 +247,10 @@ async function populateFromEvent(event: TicketedEvent) { fiat_currency: event.fiat_currency ?? 'USD', amount_tickets: event.amount_tickets ?? 0, price_per_ticket: event.price_per_ticket ?? 0, + email_notifications: event.extra?.email_notifications ?? false, + nostr_notifications: event.extra?.nostr_notifications ?? false, + notification_subject: event.extra?.notification_subject ?? '', + notification_body: event.extra?.notification_body ?? '', }) selectedCategories.value = [...(event.categories ?? [])] if (event.banner) { @@ -349,6 +365,18 @@ const onSubmit = form.handleSubmit(async (formValues) => { if (formValues.price_per_ticket) eventData.price_per_ticket = formValues.price_per_ticket if (selectedCategories.value.length > 0) eventData.categories = selectedCategories.value + // Notification config goes inside the `extra` envelope. On edit + // overlay onto the existing event.extra so unrelated fields the + // LNbits admin UI sets (promo_codes, conditional, min_tickets) + // survive the round-trip. + eventData.extra = { + ...(props.event?.extra ?? {}), + email_notifications: formValues.email_notifications, + nostr_notifications: formValues.nostr_notifications, + notification_subject: formValues.notification_subject, + notification_body: formValues.notification_body, + } + if (isEditMode.value) { if (!props.onUpdateEvent || !props.event?.id) { toastService.error('Update handler missing') @@ -649,6 +677,68 @@ const handleOpenChange = (open: boolean) => { /> + + + + + + +
+ + + Email confirmation + + + + + + + + + Nostr DM confirmation + + + + + +
+ + + + Subject + + + + Leave blank to use the default. + + + + + + + Body + +