@burdenoff/microfe-eventfullymanaged 2026.703.1 → 2026.704.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.
- package/dist/eventfullymanaged/EventfullyManagedRoutes.js +154 -66
- package/dist/eventfullymanaged/EventfullyManagedRoutes.js.map +1 -1
- package/dist/eventfullymanaged/api/eventApi.js +546 -68
- package/dist/eventfullymanaged/api/eventApi.js.map +1 -1
- package/dist/eventfullymanaged/components/ActionMenu.js +113 -0
- package/dist/eventfullymanaged/components/ActionMenu.js.map +1 -0
- package/dist/eventfullymanaged/components/EntityFormShell.js +51 -0
- package/dist/eventfullymanaged/components/EntityFormShell.js.map +1 -0
- package/dist/eventfullymanaged/components/EntityTagsField.js +146 -0
- package/dist/eventfullymanaged/components/EntityTagsField.js.map +1 -0
- package/dist/eventfullymanaged/components/Pagination.js +84 -0
- package/dist/eventfullymanaged/components/Pagination.js.map +1 -0
- package/dist/eventfullymanaged/components/SafeLink.js +32 -0
- package/dist/eventfullymanaged/components/SafeLink.js.map +1 -0
- package/dist/eventfullymanaged/components/index.js +7 -0
- package/dist/eventfullymanaged/pages/events/EventDetailPage.js +458 -0
- package/dist/eventfullymanaged/pages/events/EventDetailPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/events/EventFormPage.js +267 -0
- package/dist/eventfullymanaged/pages/events/EventFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/events/SessionFormPage.js +308 -0
- package/dist/eventfullymanaged/pages/events/SessionFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/events/TicketTypeFormPage.js +214 -0
- package/dist/eventfullymanaged/pages/events/TicketTypeFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/events/eventFormUtils.js +128 -0
- package/dist/eventfullymanaged/pages/events/eventFormUtils.js.map +1 -0
- package/dist/eventfullymanaged/pages/exhibitors/ExhibitorFormPage.js +233 -0
- package/dist/eventfullymanaged/pages/exhibitors/ExhibitorFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/exhibitors/ExhibitorsPage.js +165 -0
- package/dist/eventfullymanaged/pages/exhibitors/ExhibitorsPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/leads/LeadCaptureDialog.js +141 -0
- package/dist/eventfullymanaged/pages/leads/LeadCaptureDialog.js.map +1 -0
- package/dist/eventfullymanaged/pages/modules/AnalyticsPage.js +178 -45
- package/dist/eventfullymanaged/pages/modules/AnalyticsPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/CommunicationPage.js +240 -70
- package/dist/eventfullymanaged/pages/modules/CommunicationPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/EventsPage.js +133 -97
- package/dist/eventfullymanaged/pages/modules/EventsPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/KioskPage.js +746 -36
- package/dist/eventfullymanaged/pages/modules/KioskPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/NetworkingPage.js +210 -69
- package/dist/eventfullymanaged/pages/modules/NetworkingPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/OperationsHubPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/RegistrationPage.js +289 -77
- package/dist/eventfullymanaged/pages/modules/RegistrationPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/RoadmapPanel.js +95 -0
- package/dist/eventfullymanaged/pages/modules/RoadmapPanel.js.map +1 -0
- package/dist/eventfullymanaged/pages/modules/SponsorDetailsPage.js +77 -56
- package/dist/eventfullymanaged/pages/modules/SponsorDetailsPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/SponsorLeadsPage.js +70 -36
- package/dist/eventfullymanaged/pages/modules/SponsorLeadsPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/networking/MeetingFormPage.js +343 -0
- package/dist/eventfullymanaged/pages/networking/MeetingFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/networking/NetworkingProfileFormPage.js +236 -0
- package/dist/eventfullymanaged/pages/networking/NetworkingProfileFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/registration/AttendeeFormPage.js +181 -0
- package/dist/eventfullymanaged/pages/registration/AttendeeFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/registration/PromoCodeFormPage.js +262 -0
- package/dist/eventfullymanaged/pages/registration/PromoCodeFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/registration/RegisterAttendeePage.js +414 -0
- package/dist/eventfullymanaged/pages/registration/RegisterAttendeePage.js.map +1 -0
- package/dist/eventfullymanaged/pages/speakers/SpeakerFormPage.js +224 -0
- package/dist/eventfullymanaged/pages/speakers/SpeakerFormPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/speakers/SpeakersPage.js +96 -0
- package/dist/eventfullymanaged/pages/speakers/SpeakersPage.js.map +1 -0
- package/dist/eventfullymanaged/pages/sponsors/SponsorFormPage.js +149 -140
- package/dist/eventfullymanaged/pages/sponsors/SponsorFormPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/sponsors/SponsorsListPage.js +97 -67
- package/dist/eventfullymanaged/pages/sponsors/SponsorsListPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/venues/VenueDetailPage.js +93 -72
- package/dist/eventfullymanaged/pages/venues/VenueDetailPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/venues/VenueFormPage.js +91 -89
- package/dist/eventfullymanaged/pages/venues/VenueFormPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/venues/VenueListPage.js +83 -53
- package/dist/eventfullymanaged/pages/venues/VenueListPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KioskPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/KioskPage.tsx"],"sourcesContent":["import { EmphasisPanel, GradientText, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useMemo } from 'react';\n\nimport { useCheckInRecordsQuery, useCheckInStationsQuery } from '../../api/eventApi';\nimport { EntityListSection } from './EntityListSection';\n\ntype StationRow = {\n id: string;\n name?: string;\n title?: string;\n status?: string;\n};\n\nexport default function KioskPage() {\n const stationsQuery = useCheckInStationsQuery({ limit: 100, offset: 0 });\n const recordsQuery = useCheckInRecordsQuery({ limit: 100, offset: 0 });\n const stations = useMemo(\n () => (stationsQuery.data?.checkInStations.items ?? []) as StationRow[],\n [stationsQuery.data]\n );\n const records = useMemo(() => recordsQuery.data?.checkInRecords.items ?? [], [recordsQuery.data]);\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Kiosks are the front desk of your event. Each check-in station is a device or counter where attendees scan in,\n and check-in records are the live log of who arrived and when. Use this page to confirm your stations are\n online before doors open and to watch arrivals flow in on the day.\n </PagePurpose>\n\n <EmphasisPanel>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Kiosk</GradientText> & Check-In\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">View configured check-in stations and station status.</p>\n </EmphasisPanel>\n\n <EntityListSection\n heading={stationsQuery.loading ? 'Loading check-in stations...' : `Stations (${stations.length})`}\n emptyLabel=\"No check-in stations configured yet.\"\n rows={stations.map((row) => ({\n id: row.id,\n title: row.name ?? row.title ?? `Station ${row.id}`,\n status: row.status ?? undefined,\n }))}\n />\n\n <EntityListSection\n heading={recordsQuery.loading ? 'Loading check-in records...' : `Check-In Records (${records.length})`}\n emptyLabel=\"No check-in records found.\"\n rows={records.map((row) => ({\n id: row.id,\n title: row.attendeeId ? `Attendee ${row.attendeeId}` : `Record ${row.id}`,\n subtitle: `${row.method} • ${row.direction}`,\n status: row.status,\n }))}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;AAaA,SAAwB,IAAY;CAClC,IAAM,IAAgB,EAAwB;EAAE,OAAO;EAAK,QAAQ;EAAG,CAAC,EAClE,IAAe,EAAuB;EAAE,OAAO;EAAK,QAAQ;EAAG,CAAC,EAChE,IAAW,QACR,EAAc,MAAM,gBAAgB,SAAS,EAAE,EACtD,CAAC,EAAc,KAAK,CACrB,EACK,IAAU,QAAc,EAAa,MAAM,eAAe,SAAS,EAAE,EAAE,CAAC,EAAa,KAAK,CAAC;AAEjG,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD,EAAA,UAAa,+RAIC,CAAA;GAEd,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cAAd,CACE,kBAAC,GAAD,EAAA,UAAc,SAAoB,CAAA,EAAA,cAC/B;OACL,kBAAC,KAAD;IAAG,WAAU;cAAmC;IAAyD,CAAA,CAC3F,EAAA,CAAA;GAEhB,kBAAC,GAAD;IACE,SAAS,EAAc,UAAU,iCAAiC,aAAa,EAAS,OAAO;IAC/F,YAAW;IACX,MAAM,EAAS,KAAK,OAAS;KAC3B,IAAI,EAAI;KACR,OAAO,EAAI,QAAQ,EAAI,SAAS,WAAW,EAAI;KAC/C,QAAQ,EAAI,UAAU,KAAA;KACvB,EAAE;IACH,CAAA;GAEF,kBAAC,GAAD;IACE,SAAS,EAAa,UAAU,gCAAgC,qBAAqB,EAAQ,OAAO;IACpG,YAAW;IACX,MAAM,EAAQ,KAAK,OAAS;KAC1B,IAAI,EAAI;KACR,OAAO,EAAI,aAAa,YAAY,EAAI,eAAe,UAAU,EAAI;KACrE,UAAU,GAAG,EAAI,OAAO,KAAK,EAAI;KACjC,QAAQ,EAAI;KACb,EAAE;IACH,CAAA;GACE"}
|
|
1
|
+
{"version":3,"file":"KioskPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/KioskPage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n EmphasisPanel,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n Label,\n PagePurpose,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n} from '@burdenoff/fe-libs/ui';\nimport { LogIn, MonitorSmartphone, Plus, ScanLine } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\nimport {\n useAttendeesQuery,\n useCheckInRecordsQuery,\n useCheckInStationsQuery,\n useCreateCheckInRecordMutation,\n useCreateCheckInStationMutation,\n useDeleteCheckInRecordMutation,\n useDeleteCheckInStationMutation,\n useEventSessionsQuery,\n useEventsQuery,\n useUpdateCheckInRecordMutation,\n useUpdateCheckInStationMutation,\n} from '../../api/eventApi';\nimport { ActionMenu, Pagination, usePagination } from '../../components';\nimport { describeError, mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\n\n// ---------------------------------------------------------------------------\n// Shared types\n// ---------------------------------------------------------------------------\n\ntype StationRow = {\n id: string;\n eventId?: string | null;\n name?: string | null;\n metadata?: Record<string, unknown> | null;\n};\n\ntype RecordRow = {\n id: string;\n eventId: string;\n stationId?: string | null;\n attendeeId?: string | null;\n registrationId?: string | null;\n method: string;\n status: string;\n direction: string;\n recordedAt: string;\n metadata?: Record<string, unknown> | null;\n};\n\nconst STATION_TYPES = ['DESK', 'GATE', 'SELF_SERVICE', 'MOBILE'] as const;\nconst CHECKIN_METHODS = ['QR', 'MANUAL'] as const;\nconst CHECKIN_DIRECTIONS = ['IN', 'OUT'] as const;\n\n/**\n * The stations list resolver projects a CheckInStation onto the generic\n * SimpleEntity shape (id/name/metadata) — it does NOT expose the `code`,\n * `location` or `isActive` columns. To keep create → list → edit lossless we\n * mirror those attributes into `metadata` on every write, so an edit opened from\n * a list row can rebuild the full required input without a by-id resolver.\n */\ntype StationMeta = {\n code?: string;\n location?: string;\n type?: string;\n isActive?: boolean;\n};\n\nfunction readStationMeta(metadata: Record<string, unknown> | null | undefined): StationMeta {\n if (!metadata || typeof metadata !== 'object') {\n return {};\n }\n const m = metadata as Record<string, unknown>;\n return {\n code: typeof m.code === 'string' ? m.code : undefined,\n location: typeof m.location === 'string' ? m.location : undefined,\n type: typeof m.type === 'string' ? m.type : undefined,\n isActive: typeof m.isActive === 'boolean' ? m.isActive : undefined,\n };\n}\n\nfunction slugCode(name: string): string {\n return (\n name\n .trim()\n .toUpperCase()\n .replace(/[^A-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 24) || 'STATION'\n );\n}\n\n// ===========================================================================\n// Station create / edit dialog\n// ===========================================================================\n\ntype StationFormState = {\n name: string;\n code: string;\n location: string;\n type: string;\n isActive: boolean;\n};\n\ninterface StationDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n eventId: string;\n eventName: string;\n /** Present when editing an existing station. */\n station?: StationRow;\n}\n\nfunction StationDialog({ open, onOpenChange, eventId, eventName, station }: StationDialogProps) {\n const isEdit = Boolean(station);\n const [createStation, { loading: creating }] = useCreateCheckInStationMutation();\n const [updateStation, { loading: updating }] = useUpdateCheckInStationMutation();\n\n const initial = useMemo<StationFormState>(() => {\n if (!station) {\n return { name: '', code: '', location: '', type: 'DESK', isActive: true };\n }\n const meta = readStationMeta(station.metadata);\n return {\n name: station.name ?? '',\n code: meta.code ?? slugCode(station.name ?? ''),\n location: meta.location ?? '',\n type: meta.type ?? 'DESK',\n isActive: meta.isActive ?? true,\n };\n }, [station]);\n\n const [form, setForm] = useState<StationFormState>(initial);\n // Reset the form to the active station whenever the dialog is (re)opened.\n const [seededFor, setSeededFor] = useState<string | null>(null);\n const seedKey = `${open ? 'open' : 'closed'}:${station?.id ?? 'new'}`;\n if (open && seededFor !== seedKey) {\n setSeededFor(seedKey);\n setForm(initial);\n }\n if (!open && seededFor !== null) {\n setSeededFor(null);\n }\n\n const onChange = <K extends keyof StationFormState>(field: K, value: StationFormState[K]) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n };\n\n const saving = creating || updating;\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const code = form.code.trim() || slugCode(form.name);\n const input = {\n eventId,\n name: form.name.trim(),\n code,\n location: form.location.trim() || null,\n isActive: form.isActive,\n kioskConfig: { type: form.type },\n // Mirror the write-only columns so the SimpleEntity list can rebuild them.\n metadata: { code, location: form.location.trim(), type: form.type, isActive: form.isActive },\n };\n\n try {\n if (isEdit && station) {\n const res = await updateStation({ variables: { id: station.id, input } });\n if (!mutationSucceeded(res, res.data?.updateCheckInStation?.id, 'Could not update station')) {\n return;\n }\n notify.success('Station updated', `“${input.name}” is now ${form.isActive ? 'active' : 'disabled'}.`);\n } else {\n const res = await createStation({ variables: { input } });\n if (!mutationSucceeded(res, res.data?.createCheckInStation?.id, 'Could not create station')) {\n return;\n }\n notify.success('Station created', `“${input.name}” is ready at ${eventName}.`);\n }\n onOpenChange(false);\n } catch (error) {\n notify.error('Could not save station', describeError(error));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{isEdit ? 'Edit check-in station' : 'New check-in station'}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n A station is a desk, gate or device where attendees scan in at {eventName}.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form id=\"station-form\" onSubmit={onSubmit} className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Name</span>\n <Input\n value={form.name}\n onChange={(e) => onChange('name', e.target.value)}\n placeholder=\"Main entrance\"\n required\n />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Code</span>\n <Input\n value={form.code}\n onChange={(e) => onChange('code', e.target.value)}\n placeholder=\"Auto from name\"\n />\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Location</span>\n <Input\n value={form.location}\n onChange={(e) => onChange('location', e.target.value)}\n placeholder=\"North lobby\"\n />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Type</span>\n <Select value={form.type} onValueChange={(value) => onChange('type', value)}>\n <SelectTrigger aria-label=\"Station type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATION_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {type.replace('_', ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <div className=\"flex items-center justify-between rounded-card border border-border-seam bg-bg-surface p-3\">\n <div>\n <Label htmlFor=\"station-active\" className=\"text-text-primary\">\n Active\n </Label>\n <p className=\"text-xs text-text-secondary\">Disabled stations stay configured but cannot accept scans.</p>\n </div>\n <Switch\n id=\"station-active\"\n checked={form.isActive}\n onCheckedChange={(checked) => onChange('isActive', checked)}\n aria-label=\"Station active\"\n />\n </div>\n </form>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)} disabled={saving}>\n Cancel\n </Button>\n <Button type=\"submit\" form=\"station-form\" disabled={saving}>\n {saving ? 'Saving…' : isEdit ? 'Save station' : 'Create station'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ===========================================================================\n// Check-in record edit dialog\n// ===========================================================================\n\ntype RecordFormState = {\n method: string;\n direction: string;\n status: string;\n stationId: string;\n attendeeId: string;\n};\n\ninterface RecordDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n record: RecordRow | null;\n stations: StationRow[];\n}\n\nfunction RecordDialog({ open, onOpenChange, record, stations }: RecordDialogProps) {\n const [updateRecord, { loading }] = useUpdateCheckInRecordMutation();\n\n const initial = useMemo<RecordFormState>(\n () => ({\n method: record?.method ?? 'MANUAL',\n direction: record?.direction ?? 'IN',\n status: record?.status ?? 'checked_in',\n stationId: record?.stationId ?? '',\n attendeeId: record?.attendeeId ?? '',\n }),\n [record]\n );\n const [form, setForm] = useState<RecordFormState>(initial);\n const [seededFor, setSeededFor] = useState<string | null>(null);\n const seedKey = `${open ? 'open' : 'closed'}:${record?.id ?? 'none'}`;\n if (open && seededFor !== seedKey) {\n setSeededFor(seedKey);\n setForm(initial);\n }\n if (!open && seededFor !== null) {\n setSeededFor(null);\n }\n\n const onChange = <K extends keyof RecordFormState>(field: K, value: RecordFormState[K]) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n };\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!record) {\n return;\n }\n const input = {\n eventId: record.eventId,\n attendeeId: form.attendeeId.trim() || null,\n registrationId: record.registrationId ?? null,\n stationId: form.stationId || null,\n method: form.method,\n direction: form.direction,\n status: form.status.trim() || 'checked_in',\n metadata: record.metadata ?? {},\n };\n try {\n const res = await updateRecord({ variables: { id: record.id, input } });\n if (!mutationSucceeded(res, res.data?.updateCheckInRecord?.id, 'Could not update record')) {\n return;\n }\n notify.success('Check-in updated');\n onOpenChange(false);\n } catch (error) {\n notify.error('Could not update record', describeError(error));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Edit check-in record</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>Correct the direction, method or station for this scan.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form id=\"record-form\" onSubmit={onSubmit} className=\"space-y-4\">\n <label className=\"block space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Attendee ID</span>\n <Input value={form.attendeeId} onChange={(e) => onChange('attendeeId', e.target.value)} />\n </label>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Method</span>\n <Select value={form.method} onValueChange={(value) => onChange('method', value)}>\n <SelectTrigger aria-label=\"Method\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CHECKIN_METHODS.map((method) => (\n <SelectItem key={method} value={method}>\n {method}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Direction</span>\n <Select value={form.direction} onValueChange={(value) => onChange('direction', value)}>\n <SelectTrigger aria-label=\"Direction\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CHECKIN_DIRECTIONS.map((direction) => (\n <SelectItem key={direction} value={direction}>\n {direction}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Status</span>\n <Input value={form.status} onChange={(e) => onChange('status', e.target.value)} />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Station</span>\n <Select\n value={form.stationId || 'none'}\n onValueChange={(value) => onChange('stationId', value === 'none' ? '' : value)}\n >\n <SelectTrigger aria-label=\"Station\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">No station</SelectItem>\n {stations.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.name ?? s.id}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n </form>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button type=\"submit\" form=\"record-form\" disabled={loading}>\n {loading ? 'Saving…' : 'Save record'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ===========================================================================\n// Check-in action panel (the hero workflow)\n// ===========================================================================\n\ninterface CheckInPanelProps {\n eventId: string;\n stations: StationRow[];\n onCheckedIn: () => void;\n}\n\nfunction CheckInPanel({ eventId, stations, onCheckedIn }: CheckInPanelProps) {\n const [scanValue, setScanValue] = useState('');\n const [method, setMethod] = useState<string>('QR');\n const [direction, setDirection] = useState<string>('IN');\n const [stationId, setStationId] = useState('');\n const [sessionId, setSessionId] = useState('');\n\n const [createRecord, { loading }] = useCreateCheckInRecordMutation();\n const attendeesQuery = useAttendeesQuery({ eventId, limit: 100, offset: 0 });\n const sessionsQuery = useEventSessionsQuery({ eventId, limit: 100, offset: 0 });\n\n const attendees = attendeesQuery.data?.attendees.items ?? [];\n const sessions = sessionsQuery.data?.eventSessions.items ?? [];\n\n const resolveAttendee = (raw: string): { attendeeId: string | null; label: string } => {\n const value = raw.trim();\n if (!value) {\n return { attendeeId: null, label: 'attendee' };\n }\n if (value.includes('@')) {\n const match = attendees.find((a) => a.email?.toLowerCase() === value.toLowerCase());\n return { attendeeId: match?.id ?? null, label: match?.fullName ?? value };\n }\n const byId = attendees.find((a) => a.id === value);\n return { attendeeId: value, label: byId?.fullName ?? `attendee ${value}` };\n };\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const { attendeeId, label } = resolveAttendee(scanValue);\n if (scanValue.trim().includes('@') && !attendeeId) {\n notify.error('Attendee not found', `No attendee at this event matches “${scanValue.trim()}”.`);\n return;\n }\n const input = {\n eventId,\n attendeeId,\n stationId: stationId || null,\n method,\n direction,\n status: 'checked_in',\n recordedAt: new Date().toISOString(),\n metadata: sessionId ? { sessionId } : {},\n };\n try {\n const res = await createRecord({ variables: { input } });\n if (!mutationSucceeded(res, res.data?.createCheckInRecord?.id, 'Could not record check-in')) {\n return;\n }\n notify.success(\n `${label} checked ${direction === 'OUT' ? 'out' : 'in'}`,\n `Recorded via ${method}${stationId ? '' : ' • no station'}.`\n );\n setScanValue('');\n onCheckedIn();\n } catch (error) {\n notify.error('Could not record check-in', describeError(error));\n }\n };\n\n return (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <div className=\"flex items-center gap-2\">\n <ScanLine className=\"h-5 w-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Check in an attendee</h2>\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Scan a QR badge or type an attendee ID or email, then record the arrival.\n </p>\n\n <form onSubmit={onSubmit} className=\"mt-4 space-y-4\">\n <label className=\"block space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Attendee ID / email / QR</span>\n <Input\n value={scanValue}\n onChange={(e) => setScanValue(e.target.value)}\n placeholder=\"Scan badge or paste attendee ID / email\"\n autoComplete=\"off\"\n />\n </label>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Method</span>\n <Select value={method} onValueChange={setMethod}>\n <SelectTrigger aria-label=\"Check-in method\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CHECKIN_METHODS.map((m) => (\n <SelectItem key={m} value={m}>\n {m}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Direction</span>\n <Select value={direction} onValueChange={setDirection}>\n <SelectTrigger aria-label=\"Direction\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CHECKIN_DIRECTIONS.map((d) => (\n <SelectItem key={d} value={d}>\n {d}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Station</span>\n <Select value={stationId || 'none'} onValueChange={(value) => setStationId(value === 'none' ? '' : value)}>\n <SelectTrigger aria-label=\"Station\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">No station</SelectItem>\n {stations.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.name ?? s.id}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Session</span>\n <Select value={sessionId || 'none'} onValueChange={(value) => setSessionId(value === 'none' ? '' : value)}>\n <SelectTrigger aria-label=\"Session\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">Whole event</SelectItem>\n {sessions.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.title}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <div className=\"flex justify-end\">\n <Button type=\"submit\" disabled={loading || !scanValue.trim()}>\n <LogIn className=\"h-4 w-4\" />\n {loading ? 'Recording…' : 'Record check-in'}\n </Button>\n </div>\n </form>\n </GlassCard>\n );\n}\n\n// ===========================================================================\n// Page\n// ===========================================================================\n\nconst PAGE_SIZE = 10;\n\nexport default function KioskPage() {\n const eventsQuery = useEventsQuery({ limit: 100, offset: 0 });\n const events = eventsQuery.data?.events.items ?? [];\n const [selectedEventId, setSelectedEventId] = useState('');\n const scopeEventId = selectedEventId || undefined;\n const selectedEvent = events.find((e) => e.id === selectedEventId);\n\n const stationsPagination = usePagination({ pageSize: PAGE_SIZE, resetKey: selectedEventId });\n const recordsPagination = usePagination({ pageSize: PAGE_SIZE, resetKey: selectedEventId });\n\n const stationsQuery = useCheckInStationsQuery({\n eventId: scopeEventId,\n limit: stationsPagination.limit,\n offset: stationsPagination.offset,\n });\n const recordsQuery = useCheckInRecordsQuery({\n eventId: scopeEventId,\n limit: recordsPagination.limit,\n offset: recordsPagination.offset,\n });\n\n const stations = (stationsQuery.data?.checkInStations.items ?? []) as StationRow[];\n const stationsTotal = stationsQuery.data?.checkInStations.total ?? 0;\n const records = (recordsQuery.data?.checkInRecords.items ?? []) as RecordRow[];\n const recordsTotal = recordsQuery.data?.checkInRecords.total ?? 0;\n\n const [deleteStation] = useDeleteCheckInStationMutation();\n const [deleteRecord] = useDeleteCheckInRecordMutation();\n\n const [stationDialogOpen, setStationDialogOpen] = useState(false);\n const [editingStation, setEditingStation] = useState<StationRow | undefined>(undefined);\n const [recordDialogOpen, setRecordDialogOpen] = useState(false);\n const [editingRecord, setEditingRecord] = useState<RecordRow | null>(null);\n\n const openNewStation = () => {\n setEditingStation(undefined);\n setStationDialogOpen(true);\n };\n const openEditStation = (station: StationRow) => {\n setEditingStation(station);\n setStationDialogOpen(true);\n };\n const openEditRecord = (record: RecordRow) => {\n setEditingRecord(record);\n setRecordDialogOpen(true);\n };\n\n const onDeleteStation = async (station: StationRow) => {\n const res = await deleteStation({ variables: { id: station.id } });\n if (!mutationSucceeded(res, res.data?.deleteCheckInStation ? station.id : null, 'Could not delete station')) {\n return;\n }\n notify.success('Station deleted', `“${station.name ?? station.id}” was removed.`);\n };\n\n const onDeleteRecord = async (record: RecordRow) => {\n const res = await deleteRecord({ variables: { id: record.id } });\n if (!mutationSucceeded(res, res.data?.deleteCheckInRecord ? record.id : null, 'Could not delete record')) {\n return;\n }\n notify.success('Check-in record deleted');\n };\n\n const hasEvent = Boolean(selectedEventId);\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Kiosks are the front desk of your event. Each check-in station is a device or counter where attendees scan in,\n and check-in records are the live log of who arrived and when. Configure your stations before doors open, then\n check attendees in from this page and watch arrivals flow in on the day.\n </PagePurpose>\n\n <EmphasisPanel>\n <div className=\"flex flex-wrap items-start justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Kiosk</GradientText> & Check-In\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Manage check-in stations and record attendee arrivals against a live backend.\n </p>\n </div>\n <div className=\"flex flex-wrap items-end gap-3\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Event</span>\n <Select value={selectedEventId || 'all'} onValueChange={(v) => setSelectedEventId(v === 'all' ? '' : v)}>\n <SelectTrigger aria-label=\"Event\" className=\"min-w-52\">\n <SelectValue placeholder=\"All events\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All events</SelectItem>\n {events.map((event) => (\n <SelectItem key={event.id} value={event.id}>\n {event.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <Button type=\"button\" onClick={openNewStation} disabled={!hasEvent}>\n <Plus className=\"h-4 w-4\" />\n New station\n </Button>\n </div>\n </div>\n </EmphasisPanel>\n\n {hasEvent ? (\n <CheckInPanel\n eventId={selectedEventId}\n stations={stations}\n onCheckedIn={() => {\n recordsPagination.reset();\n void recordsQuery.refetch();\n }}\n />\n ) : (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"Select an event to check attendees in\"\n description=\"Check-in stations and records belong to a specific event. Pick one above to configure stations and record arrivals.\"\n className=\"py-8\"\n />\n </GlassCard>\n )}\n\n {/* Stations */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <div className=\"flex items-center gap-2\">\n <MonitorSmartphone className=\"h-5 w-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {stationsQuery.loading ? 'Loading stations…' : `Stations (${stationsTotal})`}\n </h2>\n </div>\n <div className=\"mt-4\">\n {stations.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No check-in stations yet\"\n description={hasEvent ? 'Create a station to start scanning attendees in.' : 'No stations configured.'}\n className=\"py-8\"\n />\n ) : (\n <ul className=\"space-y-2.5\">\n {stations.map((station) => {\n const meta = readStationMeta(station.metadata);\n const active = meta.isActive ?? true;\n const subtitle = [meta.type?.replace('_', ' '), meta.location, meta.code]\n .filter(Boolean)\n .join(' • ');\n return (\n <li\n key={station.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\">{station.name ?? station.id}</p>\n {subtitle ? <p className=\"mt-0.5 truncate text-sm text-text-secondary\">{subtitle}</p> : null}\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge variant={active ? 'success' : 'warning'} className=\"shrink-0 uppercase\">\n {active ? 'active' : 'disabled'}\n </Badge>\n <ActionMenu\n ariaLabel={`Station ${station.name ?? station.id} actions`}\n entityName={station.name ?? undefined}\n onEdit={() => openEditStation(station)}\n onDelete={() => onDeleteStation(station)}\n />\n </div>\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </div>\n <Pagination\n offset={stationsPagination.offset}\n limit={stationsPagination.limit}\n loadedCount={stations.length}\n total={stationsTotal}\n onPrev={stationsPagination.prevPage}\n onNext={stationsPagination.nextPage}\n itemLabel=\"stations\"\n loading={stationsQuery.loading}\n />\n </GlassCard>\n\n {/* Records */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {recordsQuery.loading ? 'Loading check-in records…' : `Check-In Records (${recordsTotal})`}\n </h2>\n <div className=\"mt-4\">\n {records.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No check-in records yet\"\n description=\"Arrivals recorded from this page show up here, newest first.\"\n className=\"py-8\"\n />\n ) : (\n <ul className=\"space-y-2.5\">\n {records.map((record) => (\n <li\n key={record.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\">\n {record.attendeeId ? `Attendee ${record.attendeeId}` : `Record ${record.id}`}\n </p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {record.method} • {record.direction} • {new Date(record.recordedAt).toLocaleString()}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\" className=\"shrink-0 uppercase\">\n {record.status}\n </Badge>\n <ActionMenu\n ariaLabel={`Check-in record ${record.id} actions`}\n onEdit={() => openEditRecord(record)}\n onDelete={() => onDeleteRecord(record)}\n />\n </div>\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n <Pagination\n offset={recordsPagination.offset}\n limit={recordsPagination.limit}\n loadedCount={records.length}\n total={recordsTotal}\n onPrev={recordsPagination.prevPage}\n onNext={recordsPagination.nextPage}\n itemLabel=\"records\"\n loading={recordsQuery.loading}\n />\n </GlassCard>\n\n {selectedEventId ? (\n <StationDialog\n open={stationDialogOpen}\n onOpenChange={setStationDialogOpen}\n eventId={selectedEventId}\n eventName={selectedEvent?.name ?? 'this event'}\n station={editingStation}\n />\n ) : null}\n\n <RecordDialog\n open={recordDialogOpen}\n onOpenChange={setRecordDialogOpen}\n record={editingRecord}\n stations={stations}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,84 +1,225 @@
|
|
|
1
1
|
import { useEventfullyManaged as e } from "../../context/EventfullyManagedContext.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
2
|
+
import { notify as t } from "../../lib/toast.js";
|
|
3
|
+
import { useAttendeesQuery as n, useDeleteMeetingMutation as r, useMeetingsQuery as i, useNetworkingMatchesQuery as a, useNetworkingProfilesQuery as o } from "../../api/eventApi.js";
|
|
4
|
+
import { ActionMenu as s } from "../../components/ActionMenu.js";
|
|
5
|
+
import { Pagination as c, usePagination as l } from "../../components/Pagination.js";
|
|
6
|
+
import { describeError as u, mutationSucceeded as d } from "../../lib/mutationResult.js";
|
|
7
|
+
import { useMemo as f } from "react";
|
|
8
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
9
|
+
import { CalendarDays as h, CalendarPlus as g, Megaphone as _, UserPlus as v, Users as y } from "lucide-react";
|
|
10
|
+
import { Badge as b, Button as x, EmphasisPanel as S, GlassCard as C, GradientText as w, IllustratedEmptyState as T, NextSteps as E, PagePurpose as D } from "@burdenoff/fe-libs/ui";
|
|
11
|
+
import { ContextConversationWidget as O } from "@burdenoff/fe-libs/shared";
|
|
12
|
+
import { useRegisterPageConversationContext as k } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
10
13
|
//#region src/eventfullymanaged/pages/modules/NetworkingPage.tsx
|
|
11
|
-
function
|
|
12
|
-
|
|
14
|
+
function A(e) {
|
|
15
|
+
let t = e.toLowerCase();
|
|
16
|
+
return [
|
|
17
|
+
"active",
|
|
18
|
+
"published",
|
|
19
|
+
"live",
|
|
20
|
+
"confirmed",
|
|
21
|
+
"completed",
|
|
22
|
+
"approved",
|
|
23
|
+
"public"
|
|
24
|
+
].includes(t) ? "success" : [
|
|
25
|
+
"inactive",
|
|
26
|
+
"cancelled",
|
|
27
|
+
"archived",
|
|
28
|
+
"closed",
|
|
29
|
+
"expired",
|
|
30
|
+
"private"
|
|
31
|
+
].includes(t) ? "warning" : [
|
|
32
|
+
"draft",
|
|
33
|
+
"created",
|
|
34
|
+
"pending",
|
|
35
|
+
"scheduled"
|
|
36
|
+
].includes(t) ? "info" : "secondary";
|
|
37
|
+
}
|
|
38
|
+
function j({ heading: e, loading: t, rows: n, total: r, emptyLabel: i, itemLabel: a, pagination: o, renderActions: s }) {
|
|
39
|
+
return /* @__PURE__ */ m(C, {
|
|
40
|
+
treatment: "plain",
|
|
41
|
+
className: "border-border-seam p-5",
|
|
42
|
+
children: [
|
|
43
|
+
/* @__PURE__ */ p("h2", {
|
|
44
|
+
className: "text-lg font-semibold text-text-primary",
|
|
45
|
+
children: t ? `${e}…` : `${e} (${r})`
|
|
46
|
+
}),
|
|
47
|
+
/* @__PURE__ */ p("div", {
|
|
48
|
+
className: "mt-4",
|
|
49
|
+
children: n.length === 0 ? /* @__PURE__ */ p(T, {
|
|
50
|
+
illustration: "empty-people",
|
|
51
|
+
title: i,
|
|
52
|
+
className: "py-8"
|
|
53
|
+
}) : /* @__PURE__ */ p("ul", {
|
|
54
|
+
className: "space-y-2.5",
|
|
55
|
+
children: n.map((e) => /* @__PURE__ */ p("li", {
|
|
56
|
+
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",
|
|
57
|
+
children: /* @__PURE__ */ m("div", {
|
|
58
|
+
className: "flex items-center justify-between gap-3",
|
|
59
|
+
children: [/* @__PURE__ */ m("div", {
|
|
60
|
+
className: "min-w-0",
|
|
61
|
+
children: [/* @__PURE__ */ p("p", {
|
|
62
|
+
className: "truncate font-medium text-text-primary",
|
|
63
|
+
children: e.title
|
|
64
|
+
}), e.subtitle ? /* @__PURE__ */ p("p", {
|
|
65
|
+
className: "mt-0.5 truncate text-sm text-text-secondary",
|
|
66
|
+
children: e.subtitle
|
|
67
|
+
}) : null]
|
|
68
|
+
}), /* @__PURE__ */ m("div", {
|
|
69
|
+
className: "flex shrink-0 items-center gap-2",
|
|
70
|
+
children: [e.status ? /* @__PURE__ */ p(b, {
|
|
71
|
+
variant: A(e.status),
|
|
72
|
+
className: "uppercase",
|
|
73
|
+
children: e.status
|
|
74
|
+
}) : null, s?.(e)]
|
|
75
|
+
})]
|
|
76
|
+
})
|
|
77
|
+
}, e.id))
|
|
78
|
+
})
|
|
79
|
+
}),
|
|
80
|
+
/* @__PURE__ */ p(c, {
|
|
81
|
+
offset: o.offset,
|
|
82
|
+
limit: o.limit,
|
|
83
|
+
loadedCount: n.length,
|
|
84
|
+
total: r,
|
|
85
|
+
onPrev: o.prevPage,
|
|
86
|
+
onNext: o.nextPage,
|
|
87
|
+
itemLabel: a,
|
|
88
|
+
loading: t
|
|
89
|
+
})
|
|
90
|
+
]
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function M() {
|
|
94
|
+
return k({
|
|
13
95
|
entityType: "EVENTFULLYMANAGED_NETWORKING_LOUNGE",
|
|
14
96
|
entityId: "general",
|
|
15
97
|
contextTitle: "Networking Lounge"
|
|
16
|
-
}), /* @__PURE__ */
|
|
98
|
+
}), /* @__PURE__ */ p(O, { widgetKey: "networking-lounge" });
|
|
17
99
|
}
|
|
18
|
-
function
|
|
19
|
-
let { navigate:
|
|
20
|
-
limit:
|
|
21
|
-
offset:
|
|
22
|
-
}),
|
|
100
|
+
function N() {
|
|
101
|
+
let { navigate: c } = e(), b = l(), C = l(), T = l(), O = o({
|
|
102
|
+
limit: b.limit,
|
|
103
|
+
offset: b.offset
|
|
104
|
+
}), k = a({
|
|
105
|
+
limit: C.limit,
|
|
106
|
+
offset: C.offset
|
|
107
|
+
}), A = i({
|
|
108
|
+
limit: T.limit,
|
|
109
|
+
offset: T.offset
|
|
110
|
+
}), { data: N } = n({
|
|
23
111
|
limit: 100,
|
|
24
112
|
offset: 0
|
|
25
|
-
}),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
113
|
+
}), [P] = r(), F = f(() => {
|
|
114
|
+
let e = /* @__PURE__ */ new Map();
|
|
115
|
+
for (let t of N?.attendees?.items ?? []) e.set(t.id, t.fullName);
|
|
116
|
+
return e;
|
|
117
|
+
}, [N]), I = f(() => O.data?.networkingProfiles.items ?? [], [O.data]), L = f(() => k.data?.networkingMatches.items ?? [], [k.data]), R = f(() => A.data?.meetings.items ?? [], [A.data]), z = I.map((e) => ({
|
|
118
|
+
id: e.id,
|
|
119
|
+
title: F.get(e.attendeeId) ?? (e.attendeeId ? `Attendee ${e.attendeeId}` : `Profile ${e.id}`),
|
|
120
|
+
subtitle: [e.role, e.industry].filter(Boolean).join(" • ") || void 0,
|
|
121
|
+
status: e.visibility
|
|
122
|
+
})), B = L.map((e) => ({
|
|
123
|
+
id: e.id,
|
|
124
|
+
title: e.name ?? e.title ?? `Match ${e.id}`,
|
|
125
|
+
subtitle: "Suggested by networking engine",
|
|
126
|
+
status: e.status ?? void 0
|
|
127
|
+
})), V = R.map((e) => ({
|
|
128
|
+
id: e.id,
|
|
129
|
+
title: e.title ?? e.name ?? `Meeting ${e.id}`,
|
|
130
|
+
status: e.status ?? void 0
|
|
131
|
+
})), H = async (e) => {
|
|
132
|
+
try {
|
|
133
|
+
let n = await P({ variables: { id: e.id } });
|
|
134
|
+
if (!d(n, n.data?.deleteMeeting === !0 ? e.id : void 0, "Could not delete meeting")) return;
|
|
135
|
+
t.success("Meeting removed", `${e.title} was deleted.`), await A.refetch();
|
|
136
|
+
} catch (e) {
|
|
137
|
+
t.error("Could not delete meeting", u(e));
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
return /* @__PURE__ */ m("div", {
|
|
30
141
|
className: "space-y-6 p-6",
|
|
31
142
|
children: [
|
|
32
|
-
/* @__PURE__ */
|
|
33
|
-
/* @__PURE__ */
|
|
34
|
-
className: "
|
|
35
|
-
children: /* @__PURE__ */
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
143
|
+
/* @__PURE__ */ p(D, { children: "Networking turns attendees into connections. Profiles describe who each attendee is and what they are looking for, matches are the suggestions the engine makes between them, and meetings are the 1:1s they book. Opt an attendee in, review strong matches, and book meetings that mirror straight into the calendar." }),
|
|
144
|
+
/* @__PURE__ */ m(S, {
|
|
145
|
+
className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
|
146
|
+
children: [/* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h1", {
|
|
147
|
+
className: "text-2xl font-bold text-text-primary",
|
|
148
|
+
children: /* @__PURE__ */ p(w, { children: "Networking" })
|
|
149
|
+
}), /* @__PURE__ */ p("p", {
|
|
150
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
151
|
+
children: "Manage profiles, matches and meeting schedules from live backend data."
|
|
152
|
+
})] }), /* @__PURE__ */ m("div", {
|
|
153
|
+
className: "flex flex-wrap gap-2",
|
|
154
|
+
children: [/* @__PURE__ */ m(x, {
|
|
155
|
+
type: "button",
|
|
156
|
+
variant: "outline",
|
|
157
|
+
onClick: () => c("/networking/profiles/create"),
|
|
158
|
+
children: [/* @__PURE__ */ p(v, { className: "h-4 w-4" }), "Opt in a profile"]
|
|
159
|
+
}), /* @__PURE__ */ m(x, {
|
|
160
|
+
type: "button",
|
|
161
|
+
onClick: () => c("/networking/meetings/create"),
|
|
162
|
+
children: [/* @__PURE__ */ p(g, { className: "h-4 w-4" }), "Book a meeting"]
|
|
163
|
+
})]
|
|
164
|
+
})]
|
|
165
|
+
}),
|
|
166
|
+
/* @__PURE__ */ p(j, {
|
|
167
|
+
heading: "Profiles",
|
|
168
|
+
loading: O.loading,
|
|
169
|
+
rows: z,
|
|
170
|
+
total: O.data?.networkingProfiles.total ?? 0,
|
|
171
|
+
emptyLabel: "No networking profiles yet. Opt an attendee in to get started.",
|
|
172
|
+
itemLabel: "profiles",
|
|
173
|
+
pagination: b,
|
|
174
|
+
renderActions: (e) => /* @__PURE__ */ p(s, {
|
|
175
|
+
ariaLabel: `${e.title} actions`,
|
|
176
|
+
onEdit: () => c(`/networking/profiles/${e.id}/edit`)
|
|
177
|
+
})
|
|
50
178
|
}),
|
|
51
|
-
/* @__PURE__ */
|
|
52
|
-
heading:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
179
|
+
/* @__PURE__ */ p(j, {
|
|
180
|
+
heading: "Matches",
|
|
181
|
+
loading: k.loading,
|
|
182
|
+
rows: B,
|
|
183
|
+
total: k.data?.networkingMatches.total ?? 0,
|
|
184
|
+
emptyLabel: "No networking matches yet.",
|
|
185
|
+
itemLabel: "matches",
|
|
186
|
+
pagination: C,
|
|
187
|
+
renderActions: (e) => /* @__PURE__ */ p(s, {
|
|
188
|
+
ariaLabel: `${e.title} actions`,
|
|
189
|
+
extraItems: [{
|
|
190
|
+
key: "book",
|
|
191
|
+
label: "Book meeting",
|
|
192
|
+
icon: g,
|
|
193
|
+
onSelect: () => c("/networking/meetings/create")
|
|
194
|
+
}]
|
|
195
|
+
})
|
|
61
196
|
}),
|
|
62
|
-
/* @__PURE__ */
|
|
63
|
-
heading:
|
|
64
|
-
|
|
65
|
-
rows:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
197
|
+
/* @__PURE__ */ p(j, {
|
|
198
|
+
heading: "Meetings",
|
|
199
|
+
loading: A.loading,
|
|
200
|
+
rows: V,
|
|
201
|
+
total: A.data?.meetings.total ?? 0,
|
|
202
|
+
emptyLabel: "No meetings scheduled yet.",
|
|
203
|
+
itemLabel: "meetings",
|
|
204
|
+
pagination: T,
|
|
205
|
+
renderActions: (e) => /* @__PURE__ */ p(s, {
|
|
206
|
+
ariaLabel: `${e.title} actions`,
|
|
207
|
+
entityName: e.title,
|
|
208
|
+
onEdit: () => c(`/networking/meetings/${e.id}/edit`),
|
|
209
|
+
onDelete: () => H(e)
|
|
210
|
+
})
|
|
70
211
|
}),
|
|
71
|
-
/* @__PURE__ */
|
|
212
|
+
/* @__PURE__ */ m("div", {
|
|
72
213
|
className: "space-y-3",
|
|
73
|
-
children: [/* @__PURE__ */
|
|
214
|
+
children: [/* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h2", {
|
|
74
215
|
className: "text-lg font-semibold text-text-primary",
|
|
75
216
|
children: "Networking chat"
|
|
76
|
-
}), /* @__PURE__ */
|
|
217
|
+
}), /* @__PURE__ */ p("p", {
|
|
77
218
|
className: "mt-1 text-sm text-text-secondary",
|
|
78
219
|
children: "A shared space for attendees and organizers to connect, backed by the conversations service."
|
|
79
|
-
})] }), /* @__PURE__ */
|
|
220
|
+
})] }), /* @__PURE__ */ p(M, {})]
|
|
80
221
|
}),
|
|
81
|
-
/* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ p(E, {
|
|
82
223
|
storageKey: "eventfullymanaged-networking",
|
|
83
224
|
title: "Make networking land",
|
|
84
225
|
steps: [
|
|
@@ -86,22 +227,22 @@ function v() {
|
|
|
86
227
|
id: "grow-attendees",
|
|
87
228
|
label: "Bring in more attendees",
|
|
88
229
|
description: "More registered attendees means richer matches and meetings.",
|
|
89
|
-
icon: /* @__PURE__ */
|
|
90
|
-
onClick: () =>
|
|
230
|
+
icon: /* @__PURE__ */ p(y, { className: "h-4 w-4" }),
|
|
231
|
+
onClick: () => c("/registration")
|
|
91
232
|
},
|
|
92
233
|
{
|
|
93
234
|
id: "announce-networking",
|
|
94
235
|
label: "Announce networking sessions",
|
|
95
236
|
description: "Let attendees know how and when to connect.",
|
|
96
|
-
icon: /* @__PURE__ */
|
|
97
|
-
onClick: () =>
|
|
237
|
+
icon: /* @__PURE__ */ p(_, { className: "h-4 w-4" }),
|
|
238
|
+
onClick: () => c("/communication")
|
|
98
239
|
},
|
|
99
240
|
{
|
|
100
241
|
id: "review-event",
|
|
101
242
|
label: "Review the event schedule",
|
|
102
243
|
description: "Make sure networking slots fit around your sessions.",
|
|
103
|
-
icon: /* @__PURE__ */
|
|
104
|
-
onClick: () =>
|
|
244
|
+
icon: /* @__PURE__ */ p(h, { className: "h-4 w-4" }),
|
|
245
|
+
onClick: () => c("/events")
|
|
105
246
|
}
|
|
106
247
|
]
|
|
107
248
|
})
|
|
@@ -109,6 +250,6 @@ function v() {
|
|
|
109
250
|
});
|
|
110
251
|
}
|
|
111
252
|
//#endregion
|
|
112
|
-
export {
|
|
253
|
+
export { N as default };
|
|
113
254
|
|
|
114
255
|
//# sourceMappingURL=NetworkingPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkingPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/NetworkingPage.tsx"],"sourcesContent":["import { CalendarDays, Megaphone, Users } from 'lucide-react';\nimport { ContextConversationWidget } from '@burdenoff/fe-libs/shared';\nimport { useRegisterPageConversationContext } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { EmphasisPanel, GradientText, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useMemo } from 'react';\n\nimport { useMeetingsQuery, useNetworkingMatchesQuery, useNetworkingProfilesQuery } from '../../api/eventApi';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { EntityListSection } from './EntityListSection';\n\ntype SimpleRow = {\n id: string;\n name?: string;\n title?: string;\n status?: string;\n};\n\n/**\n * Shared networking lounge chat, backed by wspace-conversations-svc. Scoped by a\n * stable networking entity so every organizer/attendee on this workspace lands in\n * the same thread.\n */\nfunction NetworkingLounge() {\n useRegisterPageConversationContext({\n entityType: 'EVENTFULLYMANAGED_NETWORKING_LOUNGE',\n entityId: 'general',\n contextTitle: 'Networking Lounge',\n });\n return <ContextConversationWidget widgetKey=\"networking-lounge\" />;\n}\n\nexport default function NetworkingPage() {\n const { navigate } = useEventfullyManaged();\n const profilesQuery = useNetworkingProfilesQuery({ limit: 100, offset: 0 });\n const matchesQuery = useNetworkingMatchesQuery({ limit: 100, offset: 0 });\n const meetingsQuery = useMeetingsQuery({ limit: 100, offset: 0 });\n\n const profiles = useMemo(() => profilesQuery.data?.networkingProfiles.items ?? [], [profilesQuery.data]);\n const matches = useMemo(() => (matchesQuery.data?.networkingMatches.items ?? []) as SimpleRow[], [matchesQuery.data]);\n const meetings = useMemo(() => (meetingsQuery.data?.meetings.items ?? []) as SimpleRow[], [meetingsQuery.data]);\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Networking turns attendees into connections. Profiles describe who each attendee is and what they are looking\n for, matches are the suggestions the engine makes between them, and meetings are the 1:1s they book. Use this\n page to spot strong matches and make sure scheduled meetings are running smoothly.\n </PagePurpose>\n\n <EmphasisPanel>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Networking</GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Manage networking matches and meeting schedules from live backend data.\n </p>\n </EmphasisPanel>\n\n <EntityListSection\n heading={profilesQuery.loading ? 'Loading networking profiles...' : `Profiles (${profiles.length})`}\n emptyLabel=\"No networking profiles available.\"\n emptyIllustration=\"empty-people\"\n rows={profiles.map((row) => ({\n id: row.id,\n title: row.attendeeId ? `Attendee ${row.attendeeId}` : `Profile ${row.id}`,\n subtitle: [row.role, row.industry].filter(Boolean).join(' • '),\n status: row.visibility,\n }))}\n />\n\n <EntityListSection\n heading={matchesQuery.loading ? 'Loading networking matches...' : `Matches (${matches.length})`}\n emptyLabel=\"No networking matches available.\"\n emptyIllustration=\"empty-people\"\n rows={matches.map((row) => ({\n id: row.id,\n title: row.name ?? row.title ?? `Match ${row.id}`,\n subtitle: 'Suggested by networking engine',\n status: row.status ?? undefined,\n }))}\n />\n\n <EntityListSection\n heading={meetingsQuery.loading ? 'Loading meetings...' : `Meetings (${meetings.length})`}\n emptyLabel=\"No meetings scheduled.\"\n rows={meetings.map((row) => ({\n id: row.id,\n title: row.title ?? row.name ?? `Meeting ${row.id}`,\n status: row.status ?? undefined,\n }))}\n />\n\n <div className=\"space-y-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Networking chat</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n A shared space for attendees and organizers to connect, backed by the conversations service.\n </p>\n </div>\n <NetworkingLounge />\n </div>\n\n <NextSteps\n storageKey=\"eventfullymanaged-networking\"\n title=\"Make networking land\"\n steps={[\n {\n id: 'grow-attendees',\n label: 'Bring in more attendees',\n description: 'More registered attendees means richer matches and meetings.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('/registration'),\n },\n {\n id: 'announce-networking',\n label: 'Announce networking sessions',\n description: 'Let attendees know how and when to connect.',\n icon: <Megaphone className=\"h-4 w-4\" />,\n onClick: () => navigate('/communication'),\n },\n {\n id: 'review-event',\n label: 'Review the event schedule',\n description: 'Make sure networking slots fit around your sessions.',\n icon: <CalendarDays className=\"h-4 w-4\" />,\n onClick: () => navigate('/events'),\n },\n ]}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NetworkingPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/NetworkingPage.tsx"],"sourcesContent":["import { CalendarDays, CalendarPlus, Megaphone, UserPlus, Users } from 'lucide-react';\nimport { ContextConversationWidget } from '@burdenoff/fe-libs/shared';\nimport { useRegisterPageConversationContext } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n Badge,\n Button,\n EmphasisPanel,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useMemo, type ReactNode } from 'react';\n\nimport {\n useAttendeesQuery,\n useDeleteMeetingMutation,\n useMeetingsQuery,\n useNetworkingMatchesQuery,\n useNetworkingProfilesQuery,\n} from '../../api/eventApi';\nimport { ActionMenu } from '../../components/ActionMenu';\nimport { Pagination, usePagination, type UsePaginationResult } from '../../components/Pagination';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { describeError, mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\n\ntype SimpleRow = {\n id: string;\n name?: string;\n title?: string;\n status?: string;\n};\n\ntype ListRow = {\n id: string;\n title: string;\n subtitle?: string;\n status?: string;\n};\n\nfunction statusVariant(status: string): 'success' | 'warning' | 'secondary' | 'info' {\n const value = status.toLowerCase();\n if (['active', 'published', 'live', 'confirmed', 'completed', 'approved', 'public'].includes(value)) {\n return 'success';\n }\n if (['inactive', 'cancelled', 'archived', 'closed', 'expired', 'private'].includes(value)) {\n return 'warning';\n }\n if (['draft', 'created', 'pending', 'scheduled'].includes(value)) {\n return 'info';\n }\n return 'secondary';\n}\n\ninterface NetworkingListProps {\n heading: string;\n loading: boolean;\n rows: ListRow[];\n total: number;\n emptyLabel: string;\n itemLabel: string;\n pagination: UsePaginationResult;\n renderActions?: (row: ListRow) => ReactNode;\n}\n\nfunction NetworkingList({\n heading,\n loading,\n rows,\n total,\n emptyLabel,\n itemLabel,\n pagination,\n renderActions,\n}: NetworkingListProps) {\n return (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <h2 className=\"text-lg font-semibold text-text-primary\">{loading ? `${heading}…` : `${heading} (${total})`}</h2>\n <div className=\"mt-4\">\n {rows.length === 0 ? (\n <IllustratedEmptyState illustration=\"empty-people\" title={emptyLabel} className=\"py-8\" />\n ) : (\n <ul className=\"space-y-2.5\">\n {rows.map((row) => (\n <li\n key={row.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\">{row.title}</p>\n {row.subtitle ? (\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">{row.subtitle}</p>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {row.status ? (\n <Badge variant={statusVariant(row.status)} className=\"uppercase\">\n {row.status}\n </Badge>\n ) : null}\n {renderActions?.(row)}\n </div>\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\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={itemLabel}\n loading={loading}\n />\n </GlassCard>\n );\n}\n\n/**\n * Shared networking lounge chat, backed by wspace-conversations-svc. Scoped by a\n * stable networking entity so every organizer/attendee on this workspace lands in\n * the same thread.\n */\nfunction NetworkingLounge() {\n useRegisterPageConversationContext({\n entityType: 'EVENTFULLYMANAGED_NETWORKING_LOUNGE',\n entityId: 'general',\n contextTitle: 'Networking Lounge',\n });\n return <ContextConversationWidget widgetKey=\"networking-lounge\" />;\n}\n\nexport default function NetworkingPage() {\n const { navigate } = useEventfullyManaged();\n\n const profilesPagination = usePagination();\n const matchesPagination = usePagination();\n const meetingsPagination = usePagination();\n\n const profilesQuery = useNetworkingProfilesQuery({\n limit: profilesPagination.limit,\n offset: profilesPagination.offset,\n });\n const matchesQuery = useNetworkingMatchesQuery({\n limit: matchesPagination.limit,\n offset: matchesPagination.offset,\n });\n const meetingsQuery = useMeetingsQuery({\n limit: meetingsPagination.limit,\n offset: meetingsPagination.offset,\n });\n const { data: attendeesData } = useAttendeesQuery({ limit: 100, offset: 0 });\n\n const [deleteMeeting] = useDeleteMeetingMutation();\n\n const attendeeNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const attendee of attendeesData?.attendees?.items ?? []) {\n map.set(attendee.id, attendee.fullName);\n }\n return map;\n }, [attendeesData]);\n\n const profiles = useMemo(() => profilesQuery.data?.networkingProfiles.items ?? [], [profilesQuery.data]);\n const matches = useMemo(() => (matchesQuery.data?.networkingMatches.items ?? []) as SimpleRow[], [matchesQuery.data]);\n const meetings = useMemo(() => (meetingsQuery.data?.meetings.items ?? []) as SimpleRow[], [meetingsQuery.data]);\n\n const profileRows: ListRow[] = profiles.map((row) => ({\n id: row.id,\n title: attendeeNames.get(row.attendeeId) ?? (row.attendeeId ? `Attendee ${row.attendeeId}` : `Profile ${row.id}`),\n subtitle: [row.role, row.industry].filter(Boolean).join(' • ') || undefined,\n status: row.visibility,\n }));\n\n const matchRows: ListRow[] = matches.map((row) => ({\n id: row.id,\n title: row.name ?? row.title ?? `Match ${row.id}`,\n subtitle: 'Suggested by networking engine',\n status: row.status ?? undefined,\n }));\n\n const meetingRows: ListRow[] = meetings.map((row) => ({\n id: row.id,\n title: row.title ?? row.name ?? `Meeting ${row.id}`,\n status: row.status ?? undefined,\n }));\n\n const onDeleteMeeting = async (row: ListRow) => {\n try {\n const response = await deleteMeeting({ variables: { id: row.id } });\n const deleted = response.data?.deleteMeeting === true;\n if (!mutationSucceeded(response, deleted ? row.id : undefined, 'Could not delete meeting')) {\n return;\n }\n notify.success('Meeting removed', `${row.title} was deleted.`);\n await meetingsQuery.refetch();\n } catch (error) {\n notify.error('Could not delete meeting', describeError(error));\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Networking turns attendees into connections. Profiles describe who each attendee is and what they are looking\n for, matches are the suggestions the engine makes between them, and meetings are the 1:1s they book. Opt an\n attendee in, review strong matches, and book meetings that mirror straight into the calendar.\n </PagePurpose>\n\n <EmphasisPanel 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>Networking</GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Manage profiles, matches and meeting schedules from live backend data.\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={() => navigate('/networking/profiles/create')}>\n <UserPlus className=\"h-4 w-4\" />\n Opt in a profile\n </Button>\n <Button type=\"button\" onClick={() => navigate('/networking/meetings/create')}>\n <CalendarPlus className=\"h-4 w-4\" />\n Book a meeting\n </Button>\n </div>\n </EmphasisPanel>\n\n <NetworkingList\n heading=\"Profiles\"\n loading={profilesQuery.loading}\n rows={profileRows}\n total={profilesQuery.data?.networkingProfiles.total ?? 0}\n emptyLabel=\"No networking profiles yet. Opt an attendee in to get started.\"\n itemLabel=\"profiles\"\n pagination={profilesPagination}\n renderActions={(row) => (\n <ActionMenu\n ariaLabel={`${row.title} actions`}\n onEdit={() => navigate(`/networking/profiles/${row.id}/edit`)}\n />\n )}\n />\n\n <NetworkingList\n heading=\"Matches\"\n loading={matchesQuery.loading}\n rows={matchRows}\n total={matchesQuery.data?.networkingMatches.total ?? 0}\n emptyLabel=\"No networking matches yet.\"\n itemLabel=\"matches\"\n pagination={matchesPagination}\n renderActions={(row) => (\n <ActionMenu\n ariaLabel={`${row.title} actions`}\n extraItems={[\n {\n key: 'book',\n label: 'Book meeting',\n icon: CalendarPlus,\n onSelect: () => navigate('/networking/meetings/create'),\n },\n ]}\n />\n )}\n />\n\n <NetworkingList\n heading=\"Meetings\"\n loading={meetingsQuery.loading}\n rows={meetingRows}\n total={meetingsQuery.data?.meetings.total ?? 0}\n emptyLabel=\"No meetings scheduled yet.\"\n itemLabel=\"meetings\"\n pagination={meetingsPagination}\n renderActions={(row) => (\n <ActionMenu\n ariaLabel={`${row.title} actions`}\n entityName={row.title}\n onEdit={() => navigate(`/networking/meetings/${row.id}/edit`)}\n onDelete={() => onDeleteMeeting(row)}\n />\n )}\n />\n\n <div className=\"space-y-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Networking chat</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n A shared space for attendees and organizers to connect, backed by the conversations service.\n </p>\n </div>\n <NetworkingLounge />\n </div>\n\n <NextSteps\n storageKey=\"eventfullymanaged-networking\"\n title=\"Make networking land\"\n steps={[\n {\n id: 'grow-attendees',\n label: 'Bring in more attendees',\n description: 'More registered attendees means richer matches and meetings.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('/registration'),\n },\n {\n id: 'announce-networking',\n label: 'Announce networking sessions',\n description: 'Let attendees know how and when to connect.',\n icon: <Megaphone className=\"h-4 w-4\" />,\n onClick: () => navigate('/communication'),\n },\n {\n id: 'review-event',\n label: 'Review the event schedule',\n description: 'Make sure networking slots fit around your sessions.',\n icon: <CalendarDays className=\"h-4 w-4\" />,\n onClick: () => navigate('/events'),\n },\n ]}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|