/* @component-map * App — Main container, view routing [app.jsx] * EventCreator — Create new events with details and cover image [components/EventCreator.jsx] * EventDashboard — List of created events with stats [components/EventDashboard.jsx] * EventView — Public event page with RSVP form and guest list [components/EventView.jsx] * @end-component-map */ // DEPLOY_CONFIG: {"cron": [], "triggers": [{"name": "close-rsvps-at-capacity", "on": "collection.update", "collection": "events", "actions": [{"type": "email", "to": "{{event.organizer_email}}", "subject": "RSVPs closed for {{event.name}}", "body": "The event \"{{event.name}}\" has reached capacity ({{event.capacity}}). RSVPs have been automatically closed."}]}]} import { useState, useEffect } from 'react'; import { useCollection, sendEmail } from '@deplixo/sdk'; import { EventCreator } from './components/EventCreator.jsx'; import { EventDashboard } from './components/EventDashboard.jsx'; import { EventView } from './components/EventView.jsx'; function App() { const [view, setView] = useState('dashboard'); const [selectedEventId, setSelectedEventId] = useState(null); const { items: events, loading, add, update, remove } = useCollection('events', { personal: true }); const { items: rsvps, add: addRsvp, remove: removeRsvp } = useCollection('rsvps', { personal: true }); const handleCreateEvent = async (eventData) => { const result = await add({ ...eventData, createdAt: new Date().toISOString() }); setSelectedEventId(result.id); setView('event-view'); }; const handleViewEvent = (eventId) => { setSelectedEventId(eventId); setView('event-view'); }; const buildEventLink = (event) => { if (!event) return ''; const baseUrl = window.location.origin + window.location.pathname; return `${baseUrl}?event=${event.id}`; }; const handleAddRsvp = async (rsvpData) => { const result = await addRsvp(rsvpData); const event = events.find(e => e.id === rsvpData.eventId); if (event && rsvpData.email) { const eventLink = buildEventLink(event); const qrLink = event.qrCodeUrl || event.qrLink || ''; const details = [ event.date ? `
Date: ${event.date}
` : '', event.time ? `Time: ${event.time}
` : '', event.location ? `Location: ${event.location}
` : '', event.description ? `Details: ${event.description}
` : '', ].join(''); const qrSection = qrLink ? `QR Code Link: ${qrLink}
` : ''; await sendEmail({ to: rsvpData.email, subject: `You're confirmed for ${event.title}`, html: `Hi ${rsvpData.name || 'there'},
Thanks for RSVPing to ${event.title}. You're confirmed!
${details}Event Link: ${eventLink}
${qrSection}We look forward to seeing you there.
`, }); } return result; }; const handleDeleteEvent = async (eventId) => { await remove(eventId); const eventRsvps = rsvps.filter(r => r.value.eventId === eventId); for (const r of eventRsvps) await removeRsvp(r.id); if (selectedEventId === eventId) setView('dashboard'); }; const getEventRsvps = (eventId) => rsvps.filter(r => r.value.eventId === eventId); if (loading) { return (Loading your events...