@burdenoff/microfe-eventfullymanaged 2026.704.4 → 2026.704.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/eventfullymanaged/api/eventApi.js +136 -97
- package/dist/eventfullymanaged/api/eventApi.js.map +1 -1
- package/dist/eventfullymanaged/pages/events/EventDetailPage.js +180 -164
- package/dist/eventfullymanaged/pages/events/EventDetailPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/RegistrationPage.js +136 -120
- package/dist/eventfullymanaged/pages/modules/RegistrationPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/SponsorDetailsPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/speakers/SpeakersPage.js +56 -47
- package/dist/eventfullymanaged/pages/speakers/SpeakersPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/venues/FloorPlansPage.js +77 -63
- package/dist/eventfullymanaged/pages/venues/FloorPlansPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventDetailPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/events/EventDetailPage.tsx"],"sourcesContent":["import { ArrowLeft, CalendarClock, Edit, MapPin, Plus, Ticket as TicketIcon, Users } from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n IllustratedEmptyState,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport {\n useDeleteTicketTypeMutation,\n useEventQuery,\n useEventSessionsQuery,\n useSpeakersQuery,\n useTicketTypesQuery,\n type TicketTypeGql,\n} from '../../api/eventApi';\nimport { ActionMenu } from '../../components/ActionMenu';\nimport { Pagination, usePagination } from '../../components/Pagination';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { notify } from '../../lib/toast';\nimport { formatDateTime } from './eventFormUtils';\n\nfunction statusVariant(status: string): 'success' | 'warning' | 'secondary' | 'info' {\n const value = status.toLowerCase();\n if (['active', 'published', 'live', 'confirmed', 'completed', 'approved'].includes(value)) {\n return 'success';\n }\n if (['inactive', 'cancelled', 'archived', 'closed', 'expired'].includes(value)) {\n return 'warning';\n }\n if (['draft', 'created', 'pending', 'scheduled'].includes(value)) {\n return 'info';\n }\n return 'secondary';\n}\n\n// ---------------------------------------------------------------------------\n\ntype SessionRow = {\n id: string;\n title: string;\n sessionType: string;\n track?: string | null;\n startsAt: string;\n endsAt: string;\n status: string;\n};\n\nfunction SessionsTab({ eventId }: { eventId: string }) {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination();\n const { data, loading } = useEventSessionsQuery({ eventId, limit: pagination.limit, offset: pagination.offset });\n\n const total = data?.eventSessions?.total ?? 0;\n const rows = (data?.eventSessions?.items ?? []) as unknown as SessionRow[];\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Agenda & Sessions</h2>\n <Button type=\"button\" size=\"sm\" onClick={() => navigate(`/events/${eventId}/sessions/create`)}>\n <Plus className=\"h-4 w-4\" />\n New Session\n </Button>\n </div>\n\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading sessions…</p>\n ) : rows.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No sessions yet.\"\n description=\"Build the agenda by adding your first session.\"\n className=\"py-8\"\n />\n ) : (\n <ul className=\"space-y-2.5\">\n {rows.map((session) => (\n <li\n key={session.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] duration-200 hover:border-border-strong hover:shadow-elevation-1\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{session.title}</p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {[session.track, session.startsAt ? formatDateTime(session.startsAt) : undefined]\n .filter(Boolean)\n .join(' • ')}\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant={statusVariant(session.status)} className=\"uppercase\">\n {session.status}\n </Badge>\n <ActionMenu\n ariaLabel={`Session actions for ${session.title}`}\n onEdit={() => navigate(`/events/${eventId}/sessions/${session.id}/edit`)}\n />\n </div>\n </div>\n </li>\n ))}\n </ul>\n )}\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={rows.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"sessions\"\n loading={loading}\n />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n\ntype SpeakerRow = { id: string; fullName: string; title?: string | null; organization?: string | null };\n\nfunction SpeakersTab() {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination();\n const { data, loading } = useSpeakersQuery({ limit: pagination.limit, offset: pagination.offset });\n\n const total = data?.speakers?.total ?? 0;\n const rows = (data?.speakers?.items ?? []) as unknown as SpeakerRow[];\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Speakers</h2>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => navigate('/speakers')}>\n Manage speakers\n </Button>\n <Button type=\"button\" size=\"sm\" onClick={() => navigate('/speakers/create')}>\n <Plus className=\"h-4 w-4\" />\n New Speaker\n </Button>\n </div>\n </div>\n\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading speakers…</p>\n ) : rows.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title=\"No speakers yet.\"\n description=\"Add speakers so you can assign them to sessions.\"\n className=\"py-8\"\n />\n ) : (\n <ul className=\"space-y-2.5\">\n {rows.map((speaker) => (\n <li\n key={speaker.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] duration-200 hover:border-border-strong hover:shadow-elevation-1\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{speaker.fullName}</p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {[speaker.title, speaker.organization].filter(Boolean).join(' • ') || 'Speaker'}\n </p>\n </div>\n <ActionMenu\n ariaLabel={`Speaker actions for ${speaker.fullName}`}\n onEdit={() => navigate(`/speakers/${speaker.id}/edit`)}\n />\n </div>\n </li>\n ))}\n </ul>\n )}\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={rows.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"speakers\"\n loading={loading}\n />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n\nfunction TicketsTab({ eventId }: { eventId: string }) {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination();\n const { data, loading, refetch } = useTicketTypesQuery({\n eventId,\n limit: pagination.limit,\n offset: pagination.offset,\n });\n const [deleteTicketType] = useDeleteTicketTypeMutation();\n\n const total = data?.ticketTypes?.total ?? 0;\n const rows = (data?.ticketTypes?.items ?? []) as TicketTypeGql[];\n\n const onDelete = async (ticket: TicketTypeGql) => {\n const response = await deleteTicketType({ variables: { id: ticket.id } });\n if (response.error) {\n notify.error('Could not delete ticket type', response.error.message);\n throw response.error;\n }\n if (!response.data?.deleteTicketType) {\n notify.error('Could not delete ticket type', 'The server did not confirm the change.');\n throw new Error('delete-unconfirmed');\n }\n notify.success('Ticket type deleted');\n await refetch();\n };\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Ticket Types</h2>\n <Button type=\"button\" size=\"sm\" onClick={() => navigate(`/events/${eventId}/tickets/create`)}>\n <Plus className=\"h-4 w-4\" />\n New Ticket Type\n </Button>\n </div>\n\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading ticket types…</p>\n ) : rows.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No ticket types yet.\"\n description=\"Add a ticket type so attendees can register.\"\n className=\"py-8\"\n />\n ) : (\n <ul className=\"space-y-2.5\">\n {rows.map((ticket) => (\n <li\n key={ticket.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] duration-200 hover:border-border-strong hover:shadow-elevation-1\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{ticket.name}</p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {ticket.price} {ticket.currency} • Sold {ticket.soldCount}\n {ticket.capacity != null ? ` / ${ticket.capacity}` : ''}\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant={ticket.isActive ? 'success' : 'warning'} className=\"uppercase\">\n {ticket.isActive ? 'Active' : 'Inactive'}\n </Badge>\n <ActionMenu\n ariaLabel={`Ticket actions for ${ticket.name}`}\n entityName={ticket.name}\n deleteLabel=\"Delete ticket type\"\n onEdit={() => navigate(`/events/${eventId}/tickets/${ticket.id}/edit`)}\n onDelete={() => onDelete(ticket)}\n />\n </div>\n </div>\n </li>\n ))}\n </ul>\n )}\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={rows.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"ticket types\"\n loading={loading}\n />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n\nexport default function EventDetailPage() {\n const { id = '' } = useParams<{ id: string }>();\n const { navigate } = useEventfullyManaged();\n const { data, loading } = useEventQuery(id);\n const [tab, setTab] = useState('overview');\n\n const event = data?.event ?? null;\n const venueId = useMemo(() => {\n const metadata = (event?.metadata ?? {}) as Record<string, unknown>;\n return typeof metadata.venueId === 'string' ? (metadata.venueId as string) : '';\n }, [event]);\n\n if (loading) {\n return <div className=\"p-6 text-sm text-text-secondary\">Loading event…</div>;\n }\n\n if (!event) {\n return (\n <div className=\"space-y-4 p-6\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => navigate('/events')}>\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Events\n </Button>\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"Event not found.\"\n description=\"This event may have been removed or is outside your current scope.\"\n />\n </GlassCard>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-3\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => navigate('/events')}>\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Events\n </Button>\n <div>\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-2xl font-bold text-text-primary\">{event.name}</h1>\n <Badge variant={statusVariant(event.status)} className=\"uppercase\">\n {event.status}\n </Badge>\n </div>\n <p className=\"mt-1 flex items-center gap-2 text-sm text-text-secondary\">\n <CalendarClock className=\"h-4 w-4\" />\n {formatDateTime(event.startAt)} — {formatDateTime(event.endAt)}\n </p>\n </div>\n </div>\n <Button type=\"button\" onClick={() => navigate(`/events/${id}/edit`)}>\n <Edit className=\"h-4 w-4\" />\n Edit Event\n </Button>\n </div>\n\n <Tabs value={tab} onValueChange={setTab}>\n <TabsList>\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"sessions\">Sessions</TabsTrigger>\n <TabsTrigger value=\"speakers\">Speakers</TabsTrigger>\n <TabsTrigger value=\"tickets\">Tickets</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"mt-4\">\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"mb-2 flex items-center gap-2 text-sm font-medium text-text-primary\">\n <TicketIcon className=\"h-4 w-4 text-action-primary-bg\" />\n Type\n </div>\n <p className=\"text-sm uppercase text-text-secondary\">{event.type}</p>\n </GlassCard>\n <GlassCard treatment=\"glass\" glow className=\"p-4\">\n <div className=\"mb-2 flex items-center gap-2 text-sm font-medium text-text-primary\">\n <Users className=\"h-4 w-4 text-action-primary-bg\" />\n Capacity\n </div>\n <p className=\"text-sm tabular-nums text-text-secondary\">{event.capacity ?? 0} attendees</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"mb-2 flex items-center gap-2 text-sm font-medium text-text-primary\">\n <MapPin className=\"h-4 w-4 text-action-primary-bg\" />\n Timezone\n </div>\n <p className=\"text-sm text-text-secondary\">{event.timezone}</p>\n </GlassCard>\n </div>\n\n <GlassCard treatment=\"plain\" className=\"mt-4 border-border-seam p-5\">\n <h2 className=\"text-lg font-semibold text-text-primary\">About</h2>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {event.description?.trim() ? event.description : 'No description provided.'}\n </p>\n <dl className=\"mt-4 grid grid-cols-1 gap-3 text-sm sm:grid-cols-2\">\n <div>\n <dt className=\"text-text-muted\">Visibility</dt>\n <dd className=\"capitalize text-text-primary\">{event.visibility}</dd>\n </div>\n <div>\n <dt className=\"text-text-muted\">Venue</dt>\n <dd className=\"text-text-primary\">\n {venueId ? (\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"sm\"\n className=\"h-auto p-0\"\n onClick={() => navigate(`/venues/${venueId}`)}\n >\n View venue\n </Button>\n ) : (\n 'No venue assigned'\n )}\n </dd>\n </div>\n </dl>\n <div className=\"mt-4\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => navigate(`/events/${id}/edit`)}>\n <Edit className=\"h-4 w-4\" />\n Edit event details\n </Button>\n </div>\n </GlassCard>\n </TabsContent>\n\n <TabsContent value=\"sessions\" className=\"mt-4\">\n <SessionsTab eventId={id} />\n </TabsContent>\n\n <TabsContent value=\"speakers\" className=\"mt-4\">\n <SpeakersTab />\n </TabsContent>\n\n <TabsContent value=\"tickets\" className=\"mt-4\">\n <TicketsTab eventId={id} />\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AA4BA,SAAS,EAAc,GAA8D;CACnF,IAAM,IAAQ,EAAO,aAAa;AAUlC,QATI;EAAC;EAAU;EAAa;EAAQ;EAAa;EAAa;EAAW,CAAC,SAAS,EAAM,GAChF,YAEL;EAAC;EAAY;EAAa;EAAY;EAAU;EAAU,CAAC,SAAS,EAAM,GACrE,YAEL;EAAC;EAAS;EAAW;EAAW;EAAY,CAAC,SAAS,EAAM,GACvD,SAEF;;AAeT,SAAS,EAAY,EAAE,cAAgC;CACrD,IAAM,EAAE,gBAAa,GAAsB,EACrC,IAAa,GAAe,EAC5B,EAAE,SAAM,eAAY,EAAsB;EAAE;EAAS,OAAO,EAAW;EAAO,QAAQ,EAAW;EAAQ,CAAC,EAE1G,IAAQ,GAAM,eAAe,SAAS,GACtC,IAAQ,GAAM,eAAe,SAAS,EAAE;AAE9C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eAA0C;KAA0B,CAAA,EAClF,kBAAC,GAAD;KAAQ,MAAK;KAAS,MAAK;KAAK,eAAe,EAAS,WAAW,EAAQ,kBAAkB;eAA7F,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,cAErB;OACL;;GAEL,IACC,kBAAC,KAAD;IAAG,WAAU;cAA8B;IAAqB,CAAA,GAC9D,EAAK,WAAW,IAClB,kBAAC,GAAD;IACE,cAAa;IACb,OAAM;IACN,aAAY;IACZ,WAAU;IACV,CAAA,GAEF,kBAAC,MAAD;IAAI,WAAU;cACX,EAAK,KAAK,MACT,kBAAC,MAAD;KAEE,WAAU;eAEV,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA0C,EAAQ;QAAU,CAAA,EACzE,kBAAC,KAAD;QAAG,WAAU;kBACV,CAAC,EAAQ,OAAO,EAAQ,WAAW,EAAe,EAAQ,SAAS,GAAG,KAAA,EAAU,CAC9E,OAAO,QAAQ,CACf,KAAK,MAAM;QACZ,CAAA,CACA;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAS,EAAc,EAAQ,OAAO;QAAE,WAAU;kBACtD,EAAQ;QACH,CAAA,EACR,kBAAC,GAAD;QACE,WAAW,uBAAuB,EAAQ;QAC1C,cAAc,EAAS,WAAW,EAAQ,YAAY,EAAQ,GAAG,OAAO;QACxE,CAAA,CACE;SACF;;KACH,EAtBE,EAAQ,GAsBV,CACL;IACC,CAAA;GAGP,kBAAC,GAAD;IACE,QAAQ,EAAW;IACnB,OAAO,EAAW;IAClB,aAAa,EAAK;IACX;IACP,QAAQ,EAAW;IACnB,QAAQ,EAAW;IACnB,WAAU;IACD;IACT,CAAA;GACE;;;AAQV,SAAS,IAAc;CACrB,IAAM,EAAE,gBAAa,GAAsB,EACrC,IAAa,GAAe,EAC5B,EAAE,SAAM,eAAY,EAAiB;EAAE,OAAO,EAAW;EAAO,QAAQ,EAAW;EAAQ,CAAC,EAE5F,IAAQ,GAAM,UAAU,SAAS,GACjC,IAAQ,GAAM,UAAU,SAAS,EAAE;AAEzC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eAA0C;KAAa,CAAA,EACrE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAQ,MAAK;MAAS,SAAQ;MAAU,MAAK;MAAK,eAAe,EAAS,YAAY;gBAAE;MAE/E,CAAA,EACT,kBAAC,GAAD;MAAQ,MAAK;MAAS,MAAK;MAAK,eAAe,EAAS,mBAAmB;gBAA3E,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,cAErB;QACL;OACF;;GAEL,IACC,kBAAC,KAAD;IAAG,WAAU;cAA8B;IAAqB,CAAA,GAC9D,EAAK,WAAW,IAClB,kBAAC,GAAD;IACE,cAAa;IACb,OAAM;IACN,aAAY;IACZ,WAAU;IACV,CAAA,GAEF,kBAAC,MAAD;IAAI,WAAU;cACX,EAAK,KAAK,MACT,kBAAC,MAAD;KAEE,WAAU;eAEV,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA0C,EAAQ;QAAa,CAAA,EAC5E,kBAAC,KAAD;QAAG,WAAU;kBACV,CAAC,EAAQ,OAAO,EAAQ,aAAa,CAAC,OAAO,QAAQ,CAAC,KAAK,MAAM,IAAI;QACpE,CAAA,CACA;UACN,kBAAC,GAAD;OACE,WAAW,uBAAuB,EAAQ;OAC1C,cAAc,EAAS,aAAa,EAAQ,GAAG,OAAO;OACtD,CAAA,CACE;;KACH,EAfE,EAAQ,GAeV,CACL;IACC,CAAA;GAGP,kBAAC,GAAD;IACE,QAAQ,EAAW;IACnB,OAAO,EAAW;IAClB,aAAa,EAAK;IACX;IACP,QAAQ,EAAW;IACnB,QAAQ,EAAW;IACnB,WAAU;IACD;IACT,CAAA;GACE;;;AAMV,SAAS,EAAW,EAAE,cAAgC;CACpD,IAAM,EAAE,gBAAa,GAAsB,EACrC,IAAa,GAAe,EAC5B,EAAE,SAAM,YAAS,eAAY,EAAoB;EACrD;EACA,OAAO,EAAW;EAClB,QAAQ,EAAW;EACpB,CAAC,EACI,CAAC,KAAoB,GAA6B,EAElD,IAAQ,GAAM,aAAa,SAAS,GACpC,IAAQ,GAAM,aAAa,SAAS,EAAE,EAEtC,IAAW,OAAO,MAA0B;EAChD,IAAM,IAAW,MAAM,EAAiB,EAAE,WAAW,EAAE,IAAI,EAAO,IAAI,EAAE,CAAC;AACzE,MAAI,EAAS,MAEX,OADA,EAAO,MAAM,gCAAgC,EAAS,MAAM,QAAQ,EAC9D,EAAS;AAEjB,MAAI,CAAC,EAAS,MAAM,iBAElB,OADA,EAAO,MAAM,gCAAgC,yCAAyC,EAC5E,MAAM,qBAAqB;AAGvC,EADA,EAAO,QAAQ,sBAAsB,EACrC,MAAM,GAAS;;AAGjB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eAA0C;KAAiB,CAAA,EACzE,kBAAC,GAAD;KAAQ,MAAK;KAAS,MAAK;KAAK,eAAe,EAAS,WAAW,EAAQ,iBAAiB;eAA5F,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,kBAErB;OACL;;GAEL,IACC,kBAAC,KAAD;IAAG,WAAU;cAA8B;IAAyB,CAAA,GAClE,EAAK,WAAW,IAClB,kBAAC,GAAD;IACE,cAAa;IACb,OAAM;IACN,aAAY;IACZ,WAAU;IACV,CAAA,GAEF,kBAAC,MAAD;IAAI,WAAU;cACX,EAAK,KAAK,MACT,kBAAC,MAAD;KAEE,WAAU;eAEV,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA0C,EAAO;QAAS,CAAA,EACvE,kBAAC,KAAD;QAAG,WAAU;kBAAb;SACG,EAAO;SAAM;SAAE,EAAO;SAAS;SAAS,EAAO;SAC/C,EAAO,YAAY,OAAiC,KAA1B,MAAM,EAAO;SACtC;UACA;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAS,EAAO,WAAW,YAAY;QAAW,WAAU;kBAChE,EAAO,WAAW,WAAW;QACxB,CAAA,EACR,kBAAC,GAAD;QACE,WAAW,sBAAsB,EAAO;QACxC,YAAY,EAAO;QACnB,aAAY;QACZ,cAAc,EAAS,WAAW,EAAQ,WAAW,EAAO,GAAG,OAAO;QACtE,gBAAgB,EAAS,EAAO;QAChC,CAAA,CACE;SACF;;KACH,EAxBE,EAAO,GAwBT,CACL;IACC,CAAA;GAGP,kBAAC,GAAD;IACE,QAAQ,EAAW;IACnB,OAAO,EAAW;IAClB,aAAa,EAAK;IACX;IACP,QAAQ,EAAW;IACnB,QAAQ,EAAW;IACnB,WAAU;IACD;IACT,CAAA;GACE;;;AAMV,SAAwB,IAAkB;CACxC,IAAM,EAAE,QAAK,OAAO,GAA2B,EACzC,EAAE,gBAAa,GAAsB,EACrC,EAAE,SAAM,eAAY,EAAc,EAAG,EACrC,CAAC,GAAK,KAAU,EAAS,WAAW,EAEpC,IAAQ,GAAM,SAAS,MACvB,IAAU,QAAc;EAC5B,IAAM,IAAY,GAAO,YAAY,EAAE;AACvC,SAAO,OAAO,EAAS,WAAY,WAAY,EAAS,UAAqB;IAC5E,CAAC,EAAM,CAAC;AAwBX,QAtBI,IACK,kBAAC,OAAD;EAAK,WAAU;YAAkC;EAAoB,CAAA,GAGzE,IAmBH,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAQ,MAAK;KAAS,SAAQ;KAAQ,MAAK;KAAK,eAAe,EAAS,UAAU;eAAlF,CACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAAA,iBAE1B;QACT,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,MAAD;MAAI,WAAU;gBAAwC,EAAM;MAAU,CAAA,EACtE,kBAAC,GAAD;MAAO,SAAS,EAAc,EAAM,OAAO;MAAE,WAAU;gBACpD,EAAM;MACD,CAAA,CACJ;QACN,kBAAC,KAAD;KAAG,WAAU;eAAb;MACE,kBAAC,GAAD,EAAe,WAAU,WAAY,CAAA;MACpC,EAAe,EAAM,QAAQ;MAAC;MAAI,EAAe,EAAM,MAAM;MAC5D;OACA,EAAA,CAAA,CACF;OACN,kBAAC,GAAD;IAAQ,MAAK;IAAS,eAAe,EAAS,WAAW,EAAG,OAAO;cAAnE,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,aAErB;MACL;MAEN,kBAAC,GAAD;GAAM,OAAO;GAAK,eAAe;aAAjC;IACE,kBAAC,GAAD,EAAA,UAAA;KACE,kBAAC,GAAD;MAAa,OAAM;gBAAW;MAAsB,CAAA;KACpD,kBAAC,GAAD;MAAa,OAAM;gBAAW;MAAsB,CAAA;KACpD,kBAAC,GAAD;MAAa,OAAM;gBAAW;MAAsB,CAAA;KACpD,kBAAC,GAAD;MAAa,OAAM;gBAAU;MAAqB,CAAA;KACzC,EAAA,CAAA;IAEX,kBAAC,GAAD;KAAa,OAAM;KAAW,WAAU;eAAxC,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,GAAD;QAAW,WAAU;QAAS,WAAU;kBAAxC,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD,EAAY,WAAU,kCAAmC,CAAA,EAAA,OAErD;YACN,kBAAC,KAAD;SAAG,WAAU;mBAAyC,EAAM;SAAS,CAAA,CAC3D;;OACZ,kBAAC,GAAD;QAAW,WAAU;QAAQ,MAAA;QAAK,WAAU;kBAA5C,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,kCAAmC,CAAA,EAAA,WAEhD;YACN,kBAAC,KAAD;SAAG,WAAU;mBAAb,CAAyD,EAAM,YAAY,GAAE,aAAc;WACjF;;OACZ,kBAAC,GAAD;QAAW,WAAU;QAAS,WAAU;kBAAxC,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,kCAAmC,CAAA,EAAA,WAEjD;YACN,kBAAC,KAAD;SAAG,WAAU;mBAA+B,EAAM;SAAa,CAAA,CACrD;;OACR;SAEN,kBAAC,GAAD;MAAW,WAAU;MAAQ,WAAU;gBAAvC;OACE,kBAAC,MAAD;QAAI,WAAU;kBAA0C;QAAU,CAAA;OAClE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAM,aAAa,MAAM,GAAG,EAAM,cAAc;QAC/C,CAAA;OACJ,kBAAC,MAAD;QAAI,WAAU;kBAAd,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAAkB;SAAe,CAAA,EAC/C,kBAAC,MAAD;SAAI,WAAU;mBAAgC,EAAM;SAAgB,CAAA,CAChE,EAAA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAAkB;SAAU,CAAA,EAC1C,kBAAC,MAAD;SAAI,WAAU;mBACX,IACC,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,MAAK;UACL,WAAU;UACV,eAAe,EAAS,WAAW,IAAU;oBAC9C;UAEQ,CAAA,GAET;SAEC,CAAA,CACD,EAAA,CAAA,CACH;;OACL,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,GAAD;SAAQ,MAAK;SAAS,SAAQ;SAAU,MAAK;SAAK,eAAe,EAAS,WAAW,EAAG,OAAO;mBAA/F,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,qBAErB;;QACL,CAAA;OACI;QACA;;IAEd,kBAAC,GAAD;KAAa,OAAM;KAAW,WAAU;eACtC,kBAAC,GAAD,EAAa,SAAS,GAAM,CAAA;KAChB,CAAA;IAEd,kBAAC,GAAD;KAAa,OAAM;KAAW,WAAU;eACtC,kBAAC,GAAD,EAAe,CAAA;KACH,CAAA;IAEd,kBAAC,GAAD;KAAa,OAAM;KAAU,WAAU;eACrC,kBAAC,GAAD,EAAY,SAAS,GAAM,CAAA;KACf,CAAA;IACT;KACH;MA9HJ,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD;GAAQ,MAAK;GAAS,SAAQ;GAAQ,MAAK;GAAK,eAAe,EAAS,UAAU;aAAlF,CACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAAA,iBAE1B;MACT,kBAAC,GAAD;GAAW,WAAU;GAAQ,WAAU;aACrC,kBAAC,GAAD;IACE,cAAa;IACb,OAAM;IACN,aAAY;IACZ,CAAA;GACQ,CAAA,CACR"}
|
|
1
|
+
{"version":3,"file":"EventDetailPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/events/EventDetailPage.tsx"],"sourcesContent":["import { ArrowLeft, CalendarClock, Edit, MapPin, Plus, Ticket as TicketIcon, Users } from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n IllustratedEmptyState,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport {\n useDeleteEventSessionMutation,\n useDeleteSpeakerMutation,\n useDeleteTicketTypeMutation,\n useEventQuery,\n useEventSessionsQuery,\n useSpeakersQuery,\n useTicketTypesQuery,\n type TicketTypeGql,\n} from '../../api/eventApi';\nimport { ActionMenu } from '../../components/ActionMenu';\nimport { Pagination, usePagination } from '../../components/Pagination';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { notify } from '../../lib/toast';\nimport { formatDateTime } from './eventFormUtils';\n\nfunction statusVariant(status: string): 'success' | 'warning' | 'secondary' | 'info' {\n const value = status.toLowerCase();\n if (['active', 'published', 'live', 'confirmed', 'completed', 'approved'].includes(value)) {\n return 'success';\n }\n if (['inactive', 'cancelled', 'archived', 'closed', 'expired'].includes(value)) {\n return 'warning';\n }\n if (['draft', 'created', 'pending', 'scheduled'].includes(value)) {\n return 'info';\n }\n return 'secondary';\n}\n\n// ---------------------------------------------------------------------------\n\ntype SessionRow = {\n id: string;\n title: string;\n sessionType: string;\n track?: string | null;\n startsAt: string;\n endsAt: string;\n status: string;\n};\n\nfunction SessionsTab({ eventId }: { eventId: string }) {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination();\n const { data, loading, refetch } = useEventSessionsQuery({\n eventId,\n limit: pagination.limit,\n offset: pagination.offset,\n });\n const [deleteEventSession] = useDeleteEventSessionMutation();\n\n const total = data?.eventSessions?.total ?? 0;\n const rows = (data?.eventSessions?.items ?? []) as unknown as SessionRow[];\n\n const onDelete = async (session: SessionRow) => {\n const response = await deleteEventSession({ variables: { id: session.id } });\n if (response.error) {\n notify.error('Could not delete session', response.error.message);\n throw response.error;\n }\n if (!response.data?.deleteEventSession) {\n notify.error('Could not delete session', 'The server did not confirm the change.');\n throw new Error('delete-unconfirmed');\n }\n notify.success('Session deleted', session.title);\n await refetch();\n };\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Agenda & Sessions</h2>\n <Button type=\"button\" size=\"sm\" onClick={() => navigate(`/events/${eventId}/sessions/create`)}>\n <Plus className=\"h-4 w-4\" />\n New Session\n </Button>\n </div>\n\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading sessions…</p>\n ) : rows.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No sessions yet.\"\n description=\"Build the agenda by adding your first session.\"\n className=\"py-8\"\n />\n ) : (\n <ul className=\"space-y-2.5\">\n {rows.map((session) => (\n <li\n key={session.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] duration-200 hover:border-border-strong hover:shadow-elevation-1\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{session.title}</p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {[session.track, session.startsAt ? formatDateTime(session.startsAt) : undefined]\n .filter(Boolean)\n .join(' • ')}\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant={statusVariant(session.status)} className=\"uppercase\">\n {session.status}\n </Badge>\n <ActionMenu\n ariaLabel={`Session actions for ${session.title}`}\n entityName={session.title}\n deleteLabel=\"Delete session\"\n onEdit={() => navigate(`/events/${eventId}/sessions/${session.id}/edit`)}\n onDelete={() => onDelete(session)}\n />\n </div>\n </div>\n </li>\n ))}\n </ul>\n )}\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={rows.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"sessions\"\n loading={loading}\n />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n\ntype SpeakerRow = { id: string; fullName: string; title?: string | null; organization?: string | null };\n\nfunction SpeakersTab() {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination();\n const { data, loading, refetch } = useSpeakersQuery({ limit: pagination.limit, offset: pagination.offset });\n const [deleteSpeaker] = useDeleteSpeakerMutation();\n\n const total = data?.speakers?.total ?? 0;\n const rows = (data?.speakers?.items ?? []) as unknown as SpeakerRow[];\n\n const onDelete = async (speaker: SpeakerRow) => {\n const response = await deleteSpeaker({ variables: { id: speaker.id } });\n if (response.error) {\n notify.error('Could not delete speaker', response.error.message);\n throw response.error;\n }\n if (!response.data?.deleteSpeaker) {\n notify.error('Could not delete speaker', 'The server did not confirm the change.');\n throw new Error('delete-unconfirmed');\n }\n notify.success('Speaker deleted', speaker.fullName);\n await refetch();\n };\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Speakers</h2>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => navigate('/speakers')}>\n Manage speakers\n </Button>\n <Button type=\"button\" size=\"sm\" onClick={() => navigate('/speakers/create')}>\n <Plus className=\"h-4 w-4\" />\n New Speaker\n </Button>\n </div>\n </div>\n\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading speakers…</p>\n ) : rows.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title=\"No speakers yet.\"\n description=\"Add speakers so you can assign them to sessions.\"\n className=\"py-8\"\n />\n ) : (\n <ul className=\"space-y-2.5\">\n {rows.map((speaker) => (\n <li\n key={speaker.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] duration-200 hover:border-border-strong hover:shadow-elevation-1\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{speaker.fullName}</p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {[speaker.title, speaker.organization].filter(Boolean).join(' • ') || 'Speaker'}\n </p>\n </div>\n <ActionMenu\n ariaLabel={`Speaker actions for ${speaker.fullName}`}\n entityName={speaker.fullName}\n deleteLabel=\"Delete speaker\"\n onEdit={() => navigate(`/speakers/${speaker.id}/edit`)}\n onDelete={() => onDelete(speaker)}\n />\n </div>\n </li>\n ))}\n </ul>\n )}\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={rows.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"speakers\"\n loading={loading}\n />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n\nfunction TicketsTab({ eventId }: { eventId: string }) {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination();\n const { data, loading, refetch } = useTicketTypesQuery({\n eventId,\n limit: pagination.limit,\n offset: pagination.offset,\n });\n const [deleteTicketType] = useDeleteTicketTypeMutation();\n\n const total = data?.ticketTypes?.total ?? 0;\n const rows = (data?.ticketTypes?.items ?? []) as TicketTypeGql[];\n\n const onDelete = async (ticket: TicketTypeGql) => {\n const response = await deleteTicketType({ variables: { id: ticket.id } });\n if (response.error) {\n notify.error('Could not delete ticket type', response.error.message);\n throw response.error;\n }\n if (!response.data?.deleteTicketType) {\n notify.error('Could not delete ticket type', 'The server did not confirm the change.');\n throw new Error('delete-unconfirmed');\n }\n notify.success('Ticket type deleted');\n await refetch();\n };\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Ticket Types</h2>\n <Button type=\"button\" size=\"sm\" onClick={() => navigate(`/events/${eventId}/tickets/create`)}>\n <Plus className=\"h-4 w-4\" />\n New Ticket Type\n </Button>\n </div>\n\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading ticket types…</p>\n ) : rows.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No ticket types yet.\"\n description=\"Add a ticket type so attendees can register.\"\n className=\"py-8\"\n />\n ) : (\n <ul className=\"space-y-2.5\">\n {rows.map((ticket) => (\n <li\n key={ticket.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] duration-200 hover:border-border-strong hover:shadow-elevation-1\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{ticket.name}</p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {ticket.price} {ticket.currency} • Sold {ticket.soldCount}\n {ticket.capacity != null ? ` / ${ticket.capacity}` : ''}\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant={ticket.isActive ? 'success' : 'warning'} className=\"uppercase\">\n {ticket.isActive ? 'Active' : 'Inactive'}\n </Badge>\n <ActionMenu\n ariaLabel={`Ticket actions for ${ticket.name}`}\n entityName={ticket.name}\n deleteLabel=\"Delete ticket type\"\n onEdit={() => navigate(`/events/${eventId}/tickets/${ticket.id}/edit`)}\n onDelete={() => onDelete(ticket)}\n />\n </div>\n </div>\n </li>\n ))}\n </ul>\n )}\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={rows.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"ticket types\"\n loading={loading}\n />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n\nexport default function EventDetailPage() {\n const { id = '' } = useParams<{ id: string }>();\n const { navigate } = useEventfullyManaged();\n const { data, loading } = useEventQuery(id);\n const [tab, setTab] = useState('overview');\n\n const event = data?.event ?? null;\n const venueId = useMemo(() => {\n const metadata = (event?.metadata ?? {}) as Record<string, unknown>;\n return typeof metadata.venueId === 'string' ? (metadata.venueId as string) : '';\n }, [event]);\n\n if (loading) {\n return <div className=\"p-6 text-sm text-text-secondary\">Loading event…</div>;\n }\n\n if (!event) {\n return (\n <div className=\"space-y-4 p-6\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => navigate('/events')}>\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Events\n </Button>\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"Event not found.\"\n description=\"This event may have been removed or is outside your current scope.\"\n />\n </GlassCard>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-3\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => navigate('/events')}>\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Events\n </Button>\n <div>\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-2xl font-bold text-text-primary\">{event.name}</h1>\n <Badge variant={statusVariant(event.status)} className=\"uppercase\">\n {event.status}\n </Badge>\n </div>\n <p className=\"mt-1 flex items-center gap-2 text-sm text-text-secondary\">\n <CalendarClock className=\"h-4 w-4\" />\n {formatDateTime(event.startAt)} — {formatDateTime(event.endAt)}\n </p>\n </div>\n </div>\n <Button type=\"button\" onClick={() => navigate(`/events/${id}/edit`)}>\n <Edit className=\"h-4 w-4\" />\n Edit Event\n </Button>\n </div>\n\n <Tabs value={tab} onValueChange={setTab}>\n <TabsList>\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"sessions\">Sessions</TabsTrigger>\n <TabsTrigger value=\"speakers\">Speakers</TabsTrigger>\n <TabsTrigger value=\"tickets\">Tickets</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"mt-4\">\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"mb-2 flex items-center gap-2 text-sm font-medium text-text-primary\">\n <TicketIcon className=\"h-4 w-4 text-action-primary-bg\" />\n Type\n </div>\n <p className=\"text-sm uppercase text-text-secondary\">{event.type}</p>\n </GlassCard>\n <GlassCard treatment=\"glass\" glow className=\"p-4\">\n <div className=\"mb-2 flex items-center gap-2 text-sm font-medium text-text-primary\">\n <Users className=\"h-4 w-4 text-action-primary-bg\" />\n Capacity\n </div>\n <p className=\"text-sm tabular-nums text-text-secondary\">{event.capacity ?? 0} attendees</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"mb-2 flex items-center gap-2 text-sm font-medium text-text-primary\">\n <MapPin className=\"h-4 w-4 text-action-primary-bg\" />\n Timezone\n </div>\n <p className=\"text-sm text-text-secondary\">{event.timezone}</p>\n </GlassCard>\n </div>\n\n <GlassCard treatment=\"plain\" className=\"mt-4 border-border-seam p-5\">\n <h2 className=\"text-lg font-semibold text-text-primary\">About</h2>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {event.description?.trim() ? event.description : 'No description provided.'}\n </p>\n <dl className=\"mt-4 grid grid-cols-1 gap-3 text-sm sm:grid-cols-2\">\n <div>\n <dt className=\"text-text-muted\">Visibility</dt>\n <dd className=\"capitalize text-text-primary\">{event.visibility}</dd>\n </div>\n <div>\n <dt className=\"text-text-muted\">Venue</dt>\n <dd className=\"text-text-primary\">\n {venueId ? (\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"sm\"\n className=\"h-auto p-0\"\n onClick={() => navigate(`/venues/${venueId}`)}\n >\n View venue\n </Button>\n ) : (\n 'No venue assigned'\n )}\n </dd>\n </div>\n </dl>\n <div className=\"mt-4\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => navigate(`/events/${id}/edit`)}>\n <Edit className=\"h-4 w-4\" />\n Edit event details\n </Button>\n </div>\n </GlassCard>\n </TabsContent>\n\n <TabsContent value=\"sessions\" className=\"mt-4\">\n <SessionsTab eventId={id} />\n </TabsContent>\n\n <TabsContent value=\"speakers\" className=\"mt-4\">\n <SpeakersTab />\n </TabsContent>\n\n <TabsContent value=\"tickets\" className=\"mt-4\">\n <TicketsTab eventId={id} />\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { useEventfullyManaged as e } from "../../context/EventfullyManagedContext.js";
|
|
2
2
|
import { notify as t } from "../../lib/toast.js";
|
|
3
|
-
import { useAttendeesQuery as n,
|
|
4
|
-
import { ActionMenu as
|
|
5
|
-
import { Pagination as
|
|
6
|
-
import { mutationSucceeded as
|
|
7
|
-
import { useMemo as
|
|
8
|
-
import { jsx as
|
|
9
|
-
import { Megaphone as
|
|
10
|
-
import { Badge as
|
|
3
|
+
import { useAttendeesQuery as n, useDeleteAttendeeMutation as r, useDeletePromoCodeMutation as i, useDeleteRegistrationMutation as a, usePromoCodesQuery as o, useRegistrationsQuery as s, useUpdateRegistrationMutation as c } from "../../api/eventApi.js";
|
|
4
|
+
import { ActionMenu as l } from "../../components/ActionMenu.js";
|
|
5
|
+
import { Pagination as u, usePagination as d } from "../../components/Pagination.js";
|
|
6
|
+
import { mutationSucceeded as f } from "../../lib/mutationResult.js";
|
|
7
|
+
import { useMemo as p } from "react";
|
|
8
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
9
|
+
import { Megaphone as g, Tag as _, TicketPlus as v, UserPlus as y, Users as b } from "lucide-react";
|
|
10
|
+
import { Badge as x, Button as S, EmphasisPanel as C, GlassCard as w, GradientText as T, IllustratedEmptyState as E, NextSteps as D, PagePurpose as O } from "@burdenoff/fe-libs/ui";
|
|
11
11
|
//#region src/eventfullymanaged/pages/modules/RegistrationPage.tsx
|
|
12
|
-
var
|
|
12
|
+
var k = [
|
|
13
13
|
"PENDING",
|
|
14
14
|
"CONFIRMED",
|
|
15
15
|
"WAITLISTED",
|
|
16
16
|
"CANCELLED",
|
|
17
17
|
"CHECKED_IN"
|
|
18
18
|
];
|
|
19
|
-
function
|
|
19
|
+
function A(e) {
|
|
20
20
|
switch ((e ?? "").toUpperCase()) {
|
|
21
21
|
case "CONFIRMED":
|
|
22
22
|
case "CHECKED_IN": return "default";
|
|
@@ -25,19 +25,19 @@ function O(e) {
|
|
|
25
25
|
default: return "secondary";
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
function
|
|
29
|
-
let e =
|
|
28
|
+
function j() {
|
|
29
|
+
let e = d({ pageSize: 10 }), { data: r, loading: i } = s({
|
|
30
30
|
limit: e.limit,
|
|
31
31
|
offset: e.offset
|
|
32
|
-
}), [
|
|
32
|
+
}), [o] = c(), [g] = a(), { data: _ } = n({
|
|
33
33
|
limit: 200,
|
|
34
34
|
offset: 0
|
|
35
|
-
}),
|
|
35
|
+
}), v = p(() => {
|
|
36
36
|
let e = /* @__PURE__ */ new Map();
|
|
37
|
-
for (let t of
|
|
37
|
+
for (let t of _?.attendees.items ?? []) t.id && t.fullName && e.set(t.id, t.fullName);
|
|
38
38
|
return e;
|
|
39
|
-
}, [
|
|
40
|
-
let r = await
|
|
39
|
+
}, [_]), y = (e) => e ? v.get(e) ?? `Attendee ${e.slice(0, 8)}…` : null, b = p(() => r?.registrations.items ?? [], [r]), S = r?.registrations.total ?? 0, C = async (e, n) => {
|
|
40
|
+
let r = await o({ variables: {
|
|
41
41
|
id: e.id,
|
|
42
42
|
input: {
|
|
43
43
|
eventId: e.eventId,
|
|
@@ -49,59 +49,67 @@ function k() {
|
|
|
49
49
|
status: n
|
|
50
50
|
}
|
|
51
51
|
} });
|
|
52
|
-
|
|
52
|
+
f(r, r.data?.updateRegistration?.id, "Could not update registration") && t.success("Registration updated", `Status set to ${n}`);
|
|
53
|
+
}, T = async (e, n) => {
|
|
54
|
+
let r = await g({ variables: { id: e.id } });
|
|
55
|
+
if (r.error) throw t.error("Could not delete registration", r.error.message), r.error;
|
|
56
|
+
if (!r.data?.deleteRegistration) throw t.error("Could not delete registration", "The server did not confirm the change."), Error("delete-unconfirmed");
|
|
57
|
+
t.success("Registration deleted", n);
|
|
53
58
|
};
|
|
54
|
-
return /* @__PURE__ */
|
|
59
|
+
return /* @__PURE__ */ h(w, {
|
|
55
60
|
treatment: "plain",
|
|
56
61
|
className: "border-border-seam p-5",
|
|
57
62
|
children: [
|
|
58
|
-
/* @__PURE__ */
|
|
63
|
+
/* @__PURE__ */ m("h2", {
|
|
59
64
|
className: "text-lg font-semibold text-text-primary",
|
|
60
|
-
children: i ? "Loading registrations…" : `Registrations (${
|
|
65
|
+
children: i ? "Loading registrations…" : `Registrations (${S})`
|
|
61
66
|
}),
|
|
62
|
-
|
|
67
|
+
b.length === 0 && !i ? /* @__PURE__ */ m(E, {
|
|
63
68
|
illustration: "empty-data",
|
|
64
69
|
title: "No registrations yet.",
|
|
65
70
|
description: "Register your first attendee to start tracking sign-ups.",
|
|
66
71
|
className: "mt-4"
|
|
67
|
-
}) : /* @__PURE__ */
|
|
72
|
+
}) : /* @__PURE__ */ m("ul", {
|
|
68
73
|
className: "mt-4 space-y-2",
|
|
69
|
-
children:
|
|
70
|
-
let t =
|
|
74
|
+
children: b.map((e) => {
|
|
75
|
+
let t = y(e.attendeeId) ?? `Registration ${e.id}`, n = k.filter((t) => t !== (e.status ?? "").toUpperCase()).map((t, n) => ({
|
|
71
76
|
key: t,
|
|
72
77
|
label: `Set ${t.replace("_", " ").toLowerCase()}`,
|
|
73
|
-
onSelect: () => void
|
|
78
|
+
onSelect: () => void C(e, t),
|
|
74
79
|
separatorBefore: n === 0
|
|
75
80
|
}));
|
|
76
|
-
return /* @__PURE__ */
|
|
81
|
+
return /* @__PURE__ */ h("li", {
|
|
77
82
|
className: "flex items-center justify-between gap-3 rounded-input border border-border-seam bg-bg-surface px-3 py-2",
|
|
78
|
-
children: [/* @__PURE__ */
|
|
83
|
+
children: [/* @__PURE__ */ h("div", {
|
|
79
84
|
className: "min-w-0",
|
|
80
|
-
children: [/* @__PURE__ */
|
|
85
|
+
children: [/* @__PURE__ */ m("p", {
|
|
81
86
|
className: "truncate text-sm font-medium text-text-primary",
|
|
82
|
-
children:
|
|
83
|
-
}), /* @__PURE__ */
|
|
87
|
+
children: t
|
|
88
|
+
}), /* @__PURE__ */ m("p", {
|
|
84
89
|
className: "truncate text-xs text-text-secondary",
|
|
85
90
|
children: [`Qty ${e.quantity}`, e.totalAmount ? `${e.totalAmount} ${e.currency}` : void 0].filter(Boolean).join(" • ")
|
|
86
91
|
})]
|
|
87
|
-
}), /* @__PURE__ */
|
|
92
|
+
}), /* @__PURE__ */ h("div", {
|
|
88
93
|
className: "flex shrink-0 items-center gap-2",
|
|
89
|
-
children: [/* @__PURE__ */
|
|
90
|
-
variant:
|
|
94
|
+
children: [/* @__PURE__ */ m(x, {
|
|
95
|
+
variant: A(e.status),
|
|
91
96
|
children: e.status ?? "UNKNOWN"
|
|
92
|
-
}), /* @__PURE__ */
|
|
97
|
+
}), /* @__PURE__ */ m(l, {
|
|
93
98
|
ariaLabel: "Registration actions",
|
|
94
|
-
|
|
99
|
+
entityName: t,
|
|
100
|
+
deleteLabel: "Delete registration",
|
|
101
|
+
extraItems: n,
|
|
102
|
+
onDelete: () => T(e, t)
|
|
95
103
|
})]
|
|
96
104
|
})]
|
|
97
105
|
}, e.id);
|
|
98
106
|
})
|
|
99
107
|
}),
|
|
100
|
-
/* @__PURE__ */
|
|
108
|
+
/* @__PURE__ */ m(u, {
|
|
101
109
|
offset: e.offset,
|
|
102
110
|
limit: e.limit,
|
|
103
|
-
loadedCount:
|
|
104
|
-
total:
|
|
111
|
+
loadedCount: b.length,
|
|
112
|
+
total: S,
|
|
105
113
|
onPrev: e.prevPage,
|
|
106
114
|
onNext: e.nextPage,
|
|
107
115
|
itemLabel: "registrations",
|
|
@@ -110,43 +118,48 @@ function k() {
|
|
|
110
118
|
]
|
|
111
119
|
});
|
|
112
120
|
}
|
|
113
|
-
function
|
|
114
|
-
let { navigate:
|
|
115
|
-
limit:
|
|
116
|
-
offset:
|
|
117
|
-
}),
|
|
118
|
-
|
|
121
|
+
function M() {
|
|
122
|
+
let { navigate: i } = e(), a = d({ pageSize: 10 }), { data: o, loading: s } = n({
|
|
123
|
+
limit: a.limit,
|
|
124
|
+
offset: a.offset
|
|
125
|
+
}), [c] = r(), f = p(() => o?.attendees.items ?? [], [o]), g = o?.attendees.total ?? 0, _ = async (e) => {
|
|
126
|
+
let n = await c({ variables: { id: e.id } });
|
|
127
|
+
if (n.error) throw t.error("Could not delete attendee", n.error.message), n.error;
|
|
128
|
+
if (!n.data?.deleteAttendee) throw t.error("Could not delete attendee", "The server did not confirm the change."), Error("delete-unconfirmed");
|
|
129
|
+
t.success("Attendee deleted", e.fullName);
|
|
130
|
+
};
|
|
131
|
+
return /* @__PURE__ */ h(w, {
|
|
119
132
|
treatment: "plain",
|
|
120
133
|
className: "border-border-seam p-5",
|
|
121
134
|
children: [
|
|
122
|
-
/* @__PURE__ */
|
|
135
|
+
/* @__PURE__ */ h("div", {
|
|
123
136
|
className: "flex items-center justify-between gap-3",
|
|
124
|
-
children: [/* @__PURE__ */
|
|
137
|
+
children: [/* @__PURE__ */ m("h2", {
|
|
125
138
|
className: "text-lg font-semibold text-text-primary",
|
|
126
|
-
children:
|
|
127
|
-
}), /* @__PURE__ */
|
|
139
|
+
children: s ? "Loading attendees…" : `Attendees (${g})`
|
|
140
|
+
}), /* @__PURE__ */ h(S, {
|
|
128
141
|
type: "button",
|
|
129
142
|
size: "sm",
|
|
130
143
|
variant: "outline",
|
|
131
|
-
onClick: () =>
|
|
132
|
-
children: [/* @__PURE__ */
|
|
144
|
+
onClick: () => i("/registration/attendees/create"),
|
|
145
|
+
children: [/* @__PURE__ */ m(y, { className: "h-4 w-4" }), "Add attendee"]
|
|
133
146
|
})]
|
|
134
147
|
}),
|
|
135
|
-
|
|
148
|
+
f.length === 0 && !s ? /* @__PURE__ */ m(E, {
|
|
136
149
|
illustration: "empty-people",
|
|
137
150
|
title: "No attendees yet.",
|
|
138
151
|
description: "Add attendees or register one to build your guest list.",
|
|
139
152
|
className: "mt-4"
|
|
140
|
-
}) : /* @__PURE__ */
|
|
153
|
+
}) : /* @__PURE__ */ m("ul", {
|
|
141
154
|
className: "mt-4 space-y-2",
|
|
142
|
-
children:
|
|
155
|
+
children: f.map((e) => /* @__PURE__ */ h("li", {
|
|
143
156
|
className: "flex items-center justify-between gap-3 rounded-input border border-border-seam bg-bg-surface px-3 py-2",
|
|
144
|
-
children: [/* @__PURE__ */
|
|
157
|
+
children: [/* @__PURE__ */ h("div", {
|
|
145
158
|
className: "min-w-0",
|
|
146
|
-
children: [/* @__PURE__ */
|
|
159
|
+
children: [/* @__PURE__ */ m("p", {
|
|
147
160
|
className: "truncate text-sm font-medium text-text-primary",
|
|
148
161
|
children: e.fullName
|
|
149
|
-
}), /* @__PURE__ */
|
|
162
|
+
}), /* @__PURE__ */ m("p", {
|
|
150
163
|
className: "truncate text-xs text-text-secondary",
|
|
151
164
|
children: [
|
|
152
165
|
e.email,
|
|
@@ -154,138 +167,141 @@ function A() {
|
|
|
154
167
|
e.role
|
|
155
168
|
].filter(Boolean).join(" • ")
|
|
156
169
|
})]
|
|
157
|
-
}), /* @__PURE__ */
|
|
170
|
+
}), /* @__PURE__ */ m(l, {
|
|
158
171
|
ariaLabel: `Actions for ${e.fullName}`,
|
|
159
|
-
|
|
160
|
-
|
|
172
|
+
entityName: e.fullName,
|
|
173
|
+
deleteLabel: "Delete attendee",
|
|
174
|
+
onView: () => i(`/attendees/${e.id}/profile`),
|
|
175
|
+
onEdit: () => i(`/registration/attendees/${e.id}/edit`),
|
|
176
|
+
onDelete: () => _(e)
|
|
161
177
|
})]
|
|
162
178
|
}, e.id))
|
|
163
179
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
165
|
-
offset:
|
|
166
|
-
limit:
|
|
167
|
-
loadedCount:
|
|
168
|
-
total:
|
|
169
|
-
onPrev:
|
|
170
|
-
onNext:
|
|
180
|
+
/* @__PURE__ */ m(u, {
|
|
181
|
+
offset: a.offset,
|
|
182
|
+
limit: a.limit,
|
|
183
|
+
loadedCount: f.length,
|
|
184
|
+
total: g,
|
|
185
|
+
onPrev: a.prevPage,
|
|
186
|
+
onNext: a.nextPage,
|
|
171
187
|
itemLabel: "attendees",
|
|
172
|
-
loading:
|
|
188
|
+
loading: s
|
|
173
189
|
})
|
|
174
190
|
]
|
|
175
191
|
});
|
|
176
192
|
}
|
|
177
|
-
function
|
|
178
|
-
let { navigate: n } = e(),
|
|
179
|
-
limit:
|
|
180
|
-
offset:
|
|
181
|
-
}), [
|
|
182
|
-
let n = await
|
|
193
|
+
function N() {
|
|
194
|
+
let { navigate: n } = e(), r = d({ pageSize: 10 }), { data: a, loading: s } = o({
|
|
195
|
+
limit: r.limit,
|
|
196
|
+
offset: r.offset
|
|
197
|
+
}), [c] = i(), f = p(() => a?.promoCodes.items ?? [], [a]), g = a?.promoCodes.total ?? 0, _ = async (e) => {
|
|
198
|
+
let n = await c({ variables: { id: e.id } });
|
|
183
199
|
if (n.error) throw t.error("Could not delete promo code", n.error.message), n.error;
|
|
184
200
|
t.success("Promo code deleted", e.code);
|
|
185
201
|
};
|
|
186
|
-
return /* @__PURE__ */
|
|
202
|
+
return /* @__PURE__ */ h(w, {
|
|
187
203
|
treatment: "plain",
|
|
188
204
|
className: "border-border-seam p-5",
|
|
189
205
|
children: [
|
|
190
|
-
/* @__PURE__ */
|
|
206
|
+
/* @__PURE__ */ h("div", {
|
|
191
207
|
className: "flex items-center justify-between gap-3",
|
|
192
|
-
children: [/* @__PURE__ */
|
|
208
|
+
children: [/* @__PURE__ */ m("h2", {
|
|
193
209
|
className: "text-lg font-semibold text-text-primary",
|
|
194
|
-
children:
|
|
195
|
-
}), /* @__PURE__ */
|
|
210
|
+
children: s ? "Loading promo codes…" : `Promo Codes (${g})`
|
|
211
|
+
}), /* @__PURE__ */ h(S, {
|
|
196
212
|
type: "button",
|
|
197
213
|
size: "sm",
|
|
198
214
|
variant: "outline",
|
|
199
215
|
onClick: () => n("/registration/promo-codes/create"),
|
|
200
|
-
children: [/* @__PURE__ */
|
|
216
|
+
children: [/* @__PURE__ */ m(v, { className: "h-4 w-4" }), "New promo code"]
|
|
201
217
|
})]
|
|
202
218
|
}),
|
|
203
|
-
|
|
219
|
+
f.length === 0 && !s ? /* @__PURE__ */ m(E, {
|
|
204
220
|
illustration: "empty-data",
|
|
205
221
|
title: "No promo codes yet.",
|
|
206
222
|
description: "Create a code to offer discounts and drive registrations.",
|
|
207
223
|
className: "mt-4"
|
|
208
|
-
}) : /* @__PURE__ */
|
|
224
|
+
}) : /* @__PURE__ */ m("ul", {
|
|
209
225
|
className: "mt-4 space-y-2",
|
|
210
|
-
children:
|
|
226
|
+
children: f.map((e) => /* @__PURE__ */ h("li", {
|
|
211
227
|
className: "flex items-center justify-between gap-3 rounded-input border border-border-seam bg-bg-surface px-3 py-2",
|
|
212
|
-
children: [/* @__PURE__ */
|
|
228
|
+
children: [/* @__PURE__ */ h("div", {
|
|
213
229
|
className: "min-w-0",
|
|
214
|
-
children: [/* @__PURE__ */
|
|
230
|
+
children: [/* @__PURE__ */ m("p", {
|
|
215
231
|
className: "truncate text-sm font-medium text-text-primary",
|
|
216
232
|
children: e.code
|
|
217
|
-
}), /* @__PURE__ */
|
|
233
|
+
}), /* @__PURE__ */ h("p", {
|
|
218
234
|
className: "truncate text-xs text-text-secondary",
|
|
219
235
|
children: [e.discountType === "PERCENT" ? `${e.discountValue}% off` : `${e.discountValue} off`, e.maxUses == null ? ` • ${e.usedCount} used` : ` • ${e.usedCount}/${e.maxUses} used`]
|
|
220
236
|
})]
|
|
221
|
-
}), /* @__PURE__ */
|
|
237
|
+
}), /* @__PURE__ */ h("div", {
|
|
222
238
|
className: "flex shrink-0 items-center gap-2",
|
|
223
|
-
children: [/* @__PURE__ */
|
|
239
|
+
children: [/* @__PURE__ */ m(x, {
|
|
224
240
|
variant: e.isActive ? "default" : "secondary",
|
|
225
241
|
children: e.isActive ? "Active" : "Inactive"
|
|
226
|
-
}), /* @__PURE__ */
|
|
242
|
+
}), /* @__PURE__ */ m(l, {
|
|
227
243
|
ariaLabel: `Actions for ${e.code}`,
|
|
228
244
|
onEdit: () => n(`/registration/promo-codes/${e.id}/edit`),
|
|
229
|
-
onDelete: () =>
|
|
245
|
+
onDelete: () => _(e),
|
|
230
246
|
entityName: e.code
|
|
231
247
|
})]
|
|
232
248
|
})]
|
|
233
249
|
}, e.id))
|
|
234
250
|
}),
|
|
235
|
-
/* @__PURE__ */
|
|
236
|
-
offset:
|
|
237
|
-
limit:
|
|
238
|
-
loadedCount:
|
|
239
|
-
total:
|
|
240
|
-
onPrev:
|
|
241
|
-
onNext:
|
|
251
|
+
/* @__PURE__ */ m(u, {
|
|
252
|
+
offset: r.offset,
|
|
253
|
+
limit: r.limit,
|
|
254
|
+
loadedCount: f.length,
|
|
255
|
+
total: g,
|
|
256
|
+
onPrev: r.prevPage,
|
|
257
|
+
onNext: r.nextPage,
|
|
242
258
|
itemLabel: "promo codes",
|
|
243
|
-
loading:
|
|
259
|
+
loading: s
|
|
244
260
|
})
|
|
245
261
|
]
|
|
246
262
|
});
|
|
247
263
|
}
|
|
248
|
-
function
|
|
264
|
+
function P() {
|
|
249
265
|
let { navigate: t } = e();
|
|
250
|
-
return /* @__PURE__ */
|
|
266
|
+
return /* @__PURE__ */ h("div", {
|
|
251
267
|
className: "space-y-6 p-6",
|
|
252
268
|
children: [
|
|
253
|
-
/* @__PURE__ */
|
|
254
|
-
/* @__PURE__ */
|
|
269
|
+
/* @__PURE__ */ m(O, { children: "This is where you see who is coming. Registrations are the paid or confirmed sign-ups, attendees are the people behind them, and promo codes let you offer discounts. Register attendees, edit their details, change a registration's status, and manage discount codes — all backed by live GraphQL APIs." }),
|
|
270
|
+
/* @__PURE__ */ m(C, { children: /* @__PURE__ */ h("div", {
|
|
255
271
|
className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
|
256
|
-
children: [/* @__PURE__ */
|
|
272
|
+
children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h1", {
|
|
257
273
|
className: "text-2xl font-bold text-text-primary",
|
|
258
|
-
children: /* @__PURE__ */
|
|
259
|
-
}), /* @__PURE__ */
|
|
274
|
+
children: /* @__PURE__ */ m(T, { children: "Registration" })
|
|
275
|
+
}), /* @__PURE__ */ m("p", {
|
|
260
276
|
className: "mt-1 text-sm text-text-secondary",
|
|
261
277
|
children: "Track registrations, attendees, and promo codes with backend persistence."
|
|
262
|
-
})] }), /* @__PURE__ */
|
|
278
|
+
})] }), /* @__PURE__ */ h("div", {
|
|
263
279
|
className: "flex flex-wrap gap-2",
|
|
264
280
|
children: [
|
|
265
|
-
/* @__PURE__ */
|
|
281
|
+
/* @__PURE__ */ h(S, {
|
|
266
282
|
type: "button",
|
|
267
283
|
onClick: () => t("/registration/register"),
|
|
268
|
-
children: [/* @__PURE__ */
|
|
284
|
+
children: [/* @__PURE__ */ m(v, { className: "h-4 w-4" }), "Register attendee"]
|
|
269
285
|
}),
|
|
270
|
-
/* @__PURE__ */
|
|
286
|
+
/* @__PURE__ */ h(S, {
|
|
271
287
|
type: "button",
|
|
272
288
|
variant: "outline",
|
|
273
289
|
onClick: () => t("/registration/attendees/create"),
|
|
274
|
-
children: [/* @__PURE__ */
|
|
290
|
+
children: [/* @__PURE__ */ m(y, { className: "h-4 w-4" }), "Add attendee"]
|
|
275
291
|
}),
|
|
276
|
-
/* @__PURE__ */
|
|
292
|
+
/* @__PURE__ */ h(S, {
|
|
277
293
|
type: "button",
|
|
278
294
|
variant: "outline",
|
|
279
295
|
onClick: () => t("/registration/promo-codes/create"),
|
|
280
|
-
children: [/* @__PURE__ */
|
|
296
|
+
children: [/* @__PURE__ */ m(_, { className: "h-4 w-4" }), "New promo code"]
|
|
281
297
|
})
|
|
282
298
|
]
|
|
283
299
|
})]
|
|
284
300
|
}) }),
|
|
285
|
-
/* @__PURE__ */
|
|
286
|
-
/* @__PURE__ */
|
|
287
|
-
/* @__PURE__ */
|
|
288
|
-
/* @__PURE__ */
|
|
301
|
+
/* @__PURE__ */ m(j, {}),
|
|
302
|
+
/* @__PURE__ */ m(M, {}),
|
|
303
|
+
/* @__PURE__ */ m(N, {}),
|
|
304
|
+
/* @__PURE__ */ m(D, {
|
|
289
305
|
storageKey: "eventfullymanaged-registration",
|
|
290
306
|
title: "Grow your registrations",
|
|
291
307
|
steps: [
|
|
@@ -293,21 +309,21 @@ function M() {
|
|
|
293
309
|
id: "view-networking",
|
|
294
310
|
label: "Set up attendee networking",
|
|
295
311
|
description: "Turn registered attendees into connections with matchmaking.",
|
|
296
|
-
icon: /* @__PURE__ */
|
|
312
|
+
icon: /* @__PURE__ */ m(b, { className: "h-4 w-4" }),
|
|
297
313
|
onClick: () => t("/networking")
|
|
298
314
|
},
|
|
299
315
|
{
|
|
300
316
|
id: "promote",
|
|
301
317
|
label: "Promote with a campaign",
|
|
302
318
|
description: "Send reminders and offers to drive more sign-ups.",
|
|
303
|
-
icon: /* @__PURE__ */
|
|
319
|
+
icon: /* @__PURE__ */ m(g, { className: "h-4 w-4" }),
|
|
304
320
|
onClick: () => t("/communication")
|
|
305
321
|
},
|
|
306
322
|
{
|
|
307
323
|
id: "analyze",
|
|
308
324
|
label: "Snapshot your numbers",
|
|
309
325
|
description: "Capture an analytics snapshot to track registration trends.",
|
|
310
|
-
icon: /* @__PURE__ */
|
|
326
|
+
icon: /* @__PURE__ */ m(_, { className: "h-4 w-4" }),
|
|
311
327
|
onClick: () => t("/analytics")
|
|
312
328
|
}
|
|
313
329
|
]
|
|
@@ -316,6 +332,6 @@ function M() {
|
|
|
316
332
|
});
|
|
317
333
|
}
|
|
318
334
|
//#endregion
|
|
319
|
-
export {
|
|
335
|
+
export { P as default };
|
|
320
336
|
|
|
321
337
|
//# sourceMappingURL=RegistrationPage.js.map
|