Form with client-side validation, server error handling, aria-invalid/ aria-describedby for a11y, localStorage persistence via useEventStorage composable. Routes for /create and /events/:token. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
42 lines
1023 B
TypeScript
42 lines
1023 B
TypeScript
export interface StoredEvent {
|
|
eventToken: string
|
|
organizerToken?: string
|
|
title: string
|
|
dateTime: string
|
|
expiryDate: string
|
|
}
|
|
|
|
const STORAGE_KEY = 'fete:events'
|
|
|
|
function readEvents(): StoredEvent[] {
|
|
try {
|
|
const raw = localStorage.getItem(STORAGE_KEY)
|
|
return raw ? (JSON.parse(raw) as StoredEvent[]) : []
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
function writeEvents(events: StoredEvent[]): void {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(events))
|
|
}
|
|
|
|
export function useEventStorage() {
|
|
function saveCreatedEvent(event: StoredEvent): void {
|
|
const events = readEvents().filter((e) => e.eventToken !== event.eventToken)
|
|
events.push(event)
|
|
writeEvents(events)
|
|
}
|
|
|
|
function getStoredEvents(): StoredEvent[] {
|
|
return readEvents()
|
|
}
|
|
|
|
function getOrganizerToken(eventToken: string): string | undefined {
|
|
const event = readEvents().find((e) => e.eventToken === eventToken)
|
|
return event?.organizerToken
|
|
}
|
|
|
|
return { saveCreatedEvent, getStoredEvents, getOrganizerToken }
|
|
}
|