@burdenoff/microfe-eventfullymanaged 2026.728.1 → 2026.731.1

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.
Files changed (37) hide show
  1. package/dist/eventfullymanaged/EventfullyManagedRoutes.d.ts.map +1 -1
  2. package/dist/eventfullymanaged/EventfullyManagedRoutes.js +60 -76
  3. package/dist/eventfullymanaged/EventfullyManagedRoutes.js.map +1 -1
  4. package/dist/eventfullymanaged/api/eventApi.d.ts +245 -1
  5. package/dist/eventfullymanaged/api/eventApi.d.ts.map +1 -1
  6. package/dist/eventfullymanaged/api/eventApi.js +482 -264
  7. package/dist/eventfullymanaged/api/eventApi.js.map +1 -1
  8. package/dist/eventfullymanaged/hooks/useEvmSubscription.d.ts +18 -0
  9. package/dist/eventfullymanaged/hooks/useEvmSubscription.d.ts.map +1 -0
  10. package/dist/eventfullymanaged/hooks/useEvmSubscription.js +110 -0
  11. package/dist/eventfullymanaged/hooks/useEvmSubscription.js.map +1 -0
  12. package/dist/eventfullymanaged/hooks/useVirtualCall.d.ts +47 -0
  13. package/dist/eventfullymanaged/hooks/useVirtualCall.d.ts.map +1 -0
  14. package/dist/eventfullymanaged/hooks/useVirtualCall.js +209 -0
  15. package/dist/eventfullymanaged/hooks/useVirtualCall.js.map +1 -0
  16. package/dist/eventfullymanaged/pages/events/EventDetailPage.d.ts.map +1 -1
  17. package/dist/eventfullymanaged/pages/events/EventDetailPage.js +79 -71
  18. package/dist/eventfullymanaged/pages/events/EventDetailPage.js.map +1 -1
  19. package/dist/eventfullymanaged/pages/events/VirtualSessionPage.d.ts +2 -0
  20. package/dist/eventfullymanaged/pages/events/VirtualSessionPage.d.ts.map +1 -0
  21. package/dist/eventfullymanaged/pages/events/VirtualSessionPage.js +353 -0
  22. package/dist/eventfullymanaged/pages/events/VirtualSessionPage.js.map +1 -0
  23. package/dist/eventfullymanaged/pages/modules/IntegrationsPage.d.ts +2 -0
  24. package/dist/eventfullymanaged/pages/modules/IntegrationsPage.d.ts.map +1 -0
  25. package/dist/eventfullymanaged/pages/modules/IntegrationsPage.js +336 -0
  26. package/dist/eventfullymanaged/pages/modules/IntegrationsPage.js.map +1 -0
  27. package/dist/eventfullymanaged/pages/modules/NetworkingPage.d.ts.map +1 -1
  28. package/dist/eventfullymanaged/pages/modules/NetworkingPage.js +211 -177
  29. package/dist/eventfullymanaged/pages/modules/NetworkingPage.js.map +1 -1
  30. package/dist/eventfullymanaged/pages/modules/RegistrationPage.d.ts.map +1 -1
  31. package/dist/eventfullymanaged/pages/modules/RegistrationPage.js +204 -174
  32. package/dist/eventfullymanaged/pages/modules/RegistrationPage.js.map +1 -1
  33. package/dist/eventfullymanaged/utils/shellBridge.d.ts +46 -0
  34. package/dist/eventfullymanaged/utils/shellBridge.d.ts.map +1 -0
  35. package/dist/eventfullymanaged/utils/shellBridge.js +19 -0
  36. package/dist/eventfullymanaged/utils/shellBridge.js.map +1 -0
  37. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"RegistrationPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/RegistrationPage.tsx"],"sourcesContent":["import { Megaphone, QrCode, Tag, TicketPlus, UserPlus, Users } from 'lucide-react';\nimport {\n Badge,\n Button,\n EmphasisPanel,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { useMemo, useState } from 'react';\n\nimport {\n useAttendeesQuery,\n useCheckInTokenQuery,\n useDeleteAttendeeMutation,\n useDeletePromoCodeMutation,\n useDeleteRegistrationMutation,\n usePromoCodesQuery,\n useRegistrationsQuery,\n useTicketTypesQuery,\n useUpdateRegistrationMutation,\n type AttendeeGql,\n type PromoCodeGql,\n type RegistrationGql,\n} from '../../api/eventApi';\nimport { ActionMenu, type ActionMenuItem } from '../../components/ActionMenu';\nimport { Pagination, usePagination } from '../../components/Pagination';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { formatMoney } from '../../lib/format';\nimport { mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\n\n/**\n * BOFF-4330 — displays a registration's signed QR check-in token. Fetched on\n * demand (never persisted client-side) so it always reflects the\n * registration's current signature; a kiosk scans this exact image/token via\n * `eventfullyManagedScanCheckIn`.\n */\nfunction CheckInQrDialog({\n registrationId,\n label,\n onOpenChange,\n}: {\n registrationId: string;\n label: string;\n onOpenChange: (open: boolean) => void;\n}) {\n const { data, loading, error } = useCheckInTokenQuery(registrationId);\n const token = data?.checkInToken;\n\n return (\n <ResponsiveDialog open onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-w-sm\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Check-in QR</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {label} scans this code at any check-in station to check in — it works even if the station has no connection\n at the moment.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex flex-col items-center gap-3 py-2\">\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Generating…</p>\n ) : error || !token ? (\n <p className=\"text-sm text-status-danger-text\">Could not generate a check-in QR for this registration.</p>\n ) : (\n <>\n <img\n src={token.qrDataUrl}\n alt={`Check-in QR code for ${label}`}\n className=\"h-56 w-56 rounded-card border border-border-seam bg-white p-2\"\n />\n <code className=\"max-w-full break-all rounded bg-bg-sunken px-2 py-1 text-xs text-text-secondary\">\n {token.token}\n </code>\n </>\n )}\n </div>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)}>\n Close\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\nconst REGISTRATION_STATUSES = ['PENDING', 'CONFIRMED', 'WAITLISTED', 'CANCELLED', 'CHECKED_IN'] as const;\n\nfunction statusVariant(status?: string | null): 'default' | 'secondary' | 'destructive' | 'outline' {\n switch ((status ?? '').toUpperCase()) {\n case 'CONFIRMED':\n case 'CHECKED_IN':\n return 'default';\n case 'CANCELLED':\n return 'destructive';\n case 'WAITLISTED':\n return 'outline';\n default:\n return 'secondary';\n }\n}\n\n/** Compact used/max meter for promo redemptions — semantic-token only. */\nfunction UsageMeter({ used, max }: { used: number; max?: number | null }) {\n if (max == null || max <= 0) {\n return <span className=\"text-xs text-text-secondary\">{used} used</span>;\n }\n const pct = Math.min(100, Math.round((used / max) * 100));\n const nearLimit = pct >= 90;\n return (\n <div className=\"min-w-[7rem] space-y-1\">\n <div className=\"flex items-center justify-between text-xs tabular-nums text-text-secondary\">\n <span>\n {used} / {max}\n </span>\n <span className=\"text-text-muted\">{pct}%</span>\n </div>\n <div className=\"h-1.5 w-full overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className={`h-full rounded-full ${nearLimit ? 'bg-status-warning' : 'bg-action-primary-bg'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n}\n\nfunction SectionCard({\n icon,\n title,\n count,\n loading,\n action,\n children,\n}: {\n icon: React.ReactNode;\n title: string;\n count?: number;\n loading?: boolean;\n action?: React.ReactNode;\n children: React.ReactNode;\n}) {\n return (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n <span className=\"flex h-9 w-9 items-center justify-center rounded-input bg-accent-wash text-action-primary\">\n {icon}\n </span>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {loading ? `Loading ${title.toLowerCase()}…` : title}\n {!loading && count != null ? (\n <span className=\"ml-2 text-sm font-normal text-text-secondary\">({count.toLocaleString()})</span>\n ) : null}\n </h2>\n </div>\n {action}\n </div>\n <div className=\"mt-4\">{children}</div>\n </GlassCard>\n );\n}\n\nfunction RegistrationsSection() {\n const pagination = usePagination({ pageSize: 10 });\n const { data, loading } = useRegistrationsQuery({ limit: pagination.limit, offset: pagination.offset });\n const [updateRegistration] = useUpdateRegistrationMutation();\n const [deleteRegistration] = useDeleteRegistrationMutation();\n // BOFF-4330 — registration id currently showing its check-in QR, if any.\n const [qrRegistrationId, setQrRegistrationId] = useState<string | null>(null);\n\n // Resolve attendee display names and ticket-type names (the registrations query\n // returns only ids). Pull a page of each to build id -> label lookups so rows\n // read \"Ada Lovelace\" / \"VIP\" instead of raw UUIDs.\n const { data: attendeesData } = useAttendeesQuery({ limit: 200, offset: 0 });\n const { data: ticketsData } = useTicketTypesQuery({ limit: 200, offset: 0 });\n const nameById = useMemo(() => {\n const map = new Map<string, string>();\n for (const attendee of attendeesData?.attendees.items ?? []) {\n if (attendee.id && attendee.fullName) map.set(attendee.id, attendee.fullName);\n }\n return map;\n }, [attendeesData]);\n const ticketById = useMemo(() => {\n const map = new Map<string, string>();\n for (const ticket of ticketsData?.ticketTypes.items ?? []) {\n if (ticket.id && ticket.name) map.set(ticket.id, ticket.name);\n }\n return map;\n }, [ticketsData]);\n const attendeeLabel = (attendeeId?: string | null): string | null => {\n if (!attendeeId) return null;\n return nameById.get(attendeeId) ?? `Attendee ${attendeeId.slice(0, 8)}…`;\n };\n\n const items = useMemo<RegistrationGql[]>(() => data?.registrations.items ?? [], [data]);\n const total = data?.registrations.total ?? 0;\n\n const changeStatus = async (row: RegistrationGql, status: string) => {\n const response = await updateRegistration({\n variables: {\n id: row.id,\n input: {\n eventId: row.eventId,\n attendeeId: row.attendeeId ?? null,\n ticketTypeId: row.ticketTypeId ?? null,\n quantity: row.quantity,\n currency: row.currency,\n totalAmount: row.totalAmount ?? null,\n status,\n },\n },\n });\n if (!mutationSucceeded(response, response.data?.updateRegistration?.id, 'Could not update registration')) {\n return;\n }\n notify.success('Registration updated', `Status set to ${status}`);\n };\n\n const onDelete = async (row: RegistrationGql, label: string) => {\n const response = await deleteRegistration({ variables: { id: row.id } });\n if (response.error) {\n notify.error('Could not delete registration', response.error.message);\n throw response.error;\n }\n if (!response.data?.deleteRegistration) {\n notify.error('Could not delete registration', 'The server did not confirm the change.');\n throw new Error('delete-unconfirmed');\n }\n notify.success('Registration deleted', label);\n };\n\n const rowLabel = (row: RegistrationGql) => attendeeLabel(row.attendeeId) ?? `Registration ${row.id}`;\n\n const columns: ResponsiveTableColumn<RegistrationGql>[] = [\n {\n key: 'name',\n header: 'Name',\n priority: 'primary',\n cell: (row) => <span className=\"font-medium text-text-primary\">{rowLabel(row)}</span>,\n },\n {\n key: 'ticket',\n header: 'Ticket Type',\n mobileLabel: 'Ticket',\n cell: (row) => (\n <span className=\"text-text-secondary\">\n {row.ticketTypeId ? (ticketById.get(row.ticketTypeId) ?? '—') : '—'}\n </span>\n ),\n },\n {\n key: 'quantity',\n header: 'Qty',\n mobileLabel: 'Quantity',\n priority: 'secondary',\n cell: (row) => <span className=\"tabular-nums text-text-secondary\">{row.quantity}</span>,\n },\n {\n key: 'amount',\n header: 'Amount',\n cell: (row) => (\n <span className=\"tabular-nums text-text-primary\">\n {row.totalAmount ? formatMoney(Number(row.totalAmount), row.currency) : '—'}\n </span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'primary',\n cell: (row) => <Badge variant={statusVariant(row.status)}>{row.status ?? 'UNKNOWN'}</Badge>,\n },\n ];\n\n return (\n <SectionCard icon={<TicketPlus className=\"h-4 w-4\" />} title=\"Registrations\" count={total} loading={loading}>\n <ResponsiveTable\n columns={columns}\n data={items}\n rowKey={(row) => row.id}\n emptyState={\n loading ? null : (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No registrations yet.\"\n description=\"Register your first attendee to start tracking sign-ups.\"\n />\n )\n }\n rowActions={(row) => {\n const label = rowLabel(row);\n const statusItems: ActionMenuItem[] = REGISTRATION_STATUSES.filter(\n (candidate) => candidate !== (row.status ?? '').toUpperCase()\n ).map((candidate, index) => ({\n key: candidate,\n label: `Set ${candidate.replace('_', ' ').toLowerCase()}`,\n onSelect: () => void changeStatus(row, candidate),\n separatorBefore: index === 0,\n }));\n const extraItems: ActionMenuItem[] = [\n {\n key: 'view-qr',\n label: 'View check-in QR',\n icon: QrCode,\n onSelect: () => setQrRegistrationId(row.id),\n },\n ...statusItems,\n ];\n return (\n <ActionMenu\n ariaLabel=\"Registration actions\"\n entityName={label}\n deleteLabel=\"Delete registration\"\n extraItems={extraItems}\n onDelete={() => onDelete(row, label)}\n />\n );\n }}\n />\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={items.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"registrations\"\n loading={loading}\n />\n {qrRegistrationId\n ? (() => {\n const qrRow = items.find((r) => r.id === qrRegistrationId);\n const qrLabel = qrRow ? rowLabel(qrRow) : `Registration ${qrRegistrationId}`;\n return (\n <CheckInQrDialog\n registrationId={qrRegistrationId}\n label={qrLabel}\n onOpenChange={(open) => {\n if (!open) setQrRegistrationId(null);\n }}\n />\n );\n })()\n : null}\n </SectionCard>\n );\n}\n\nfunction AttendeesSection() {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination({ pageSize: 10 });\n const { data, loading } = useAttendeesQuery({ limit: pagination.limit, offset: pagination.offset });\n const [deleteAttendee] = useDeleteAttendeeMutation();\n\n const items = useMemo<AttendeeGql[]>(() => data?.attendees.items ?? [], [data]);\n const total = data?.attendees.total ?? 0;\n\n const onDelete = async (row: AttendeeGql) => {\n const response = await deleteAttendee({ variables: { id: row.id } });\n if (response.error) {\n notify.error('Could not delete attendee', response.error.message);\n throw response.error;\n }\n if (!response.data?.deleteAttendee) {\n notify.error('Could not delete attendee', 'The server did not confirm the change.');\n throw new Error('delete-unconfirmed');\n }\n notify.success('Attendee deleted', row.fullName);\n };\n\n const columns: ResponsiveTableColumn<AttendeeGql>[] = [\n {\n key: 'name',\n header: 'Name',\n priority: 'primary',\n cell: (row) => <span className=\"font-medium text-text-primary\">{row.fullName}</span>,\n },\n {\n key: 'email',\n header: 'Email',\n priority: 'primary',\n cell: (row) => <span className=\"text-text-secondary\">{row.email}</span>,\n },\n {\n key: 'company',\n header: 'Company',\n cell: (row) => (\n <span className=\"text-text-secondary\">{[row.company, row.role].filter(Boolean).join(' · ') || '—'}</span>\n ),\n },\n ];\n\n return (\n <SectionCard\n icon={<Users className=\"h-4 w-4\" />}\n title=\"Attendees\"\n count={total}\n loading={loading}\n action={\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={() => navigate('/registration/attendees/create')}>\n <UserPlus className=\"h-4 w-4\" />\n Add attendee\n </Button>\n }\n >\n <ResponsiveTable\n columns={columns}\n data={items}\n rowKey={(row) => row.id}\n emptyState={\n loading ? null : (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title=\"No attendees yet.\"\n description=\"Add attendees or register one to build your guest list.\"\n />\n )\n }\n rowActions={(row) => (\n <ActionMenu\n ariaLabel={`Actions for ${row.fullName}`}\n entityName={row.fullName}\n deleteLabel=\"Delete attendee\"\n onView={() => navigate(`/attendees/${row.id}/profile`)}\n onEdit={() => navigate(`/registration/attendees/${row.id}/edit`)}\n onDelete={() => onDelete(row)}\n />\n )}\n />\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={items.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"attendees\"\n loading={loading}\n />\n </SectionCard>\n );\n}\n\nfunction PromoCodesSection() {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination({ pageSize: 10 });\n const { data, loading } = usePromoCodesQuery({ limit: pagination.limit, offset: pagination.offset });\n const [deletePromoCode] = useDeletePromoCodeMutation();\n\n const items = useMemo<PromoCodeGql[]>(() => data?.promoCodes.items ?? [], [data]);\n const total = data?.promoCodes.total ?? 0;\n\n const onDelete = async (row: PromoCodeGql) => {\n const response = await deletePromoCode({ variables: { id: row.id } });\n if (response.error) {\n notify.error('Could not delete promo code', response.error.message);\n throw response.error;\n }\n notify.success('Promo code deleted', row.code);\n };\n\n const columns: ResponsiveTableColumn<PromoCodeGql>[] = [\n {\n key: 'code',\n header: 'Code',\n priority: 'primary',\n cell: (row) => <span className=\"font-mono text-sm font-semibold text-text-primary\">{row.code}</span>,\n },\n {\n key: 'discount',\n header: 'Discount',\n priority: 'primary',\n cell: (row) => (\n <span className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\">{row.discountType === 'PERCENT' ? 'PERCENT' : 'FIXED'}</Badge>\n <span className=\"text-sm text-text-secondary\">\n {row.discountType === 'PERCENT' ? `${row.discountValue}%` : row.discountValue}\n </span>\n </span>\n ),\n },\n {\n key: 'usage',\n header: 'Usage',\n cell: (row) => <UsageMeter used={row.usedCount} max={row.maxUses} />,\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'secondary',\n cell: (row) => (\n <Badge variant={row.isActive ? 'default' : 'secondary'}>{row.isActive ? 'Active' : 'Inactive'}</Badge>\n ),\n },\n ];\n\n return (\n <SectionCard\n icon={<Tag className=\"h-4 w-4\" />}\n title=\"Promo Codes\"\n count={total}\n loading={loading}\n action={\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={() => navigate('/registration/promo-codes/create')}>\n <TicketPlus className=\"h-4 w-4\" />\n New promo code\n </Button>\n }\n >\n <ResponsiveTable\n columns={columns}\n data={items}\n rowKey={(row) => row.id}\n emptyState={\n loading ? null : (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No promo codes yet.\"\n description=\"Create a code to offer discounts and drive registrations.\"\n />\n )\n }\n rowActions={(row) => (\n <ActionMenu\n ariaLabel={`Actions for ${row.code}`}\n entityName={row.code}\n onEdit={() => navigate(`/registration/promo-codes/${row.id}/edit`)}\n onDelete={() => onDelete(row)}\n />\n )}\n />\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={items.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"promo codes\"\n loading={loading}\n />\n </SectionCard>\n );\n}\n\nexport default function RegistrationPage() {\n const { navigate } = useEventfullyManaged();\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n This is where you see who is coming. Registrations are the paid or confirmed sign-ups, attendees are the people\n behind them, and promo codes let you offer discounts. Register attendees, edit their details, change a\n registration&apos;s status, and manage discount codes — all backed by live GraphQL APIs.\n </PagePurpose>\n\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Registration</GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Track registrations, attendees, and promo codes with backend persistence.\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button type=\"button\" onClick={() => navigate('/registration/register')}>\n <TicketPlus className=\"h-4 w-4\" />\n Register attendee\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => navigate('/registration/attendees/create')}>\n <UserPlus className=\"h-4 w-4\" />\n Add attendee\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => navigate('/registration/promo-codes/create')}>\n <Tag className=\"h-4 w-4\" />\n New promo code\n </Button>\n </div>\n </div>\n </EmphasisPanel>\n\n <RegistrationsSection />\n <AttendeesSection />\n <PromoCodesSection />\n\n <NextSteps\n storageKey=\"eventfullymanaged-registration\"\n title=\"Grow your registrations\"\n steps={[\n {\n id: 'view-networking',\n label: 'Set up attendee networking',\n description: 'Turn registered attendees into connections with matchmaking.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('/networking'),\n },\n {\n id: 'promote',\n label: 'Promote with a campaign',\n description: 'Send reminders and offers to drive more sign-ups.',\n icon: <Megaphone className=\"h-4 w-4\" />,\n onClick: () => navigate('/communication'),\n },\n {\n id: 'analyze',\n label: 'Snapshot your numbers',\n description: 'Capture an analytics snapshot to track registration trends.',\n icon: <Tag className=\"h-4 w-4\" />,\n onClick: () => navigate('/analytics'),\n },\n ]}\n />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"RegistrationPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/RegistrationPage.tsx"],"sourcesContent":["import { useApolloClient } from '@apollo/client/react';\nimport { Badge as BadgeIcon, Megaphone, QrCode, Tag, TicketPlus, UserPlus, Users } from 'lucide-react';\nimport {\n Badge,\n Button,\n EmphasisPanel,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { useMemo, useState } from 'react';\n\nimport {\n BADGE_PDF_QUERY,\n downloadBase64Pdf,\n useAttendeesQuery,\n useCheckInTokenQuery,\n useDeleteAttendeeMutation,\n useDeletePromoCodeMutation,\n useDeleteRegistrationMutation,\n usePromoCodesQuery,\n useRegistrationsQuery,\n useTicketTypesQuery,\n useUpdateRegistrationMutation,\n type AttendeeGql,\n type PromoCodeGql,\n type RegistrationGql,\n} from '../../api/eventApi';\nimport { ActionMenu, type ActionMenuItem } from '../../components/ActionMenu';\nimport { Pagination, usePagination } from '../../components/Pagination';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { formatMoney } from '../../lib/format';\nimport { describeError, mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\n\n/**\n * BOFF-4330 — displays a registration's signed QR check-in token. Fetched on\n * demand (never persisted client-side) so it always reflects the\n * registration's current signature; a kiosk scans this exact image/token via\n * `eventfullyManagedScanCheckIn`.\n */\nfunction CheckInQrDialog({\n registrationId,\n label,\n onOpenChange,\n}: {\n registrationId: string;\n label: string;\n onOpenChange: (open: boolean) => void;\n}) {\n const { data, loading, error } = useCheckInTokenQuery(registrationId);\n const token = data?.checkInToken;\n\n return (\n <ResponsiveDialog open onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-w-sm\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Check-in QR</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {label} scans this code at any check-in station to check in — it works even if the station has no connection\n at the moment.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex flex-col items-center gap-3 py-2\">\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Generating…</p>\n ) : error || !token ? (\n <p className=\"text-sm text-status-danger-text\">Could not generate a check-in QR for this registration.</p>\n ) : (\n <>\n <img\n src={token.qrDataUrl}\n alt={`Check-in QR code for ${label}`}\n className=\"h-56 w-56 rounded-card border border-border-seam bg-white p-2\"\n />\n <code className=\"max-w-full break-all rounded bg-bg-sunken px-2 py-1 text-xs text-text-secondary\">\n {token.token}\n </code>\n </>\n )}\n </div>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)}>\n Close\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\nconst REGISTRATION_STATUSES = ['PENDING', 'CONFIRMED', 'WAITLISTED', 'CANCELLED', 'CHECKED_IN'] as const;\n\nfunction statusVariant(status?: string | null): 'default' | 'secondary' | 'destructive' | 'outline' {\n switch ((status ?? '').toUpperCase()) {\n case 'CONFIRMED':\n case 'CHECKED_IN':\n return 'default';\n case 'CANCELLED':\n return 'destructive';\n case 'WAITLISTED':\n return 'outline';\n default:\n return 'secondary';\n }\n}\n\n/** Compact used/max meter for promo redemptions — semantic-token only. */\nfunction UsageMeter({ used, max }: { used: number; max?: number | null }) {\n if (max == null || max <= 0) {\n return <span className=\"text-xs text-text-secondary\">{used} used</span>;\n }\n const pct = Math.min(100, Math.round((used / max) * 100));\n const nearLimit = pct >= 90;\n return (\n <div className=\"min-w-[7rem] space-y-1\">\n <div className=\"flex items-center justify-between text-xs tabular-nums text-text-secondary\">\n <span>\n {used} / {max}\n </span>\n <span className=\"text-text-muted\">{pct}%</span>\n </div>\n <div className=\"h-1.5 w-full overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className={`h-full rounded-full ${nearLimit ? 'bg-status-warning' : 'bg-action-primary-bg'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n}\n\nfunction SectionCard({\n icon,\n title,\n count,\n loading,\n action,\n children,\n}: {\n icon: React.ReactNode;\n title: string;\n count?: number;\n loading?: boolean;\n action?: React.ReactNode;\n children: React.ReactNode;\n}) {\n return (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n <span className=\"flex h-9 w-9 items-center justify-center rounded-input bg-accent-wash text-action-primary\">\n {icon}\n </span>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {loading ? `Loading ${title.toLowerCase()}…` : title}\n {!loading && count != null ? (\n <span className=\"ml-2 text-sm font-normal text-text-secondary\">({count.toLocaleString()})</span>\n ) : null}\n </h2>\n </div>\n {action}\n </div>\n <div className=\"mt-4\">{children}</div>\n </GlassCard>\n );\n}\n\nfunction RegistrationsSection() {\n const pagination = usePagination({ pageSize: 10 });\n const { data, loading } = useRegistrationsQuery({ limit: pagination.limit, offset: pagination.offset });\n const [updateRegistration] = useUpdateRegistrationMutation();\n const [deleteRegistration] = useDeleteRegistrationMutation();\n // BOFF-4330 — registration id currently showing its check-in QR, if any.\n const [qrRegistrationId, setQrRegistrationId] = useState<string | null>(null);\n // BOFF-4322 — on-demand badge PDF download. A one-off query (not a hook)\n // since it's a rarely-used, heavy payload — same pattern as TimeCampus's\n // invoice PDF download.\n const apollo = useApolloClient();\n const [downloadingBadgeId, setDownloadingBadgeId] = useState<string | null>(null);\n const onDownloadBadge = async (registrationId: string, label: string) => {\n setDownloadingBadgeId(registrationId);\n try {\n const { data, error } = await apollo.query<{ badgePdf: string }>({\n query: BADGE_PDF_QUERY,\n variables: { registrationId },\n fetchPolicy: 'network-only',\n errorPolicy: 'all',\n });\n if (error || !data?.badgePdf) {\n notify.error('Could not generate badge', error?.message ?? 'Please try again.');\n return;\n }\n downloadBase64Pdf(data.badgePdf, `${label.replace(/[^a-z0-9]+/gi, '-')}-badge.pdf`);\n notify.success('Badge ready', `${label}'s badge downloaded.`);\n } catch (err) {\n notify.error('Could not generate badge', describeError(err));\n } finally {\n setDownloadingBadgeId(null);\n }\n };\n\n // Resolve attendee display names and ticket-type names (the registrations query\n // returns only ids). Pull a page of each to build id -> label lookups so rows\n // read \"Ada Lovelace\" / \"VIP\" instead of raw UUIDs.\n const { data: attendeesData } = useAttendeesQuery({ limit: 200, offset: 0 });\n const { data: ticketsData } = useTicketTypesQuery({ limit: 200, offset: 0 });\n const nameById = useMemo(() => {\n const map = new Map<string, string>();\n for (const attendee of attendeesData?.attendees.items ?? []) {\n if (attendee.id && attendee.fullName) map.set(attendee.id, attendee.fullName);\n }\n return map;\n }, [attendeesData]);\n const ticketById = useMemo(() => {\n const map = new Map<string, string>();\n for (const ticket of ticketsData?.ticketTypes.items ?? []) {\n if (ticket.id && ticket.name) map.set(ticket.id, ticket.name);\n }\n return map;\n }, [ticketsData]);\n const attendeeLabel = (attendeeId?: string | null): string | null => {\n if (!attendeeId) return null;\n return nameById.get(attendeeId) ?? `Attendee ${attendeeId.slice(0, 8)}…`;\n };\n\n const items = useMemo<RegistrationGql[]>(() => data?.registrations.items ?? [], [data]);\n const total = data?.registrations.total ?? 0;\n\n const changeStatus = async (row: RegistrationGql, status: string) => {\n const response = await updateRegistration({\n variables: {\n id: row.id,\n input: {\n eventId: row.eventId,\n attendeeId: row.attendeeId ?? null,\n ticketTypeId: row.ticketTypeId ?? null,\n quantity: row.quantity,\n currency: row.currency,\n totalAmount: row.totalAmount ?? null,\n status,\n },\n },\n });\n if (!mutationSucceeded(response, response.data?.updateRegistration?.id, 'Could not update registration')) {\n return;\n }\n notify.success('Registration updated', `Status set to ${status}`);\n };\n\n const onDelete = async (row: RegistrationGql, label: string) => {\n const response = await deleteRegistration({ variables: { id: row.id } });\n if (response.error) {\n notify.error('Could not delete registration', response.error.message);\n throw response.error;\n }\n if (!response.data?.deleteRegistration) {\n notify.error('Could not delete registration', 'The server did not confirm the change.');\n throw new Error('delete-unconfirmed');\n }\n notify.success('Registration deleted', label);\n };\n\n const rowLabel = (row: RegistrationGql) => attendeeLabel(row.attendeeId) ?? `Registration ${row.id}`;\n\n const columns: ResponsiveTableColumn<RegistrationGql>[] = [\n {\n key: 'name',\n header: 'Name',\n priority: 'primary',\n cell: (row) => <span className=\"font-medium text-text-primary\">{rowLabel(row)}</span>,\n },\n {\n key: 'ticket',\n header: 'Ticket Type',\n mobileLabel: 'Ticket',\n cell: (row) => (\n <span className=\"text-text-secondary\">\n {row.ticketTypeId ? (ticketById.get(row.ticketTypeId) ?? '—') : '—'}\n </span>\n ),\n },\n {\n key: 'quantity',\n header: 'Qty',\n mobileLabel: 'Quantity',\n priority: 'secondary',\n cell: (row) => <span className=\"tabular-nums text-text-secondary\">{row.quantity}</span>,\n },\n {\n key: 'amount',\n header: 'Amount',\n cell: (row) => (\n <span className=\"tabular-nums text-text-primary\">\n {row.totalAmount ? formatMoney(Number(row.totalAmount), row.currency) : '—'}\n </span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'primary',\n cell: (row) => <Badge variant={statusVariant(row.status)}>{row.status ?? 'UNKNOWN'}</Badge>,\n },\n ];\n\n return (\n <SectionCard icon={<TicketPlus className=\"h-4 w-4\" />} title=\"Registrations\" count={total} loading={loading}>\n <ResponsiveTable\n columns={columns}\n data={items}\n rowKey={(row) => row.id}\n emptyState={\n loading ? null : (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No registrations yet.\"\n description=\"Register your first attendee to start tracking sign-ups.\"\n />\n )\n }\n rowActions={(row) => {\n const label = rowLabel(row);\n const statusItems: ActionMenuItem[] = REGISTRATION_STATUSES.filter(\n (candidate) => candidate !== (row.status ?? '').toUpperCase()\n ).map((candidate, index) => ({\n key: candidate,\n label: `Set ${candidate.replace('_', ' ').toLowerCase()}`,\n onSelect: () => void changeStatus(row, candidate),\n separatorBefore: index === 0,\n }));\n const extraItems: ActionMenuItem[] = [\n {\n key: 'view-qr',\n label: 'View check-in QR',\n icon: QrCode,\n onSelect: () => setQrRegistrationId(row.id),\n },\n {\n key: 'download-badge',\n label: downloadingBadgeId === row.id ? 'Generating badge…' : 'Download badge',\n icon: BadgeIcon,\n disabled: downloadingBadgeId === row.id,\n onSelect: () => void onDownloadBadge(row.id, label),\n },\n ...statusItems,\n ];\n return (\n <ActionMenu\n ariaLabel=\"Registration actions\"\n entityName={label}\n deleteLabel=\"Delete registration\"\n extraItems={extraItems}\n onDelete={() => onDelete(row, label)}\n />\n );\n }}\n />\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={items.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"registrations\"\n loading={loading}\n />\n {qrRegistrationId\n ? (() => {\n const qrRow = items.find((r) => r.id === qrRegistrationId);\n const qrLabel = qrRow ? rowLabel(qrRow) : `Registration ${qrRegistrationId}`;\n return (\n <CheckInQrDialog\n registrationId={qrRegistrationId}\n label={qrLabel}\n onOpenChange={(open) => {\n if (!open) setQrRegistrationId(null);\n }}\n />\n );\n })()\n : null}\n </SectionCard>\n );\n}\n\nfunction AttendeesSection() {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination({ pageSize: 10 });\n const { data, loading } = useAttendeesQuery({ limit: pagination.limit, offset: pagination.offset });\n const [deleteAttendee] = useDeleteAttendeeMutation();\n\n const items = useMemo<AttendeeGql[]>(() => data?.attendees.items ?? [], [data]);\n const total = data?.attendees.total ?? 0;\n\n const onDelete = async (row: AttendeeGql) => {\n const response = await deleteAttendee({ variables: { id: row.id } });\n if (response.error) {\n notify.error('Could not delete attendee', response.error.message);\n throw response.error;\n }\n if (!response.data?.deleteAttendee) {\n notify.error('Could not delete attendee', 'The server did not confirm the change.');\n throw new Error('delete-unconfirmed');\n }\n notify.success('Attendee deleted', row.fullName);\n };\n\n const columns: ResponsiveTableColumn<AttendeeGql>[] = [\n {\n key: 'name',\n header: 'Name',\n priority: 'primary',\n cell: (row) => <span className=\"font-medium text-text-primary\">{row.fullName}</span>,\n },\n {\n key: 'email',\n header: 'Email',\n priority: 'primary',\n cell: (row) => <span className=\"text-text-secondary\">{row.email}</span>,\n },\n {\n key: 'company',\n header: 'Company',\n cell: (row) => (\n <span className=\"text-text-secondary\">{[row.company, row.role].filter(Boolean).join(' · ') || '—'}</span>\n ),\n },\n ];\n\n return (\n <SectionCard\n icon={<Users className=\"h-4 w-4\" />}\n title=\"Attendees\"\n count={total}\n loading={loading}\n action={\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={() => navigate('/registration/attendees/create')}>\n <UserPlus className=\"h-4 w-4\" />\n Add attendee\n </Button>\n }\n >\n <ResponsiveTable\n columns={columns}\n data={items}\n rowKey={(row) => row.id}\n emptyState={\n loading ? null : (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title=\"No attendees yet.\"\n description=\"Add attendees or register one to build your guest list.\"\n />\n )\n }\n rowActions={(row) => (\n <ActionMenu\n ariaLabel={`Actions for ${row.fullName}`}\n entityName={row.fullName}\n deleteLabel=\"Delete attendee\"\n onView={() => navigate(`/attendees/${row.id}/profile`)}\n onEdit={() => navigate(`/registration/attendees/${row.id}/edit`)}\n onDelete={() => onDelete(row)}\n />\n )}\n />\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={items.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"attendees\"\n loading={loading}\n />\n </SectionCard>\n );\n}\n\nfunction PromoCodesSection() {\n const { navigate } = useEventfullyManaged();\n const pagination = usePagination({ pageSize: 10 });\n const { data, loading } = usePromoCodesQuery({ limit: pagination.limit, offset: pagination.offset });\n const [deletePromoCode] = useDeletePromoCodeMutation();\n\n const items = useMemo<PromoCodeGql[]>(() => data?.promoCodes.items ?? [], [data]);\n const total = data?.promoCodes.total ?? 0;\n\n const onDelete = async (row: PromoCodeGql) => {\n const response = await deletePromoCode({ variables: { id: row.id } });\n if (response.error) {\n notify.error('Could not delete promo code', response.error.message);\n throw response.error;\n }\n notify.success('Promo code deleted', row.code);\n };\n\n const columns: ResponsiveTableColumn<PromoCodeGql>[] = [\n {\n key: 'code',\n header: 'Code',\n priority: 'primary',\n cell: (row) => <span className=\"font-mono text-sm font-semibold text-text-primary\">{row.code}</span>,\n },\n {\n key: 'discount',\n header: 'Discount',\n priority: 'primary',\n cell: (row) => (\n <span className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\">{row.discountType === 'PERCENT' ? 'PERCENT' : 'FIXED'}</Badge>\n <span className=\"text-sm text-text-secondary\">\n {row.discountType === 'PERCENT' ? `${row.discountValue}%` : row.discountValue}\n </span>\n </span>\n ),\n },\n {\n key: 'usage',\n header: 'Usage',\n cell: (row) => <UsageMeter used={row.usedCount} max={row.maxUses} />,\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'secondary',\n cell: (row) => (\n <Badge variant={row.isActive ? 'default' : 'secondary'}>{row.isActive ? 'Active' : 'Inactive'}</Badge>\n ),\n },\n ];\n\n return (\n <SectionCard\n icon={<Tag className=\"h-4 w-4\" />}\n title=\"Promo Codes\"\n count={total}\n loading={loading}\n action={\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={() => navigate('/registration/promo-codes/create')}>\n <TicketPlus className=\"h-4 w-4\" />\n New promo code\n </Button>\n }\n >\n <ResponsiveTable\n columns={columns}\n data={items}\n rowKey={(row) => row.id}\n emptyState={\n loading ? null : (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No promo codes yet.\"\n description=\"Create a code to offer discounts and drive registrations.\"\n />\n )\n }\n rowActions={(row) => (\n <ActionMenu\n ariaLabel={`Actions for ${row.code}`}\n entityName={row.code}\n onEdit={() => navigate(`/registration/promo-codes/${row.id}/edit`)}\n onDelete={() => onDelete(row)}\n />\n )}\n />\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={items.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"promo codes\"\n loading={loading}\n />\n </SectionCard>\n );\n}\n\nexport default function RegistrationPage() {\n const { navigate } = useEventfullyManaged();\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n This is where you see who is coming. Registrations are the paid or confirmed sign-ups, attendees are the people\n behind them, and promo codes let you offer discounts. Register attendees, edit their details, change a\n registration&apos;s status, and manage discount codes — all backed by live GraphQL APIs.\n </PagePurpose>\n\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Registration</GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Track registrations, attendees, and promo codes with backend persistence.\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button type=\"button\" onClick={() => navigate('/registration/register')}>\n <TicketPlus className=\"h-4 w-4\" />\n Register attendee\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => navigate('/registration/attendees/create')}>\n <UserPlus className=\"h-4 w-4\" />\n Add attendee\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => navigate('/registration/promo-codes/create')}>\n <Tag className=\"h-4 w-4\" />\n New promo code\n </Button>\n </div>\n </div>\n </EmphasisPanel>\n\n <RegistrationsSection />\n <AttendeesSection />\n <PromoCodesSection />\n\n <NextSteps\n storageKey=\"eventfullymanaged-registration\"\n title=\"Grow your registrations\"\n steps={[\n {\n id: 'view-networking',\n label: 'Set up attendee networking',\n description: 'Turn registered attendees into connections with matchmaking.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('/networking'),\n },\n {\n id: 'promote',\n label: 'Promote with a campaign',\n description: 'Send reminders and offers to drive more sign-ups.',\n icon: <Megaphone className=\"h-4 w-4\" />,\n onClick: () => navigate('/communication'),\n },\n {\n id: 'analyze',\n label: 'Snapshot your numbers',\n description: 'Capture an analytics snapshot to track registration trends.',\n icon: <Tag className=\"h-4 w-4\" />,\n onClick: () => navigate('/analytics'),\n },\n ]}\n />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Shell bridge — unified accessor for capabilities exposed by the host app
3
+ * shell on `globalThis.__burdenoffShell`. Each accessor is fully optional:
4
+ * the MFE must work in isolation (Storybook/standalone Vite dev) when the
5
+ * shell global is absent.
6
+ *
7
+ * Capabilities consumed:
8
+ * - `reportError` — central SRE error sink (Rybbit + backend forward)
9
+ * - `graphqlWsClient` — graphql-ws Client instance (probe-only; subs fall
10
+ * back to polling when absent)
11
+ *
12
+ * Ported from `microfe-comradecircle/src/comradecircle/utils/shellBridge.ts`
13
+ * (BOFF-4455's reference pattern, itself ported from `microfe-channel`) —
14
+ * same shell contract, product-scoped copy per the "no cross-MFE imports"
15
+ * convention. Used by the BOFF-4318 virtual-session WebRTC signaling core.
16
+ */
17
+ export interface ShellReportErrorMeta {
18
+ module: string;
19
+ context?: Record<string, unknown>;
20
+ componentStack?: string;
21
+ }
22
+ /**
23
+ * Minimal subset of a graphql-ws Client we rely on.
24
+ * https://the-guild.dev/graphql/ws/recipes#use-the-client-without-apollo
25
+ */
26
+ export interface GraphqlWsLike {
27
+ subscribe: (payload: {
28
+ query: string;
29
+ variables?: Record<string, unknown>;
30
+ operationName?: string;
31
+ }, sink: {
32
+ next: (value: {
33
+ data?: unknown;
34
+ errors?: readonly unknown[];
35
+ }) => void;
36
+ error: (err: unknown) => void;
37
+ complete: () => void;
38
+ }) => () => void;
39
+ }
40
+ /**
41
+ * Forward an error to the shell's central error sink. Falls back to
42
+ * `console.error` only when the sink is missing.
43
+ */
44
+ export declare function reportShellError(error: unknown, meta: ShellReportErrorMeta, fallbackLabel?: string): void;
45
+ export declare function getGraphqlWsClient(): GraphqlWsLike | undefined;
46
+ //# sourceMappingURL=shellBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellBridge.d.ts","sourceRoot":"","sources":["../../../src/eventfullymanaged/utils/shellBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,CACT,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,EACvF,IAAI,EAAE;QACJ,IAAI,EAAE,CAAC,KAAK,EAAE;YAAE,IAAI,CAAC,EAAE,OAAO,CAAC;YAAC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;SAAE,KAAK,IAAI,CAAC;QACvE,KAAK,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;QAC9B,QAAQ,EAAE,MAAM,IAAI,CAAC;KACtB,KACE,MAAM,IAAI,CAAC;CACjB;AAeD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAgBzG;AAED,wBAAgB,kBAAkB,IAAI,aAAa,GAAG,SAAS,CAE9D"}
@@ -0,0 +1,19 @@
1
+ //#region src/eventfullymanaged/utils/shellBridge.ts
2
+ function e() {
3
+ return globalThis.__burdenoffShell;
4
+ }
5
+ function t(t, n, r) {
6
+ let i = t instanceof Error ? t : Error(String(t)), a = e();
7
+ if (a?.reportError) try {
8
+ a.reportError(i, n);
9
+ return;
10
+ } catch {}
11
+ console.error(r || `[${n.module}]`, i, n.context ?? {});
12
+ }
13
+ function n() {
14
+ return e()?.graphqlWsClient;
15
+ }
16
+ //#endregion
17
+ export { n as getGraphqlWsClient, t as reportShellError };
18
+
19
+ //# sourceMappingURL=shellBridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellBridge.js","names":[],"sources":["../../../src/eventfullymanaged/utils/shellBridge.ts"],"sourcesContent":["/**\n * Shell bridge — unified accessor for capabilities exposed by the host app\n * shell on `globalThis.__burdenoffShell`. Each accessor is fully optional:\n * the MFE must work in isolation (Storybook/standalone Vite dev) when the\n * shell global is absent.\n *\n * Capabilities consumed:\n * - `reportError` — central SRE error sink (Rybbit + backend forward)\n * - `graphqlWsClient` — graphql-ws Client instance (probe-only; subs fall\n * back to polling when absent)\n *\n * Ported from `microfe-comradecircle/src/comradecircle/utils/shellBridge.ts`\n * (BOFF-4455's reference pattern, itself ported from `microfe-channel`) —\n * same shell contract, product-scoped copy per the \"no cross-MFE imports\"\n * convention. Used by the BOFF-4318 virtual-session WebRTC signaling core.\n */\n\nexport interface ShellReportErrorMeta {\n module: string;\n context?: Record<string, unknown>;\n componentStack?: string;\n}\n\n/**\n * Minimal subset of a graphql-ws Client we rely on.\n * https://the-guild.dev/graphql/ws/recipes#use-the-client-without-apollo\n */\nexport interface GraphqlWsLike {\n subscribe: (\n payload: { query: string; variables?: Record<string, unknown>; operationName?: string },\n sink: {\n next: (value: { data?: unknown; errors?: readonly unknown[] }) => void;\n error: (err: unknown) => void;\n complete: () => void;\n }\n ) => () => void;\n}\n\ninterface BurdenoffShell {\n reportError?: (\n sourceOrError: string | Error,\n errorOrMeta?: Error | ShellReportErrorMeta,\n meta?: ShellReportErrorMeta | Record<string, unknown>\n ) => void;\n graphqlWsClient?: GraphqlWsLike;\n}\n\nfunction getShell(): BurdenoffShell | undefined {\n return (globalThis as unknown as { __burdenoffShell?: BurdenoffShell }).__burdenoffShell;\n}\n\n/**\n * Forward an error to the shell's central error sink. Falls back to\n * `console.error` only when the sink is missing.\n */\nexport function reportShellError(error: unknown, meta: ShellReportErrorMeta, fallbackLabel?: string): void {\n const err = error instanceof Error ? error : new Error(String(error));\n const sink = getShell();\n if (sink?.reportError) {\n try {\n sink.reportError(err, meta);\n return;\n } catch {\n /* fall through to console */\n }\n }\n if (fallbackLabel) {\n console.error(fallbackLabel, err, meta.context ?? {});\n } else {\n console.error(`[${meta.module}]`, err, meta.context ?? {});\n }\n}\n\nexport function getGraphqlWsClient(): GraphqlWsLike | undefined {\n return getShell()?.graphqlWsClient;\n}\n"],"mappings":";AA+CA,SAAS,IAAuC;AAC9C,QAAQ,WAAgE;;AAO1E,SAAgB,EAAiB,GAAgB,GAA4B,GAA8B;CACzG,IAAM,IAAM,aAAiB,QAAQ,IAAY,MAAM,OAAO,EAAM,CAAC,EAC/D,IAAO,GAAU;AACvB,KAAI,GAAM,YACR,KAAI;AACF,IAAK,YAAY,GAAK,EAAK;AAC3B;SACM;AAIV,CACE,QAAQ,MADN,KAGY,IAAI,EAAK,OAAO,IAFD,GAAK,EAAK,WAAW,EAAE,CAEM;;AAI9D,SAAgB,IAAgD;AAC9D,QAAO,GAAU,EAAE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-eventfullymanaged",
3
- "version": "2026.728.1",
3
+ "version": "2026.731.1",
4
4
  "description": "EventfullyManaged - End-to-end event management platform",
5
5
  "type": "module",
6
6
  "files": [