Compare commits
No commits in common. "691f8df83088d6ed10eb41a0c2d64ff754705976" and "124cad124926363cfed6f32b3e5c5af53a653404" have entirely different histories.
691f8df830
...
124cad1249
4 changed files with 24 additions and 84 deletions
|
|
@ -62,9 +62,7 @@ const formSchema = toTypedSchema(z.object({
|
||||||
name: z.string().min(1, "Title is required").max(200, "Title too long"),
|
name: z.string().min(1, "Title is required").max(200, "Title too long"),
|
||||||
info: z.string().max(2000, "Description too long").optional().default(''),
|
info: z.string().max(2000, "Description too long").optional().default(''),
|
||||||
event_start_date: z.string().min(1, "Start date is required"),
|
event_start_date: z.string().min(1, "Start date is required"),
|
||||||
event_start_time: z.string().optional().default(''),
|
|
||||||
event_end_date: z.string().optional().default(''),
|
event_end_date: z.string().optional().default(''),
|
||||||
event_end_time: z.string().optional().default(''),
|
|
||||||
location: z.string().max(500).optional().default(''),
|
location: z.string().max(500).optional().default(''),
|
||||||
banner: z.string().optional().default(''),
|
banner: z.string().optional().default(''),
|
||||||
currency: z.string().default("sat"),
|
currency: z.string().default("sat"),
|
||||||
|
|
@ -78,9 +76,7 @@ const form = useForm({
|
||||||
name: '',
|
name: '',
|
||||||
info: '',
|
info: '',
|
||||||
event_start_date: '',
|
event_start_date: '',
|
||||||
event_start_time: '',
|
|
||||||
event_end_date: '',
|
event_end_date: '',
|
||||||
event_end_time: '',
|
|
||||||
location: '',
|
location: '',
|
||||||
banner: '',
|
banner: '',
|
||||||
currency: 'sat',
|
currency: 'sat',
|
||||||
|
|
@ -89,15 +85,6 @@ const form = useForm({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Fold a date input ("YYYY-MM-DD") and an optional time input ("HH:MM")
|
|
||||||
// into the events-extension wire format: date-only when no time given,
|
|
||||||
// ISO 8601 datetime otherwise. The publisher switches NIP-52 kinds on
|
|
||||||
// the "T" delimiter.
|
|
||||||
function foldDateTime(date: string, time: string): string {
|
|
||||||
if (!date) return ''
|
|
||||||
return time ? `${date}T${time}` : date
|
|
||||||
}
|
|
||||||
|
|
||||||
const paymentService = injectService(SERVICE_TOKENS.PAYMENT_SERVICE)
|
const paymentService = injectService(SERVICE_TOKENS.PAYMENT_SERVICE)
|
||||||
const ticketApi = injectService(SERVICE_TOKENS.TICKET_API) as TicketApiService | null
|
const ticketApi = injectService(SERVICE_TOKENS.TICKET_API) as TicketApiService | null
|
||||||
|
|
||||||
|
|
@ -157,21 +144,13 @@ const onSubmit = form.handleSubmit(async (formValues) => {
|
||||||
try {
|
try {
|
||||||
const eventData: CreateEventRequest = {
|
const eventData: CreateEventRequest = {
|
||||||
name: formValues.name,
|
name: formValues.name,
|
||||||
event_start_date: foldDateTime(
|
event_start_date: formValues.event_start_date,
|
||||||
formValues.event_start_date,
|
|
||||||
formValues.event_start_time
|
|
||||||
),
|
|
||||||
wallet: preferredWallet.id,
|
wallet: preferredWallet.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional fields — only include if provided
|
// Optional fields — only include if provided
|
||||||
if (formValues.info) eventData.info = formValues.info
|
if (formValues.info) eventData.info = formValues.info
|
||||||
if (formValues.event_end_date) {
|
if (formValues.event_end_date) eventData.event_end_date = formValues.event_end_date
|
||||||
eventData.event_end_date = foldDateTime(
|
|
||||||
formValues.event_end_date,
|
|
||||||
formValues.event_end_time
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (formValues.location) eventData.location = formValues.location
|
if (formValues.location) eventData.location = formValues.location
|
||||||
if (formValues.banner) eventData.banner = formValues.banner
|
if (formValues.banner) eventData.banner = formValues.banner
|
||||||
if (formValues.currency) eventData.currency = formValues.currency
|
if (formValues.currency) eventData.currency = formValues.currency
|
||||||
|
|
@ -228,29 +207,17 @@ const handleOpenChange = (open: boolean) => {
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<!-- Start date (required) + optional time -->
|
<!-- Start date (required) -->
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
|
||||||
<FormField v-slot="{ componentField }" name="event_start_date">
|
<FormField v-slot="{ componentField }" name="event_start_date">
|
||||||
<FormItem class="sm:col-span-2 min-w-0">
|
<FormItem>
|
||||||
<FormLabel>Start date *</FormLabel>
|
<FormLabel>Start date *</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="date" :min="today" class="w-full" v-bind="componentField" />
|
<Input type="date" :min="today" v-bind="componentField" />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField v-slot="{ componentField }" name="event_start_time">
|
|
||||||
<FormItem class="min-w-0">
|
|
||||||
<FormLabel>Start time</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input type="time" class="w-full" v-bind="componentField" />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Description (optional, visible) -->
|
<!-- Description (optional, visible) -->
|
||||||
<FormField v-slot="{ componentField }" name="info">
|
<FormField v-slot="{ componentField }" name="info">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
|
|
@ -362,28 +329,16 @@ const handleOpenChange = (open: boolean) => {
|
||||||
<CollapsibleContent class="space-y-4 pt-2">
|
<CollapsibleContent class="space-y-4 pt-2">
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
|
||||||
<FormField v-slot="{ componentField }" name="event_end_date">
|
<FormField v-slot="{ componentField }" name="event_end_date">
|
||||||
<FormItem class="sm:col-span-2 min-w-0">
|
<FormItem>
|
||||||
<FormLabel>End date</FormLabel>
|
<FormLabel>End date</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="date" :min="today" class="w-full" v-bind="componentField" />
|
<Input type="date" :min="today" v-bind="componentField" />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription class="text-xs">Defaults to start date</FormDescription>
|
<FormDescription class="text-xs">Defaults to start date if not set</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField v-slot="{ componentField }" name="event_end_time">
|
|
||||||
<FormItem class="min-w-0">
|
|
||||||
<FormLabel>End time</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input type="time" class="w-full" v-bind="componentField" />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
</CollapsibleContent>
|
</CollapsibleContent>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,14 +181,6 @@ export function parseCalendarDateEvent(event: NostrEvent): CalendarDateEvent | n
|
||||||
|
|
||||||
if (!dTag || !title || !start) return null
|
if (!dTag || !title || !start) return null
|
||||||
|
|
||||||
// NIP-52 kind 31922 requires YYYY-MM-DD. Reject anything else (including
|
|
||||||
// accidentally-published datetimes) so downstream parseIsoDate cannot
|
|
||||||
// produce an Invalid Date and crash the renderer.
|
|
||||||
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/
|
|
||||||
if (!ISO_DATE.test(start)) return null
|
|
||||||
const end = getTagValue(event.tags, 'end')
|
|
||||||
if (end && !ISO_DATE.test(end)) return null
|
|
||||||
|
|
||||||
const participants: Participant[] = event.tags
|
const participants: Participant[] = event.tags
|
||||||
.filter(t => t[0] === 'p')
|
.filter(t => t[0] === 'p')
|
||||||
.map(t => ({
|
.map(t => ({
|
||||||
|
|
@ -205,7 +197,7 @@ export function parseCalendarDateEvent(event: NostrEvent): CalendarDateEvent | n
|
||||||
content: event.content,
|
content: event.content,
|
||||||
image: getTagValue(event.tags, 'image'),
|
image: getTagValue(event.tags, 'image'),
|
||||||
start,
|
start,
|
||||||
end,
|
end: getTagValue(event.tags, 'end'),
|
||||||
location: getTagValue(event.tags, 'location'),
|
location: getTagValue(event.tags, 'location'),
|
||||||
geohash: getTagValue(event.tags, 'g'),
|
geohash: getTagValue(event.tags, 'g'),
|
||||||
hashtags: getTagValues(event.tags, 't'),
|
hashtags: getTagValues(event.tags, 't'),
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,6 @@ export interface TicketPaymentStatus {
|
||||||
/**
|
/**
|
||||||
* LNbits events extension event (database-backed ticketed event).
|
* LNbits events extension event (database-backed ticketed event).
|
||||||
* Corresponds to the Event model in the events extension.
|
* Corresponds to the Event model in the events extension.
|
||||||
*
|
|
||||||
* event_start_date / event_end_date are ISO 8601 — either date-only
|
|
||||||
* ("2026-05-19") or with a time ("2026-05-19T18:30"). Presence of "T"
|
|
||||||
* switches the publisher between NIP-52 kind 31922 and 31923.
|
|
||||||
*/
|
*/
|
||||||
export interface TicketedEvent {
|
export interface TicketedEvent {
|
||||||
id: string
|
id: string
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,7 @@ function formatDate(dateStr: string | null | undefined) {
|
||||||
if (!dateStr) return 'Date not available'
|
if (!dateStr) return 'Date not available'
|
||||||
const date = new Date(dateStr)
|
const date = new Date(dateStr)
|
||||||
if (isNaN(date.getTime())) return 'Invalid date'
|
if (isNaN(date.getTime())) return 'Invalid date'
|
||||||
// Presence of "T" in the wire value marks a time-based event (NIP-52
|
return format(date, 'MMMM do, yyyy')
|
||||||
// kind 31923 on our publisher). Show time only when one was set.
|
|
||||||
const hasTime = dateStr.includes('T')
|
|
||||||
return format(date, hasTime ? 'MMMM do, yyyy p' : 'MMMM do, yyyy')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePurchaseClick(event: {
|
function handlePurchaseClick(event: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue