@burdenoff/microfe-eventfullymanaged 2026.703.2 → 2026.704.2
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 +151 -67
- package/dist/eventfullymanaged/EventfullyManagedRoutes.js.map +1 -1
- package/dist/eventfullymanaged/api/eventApi.js +546 -67
- 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/RegistrationPage.js +295 -76
- 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 +415 -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,115 +1,136 @@
|
|
|
1
1
|
import { useEventfullyManaged as e } from "../../context/EventfullyManagedContext.js";
|
|
2
2
|
import { useCommunicationCampaignsQuery as t, useSponsorsQuery as n } from "../../api/eventApi.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
3
|
+
import { EntityTagsField as r } from "../../components/EntityTagsField.js";
|
|
4
|
+
import { EntityListSection as i } from "./EntityListSection.js";
|
|
5
|
+
import { useMemo as a } from "react";
|
|
6
|
+
import { useParams as o } from "react-router-dom";
|
|
7
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
8
|
+
import { Megaphone as l, Pencil as u, TrendingUp as d } from "lucide-react";
|
|
9
|
+
import { EmphasisPanel as f, GlassCard as p, GradientText as m, NextSteps as h, PagePurpose as g } from "@burdenoff/fe-libs/ui";
|
|
10
|
+
import { ContextConversationWidget as _ } from "@burdenoff/fe-libs/shared";
|
|
11
|
+
import { useRegisterPageConversationContext as v } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
11
12
|
//#region src/eventfullymanaged/pages/modules/SponsorDetailsPage.tsx
|
|
12
|
-
function
|
|
13
|
-
return
|
|
13
|
+
function y({ sponsorId: e, sponsorName: t }) {
|
|
14
|
+
return v({
|
|
14
15
|
entityType: "EVENTFULLYMANAGED_SPONSOR",
|
|
15
16
|
entityId: e,
|
|
16
17
|
contextTitle: `Sponsor · ${t}`
|
|
17
|
-
}), /* @__PURE__ */
|
|
18
|
+
}), /* @__PURE__ */ s(_, { widgetKey: "sponsor-message" });
|
|
18
19
|
}
|
|
19
|
-
function
|
|
20
|
-
let { id:
|
|
20
|
+
function b() {
|
|
21
|
+
let { id: _ = "" } = o(), { navigate: v } = e(), b = n({
|
|
21
22
|
limit: 100,
|
|
22
23
|
offset: 0
|
|
23
|
-
}),
|
|
24
|
+
}), x = t({
|
|
24
25
|
limit: 100,
|
|
25
26
|
offset: 0
|
|
26
|
-
}),
|
|
27
|
-
return /* @__PURE__ */
|
|
27
|
+
}), S = a(() => (b.data?.sponsors.items ?? []).find((e) => e.id === _), [_, b.data]), C = a(() => x.data?.communicationCampaigns.items ?? [], [x.data]);
|
|
28
|
+
return /* @__PURE__ */ c("div", {
|
|
28
29
|
className: "space-y-6 p-6",
|
|
29
30
|
children: [
|
|
30
|
-
/* @__PURE__ */
|
|
31
|
-
/* @__PURE__ */
|
|
32
|
-
/* @__PURE__ */
|
|
31
|
+
/* @__PURE__ */ s(g, { children: "Everything about one sponsor in one place — their tier, contacts, and the campaigns they appear in. Use this to prep for a sponsor conversation, confirm their contact details, or check how their branded campaigns are performing." }),
|
|
32
|
+
/* @__PURE__ */ c(f, { children: [
|
|
33
|
+
/* @__PURE__ */ c("h1", {
|
|
33
34
|
className: "text-2xl font-bold text-text-primary",
|
|
34
|
-
children: [/* @__PURE__ */
|
|
35
|
+
children: [/* @__PURE__ */ s(m, { children: "Sponsor" }), " Details"]
|
|
35
36
|
}),
|
|
36
|
-
/* @__PURE__ */
|
|
37
|
+
/* @__PURE__ */ s("p", {
|
|
37
38
|
className: "mt-1 text-sm text-text-secondary",
|
|
38
|
-
children:
|
|
39
|
+
children: b.loading ? "Loading sponsor details..." : S ? `Live sponsor profile for ${S.name}.` : "Sponsor not found in current query scope."
|
|
39
40
|
}),
|
|
40
|
-
|
|
41
|
+
S ? /* @__PURE__ */ c("div", {
|
|
41
42
|
className: "mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4",
|
|
42
43
|
children: [
|
|
43
|
-
/* @__PURE__ */
|
|
44
|
+
/* @__PURE__ */ c(p, {
|
|
44
45
|
treatment: "metric",
|
|
45
46
|
className: "p-3",
|
|
46
|
-
children: [/* @__PURE__ */
|
|
47
|
+
children: [/* @__PURE__ */ s("p", {
|
|
47
48
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
48
49
|
children: "Level"
|
|
49
|
-
}), /* @__PURE__ */
|
|
50
|
+
}), /* @__PURE__ */ s("p", {
|
|
50
51
|
className: "mt-1 font-medium text-text-primary",
|
|
51
|
-
children:
|
|
52
|
+
children: S.level
|
|
52
53
|
})]
|
|
53
54
|
}),
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
+
/* @__PURE__ */ c(p, {
|
|
55
56
|
treatment: "metric",
|
|
56
57
|
className: "p-3",
|
|
57
|
-
children: [/* @__PURE__ */
|
|
58
|
+
children: [/* @__PURE__ */ s("p", {
|
|
58
59
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
59
60
|
children: "Contact"
|
|
60
|
-
}), /* @__PURE__ */
|
|
61
|
+
}), /* @__PURE__ */ s("p", {
|
|
61
62
|
className: "mt-1 font-medium text-text-primary",
|
|
62
|
-
children:
|
|
63
|
+
children: S.contactName ?? "Unassigned"
|
|
63
64
|
})]
|
|
64
65
|
}),
|
|
65
|
-
/* @__PURE__ */
|
|
66
|
+
/* @__PURE__ */ c(p, {
|
|
66
67
|
treatment: "metric",
|
|
67
68
|
className: "p-3",
|
|
68
|
-
children: [/* @__PURE__ */
|
|
69
|
+
children: [/* @__PURE__ */ s("p", {
|
|
69
70
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
70
71
|
children: "Email"
|
|
71
|
-
}), /* @__PURE__ */
|
|
72
|
+
}), /* @__PURE__ */ s("p", {
|
|
72
73
|
className: "mt-1 font-medium text-text-primary",
|
|
73
|
-
children:
|
|
74
|
+
children: S.contactEmail ?? "Unavailable"
|
|
74
75
|
})]
|
|
75
76
|
}),
|
|
76
|
-
/* @__PURE__ */
|
|
77
|
+
/* @__PURE__ */ c(p, {
|
|
77
78
|
treatment: "metric",
|
|
78
79
|
className: "p-3",
|
|
79
|
-
children: [/* @__PURE__ */
|
|
80
|
+
children: [/* @__PURE__ */ s("p", {
|
|
80
81
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
81
82
|
children: "Website"
|
|
82
|
-
}), /* @__PURE__ */
|
|
83
|
+
}), /* @__PURE__ */ s("p", {
|
|
83
84
|
className: "mt-1 truncate font-medium text-text-primary",
|
|
84
|
-
children:
|
|
85
|
+
children: S.website ?? "Unavailable"
|
|
85
86
|
})]
|
|
86
87
|
})
|
|
87
88
|
]
|
|
88
89
|
}) : null
|
|
89
90
|
] }),
|
|
90
|
-
/* @__PURE__ */
|
|
91
|
-
|
|
91
|
+
S ? /* @__PURE__ */ c(p, {
|
|
92
|
+
treatment: "plain",
|
|
93
|
+
className: "border-border-seam p-5",
|
|
94
|
+
children: [
|
|
95
|
+
/* @__PURE__ */ s("h2", {
|
|
96
|
+
className: "text-lg font-semibold text-text-primary",
|
|
97
|
+
children: "Tags"
|
|
98
|
+
}),
|
|
99
|
+
/* @__PURE__ */ s("p", {
|
|
100
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
101
|
+
children: "Label this sponsor so you can segment your portfolio — for example by industry, tier or renewal status."
|
|
102
|
+
}),
|
|
103
|
+
/* @__PURE__ */ s(r, {
|
|
104
|
+
entityType: "sponsor",
|
|
105
|
+
entityId: S.id,
|
|
106
|
+
label: "Sponsor tags",
|
|
107
|
+
className: "mt-3"
|
|
108
|
+
})
|
|
109
|
+
]
|
|
110
|
+
}) : null,
|
|
111
|
+
/* @__PURE__ */ s(i, {
|
|
112
|
+
heading: x.loading ? "Loading campaigns..." : `Campaign Activity (${C.length})`,
|
|
92
113
|
emptyLabel: "No communication campaigns available for sponsor tracking.",
|
|
93
|
-
rows:
|
|
114
|
+
rows: C.map((e) => ({
|
|
94
115
|
id: e.id,
|
|
95
116
|
title: e.title ?? e.name ?? `Campaign ${e.id}`,
|
|
96
117
|
status: e.status
|
|
97
118
|
}))
|
|
98
119
|
}),
|
|
99
|
-
|
|
120
|
+
S ? /* @__PURE__ */ c("div", {
|
|
100
121
|
className: "space-y-3",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
122
|
+
children: [/* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("h2", {
|
|
102
123
|
className: "text-lg font-semibold text-text-primary",
|
|
103
124
|
children: "Sponsor messages"
|
|
104
|
-
}), /* @__PURE__ */
|
|
125
|
+
}), /* @__PURE__ */ s("p", {
|
|
105
126
|
className: "mt-1 text-sm text-text-secondary",
|
|
106
127
|
children: "Coordinate with this sponsor in a dedicated thread, backed by the conversations service."
|
|
107
|
-
})] }), /* @__PURE__ */
|
|
108
|
-
sponsorId:
|
|
109
|
-
sponsorName:
|
|
128
|
+
})] }), /* @__PURE__ */ s(y, {
|
|
129
|
+
sponsorId: S.id,
|
|
130
|
+
sponsorName: S.name
|
|
110
131
|
})]
|
|
111
132
|
}) : null,
|
|
112
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ s(h, {
|
|
113
134
|
storageKey: "eventfullymanaged-sponsor-details",
|
|
114
135
|
title: "Grow this partnership",
|
|
115
136
|
steps: [
|
|
@@ -117,22 +138,22 @@ function y() {
|
|
|
117
138
|
id: "edit-sponsor",
|
|
118
139
|
label: "Update sponsor details",
|
|
119
140
|
description: "Keep tier, contacts and contract value current.",
|
|
120
|
-
icon: /* @__PURE__ */
|
|
121
|
-
onClick: () => _
|
|
141
|
+
icon: /* @__PURE__ */ s(u, { className: "h-4 w-4" }),
|
|
142
|
+
onClick: () => v(_ ? `/sponsors/${_}/edit` : "/sponsors")
|
|
122
143
|
},
|
|
123
144
|
{
|
|
124
145
|
id: "track-leads",
|
|
125
146
|
label: "Track sponsor leads",
|
|
126
147
|
description: "See the leads this sponsor is generating at the event.",
|
|
127
|
-
icon: /* @__PURE__ */
|
|
128
|
-
onClick: () => _
|
|
148
|
+
icon: /* @__PURE__ */ s(d, { className: "h-4 w-4" }),
|
|
149
|
+
onClick: () => v(_ ? `/sponsors/${_}/leads` : "/sponsors")
|
|
129
150
|
},
|
|
130
151
|
{
|
|
131
152
|
id: "run-campaign",
|
|
132
153
|
label: "Run a co-branded campaign",
|
|
133
154
|
description: "Promote this sponsor through a communication campaign.",
|
|
134
|
-
icon: /* @__PURE__ */
|
|
135
|
-
onClick: () =>
|
|
155
|
+
icon: /* @__PURE__ */ s(l, { className: "h-4 w-4" }),
|
|
156
|
+
onClick: () => v("/communication")
|
|
136
157
|
}
|
|
137
158
|
]
|
|
138
159
|
})
|
|
@@ -140,6 +161,6 @@ function y() {
|
|
|
140
161
|
});
|
|
141
162
|
}
|
|
142
163
|
//#endregion
|
|
143
|
-
export {
|
|
164
|
+
export { b as default };
|
|
144
165
|
|
|
145
166
|
//# sourceMappingURL=SponsorDetailsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SponsorDetailsPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/SponsorDetailsPage.tsx"],"sourcesContent":["import { Megaphone, Pencil, TrendingUp } from 'lucide-react';\nimport { ContextConversationWidget } from '@burdenoff/fe-libs/shared';\nimport { useRegisterPageConversationContext } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { EmphasisPanel, GlassCard, GradientText, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { useCommunicationCampaignsQuery, useSponsorsQuery } from '../../api/eventApi';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { EntityListSection } from './EntityListSection';\n\n/**\n * Sponsor ↔ organizer message thread, backed by wspace-conversations-svc and\n * scoped to this sponsor so the conversation follows the partnership.\n */\nfunction SponsorConversation({ sponsorId, sponsorName }: { sponsorId: string; sponsorName: string }) {\n useRegisterPageConversationContext({\n entityType: 'EVENTFULLYMANAGED_SPONSOR',\n entityId: sponsorId,\n contextTitle: `Sponsor · ${sponsorName}`,\n });\n return <ContextConversationWidget widgetKey=\"sponsor-message\" />;\n}\n\ntype SponsorRow = {\n id: string;\n name: string;\n level: string;\n website?: string | null;\n contactName?: string | null;\n contactEmail?: string | null;\n};\n\ntype CampaignRow = {\n id: string;\n name?: string;\n title?: string;\n status?: string;\n};\n\nexport default function SponsorDetailsPage() {\n const { id = '' } = useParams();\n const { navigate } = useEventfullyManaged();\n const sponsorsQuery = useSponsorsQuery({ limit: 100, offset: 0 });\n const campaignsQuery = useCommunicationCampaignsQuery({ limit: 100, offset: 0 });\n\n const sponsor = useMemo(\n () => ((sponsorsQuery.data?.sponsors.items ?? []) as SponsorRow[]).find((item) => item.id === id),\n [id, sponsorsQuery.data]\n );\n const campaigns = useMemo(\n () => (campaignsQuery.data?.communicationCampaigns.items ?? []) as CampaignRow[],\n [campaignsQuery.data]\n );\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Everything about one sponsor in one place — their tier, contacts, and the campaigns they appear in. Use this to\n prep for a sponsor conversation, confirm their contact details, or check how their branded campaigns are\n performing.\n </PagePurpose>\n\n <EmphasisPanel>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Sponsor</GradientText> Details\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {sponsorsQuery.loading\n ? 'Loading sponsor details...'\n : sponsor\n ? `Live sponsor profile for ${sponsor.name}.`\n : 'Sponsor not found in current query scope.'}\n </p>\n {sponsor ? (\n <div className=\"mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"p-3\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Level</p>\n <p className=\"mt-1 font-medium text-text-primary\">{sponsor.level}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-3\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Contact</p>\n <p className=\"mt-1 font-medium text-text-primary\">{sponsor.contactName ?? 'Unassigned'}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-3\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Email</p>\n <p className=\"mt-1 font-medium text-text-primary\">{sponsor.contactEmail ?? 'Unavailable'}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-3\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Website</p>\n <p className=\"mt-1 truncate font-medium text-text-primary\">{sponsor.website ?? 'Unavailable'}</p>\n </GlassCard>\n </div>\n ) : null}\n </EmphasisPanel>\n\n <EntityListSection\n heading={campaignsQuery.loading ? 'Loading campaigns...' : `Campaign Activity (${campaigns.length})`}\n emptyLabel=\"No communication campaigns available for sponsor tracking.\"\n rows={campaigns.map((campaign) => ({\n id: campaign.id,\n title: campaign.title ?? campaign.name ?? `Campaign ${campaign.id}`,\n status: campaign.status,\n }))}\n />\n\n {sponsor ? (\n <div className=\"space-y-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Sponsor messages</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Coordinate with this sponsor in a dedicated thread, backed by the conversations service.\n </p>\n </div>\n <SponsorConversation sponsorId={sponsor.id} sponsorName={sponsor.name} />\n </div>\n ) : null}\n\n <NextSteps\n storageKey=\"eventfullymanaged-sponsor-details\"\n title=\"Grow this partnership\"\n steps={[\n {\n id: 'edit-sponsor',\n label: 'Update sponsor details',\n description: 'Keep tier, contacts and contract value current.',\n icon: <Pencil className=\"h-4 w-4\" />,\n onClick: () => navigate(id ? `/sponsors/${id}/edit` : '/sponsors'),\n },\n {\n id: 'track-leads',\n label: 'Track sponsor leads',\n description: 'See the leads this sponsor is generating at the event.',\n icon: <TrendingUp className=\"h-4 w-4\" />,\n onClick: () => navigate(id ? `/sponsors/${id}/leads` : '/sponsors'),\n },\n {\n id: 'run-campaign',\n label: 'Run a co-branded campaign',\n description: 'Promote this sponsor through a communication campaign.',\n icon: <Megaphone className=\"h-4 w-4\" />,\n onClick: () => navigate('/communication'),\n },\n ]}\n />\n </div>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"SponsorDetailsPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/SponsorDetailsPage.tsx"],"sourcesContent":["import { Megaphone, Pencil, TrendingUp } from 'lucide-react';\nimport { ContextConversationWidget } from '@burdenoff/fe-libs/shared';\nimport { useRegisterPageConversationContext } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { EmphasisPanel, GlassCard, GradientText, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { useCommunicationCampaignsQuery, useSponsorsQuery } from '../../api/eventApi';\nimport { EntityTagsField } from '../../components/EntityTagsField';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { EntityListSection } from './EntityListSection';\n\n/**\n * Sponsor ↔ organizer message thread, backed by wspace-conversations-svc and\n * scoped to this sponsor so the conversation follows the partnership.\n */\nfunction SponsorConversation({ sponsorId, sponsorName }: { sponsorId: string; sponsorName: string }) {\n useRegisterPageConversationContext({\n entityType: 'EVENTFULLYMANAGED_SPONSOR',\n entityId: sponsorId,\n contextTitle: `Sponsor · ${sponsorName}`,\n });\n return <ContextConversationWidget widgetKey=\"sponsor-message\" />;\n}\n\ntype SponsorRow = {\n id: string;\n name: string;\n level: string;\n website?: string | null;\n contactName?: string | null;\n contactEmail?: string | null;\n};\n\ntype CampaignRow = {\n id: string;\n name?: string;\n title?: string;\n status?: string;\n};\n\nexport default function SponsorDetailsPage() {\n const { id = '' } = useParams();\n const { navigate } = useEventfullyManaged();\n const sponsorsQuery = useSponsorsQuery({ limit: 100, offset: 0 });\n const campaignsQuery = useCommunicationCampaignsQuery({ limit: 100, offset: 0 });\n\n const sponsor = useMemo(\n () => ((sponsorsQuery.data?.sponsors.items ?? []) as SponsorRow[]).find((item) => item.id === id),\n [id, sponsorsQuery.data]\n );\n const campaigns = useMemo(\n () => (campaignsQuery.data?.communicationCampaigns.items ?? []) as CampaignRow[],\n [campaignsQuery.data]\n );\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Everything about one sponsor in one place — their tier, contacts, and the campaigns they appear in. Use this to\n prep for a sponsor conversation, confirm their contact details, or check how their branded campaigns are\n performing.\n </PagePurpose>\n\n <EmphasisPanel>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Sponsor</GradientText> Details\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {sponsorsQuery.loading\n ? 'Loading sponsor details...'\n : sponsor\n ? `Live sponsor profile for ${sponsor.name}.`\n : 'Sponsor not found in current query scope.'}\n </p>\n {sponsor ? (\n <div className=\"mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"p-3\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Level</p>\n <p className=\"mt-1 font-medium text-text-primary\">{sponsor.level}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-3\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Contact</p>\n <p className=\"mt-1 font-medium text-text-primary\">{sponsor.contactName ?? 'Unassigned'}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-3\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Email</p>\n <p className=\"mt-1 font-medium text-text-primary\">{sponsor.contactEmail ?? 'Unavailable'}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-3\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Website</p>\n <p className=\"mt-1 truncate font-medium text-text-primary\">{sponsor.website ?? 'Unavailable'}</p>\n </GlassCard>\n </div>\n ) : null}\n </EmphasisPanel>\n\n {sponsor ? (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Tags</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Label this sponsor so you can segment your portfolio — for example by industry, tier or renewal status.\n </p>\n <EntityTagsField entityType=\"sponsor\" entityId={sponsor.id} label=\"Sponsor tags\" className=\"mt-3\" />\n </GlassCard>\n ) : null}\n\n <EntityListSection\n heading={campaignsQuery.loading ? 'Loading campaigns...' : `Campaign Activity (${campaigns.length})`}\n emptyLabel=\"No communication campaigns available for sponsor tracking.\"\n rows={campaigns.map((campaign) => ({\n id: campaign.id,\n title: campaign.title ?? campaign.name ?? `Campaign ${campaign.id}`,\n status: campaign.status,\n }))}\n />\n\n {sponsor ? (\n <div className=\"space-y-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Sponsor messages</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Coordinate with this sponsor in a dedicated thread, backed by the conversations service.\n </p>\n </div>\n <SponsorConversation sponsorId={sponsor.id} sponsorName={sponsor.name} />\n </div>\n ) : null}\n\n <NextSteps\n storageKey=\"eventfullymanaged-sponsor-details\"\n title=\"Grow this partnership\"\n steps={[\n {\n id: 'edit-sponsor',\n label: 'Update sponsor details',\n description: 'Keep tier, contacts and contract value current.',\n icon: <Pencil className=\"h-4 w-4\" />,\n onClick: () => navigate(id ? `/sponsors/${id}/edit` : '/sponsors'),\n },\n {\n id: 'track-leads',\n label: 'Track sponsor leads',\n description: 'See the leads this sponsor is generating at the event.',\n icon: <TrendingUp className=\"h-4 w-4\" />,\n onClick: () => navigate(id ? `/sponsors/${id}/leads` : '/sponsors'),\n },\n {\n id: 'run-campaign',\n label: 'Run a co-branded campaign',\n description: 'Promote this sponsor through a communication campaign.',\n icon: <Megaphone className=\"h-4 w-4\" />,\n onClick: () => navigate('/communication'),\n },\n ]}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,SAAS,EAAoB,EAAE,cAAW,kBAA2D;AAMnG,QALA,EAAmC;EACjC,YAAY;EACZ,UAAU;EACV,cAAc,aAAa;EAC5B,CAAC,EACK,kBAAC,GAAD,EAA2B,WAAU,mBAAoB,CAAA;;AAmBlE,SAAwB,IAAqB;CAC3C,IAAM,EAAE,QAAK,OAAO,GAAW,EACzB,EAAE,gBAAa,GAAsB,EACrC,IAAgB,EAAiB;EAAE,OAAO;EAAK,QAAQ;EAAG,CAAC,EAC3D,IAAiB,EAA+B;EAAE,OAAO;EAAK,QAAQ;EAAG,CAAC,EAE1E,IAAU,SACN,EAAc,MAAM,SAAS,SAAS,EAAE,EAAmB,MAAM,MAAS,EAAK,OAAO,EAAG,EACjG,CAAC,GAAI,EAAc,KAAK,CACzB,EACK,IAAY,QACT,EAAe,MAAM,uBAAuB,SAAS,EAAE,EAC9D,CAAC,EAAe,KAAK,CACtB;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD,EAAA,UAAa,wOAIC,CAAA;GAEd,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,MAAD;KAAI,WAAU;eAAd,CACE,kBAAC,GAAD,EAAA,UAAc,WAAsB,CAAA,EAAA,WACjC;;IACL,kBAAC,KAAD;KAAG,WAAU;eACV,EAAc,UACX,+BACA,IACE,4BAA4B,EAAQ,KAAK,KACzC;KACJ,CAAA;IACH,IACC,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OAAW,WAAU;OAAS,WAAU;iBAAxC,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAsD;QAAS,CAAA,EAC5E,kBAAC,KAAD;QAAG,WAAU;kBAAsC,EAAQ;QAAU,CAAA,CAC3D;;MACZ,kBAAC,GAAD;OAAW,WAAU;OAAS,WAAU;iBAAxC,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAsD;QAAW,CAAA,EAC9E,kBAAC,KAAD;QAAG,WAAU;kBAAsC,EAAQ,eAAe;QAAiB,CAAA,CACjF;;MACZ,kBAAC,GAAD;OAAW,WAAU;OAAS,WAAU;iBAAxC,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAsD;QAAS,CAAA,EAC5E,kBAAC,KAAD;QAAG,WAAU;kBAAsC,EAAQ,gBAAgB;QAAkB,CAAA,CACnF;;MACZ,kBAAC,GAAD;OAAW,WAAU;OAAS,WAAU;iBAAxC,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAsD;QAAW,CAAA,EAC9E,kBAAC,KAAD;QAAG,WAAU;kBAA+C,EAAQ,WAAW;QAAkB,CAAA,CACvF;;MACR;SACJ;IACU,EAAA,CAAA;GAEf,IACC,kBAAC,GAAD;IAAW,WAAU;IAAQ,WAAU;cAAvC;KACE,kBAAC,MAAD;MAAI,WAAU;gBAA0C;MAAS,CAAA;KACjE,kBAAC,KAAD;MAAG,WAAU;gBAAmC;MAE5C,CAAA;KACJ,kBAAC,GAAD;MAAiB,YAAW;MAAU,UAAU,EAAQ;MAAI,OAAM;MAAe,WAAU;MAAS,CAAA;KAC1F;QACV;GAEJ,kBAAC,GAAD;IACE,SAAS,EAAe,UAAU,yBAAyB,sBAAsB,EAAU,OAAO;IAClG,YAAW;IACX,MAAM,EAAU,KAAK,OAAc;KACjC,IAAI,EAAS;KACb,OAAO,EAAS,SAAS,EAAS,QAAQ,YAAY,EAAS;KAC/D,QAAQ,EAAS;KAClB,EAAE;IACH,CAAA;GAED,IACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAA0C;KAAqB,CAAA,EAC7E,kBAAC,KAAD;KAAG,WAAU;eAAmC;KAE5C,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,GAAD;KAAqB,WAAW,EAAQ;KAAI,aAAa,EAAQ;KAAQ,CAAA,CACrE;QACJ;GAEJ,kBAAC,GAAD;IACE,YAAW;IACX,OAAM;IACN,OAAO;KACL;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;MACpC,eAAe,EAAS,IAAK,aAAa,EAAG,SAAS,YAAY;MACnE;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;MACxC,eAAe,EAAS,IAAK,aAAa,EAAG,UAAU,YAAY;MACpE;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;MACvC,eAAe,EAAS,iBAAiB;MAC1C;KACF;IACD,CAAA;GACE"}
|
|
@@ -1,54 +1,78 @@
|
|
|
1
1
|
import { useEventfullyManaged as e } from "../../context/EventfullyManagedContext.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import { useLeadsQuery as t, useMeetingsQuery as n, useNetworkingMatchesQuery as r, useSponsorsQuery as i } from "../../api/eventApi.js";
|
|
3
|
+
import { LeadCaptureDialog as a } from "../leads/LeadCaptureDialog.js";
|
|
4
|
+
import { EntityListSection as o } from "./EntityListSection.js";
|
|
5
|
+
import { useMemo as s, useState as c } from "react";
|
|
6
|
+
import { useParams as l } from "react-router-dom";
|
|
7
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
8
|
+
import { Megaphone as f, User as p, UserPlus as m, Users as h } from "lucide-react";
|
|
9
|
+
import { Button as g, EmphasisPanel as _, GradientText as v, NextSteps as y, PagePurpose as b } from "@burdenoff/fe-libs/ui";
|
|
9
10
|
//#region src/eventfullymanaged/pages/modules/SponsorLeadsPage.tsx
|
|
10
|
-
function
|
|
11
|
-
let { id:
|
|
11
|
+
function x() {
|
|
12
|
+
let { id: x = "" } = l(), { navigate: S } = e(), [C, w] = c(!1), T = i({
|
|
12
13
|
limit: 100,
|
|
13
14
|
offset: 0
|
|
14
|
-
}),
|
|
15
|
+
}), E = r({
|
|
15
16
|
limit: 100,
|
|
16
17
|
offset: 0
|
|
17
|
-
}),
|
|
18
|
+
}), D = n({
|
|
18
19
|
limit: 100,
|
|
19
20
|
offset: 0
|
|
20
|
-
}),
|
|
21
|
-
|
|
21
|
+
}), O = s(() => (T.data?.sponsors.items ?? []).find((e) => e.id === x), [x, T.data]), k = O?.eventId ?? "", A = t({
|
|
22
|
+
eventId: k || void 0,
|
|
23
|
+
limit: 100,
|
|
24
|
+
offset: 0
|
|
25
|
+
}), j = s(() => (A.data?.leads.items ?? []).filter((e) => e.sponsorId === x), [x, A.data]), M = s(() => E.data?.networkingMatches.items ?? [], [E.data]), N = s(() => D.data?.meetings.items ?? [], [D.data]);
|
|
26
|
+
return /* @__PURE__ */ d("div", {
|
|
22
27
|
className: "space-y-6 p-6",
|
|
23
28
|
children: [
|
|
24
|
-
/* @__PURE__ */
|
|
25
|
-
/* @__PURE__ */
|
|
26
|
-
className: "
|
|
27
|
-
children: [/* @__PURE__ */
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
/* @__PURE__ */ u(b, { children: "The return on a sponsorship is the people it puts in front of the sponsor. This page pulls together the leads captured for this sponsor, the potential leads from networking matches, and the booked sponsor meetings — so you can show them exactly who they met and why their investment paid off." }),
|
|
30
|
+
/* @__PURE__ */ d(_, {
|
|
31
|
+
className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
|
32
|
+
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ d("h1", {
|
|
33
|
+
className: "text-2xl font-bold text-text-primary",
|
|
34
|
+
children: [/* @__PURE__ */ u(v, { children: "Sponsor" }), " Leads"]
|
|
35
|
+
}), /* @__PURE__ */ u("p", {
|
|
36
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
37
|
+
children: O ? `${O.name} lead funnel sourced from captured leads, networking and meetings.` : "Lead funnel sourced from captured leads, networking and meeting streams."
|
|
38
|
+
})] }), /* @__PURE__ */ d(g, {
|
|
39
|
+
type: "button",
|
|
40
|
+
onClick: () => w(!0),
|
|
41
|
+
disabled: !O,
|
|
42
|
+
children: [/* @__PURE__ */ u(m, { className: "h-4 w-4" }), "Add lead"]
|
|
43
|
+
})]
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ u(o, {
|
|
46
|
+
heading: A.loading ? "Loading captured leads..." : `Captured Leads (${j.length})`,
|
|
47
|
+
emptyLabel: "No leads captured for this sponsor yet.",
|
|
48
|
+
emptyIllustration: "empty-people",
|
|
49
|
+
rows: j.map((e) => ({
|
|
50
|
+
id: e.id,
|
|
51
|
+
title: e.attendeeName,
|
|
52
|
+
subtitle: [e.attendeeEmail, e.score == null ? void 0 : `Score ${e.score}`].filter(Boolean).join(" • "),
|
|
53
|
+
status: e.status
|
|
54
|
+
}))
|
|
55
|
+
}),
|
|
56
|
+
/* @__PURE__ */ u(o, {
|
|
57
|
+
heading: E.loading ? "Loading networking matches..." : `Potential Leads (${M.length})`,
|
|
34
58
|
emptyLabel: "No networking leads found.",
|
|
35
59
|
emptyIllustration: "empty-people",
|
|
36
|
-
rows:
|
|
60
|
+
rows: M.map((e) => ({
|
|
37
61
|
id: e.id,
|
|
38
62
|
title: e.title ?? e.name ?? `Lead ${e.id}`,
|
|
39
63
|
status: e.status
|
|
40
64
|
}))
|
|
41
65
|
}),
|
|
42
|
-
/* @__PURE__ */
|
|
43
|
-
heading:
|
|
66
|
+
/* @__PURE__ */ u(o, {
|
|
67
|
+
heading: D.loading ? "Loading meetings..." : `Sponsor Meetings (${N.length})`,
|
|
44
68
|
emptyLabel: "No sponsor meetings recorded.",
|
|
45
|
-
rows:
|
|
69
|
+
rows: N.map((e) => ({
|
|
46
70
|
id: e.id,
|
|
47
71
|
title: e.title ?? e.name ?? `Meeting ${e.id}`,
|
|
48
72
|
status: e.status
|
|
49
73
|
}))
|
|
50
74
|
}),
|
|
51
|
-
/* @__PURE__ */
|
|
75
|
+
/* @__PURE__ */ u(y, {
|
|
52
76
|
storageKey: "eventfullymanaged-sponsor-leads",
|
|
53
77
|
title: "Turn leads into wins",
|
|
54
78
|
steps: [
|
|
@@ -56,29 +80,39 @@ function g() {
|
|
|
56
80
|
id: "sponsor-profile",
|
|
57
81
|
label: "Back to sponsor profile",
|
|
58
82
|
description: "Review this sponsor’s tier, contacts and contract value.",
|
|
59
|
-
icon: /* @__PURE__ */
|
|
60
|
-
onClick: () =>
|
|
83
|
+
icon: /* @__PURE__ */ u(p, { className: "h-4 w-4" }),
|
|
84
|
+
onClick: () => S(x ? `/sponsors/${x}` : "/sponsors")
|
|
61
85
|
},
|
|
62
86
|
{
|
|
63
87
|
id: "boost-networking",
|
|
64
88
|
label: "Boost networking",
|
|
65
89
|
description: "Improve matchmaking so sponsors meet more of the right people.",
|
|
66
|
-
icon: /* @__PURE__ */
|
|
67
|
-
onClick: () =>
|
|
90
|
+
icon: /* @__PURE__ */ u(h, { className: "h-4 w-4" }),
|
|
91
|
+
onClick: () => S("/networking")
|
|
68
92
|
},
|
|
69
93
|
{
|
|
70
94
|
id: "follow-up",
|
|
71
95
|
label: "Follow up with attendees",
|
|
72
96
|
description: "Send a campaign to nurture the leads after the event.",
|
|
73
|
-
icon: /* @__PURE__ */
|
|
74
|
-
onClick: () =>
|
|
97
|
+
icon: /* @__PURE__ */ u(f, { className: "h-4 w-4" }),
|
|
98
|
+
onClick: () => S("/communication")
|
|
75
99
|
}
|
|
76
100
|
]
|
|
77
|
-
})
|
|
101
|
+
}),
|
|
102
|
+
O ? /* @__PURE__ */ u(a, {
|
|
103
|
+
open: C,
|
|
104
|
+
onOpenChange: w,
|
|
105
|
+
eventId: k,
|
|
106
|
+
sponsorId: O.id,
|
|
107
|
+
contextLabel: O.name,
|
|
108
|
+
onCreated: () => {
|
|
109
|
+
A.refetch();
|
|
110
|
+
}
|
|
111
|
+
}) : null
|
|
78
112
|
]
|
|
79
113
|
});
|
|
80
114
|
}
|
|
81
115
|
//#endregion
|
|
82
|
-
export {
|
|
116
|
+
export { x as default };
|
|
83
117
|
|
|
84
118
|
//# sourceMappingURL=SponsorLeadsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SponsorLeadsPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/SponsorLeadsPage.tsx"],"sourcesContent":["import { Megaphone, User, Users } from 'lucide-react';\nimport { EmphasisPanel, GradientText, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { useMeetingsQuery, useNetworkingMatchesQuery, useSponsorsQuery } from '../../api/eventApi';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { EntityListSection } from './EntityListSection';\n\ntype SponsorRow = {\n id: string;\n name: string;\n level: string;\n};\n\ntype SimpleRow = {\n id: string;\n name?: string;\n title?: string;\n status?: string;\n};\n\nexport default function SponsorLeadsPage() {\n const { id = '' } = useParams();\n const { navigate } = useEventfullyManaged();\n const sponsorsQuery = useSponsorsQuery({ limit: 100, offset: 0 });\n const matchesQuery = useNetworkingMatchesQuery({ limit: 100, offset: 0 });\n const meetingsQuery = useMeetingsQuery({ limit: 100, offset: 0 });\n\n const sponsor = useMemo(\n () => ((sponsorsQuery.data?.sponsors.items ?? []) as SponsorRow[]).find((item) => item.id === id),\n [id, sponsorsQuery.data]\n );\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 The return on a sponsorship is the people it puts in front of the sponsor. This page pulls together the\n potential leads
|
|
1
|
+
{"version":3,"file":"SponsorLeadsPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/SponsorLeadsPage.tsx"],"sourcesContent":["import { Megaphone, User, UserPlus, Users } from 'lucide-react';\nimport { Button, EmphasisPanel, GradientText, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { useLeadsQuery, useMeetingsQuery, useNetworkingMatchesQuery, useSponsorsQuery } from '../../api/eventApi';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { LeadCaptureDialog } from '../leads/LeadCaptureDialog';\nimport { EntityListSection } from './EntityListSection';\n\ntype SponsorRow = {\n id: string;\n name: string;\n level: string;\n eventId?: string | null;\n};\n\ntype SimpleRow = {\n id: string;\n name?: string;\n title?: string;\n status?: string;\n};\n\ntype LeadRow = {\n id: string;\n sponsorId?: string | null;\n attendeeName: string;\n attendeeEmail: string;\n status: string;\n score?: number | null;\n};\n\nexport default function SponsorLeadsPage() {\n const { id = '' } = useParams();\n const { navigate } = useEventfullyManaged();\n const [leadOpen, setLeadOpen] = useState(false);\n\n const sponsorsQuery = useSponsorsQuery({ limit: 100, offset: 0 });\n const matchesQuery = useNetworkingMatchesQuery({ limit: 100, offset: 0 });\n const meetingsQuery = useMeetingsQuery({ limit: 100, offset: 0 });\n\n const sponsor = useMemo(\n () => ((sponsorsQuery.data?.sponsors.items ?? []) as SponsorRow[]).find((item) => item.id === id),\n [id, sponsorsQuery.data]\n );\n const eventId = sponsor?.eventId ?? '';\n\n const leadsQuery = useLeadsQuery({ eventId: eventId || undefined, limit: 100, offset: 0 });\n const capturedLeads = useMemo(\n () => ((leadsQuery.data?.leads.items ?? []) as LeadRow[]).filter((lead) => lead.sponsorId === id),\n [id, leadsQuery.data]\n );\n\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 The return on a sponsorship is the people it puts in front of the sponsor. This page pulls together the leads\n captured for this sponsor, the potential leads from networking matches, and the booked sponsor meetings — so you\n can show them exactly who they met and why their investment paid off.\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>Sponsor</GradientText> Leads\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {sponsor\n ? `${sponsor.name} lead funnel sourced from captured leads, networking and meetings.`\n : 'Lead funnel sourced from captured leads, networking and meeting streams.'}\n </p>\n </div>\n <Button type=\"button\" onClick={() => setLeadOpen(true)} disabled={!sponsor}>\n <UserPlus className=\"h-4 w-4\" />\n Add lead\n </Button>\n </EmphasisPanel>\n\n <EntityListSection\n heading={leadsQuery.loading ? 'Loading captured leads...' : `Captured Leads (${capturedLeads.length})`}\n emptyLabel=\"No leads captured for this sponsor yet.\"\n emptyIllustration=\"empty-people\"\n rows={capturedLeads.map((lead) => ({\n id: lead.id,\n title: lead.attendeeName,\n subtitle: [lead.attendeeEmail, lead.score != null ? `Score ${lead.score}` : undefined]\n .filter(Boolean)\n .join(' • '),\n status: lead.status,\n }))}\n />\n\n <EntityListSection\n heading={matchesQuery.loading ? 'Loading networking matches...' : `Potential Leads (${matches.length})`}\n emptyLabel=\"No networking leads found.\"\n emptyIllustration=\"empty-people\"\n rows={matches.map((match) => ({\n id: match.id,\n title: match.title ?? match.name ?? `Lead ${match.id}`,\n status: match.status,\n }))}\n />\n\n <EntityListSection\n heading={meetingsQuery.loading ? 'Loading meetings...' : `Sponsor Meetings (${meetings.length})`}\n emptyLabel=\"No sponsor meetings recorded.\"\n rows={meetings.map((meeting) => ({\n id: meeting.id,\n title: meeting.title ?? meeting.name ?? `Meeting ${meeting.id}`,\n status: meeting.status,\n }))}\n />\n\n <NextSteps\n storageKey=\"eventfullymanaged-sponsor-leads\"\n title=\"Turn leads into wins\"\n steps={[\n {\n id: 'sponsor-profile',\n label: 'Back to sponsor profile',\n description: 'Review this sponsor’s tier, contacts and contract value.',\n icon: <User className=\"h-4 w-4\" />,\n onClick: () => navigate(id ? `/sponsors/${id}` : '/sponsors'),\n },\n {\n id: 'boost-networking',\n label: 'Boost networking',\n description: 'Improve matchmaking so sponsors meet more of the right people.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('/networking'),\n },\n {\n id: 'follow-up',\n label: 'Follow up with attendees',\n description: 'Send a campaign to nurture the leads after the event.',\n icon: <Megaphone className=\"h-4 w-4\" />,\n onClick: () => navigate('/communication'),\n },\n ]}\n />\n\n {sponsor ? (\n <LeadCaptureDialog\n open={leadOpen}\n onOpenChange={setLeadOpen}\n eventId={eventId}\n sponsorId={sponsor.id}\n contextLabel={sponsor.name}\n onCreated={() => {\n void leadsQuery.refetch();\n }}\n />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
|