@burdenoff/microfe-eventfullymanaged 2026.703.2 → 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 -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 +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
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
//#region src/eventfullymanaged/pages/events/eventFormUtils.ts
|
|
2
|
+
var e = (e) => String(e).padStart(2, "0");
|
|
3
|
+
function t(t) {
|
|
4
|
+
if (!t) return "";
|
|
5
|
+
let n = new Date(t);
|
|
6
|
+
return Number.isNaN(n.getTime()) ? "" : `${n.getFullYear()}-${e(n.getMonth() + 1)}-${e(n.getDate())}T${e(n.getHours())}:${e(n.getMinutes())}`;
|
|
7
|
+
}
|
|
8
|
+
function n(e) {
|
|
9
|
+
if (!e) return "";
|
|
10
|
+
let t = new Date(e);
|
|
11
|
+
return Number.isNaN(t.getTime()) ? "" : t.toISOString();
|
|
12
|
+
}
|
|
13
|
+
function r(e) {
|
|
14
|
+
if (!e) return "";
|
|
15
|
+
let t = new Date(e);
|
|
16
|
+
return Number.isNaN(t.getTime()) ? "" : t.toLocaleString();
|
|
17
|
+
}
|
|
18
|
+
var i = [
|
|
19
|
+
{
|
|
20
|
+
value: "IN_PERSON",
|
|
21
|
+
label: "In person"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
value: "VIRTUAL",
|
|
25
|
+
label: "Virtual"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: "HYBRID",
|
|
29
|
+
label: "Hybrid"
|
|
30
|
+
}
|
|
31
|
+
], a = [
|
|
32
|
+
{
|
|
33
|
+
value: "DRAFT",
|
|
34
|
+
label: "Draft"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
value: "PUBLISHED",
|
|
38
|
+
label: "Published"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
value: "LIVE",
|
|
42
|
+
label: "Live"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
value: "COMPLETED",
|
|
46
|
+
label: "Completed"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
value: "CANCELLED",
|
|
50
|
+
label: "Cancelled"
|
|
51
|
+
}
|
|
52
|
+
], o = [
|
|
53
|
+
{
|
|
54
|
+
value: "private",
|
|
55
|
+
label: "Private"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
value: "public",
|
|
59
|
+
label: "Public"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
value: "unlisted",
|
|
63
|
+
label: "Unlisted"
|
|
64
|
+
}
|
|
65
|
+
], s = [
|
|
66
|
+
{
|
|
67
|
+
value: "TALK",
|
|
68
|
+
label: "Talk"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
value: "KEYNOTE",
|
|
72
|
+
label: "Keynote"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
value: "WORKSHOP",
|
|
76
|
+
label: "Workshop"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
value: "PANEL",
|
|
80
|
+
label: "Panel"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
value: "BREAKOUT",
|
|
84
|
+
label: "Breakout"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
value: "BREAK",
|
|
88
|
+
label: "Break"
|
|
89
|
+
}
|
|
90
|
+
], c = [
|
|
91
|
+
{
|
|
92
|
+
value: "SCHEDULED",
|
|
93
|
+
label: "Scheduled"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
value: "LIVE",
|
|
97
|
+
label: "Live"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
value: "COMPLETED",
|
|
101
|
+
label: "Completed"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
value: "CANCELLED",
|
|
105
|
+
label: "Cancelled"
|
|
106
|
+
}
|
|
107
|
+
], l = [
|
|
108
|
+
{
|
|
109
|
+
value: "INR",
|
|
110
|
+
label: "INR (₹)"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
value: "USD",
|
|
114
|
+
label: "USD ($)"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
value: "EUR",
|
|
118
|
+
label: "EUR (€)"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
value: "GBP",
|
|
122
|
+
label: "GBP (£)"
|
|
123
|
+
}
|
|
124
|
+
];
|
|
125
|
+
//#endregion
|
|
126
|
+
export { l as CURRENCY_OPTIONS, a as EVENT_STATUS_OPTIONS, i as EVENT_TYPE_OPTIONS, o as EVENT_VISIBILITY_OPTIONS, c as SESSION_STATUS_OPTIONS, s as SESSION_TYPE_OPTIONS, r as formatDateTime, n as inputValueToIso, t as isoToInputValue };
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=eventFormUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventFormUtils.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/events/eventFormUtils.ts"],"sourcesContent":["/**\n * Shared helpers for the event-scoped forms (event, session, ticket-type).\n *\n * The backend persists all timestamps as ISO-8601 `DateTime` scalar strings,\n * while the browser `<input type=\"datetime-local\">` control speaks the\n * `YYYY-MM-DDTHH:mm` local-time format. These two helpers are the single choke\n * point that converts between them so every form treats dates consistently and\n * never sends an unparseable value to the resolver.\n */\n\nconst pad = (value: number): string => String(value).padStart(2, '0');\n\n/** ISO string → `datetime-local` input value (local time). Empty on bad input. */\nexport function isoToInputValue(iso: string | null | undefined): string {\n if (!iso) {\n return '';\n }\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(\n date.getMinutes()\n )}`;\n}\n\n/** `datetime-local` input value → ISO string. Empty string when unset/invalid. */\nexport function inputValueToIso(value: string): string {\n if (!value) {\n return '';\n }\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n return date.toISOString();\n}\n\n/** Human-friendly label for event/session headers. Empty when unparseable. */\nexport function formatDateTime(iso: string | null | undefined): string {\n if (!iso) {\n return '';\n }\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n return date.toLocaleString();\n}\n\nexport const EVENT_TYPE_OPTIONS: ReadonlyArray<{ value: string; label: string }> = [\n { value: 'IN_PERSON', label: 'In person' },\n { value: 'VIRTUAL', label: 'Virtual' },\n { value: 'HYBRID', label: 'Hybrid' },\n];\n\nexport const EVENT_STATUS_OPTIONS: ReadonlyArray<{ value: string; label: string }> = [\n { value: 'DRAFT', label: 'Draft' },\n { value: 'PUBLISHED', label: 'Published' },\n { value: 'LIVE', label: 'Live' },\n { value: 'COMPLETED', label: 'Completed' },\n { value: 'CANCELLED', label: 'Cancelled' },\n];\n\nexport const EVENT_VISIBILITY_OPTIONS: ReadonlyArray<{ value: string; label: string }> = [\n { value: 'private', label: 'Private' },\n { value: 'public', label: 'Public' },\n { value: 'unlisted', label: 'Unlisted' },\n];\n\nexport const SESSION_TYPE_OPTIONS: ReadonlyArray<{ value: string; label: string }> = [\n { value: 'TALK', label: 'Talk' },\n { value: 'KEYNOTE', label: 'Keynote' },\n { value: 'WORKSHOP', label: 'Workshop' },\n { value: 'PANEL', label: 'Panel' },\n { value: 'BREAKOUT', label: 'Breakout' },\n { value: 'BREAK', label: 'Break' },\n];\n\nexport const SESSION_STATUS_OPTIONS: ReadonlyArray<{ value: string; label: string }> = [\n { value: 'SCHEDULED', label: 'Scheduled' },\n { value: 'LIVE', label: 'Live' },\n { value: 'COMPLETED', label: 'Completed' },\n { value: 'CANCELLED', label: 'Cancelled' },\n];\n\nexport const CURRENCY_OPTIONS: ReadonlyArray<{ value: string; label: string }> = [\n { value: 'INR', label: 'INR (₹)' },\n { value: 'USD', label: 'USD ($)' },\n { value: 'EUR', label: 'EUR (€)' },\n { value: 'GBP', label: 'GBP (£)' },\n];\n"],"mappings":";AAUA,IAAM,KAAO,MAA0B,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI;AAGrE,SAAgB,EAAgB,GAAwC;AACtE,KAAI,CAAC,EACH,QAAO;CAET,IAAM,IAAO,IAAI,KAAK,EAAI;AAI1B,QAHI,OAAO,MAAM,EAAK,SAAS,CAAC,GACvB,KAEF,GAAG,EAAK,aAAa,CAAC,GAAG,EAAI,EAAK,UAAU,GAAG,EAAE,CAAC,GAAG,EAAI,EAAK,SAAS,CAAC,CAAC,GAAG,EAAI,EAAK,UAAU,CAAC,CAAC,GAAG,EACzG,EAAK,YAAY,CAClB;;AAIH,SAAgB,EAAgB,GAAuB;AACrD,KAAI,CAAC,EACH,QAAO;CAET,IAAM,IAAO,IAAI,KAAK,EAAM;AAI5B,QAHI,OAAO,MAAM,EAAK,SAAS,CAAC,GACvB,KAEF,EAAK,aAAa;;AAI3B,SAAgB,EAAe,GAAwC;AACrE,KAAI,CAAC,EACH,QAAO;CAET,IAAM,IAAO,IAAI,KAAK,EAAI;AAI1B,QAHI,OAAO,MAAM,EAAK,SAAS,CAAC,GACvB,KAEF,EAAK,gBAAgB;;AAG9B,IAAa,IAAsE;CACjF;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAW,OAAO;EAAW;CACtC;EAAE,OAAO;EAAU,OAAO;EAAU;CACrC,EAEY,IAAwE;CACnF;EAAE,OAAO;EAAS,OAAO;EAAS;CAClC;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAQ,OAAO;EAAQ;CAChC;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAa,OAAO;EAAa;CAC3C,EAEY,IAA4E;CACvF;EAAE,OAAO;EAAW,OAAO;EAAW;CACtC;EAAE,OAAO;EAAU,OAAO;EAAU;CACpC;EAAE,OAAO;EAAY,OAAO;EAAY;CACzC,EAEY,IAAwE;CACnF;EAAE,OAAO;EAAQ,OAAO;EAAQ;CAChC;EAAE,OAAO;EAAW,OAAO;EAAW;CACtC;EAAE,OAAO;EAAY,OAAO;EAAY;CACxC;EAAE,OAAO;EAAS,OAAO;EAAS;CAClC;EAAE,OAAO;EAAY,OAAO;EAAY;CACxC;EAAE,OAAO;EAAS,OAAO;EAAS;CACnC,EAEY,IAA0E;CACrF;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAQ,OAAO;EAAQ;CAChC;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAa,OAAO;EAAa;CAC3C,EAEY,IAAoE;CAC/E;EAAE,OAAO;EAAO,OAAO;EAAW;CAClC;EAAE,OAAO;EAAO,OAAO;EAAW;CAClC;EAAE,OAAO;EAAO,OAAO;EAAW;CAClC;EAAE,OAAO;EAAO,OAAO;EAAW;CACnC"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { useEventfullyManaged as e } from "../../context/EventfullyManagedContext.js";
|
|
2
|
+
import { notify as t } from "../../lib/toast.js";
|
|
3
|
+
import { useCreateExhibitorMutation as n, useEventsQuery as r, useExhibitorsQuery as i, useUpdateExhibitorMutation as a } from "../../api/eventApi.js";
|
|
4
|
+
import { EntityFormShell as o } from "../../components/EntityFormShell.js";
|
|
5
|
+
import { describeError as s, mutationSucceeded as c } from "../../lib/mutationResult.js";
|
|
6
|
+
import { EntityTagsField as l } from "../../components/EntityTagsField.js";
|
|
7
|
+
import { safeUrl as u } from "../../components/SafeLink.js";
|
|
8
|
+
import { useEffect as d, useMemo as f, useState as p } from "react";
|
|
9
|
+
import { useParams as m } from "react-router-dom";
|
|
10
|
+
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
11
|
+
import { Input as _, Select as v, SelectContent as y, SelectItem as b, SelectTrigger as x, SelectValue as S } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
//#region src/eventfullymanaged/pages/exhibitors/ExhibitorFormPage.tsx
|
|
13
|
+
var C = {
|
|
14
|
+
eventId: "",
|
|
15
|
+
name: "",
|
|
16
|
+
boothCode: "",
|
|
17
|
+
category: "",
|
|
18
|
+
status: "CONFIRMED",
|
|
19
|
+
website: "",
|
|
20
|
+
contactName: "",
|
|
21
|
+
contactEmail: ""
|
|
22
|
+
}, w = [
|
|
23
|
+
{
|
|
24
|
+
value: "INVITED",
|
|
25
|
+
label: "Invited"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: "CONFIRMED",
|
|
29
|
+
label: "Confirmed"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
value: "ACTIVE",
|
|
33
|
+
label: "Active"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
value: "CANCELLED",
|
|
37
|
+
label: "Cancelled"
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
function T() {
|
|
41
|
+
let { id: T = "" } = m(), E = f(() => !!T, [T]), { navigate: D } = e(), { data: O } = r({
|
|
42
|
+
limit: 100,
|
|
43
|
+
offset: 0
|
|
44
|
+
}), { data: k } = i({
|
|
45
|
+
limit: 100,
|
|
46
|
+
offset: 0
|
|
47
|
+
}), A = f(() => (k?.exhibitors?.items ?? []).find((e) => e.id === T), [k, T]), [j, { loading: M }] = n(), [N, { loading: P }] = a(), [F, I] = p(C);
|
|
48
|
+
d(() => {
|
|
49
|
+
if (!E || !A) return;
|
|
50
|
+
let e = A.metadata ?? {}, t = typeof e.website == "string" ? e.website : "";
|
|
51
|
+
I({
|
|
52
|
+
eventId: A.eventId ?? "",
|
|
53
|
+
name: A.name ?? "",
|
|
54
|
+
boothCode: A.boothCode ?? "",
|
|
55
|
+
category: A.category ?? "",
|
|
56
|
+
status: A.status ?? "CONFIRMED",
|
|
57
|
+
website: t,
|
|
58
|
+
contactName: A.contactName ?? "",
|
|
59
|
+
contactEmail: A.contactEmail ?? ""
|
|
60
|
+
});
|
|
61
|
+
}, [A, E]);
|
|
62
|
+
let L = (e, t) => {
|
|
63
|
+
I((n) => ({
|
|
64
|
+
...n,
|
|
65
|
+
[e]: t
|
|
66
|
+
}));
|
|
67
|
+
}, R = async (e) => {
|
|
68
|
+
if (e.preventDefault(), !F.eventId) {
|
|
69
|
+
t.error("Event required", "Choose the event this exhibitor belongs to.");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
let n = u(F.website);
|
|
73
|
+
if (F.website.trim() && !n) {
|
|
74
|
+
t.error("Invalid website", "Enter a valid http(s) URL, or leave it blank.");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
let r = A?.metadata ?? {}, i = {
|
|
78
|
+
eventId: F.eventId,
|
|
79
|
+
name: F.name,
|
|
80
|
+
boothCode: F.boothCode,
|
|
81
|
+
category: F.category,
|
|
82
|
+
status: F.status,
|
|
83
|
+
contactName: F.contactName,
|
|
84
|
+
contactEmail: F.contactEmail,
|
|
85
|
+
metadata: {
|
|
86
|
+
...r,
|
|
87
|
+
website: n ?? ""
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
try {
|
|
91
|
+
if (E) {
|
|
92
|
+
let e = await N({ variables: {
|
|
93
|
+
id: T,
|
|
94
|
+
input: i
|
|
95
|
+
} });
|
|
96
|
+
if (!c(e, e.data?.updateExhibitor?.id, "Could not update exhibitor")) return;
|
|
97
|
+
D("/exhibitors");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
let e = await j({ variables: { input: i } });
|
|
101
|
+
if (!c(e, e.data?.createExhibitor?.id, "Could not create exhibitor")) return;
|
|
102
|
+
D("/exhibitors");
|
|
103
|
+
} catch (e) {
|
|
104
|
+
t.error("Could not save exhibitor", s(e));
|
|
105
|
+
}
|
|
106
|
+
}, z = M || P, B = O?.events?.items ?? [];
|
|
107
|
+
return /* @__PURE__ */ g(o, {
|
|
108
|
+
title: E ? "Edit Exhibitor" : "New Exhibitor",
|
|
109
|
+
description: "Manage a booth exhibitor with live backend persistence.",
|
|
110
|
+
purpose: "Register a company staffing a booth: link it to the event, give it a booth code and category, and record who to contact. Once saved, capture the leads their booth scans from the exhibitor list.",
|
|
111
|
+
backLabel: "Back to Exhibitors",
|
|
112
|
+
onBack: () => D("/exhibitors"),
|
|
113
|
+
onSubmit: R,
|
|
114
|
+
submitLabel: E ? "Save Exhibitor" : "Create Exhibitor",
|
|
115
|
+
saving: z,
|
|
116
|
+
children: [
|
|
117
|
+
/* @__PURE__ */ g("div", {
|
|
118
|
+
className: "grid grid-cols-1 gap-4 md:grid-cols-2",
|
|
119
|
+
children: [/* @__PURE__ */ g("label", {
|
|
120
|
+
className: "space-y-1 text-sm",
|
|
121
|
+
children: [/* @__PURE__ */ h("span", {
|
|
122
|
+
className: "font-medium text-text-primary",
|
|
123
|
+
children: "Event"
|
|
124
|
+
}), /* @__PURE__ */ g(v, {
|
|
125
|
+
value: F.eventId,
|
|
126
|
+
onValueChange: (e) => L("eventId", e),
|
|
127
|
+
children: [/* @__PURE__ */ h(x, {
|
|
128
|
+
"aria-label": "Event",
|
|
129
|
+
children: /* @__PURE__ */ h(S, { placeholder: "Select event" })
|
|
130
|
+
}), /* @__PURE__ */ h(y, { children: B.map((e) => /* @__PURE__ */ h(b, {
|
|
131
|
+
value: e.id,
|
|
132
|
+
children: e.name
|
|
133
|
+
}, e.id)) })]
|
|
134
|
+
})]
|
|
135
|
+
}), /* @__PURE__ */ g("label", {
|
|
136
|
+
className: "space-y-1 text-sm",
|
|
137
|
+
children: [/* @__PURE__ */ h("span", {
|
|
138
|
+
className: "font-medium text-text-primary",
|
|
139
|
+
children: "Name"
|
|
140
|
+
}), /* @__PURE__ */ h(_, {
|
|
141
|
+
value: F.name,
|
|
142
|
+
onChange: (e) => L("name", e.target.value),
|
|
143
|
+
required: !0
|
|
144
|
+
})]
|
|
145
|
+
})]
|
|
146
|
+
}),
|
|
147
|
+
/* @__PURE__ */ g("div", {
|
|
148
|
+
className: "grid grid-cols-1 gap-4 md:grid-cols-3",
|
|
149
|
+
children: [
|
|
150
|
+
/* @__PURE__ */ g("label", {
|
|
151
|
+
className: "space-y-1 text-sm",
|
|
152
|
+
children: [/* @__PURE__ */ h("span", {
|
|
153
|
+
className: "font-medium text-text-primary",
|
|
154
|
+
children: "Booth Code"
|
|
155
|
+
}), /* @__PURE__ */ h(_, {
|
|
156
|
+
value: F.boothCode,
|
|
157
|
+
onChange: (e) => L("boothCode", e.target.value)
|
|
158
|
+
})]
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ g("label", {
|
|
161
|
+
className: "space-y-1 text-sm",
|
|
162
|
+
children: [/* @__PURE__ */ h("span", {
|
|
163
|
+
className: "font-medium text-text-primary",
|
|
164
|
+
children: "Category"
|
|
165
|
+
}), /* @__PURE__ */ h(_, {
|
|
166
|
+
value: F.category,
|
|
167
|
+
onChange: (e) => L("category", e.target.value)
|
|
168
|
+
})]
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ g("label", {
|
|
171
|
+
className: "space-y-1 text-sm",
|
|
172
|
+
children: [/* @__PURE__ */ h("span", {
|
|
173
|
+
className: "font-medium text-text-primary",
|
|
174
|
+
children: "Status"
|
|
175
|
+
}), /* @__PURE__ */ g(v, {
|
|
176
|
+
value: F.status,
|
|
177
|
+
onValueChange: (e) => L("status", e),
|
|
178
|
+
children: [/* @__PURE__ */ h(x, {
|
|
179
|
+
"aria-label": "Status",
|
|
180
|
+
children: /* @__PURE__ */ h(S, {})
|
|
181
|
+
}), /* @__PURE__ */ h(y, { children: w.map((e) => /* @__PURE__ */ h(b, {
|
|
182
|
+
value: e.value,
|
|
183
|
+
children: e.label
|
|
184
|
+
}, e.value)) })]
|
|
185
|
+
})]
|
|
186
|
+
})
|
|
187
|
+
]
|
|
188
|
+
}),
|
|
189
|
+
/* @__PURE__ */ g("label", {
|
|
190
|
+
className: "block space-y-1 text-sm",
|
|
191
|
+
children: [/* @__PURE__ */ h("span", {
|
|
192
|
+
className: "font-medium text-text-primary",
|
|
193
|
+
children: "Website"
|
|
194
|
+
}), /* @__PURE__ */ h(_, {
|
|
195
|
+
value: F.website,
|
|
196
|
+
onChange: (e) => L("website", e.target.value),
|
|
197
|
+
placeholder: "https://example.com"
|
|
198
|
+
})]
|
|
199
|
+
}),
|
|
200
|
+
/* @__PURE__ */ g("div", {
|
|
201
|
+
className: "grid grid-cols-1 gap-4 md:grid-cols-2",
|
|
202
|
+
children: [/* @__PURE__ */ g("label", {
|
|
203
|
+
className: "space-y-1 text-sm",
|
|
204
|
+
children: [/* @__PURE__ */ h("span", {
|
|
205
|
+
className: "font-medium text-text-primary",
|
|
206
|
+
children: "Contact Name"
|
|
207
|
+
}), /* @__PURE__ */ h(_, {
|
|
208
|
+
value: F.contactName,
|
|
209
|
+
onChange: (e) => L("contactName", e.target.value)
|
|
210
|
+
})]
|
|
211
|
+
}), /* @__PURE__ */ g("label", {
|
|
212
|
+
className: "space-y-1 text-sm",
|
|
213
|
+
children: [/* @__PURE__ */ h("span", {
|
|
214
|
+
className: "font-medium text-text-primary",
|
|
215
|
+
children: "Contact Email"
|
|
216
|
+
}), /* @__PURE__ */ h(_, {
|
|
217
|
+
type: "email",
|
|
218
|
+
value: F.contactEmail,
|
|
219
|
+
onChange: (e) => L("contactEmail", e.target.value)
|
|
220
|
+
})]
|
|
221
|
+
})]
|
|
222
|
+
}),
|
|
223
|
+
E ? /* @__PURE__ */ h(l, {
|
|
224
|
+
entityType: "exhibitor",
|
|
225
|
+
entityId: T
|
|
226
|
+
}) : null
|
|
227
|
+
]
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
//#endregion
|
|
231
|
+
export { T as default };
|
|
232
|
+
|
|
233
|
+
//# sourceMappingURL=ExhibitorFormPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExhibitorFormPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/exhibitors/ExhibitorFormPage.tsx"],"sourcesContent":["/* eslint-disable react-hooks/set-state-in-effect */\nimport {\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport {\n useCreateExhibitorMutation,\n useEventsQuery,\n useExhibitorsQuery,\n useUpdateExhibitorMutation,\n} from '../../api/eventApi';\nimport { EntityFormShell } from '../../components/EntityFormShell';\nimport { EntityTagsField } from '../../components/EntityTagsField';\nimport { safeUrl } from '../../components/SafeLink';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { describeError, mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\n\ntype ExhibitorFormState = {\n eventId: string;\n name: string;\n boothCode: string;\n category: string;\n status: string;\n website: string;\n contactName: string;\n contactEmail: string;\n};\n\nconst initialState: ExhibitorFormState = {\n eventId: '',\n name: '',\n boothCode: '',\n category: '',\n status: 'CONFIRMED',\n website: '',\n contactName: '',\n contactEmail: '',\n};\n\nconst STATUS_OPTIONS = [\n { value: 'INVITED', label: 'Invited' },\n { value: 'CONFIRMED', label: 'Confirmed' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'CANCELLED', label: 'Cancelled' },\n];\n\nexport default function ExhibitorFormPage() {\n const { id = '' } = useParams<{ id: string }>();\n const isEdit = useMemo(() => Boolean(id), [id]);\n const { navigate } = useEventfullyManaged();\n\n const { data: eventsData } = useEventsQuery({ limit: 100, offset: 0 });\n // No by-id resolver exists for exhibitors, so the edit initial-state is derived\n // from the list query row.\n const { data: exhibitorsData } = useExhibitorsQuery({ limit: 100, offset: 0 });\n\n const existing = useMemo(\n () => (exhibitorsData?.exhibitors?.items ?? []).find((item) => item.id === id),\n [exhibitorsData, id]\n );\n\n const [createExhibitor, { loading: creating }] = useCreateExhibitorMutation();\n const [updateExhibitor, { loading: updating }] = useUpdateExhibitorMutation();\n const [form, setForm] = useState<ExhibitorFormState>(initialState);\n\n useEffect(() => {\n if (!isEdit || !existing) {\n return;\n }\n const metadata = existing.metadata ?? {};\n const website = typeof metadata.website === 'string' ? metadata.website : '';\n setForm({\n eventId: existing.eventId ?? '',\n name: existing.name ?? '',\n boothCode: existing.boothCode ?? '',\n category: existing.category ?? '',\n status: existing.status ?? 'CONFIRMED',\n website,\n contactName: existing.contactName ?? '',\n contactEmail: existing.contactEmail ?? '',\n });\n }, [existing, isEdit]);\n\n const onChange = (field: keyof ExhibitorFormState, value: string) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n };\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n if (!form.eventId) {\n notify.error('Event required', 'Choose the event this exhibitor belongs to.');\n return;\n }\n\n // The website is free text persisted verbatim, so normalise/reject it before\n // it is stored and later rendered as a link.\n const normalizedWebsite = safeUrl(form.website);\n if (form.website.trim() && !normalizedWebsite) {\n notify.error('Invalid website', 'Enter a valid http(s) URL, or leave it blank.');\n return;\n }\n\n const existingMetadata = existing?.metadata ?? {};\n const input = {\n eventId: form.eventId,\n name: form.name,\n boothCode: form.boothCode,\n category: form.category,\n status: form.status,\n contactName: form.contactName,\n contactEmail: form.contactEmail,\n metadata: { ...existingMetadata, website: normalizedWebsite ?? '' },\n };\n\n try {\n if (isEdit) {\n const response = await updateExhibitor({ variables: { id, input } });\n if (!mutationSucceeded(response, response.data?.updateExhibitor?.id, 'Could not update exhibitor')) {\n return;\n }\n navigate('/exhibitors');\n return;\n }\n\n const response = await createExhibitor({ variables: { input } });\n if (!mutationSucceeded(response, response.data?.createExhibitor?.id, 'Could not create exhibitor')) {\n return;\n }\n navigate('/exhibitors');\n } catch (error) {\n notify.error('Could not save exhibitor', describeError(error));\n }\n };\n\n const saving = creating || updating;\n const events = eventsData?.events?.items ?? [];\n\n return (\n <EntityFormShell\n title={isEdit ? 'Edit Exhibitor' : 'New Exhibitor'}\n description=\"Manage a booth exhibitor with live backend persistence.\"\n purpose=\"Register a company staffing a booth: link it to the event, give it a booth code and category, and record who to contact. Once saved, capture the leads their booth scans from the exhibitor list.\"\n backLabel=\"Back to Exhibitors\"\n onBack={() => navigate('/exhibitors')}\n onSubmit={onSubmit}\n submitLabel={isEdit ? 'Save Exhibitor' : 'Create Exhibitor'}\n saving={saving}\n >\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Event</span>\n <Select value={form.eventId} onValueChange={(value) => onChange('eventId', value)}>\n <SelectTrigger aria-label=\"Event\">\n <SelectValue placeholder=\"Select event\" />\n </SelectTrigger>\n <SelectContent>\n {events.map((eventItem) => (\n <SelectItem key={eventItem.id} value={eventItem.id}>\n {eventItem.name}\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\">Name</span>\n <Input value={form.name} onChange={(e) => onChange('name', e.target.value)} required />\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Booth Code</span>\n <Input value={form.boothCode} onChange={(e) => onChange('boothCode', e.target.value)} />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Category</span>\n <Input value={form.category} onChange={(e) => onChange('category', e.target.value)} />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Status</span>\n <Select value={form.status} onValueChange={(value) => onChange('status', value)}>\n <SelectTrigger aria-label=\"Status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <label className=\"block space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Website</span>\n <Input\n value={form.website}\n onChange={(e) => onChange('website', e.target.value)}\n placeholder=\"https://example.com\"\n />\n </label>\n\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Contact Name</span>\n <Input value={form.contactName} onChange={(e) => onChange('contactName', e.target.value)} />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Contact Email</span>\n <Input\n type=\"email\"\n value={form.contactEmail}\n onChange={(e) => onChange('contactEmail', e.target.value)}\n />\n </label>\n </div>\n\n {isEdit ? <EntityTagsField entityType=\"exhibitor\" entityId={id} /> : null}\n </EntityFormShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAoCA,IAAM,IAAmC;CACvC,SAAS;CACT,MAAM;CACN,WAAW;CACX,UAAU;CACV,QAAQ;CACR,SAAS;CACT,aAAa;CACb,cAAc;CACf,EAEK,IAAiB;CACrB;EAAE,OAAO;EAAW,OAAO;EAAW;CACtC;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAU,OAAO;EAAU;CACpC;EAAE,OAAO;EAAa,OAAO;EAAa;CAC3C;AAED,SAAwB,IAAoB;CAC1C,IAAM,EAAE,QAAK,OAAO,GAA2B,EACzC,IAAS,QAAc,EAAQ,GAAK,CAAC,EAAG,CAAC,EACzC,EAAE,gBAAa,GAAsB,EAErC,EAAE,MAAM,MAAe,EAAe;EAAE,OAAO;EAAK,QAAQ;EAAG,CAAC,EAGhE,EAAE,MAAM,MAAmB,EAAmB;EAAE,OAAO;EAAK,QAAQ;EAAG,CAAC,EAExE,IAAW,SACR,GAAgB,YAAY,SAAS,EAAE,EAAE,MAAM,MAAS,EAAK,OAAO,EAAG,EAC9E,CAAC,GAAgB,EAAG,CACrB,EAEK,CAAC,GAAiB,EAAE,SAAS,OAAc,GAA4B,EACvE,CAAC,GAAiB,EAAE,SAAS,OAAc,GAA4B,EACvE,CAAC,GAAM,KAAW,EAA6B,EAAa;AAElE,SAAgB;AACd,MAAI,CAAC,KAAU,CAAC,EACd;EAEF,IAAM,IAAW,EAAS,YAAY,EAAE,EAClC,IAAU,OAAO,EAAS,WAAY,WAAW,EAAS,UAAU;AAC1E,IAAQ;GACN,SAAS,EAAS,WAAW;GAC7B,MAAM,EAAS,QAAQ;GACvB,WAAW,EAAS,aAAa;GACjC,UAAU,EAAS,YAAY;GAC/B,QAAQ,EAAS,UAAU;GAC3B;GACA,aAAa,EAAS,eAAe;GACrC,cAAc,EAAS,gBAAgB;GACxC,CAAC;IACD,CAAC,GAAU,EAAO,CAAC;CAEtB,IAAM,KAAY,GAAiC,MAAkB;AACnE,KAAS,OAAU;GAAE,GAAG;IAAO,IAAQ;GAAO,EAAE;IAG5C,IAAW,OAAO,MAA4C;AAGlE,MAFA,EAAM,gBAAgB,EAElB,CAAC,EAAK,SAAS;AACjB,KAAO,MAAM,kBAAkB,8CAA8C;AAC7E;;EAKF,IAAM,IAAoB,EAAQ,EAAK,QAAQ;AAC/C,MAAI,EAAK,QAAQ,MAAM,IAAI,CAAC,GAAmB;AAC7C,KAAO,MAAM,mBAAmB,gDAAgD;AAChF;;EAGF,IAAM,IAAmB,GAAU,YAAY,EAAE,EAC3C,IAAQ;GACZ,SAAS,EAAK;GACd,MAAM,EAAK;GACX,WAAW,EAAK;GAChB,UAAU,EAAK;GACf,QAAQ,EAAK;GACb,aAAa,EAAK;GAClB,cAAc,EAAK;GACnB,UAAU;IAAE,GAAG;IAAkB,SAAS,KAAqB;IAAI;GACpE;AAED,MAAI;AACF,OAAI,GAAQ;IACV,IAAM,IAAW,MAAM,EAAgB,EAAE,WAAW;KAAE;KAAI;KAAO,EAAE,CAAC;AACpE,QAAI,CAAC,EAAkB,GAAU,EAAS,MAAM,iBAAiB,IAAI,6BAA6B,CAChG;AAEF,MAAS,cAAc;AACvB;;GAGF,IAAM,IAAW,MAAM,EAAgB,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC;AAChE,OAAI,CAAC,EAAkB,GAAU,EAAS,MAAM,iBAAiB,IAAI,6BAA6B,CAChG;AAEF,KAAS,cAAc;WAChB,GAAO;AACd,KAAO,MAAM,4BAA4B,EAAc,EAAM,CAAC;;IAI5D,IAAS,KAAY,GACrB,IAAS,GAAY,QAAQ,SAAS,EAAE;AAE9C,QACE,kBAAC,GAAD;EACE,OAAO,IAAS,mBAAmB;EACnC,aAAY;EACZ,SAAQ;EACR,WAAU;EACV,cAAc,EAAS,cAAc;EAC3B;EACV,aAAa,IAAS,mBAAmB;EACjC;YARV;GAUE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAgC;MAAY,CAAA,EAC5D,kBAAC,GAAD;MAAQ,OAAO,EAAK;MAAS,gBAAgB,MAAU,EAAS,WAAW,EAAM;gBAAjF,CACE,kBAAC,GAAD;OAAe,cAAW;iBACxB,kBAAC,GAAD,EAAa,aAAY,gBAAiB,CAAA;OAC5B,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAO,KAAK,MACX,kBAAC,GAAD;OAA+B,OAAO,EAAU;iBAC7C,EAAU;OACA,EAFI,EAAU,GAEd,CACb,EACY,CAAA,CACT;QACH;QACR,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAgC;MAAW,CAAA,EAC3D,kBAAC,GAAD;MAAO,OAAO,EAAK;MAAM,WAAW,MAAM,EAAS,QAAQ,EAAE,OAAO,MAAM;MAAE,UAAA;MAAW,CAAA,CACjF;OACJ;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAgC;OAAiB,CAAA,EACjE,kBAAC,GAAD;OAAO,OAAO,EAAK;OAAW,WAAW,MAAM,EAAS,aAAa,EAAE,OAAO,MAAM;OAAI,CAAA,CAClF;;KACR,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAgC;OAAe,CAAA,EAC/D,kBAAC,GAAD;OAAO,OAAO,EAAK;OAAU,WAAW,MAAM,EAAS,YAAY,EAAE,OAAO,MAAM;OAAI,CAAA,CAChF;;KACR,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAgC;OAAa,CAAA,EAC7D,kBAAC,GAAD;OAAQ,OAAO,EAAK;OAAQ,gBAAgB,MAAU,EAAS,UAAU,EAAM;iBAA/E,CACE,kBAAC,GAAD;QAAe,cAAW;kBACxB,kBAAC,GAAD,EAAe,CAAA;QACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAe,KAAK,MACnB,kBAAC,GAAD;QAA+B,OAAO,EAAO;kBAC1C,EAAO;QACG,EAFI,EAAO,MAEX,CACb,EACY,CAAA,CACT;SACH;;KACJ;;GAEN,kBAAC,SAAD;IAAO,WAAU;cAAjB,CACE,kBAAC,QAAD;KAAM,WAAU;eAAgC;KAAc,CAAA,EAC9D,kBAAC,GAAD;KACE,OAAO,EAAK;KACZ,WAAW,MAAM,EAAS,WAAW,EAAE,OAAO,MAAM;KACpD,aAAY;KACZ,CAAA,CACI;;GAER,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAgC;MAAmB,CAAA,EACnE,kBAAC,GAAD;MAAO,OAAO,EAAK;MAAa,WAAW,MAAM,EAAS,eAAe,EAAE,OAAO,MAAM;MAAI,CAAA,CACtF;QACR,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAgC;MAAoB,CAAA,EACpE,kBAAC,GAAD;MACE,MAAK;MACL,OAAO,EAAK;MACZ,WAAW,MAAM,EAAS,gBAAgB,EAAE,OAAO,MAAM;MACzD,CAAA,CACI;OACJ;;GAEL,IAAS,kBAAC,GAAD;IAAiB,YAAW;IAAY,UAAU;IAAM,CAAA,GAAG;GACrD"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { useEventfullyManaged as e } from "../../context/EventfullyManagedContext.js";
|
|
2
|
+
import { notify as t } from "../../lib/toast.js";
|
|
3
|
+
import { useDeleteExhibitorMutation as n, useExhibitorsQuery as r } from "../../api/eventApi.js";
|
|
4
|
+
import { ActionMenu as i } from "../../components/ActionMenu.js";
|
|
5
|
+
import { Pagination as a, usePagination as o } from "../../components/Pagination.js";
|
|
6
|
+
import { describeError as s, mutationSucceeded as c } from "../../lib/mutationResult.js";
|
|
7
|
+
import { SafeLink as l } from "../../components/SafeLink.js";
|
|
8
|
+
import { LeadCaptureDialog as u } from "../leads/LeadCaptureDialog.js";
|
|
9
|
+
import { useMemo as d, useState as f } from "react";
|
|
10
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
11
|
+
import { ExternalLink as h, LayoutGrid as g, Plus as _, Search as v, Store as y, UserPlus as b } from "lucide-react";
|
|
12
|
+
import { Badge as x, Button as S, EmphasisPanel as C, GlassCard as w, IllustratedEmptyState as T, Input as E, PagePurpose as D } from "@burdenoff/fe-libs/ui";
|
|
13
|
+
//#region src/eventfullymanaged/pages/exhibitors/ExhibitorsPage.tsx
|
|
14
|
+
function O(e) {
|
|
15
|
+
let t = e?.website;
|
|
16
|
+
return typeof t == "string" && t.trim() ? t : null;
|
|
17
|
+
}
|
|
18
|
+
function k() {
|
|
19
|
+
let { navigate: k } = e(), [A, j] = f(""), M = o({ resetKey: A }), { data: N, loading: P, refetch: F } = r({
|
|
20
|
+
search: A,
|
|
21
|
+
limit: M.limit,
|
|
22
|
+
offset: M.offset
|
|
23
|
+
}), [I] = n(), [L, R] = f(null), z = d(() => N?.exhibitors?.items ?? [], [N]), B = N?.exhibitors?.total ?? 0, V = async (e) => {
|
|
24
|
+
try {
|
|
25
|
+
let n = await I({ variables: { id: e.id } });
|
|
26
|
+
if (!c(n, n.data?.deleteExhibitor === !0 ? e.id : void 0, "Could not delete exhibitor")) return;
|
|
27
|
+
t.success("Exhibitor removed", `${e.name} was deleted.`), await F();
|
|
28
|
+
} catch (e) {
|
|
29
|
+
t.error("Could not delete exhibitor", s(e));
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
return /* @__PURE__ */ m("div", {
|
|
33
|
+
className: "space-y-6 p-6",
|
|
34
|
+
children: [
|
|
35
|
+
/* @__PURE__ */ p(D, { children: "Exhibitors are the companies staffing booths at your event. Track each booth, the category it belongs to, and the contact who runs it — then capture the leads they scan on the floor so you can prove the value of their stand. Start here to onboard a new exhibitor or work the booth pipeline." }),
|
|
36
|
+
/* @__PURE__ */ m(C, {
|
|
37
|
+
className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
|
38
|
+
children: [/* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h1", {
|
|
39
|
+
className: "text-2xl font-bold text-text-primary",
|
|
40
|
+
children: "Exhibitors"
|
|
41
|
+
}), /* @__PURE__ */ p("p", {
|
|
42
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
43
|
+
children: "Manage booth exhibitors and capture floor leads from live backend data."
|
|
44
|
+
})] }), /* @__PURE__ */ m(S, {
|
|
45
|
+
type: "button",
|
|
46
|
+
onClick: () => k("/exhibitors/create"),
|
|
47
|
+
children: [/* @__PURE__ */ p(_, { className: "h-4 w-4" }), "New Exhibitor"]
|
|
48
|
+
})]
|
|
49
|
+
}),
|
|
50
|
+
/* @__PURE__ */ m("div", {
|
|
51
|
+
className: "relative",
|
|
52
|
+
children: [/* @__PURE__ */ p(v, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted" }), /* @__PURE__ */ p(E, {
|
|
53
|
+
type: "text",
|
|
54
|
+
value: A,
|
|
55
|
+
onChange: (e) => j(e.target.value),
|
|
56
|
+
placeholder: "Search exhibitors by name or booth",
|
|
57
|
+
"aria-label": "Search exhibitors by name or booth",
|
|
58
|
+
className: "pl-10"
|
|
59
|
+
})]
|
|
60
|
+
}),
|
|
61
|
+
P ? /* @__PURE__ */ p(w, {
|
|
62
|
+
treatment: "plain",
|
|
63
|
+
className: "border-border-seam p-8 text-center text-sm text-text-secondary",
|
|
64
|
+
children: "Loading exhibitors..."
|
|
65
|
+
}) : z.length === 0 ? /* @__PURE__ */ p(w, {
|
|
66
|
+
treatment: "plain",
|
|
67
|
+
className: "border-border-seam",
|
|
68
|
+
children: /* @__PURE__ */ p(T, {
|
|
69
|
+
illustration: A ? "empty-search" : "empty-data",
|
|
70
|
+
title: A ? "No exhibitors match your search." : "No exhibitors yet.",
|
|
71
|
+
description: A ? "Try a different name or booth code." : "Add your first exhibitor to start building the booth floor.",
|
|
72
|
+
action: A ? void 0 : /* @__PURE__ */ m(S, {
|
|
73
|
+
type: "button",
|
|
74
|
+
onClick: () => k("/exhibitors/create"),
|
|
75
|
+
children: [/* @__PURE__ */ p(_, { className: "h-4 w-4" }), "New Exhibitor"]
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
}) : /* @__PURE__ */ p("div", {
|
|
79
|
+
className: "grid grid-cols-1 gap-4 lg:grid-cols-2",
|
|
80
|
+
children: z.map((e) => {
|
|
81
|
+
let t = O(e.metadata);
|
|
82
|
+
return /* @__PURE__ */ m(w, {
|
|
83
|
+
treatment: "plain",
|
|
84
|
+
className: "border-border-seam p-5",
|
|
85
|
+
children: [/* @__PURE__ */ m("div", {
|
|
86
|
+
className: "flex items-start justify-between gap-3",
|
|
87
|
+
children: [/* @__PURE__ */ m("div", {
|
|
88
|
+
className: "min-w-0",
|
|
89
|
+
children: [/* @__PURE__ */ p("h2", {
|
|
90
|
+
className: "truncate text-lg font-semibold text-text-primary",
|
|
91
|
+
children: e.name
|
|
92
|
+
}), /* @__PURE__ */ m("p", {
|
|
93
|
+
className: "mt-1 flex flex-wrap items-center gap-2 text-sm text-text-secondary",
|
|
94
|
+
children: [e.boothCode ? /* @__PURE__ */ m("span", {
|
|
95
|
+
className: "inline-flex items-center gap-1",
|
|
96
|
+
children: [/* @__PURE__ */ p(y, { className: "h-4 w-4" }), e.boothCode]
|
|
97
|
+
}) : null, e.category ? /* @__PURE__ */ p("span", { children: e.category }) : null]
|
|
98
|
+
})]
|
|
99
|
+
}), /* @__PURE__ */ m("div", {
|
|
100
|
+
className: "flex shrink-0 items-center gap-2",
|
|
101
|
+
children: [/* @__PURE__ */ p(x, {
|
|
102
|
+
variant: "secondary",
|
|
103
|
+
className: "uppercase",
|
|
104
|
+
children: e.status
|
|
105
|
+
}), /* @__PURE__ */ p(i, {
|
|
106
|
+
ariaLabel: `${e.name} actions`,
|
|
107
|
+
entityName: e.name,
|
|
108
|
+
onEdit: () => k(`/exhibitors/${e.id}/edit`),
|
|
109
|
+
onDelete: () => V(e),
|
|
110
|
+
extraItems: [{
|
|
111
|
+
key: "add-lead",
|
|
112
|
+
label: "Add lead",
|
|
113
|
+
icon: b,
|
|
114
|
+
onSelect: () => R(e)
|
|
115
|
+
}]
|
|
116
|
+
})]
|
|
117
|
+
})]
|
|
118
|
+
}), /* @__PURE__ */ m("div", {
|
|
119
|
+
className: "mt-4 grid grid-cols-1 gap-2 text-sm text-text-secondary sm:grid-cols-2",
|
|
120
|
+
children: [/* @__PURE__ */ m("div", {
|
|
121
|
+
className: "min-w-0 truncate",
|
|
122
|
+
children: [e.contactName ? e.contactName : "No contact set", e.contactEmail ? ` • ${e.contactEmail}` : ""]
|
|
123
|
+
}), t ? /* @__PURE__ */ m(l, {
|
|
124
|
+
href: t,
|
|
125
|
+
className: "inline-flex items-center gap-1 text-text-link hover:underline",
|
|
126
|
+
fallbackClassName: "text-text-secondary",
|
|
127
|
+
children: [/* @__PURE__ */ p(h, { className: "h-4 w-4" }), "Website"]
|
|
128
|
+
}) : null]
|
|
129
|
+
})]
|
|
130
|
+
}, e.id);
|
|
131
|
+
})
|
|
132
|
+
}),
|
|
133
|
+
/* @__PURE__ */ p(a, {
|
|
134
|
+
offset: M.offset,
|
|
135
|
+
limit: M.limit,
|
|
136
|
+
loadedCount: z.length,
|
|
137
|
+
total: B,
|
|
138
|
+
onPrev: M.prevPage,
|
|
139
|
+
onNext: M.nextPage,
|
|
140
|
+
itemLabel: "exhibitors",
|
|
141
|
+
loading: P
|
|
142
|
+
}),
|
|
143
|
+
z.length > 0 ? /* @__PURE__ */ m(C, {
|
|
144
|
+
className: "flex items-center gap-3",
|
|
145
|
+
children: [/* @__PURE__ */ p(g, { className: "h-5 w-5 text-text-muted" }), /* @__PURE__ */ p("p", {
|
|
146
|
+
className: "text-sm text-text-secondary",
|
|
147
|
+
children: "Use the row menu to edit a booth, capture a floor lead, or remove an exhibitor."
|
|
148
|
+
})]
|
|
149
|
+
}) : null,
|
|
150
|
+
L ? /* @__PURE__ */ p(u, {
|
|
151
|
+
open: !!L,
|
|
152
|
+
onOpenChange: (e) => {
|
|
153
|
+
e || R(null);
|
|
154
|
+
},
|
|
155
|
+
eventId: L.eventId,
|
|
156
|
+
exhibitorId: L.id,
|
|
157
|
+
contextLabel: L.name
|
|
158
|
+
}) : null
|
|
159
|
+
]
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
163
|
+
export { k as default };
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=ExhibitorsPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExhibitorsPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/exhibitors/ExhibitorsPage.tsx"],"sourcesContent":["import { ExternalLink, LayoutGrid, Plus, Search, Store, UserPlus } from 'lucide-react';\nimport {\n Badge,\n Button,\n EmphasisPanel,\n GlassCard,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useMemo, useState } from 'react';\n\nimport { useDeleteExhibitorMutation, useExhibitorsQuery } from '../../api/eventApi';\nimport { ActionMenu } from '../../components/ActionMenu';\nimport { Pagination, usePagination } from '../../components/Pagination';\nimport { SafeLink } from '../../components/SafeLink';\nimport { useEventfullyManaged } from '../../context/EventfullyManagedContext';\nimport { describeError, mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\nimport { LeadCaptureDialog } from '../leads/LeadCaptureDialog';\n\ntype ExhibitorItem = {\n id: string;\n eventId: string;\n name: string;\n boothCode?: string | null;\n category?: string | null;\n contactName?: string | null;\n contactEmail?: string | null;\n status: string;\n metadata?: Record<string, unknown> | null;\n};\n\nfunction readWebsite(metadata: Record<string, unknown> | null | undefined): string | null {\n const value = metadata?.website;\n return typeof value === 'string' && value.trim() ? value : null;\n}\n\nexport default function ExhibitorsPage() {\n const { navigate } = useEventfullyManaged();\n const [search, setSearch] = useState('');\n const pagination = usePagination({ resetKey: search });\n const { data, loading, refetch } = useExhibitorsQuery({\n search,\n limit: pagination.limit,\n offset: pagination.offset,\n });\n\n const [deleteExhibitor] = useDeleteExhibitorMutation();\n const [leadTarget, setLeadTarget] = useState<ExhibitorItem | null>(null);\n\n const exhibitors = useMemo(() => (data?.exhibitors?.items ?? []) as ExhibitorItem[], [data]);\n const total = data?.exhibitors?.total ?? 0;\n\n const onDelete = async (exhibitor: ExhibitorItem) => {\n try {\n const response = await deleteExhibitor({ variables: { id: exhibitor.id } });\n const deleted = response.data?.deleteExhibitor === true;\n if (!mutationSucceeded(response, deleted ? exhibitor.id : undefined, 'Could not delete exhibitor')) {\n return;\n }\n notify.success('Exhibitor removed', `${exhibitor.name} was deleted.`);\n await refetch();\n } catch (error) {\n notify.error('Could not delete exhibitor', describeError(error));\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Exhibitors are the companies staffing booths at your event. Track each booth, the category it belongs to, and\n the contact who runs it — then capture the leads they scan on the floor so you can prove the value of their\n stand. Start here to onboard a new exhibitor or work the booth pipeline.\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\">Exhibitors</h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Manage booth exhibitors and capture floor leads from live backend data.\n </p>\n </div>\n <Button type=\"button\" onClick={() => navigate('/exhibitors/create')}>\n <Plus className=\"h-4 w-4\" />\n New Exhibitor\n </Button>\n </EmphasisPanel>\n\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n type=\"text\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n placeholder=\"Search exhibitors by name or booth\"\n aria-label=\"Search exhibitors by name or booth\"\n className=\"pl-10\"\n />\n </div>\n\n {loading ? (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-8 text-center text-sm text-text-secondary\">\n Loading exhibitors...\n </GlassCard>\n ) : exhibitors.length === 0 ? (\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration={search ? 'empty-search' : 'empty-data'}\n title={search ? 'No exhibitors match your search.' : 'No exhibitors yet.'}\n description={\n search\n ? 'Try a different name or booth code.'\n : 'Add your first exhibitor to start building the booth floor.'\n }\n action={\n !search ? (\n <Button type=\"button\" onClick={() => navigate('/exhibitors/create')}>\n <Plus className=\"h-4 w-4\" />\n New Exhibitor\n </Button>\n ) : undefined\n }\n />\n </GlassCard>\n ) : (\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n {exhibitors.map((exhibitor) => {\n const website = readWebsite(exhibitor.metadata);\n return (\n <GlassCard key={exhibitor.id} treatment=\"plain\" className=\"border-border-seam p-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-lg font-semibold text-text-primary\">{exhibitor.name}</h2>\n <p className=\"mt-1 flex flex-wrap items-center gap-2 text-sm text-text-secondary\">\n {exhibitor.boothCode ? (\n <span className=\"inline-flex items-center gap-1\">\n <Store className=\"h-4 w-4\" />\n {exhibitor.boothCode}\n </span>\n ) : null}\n {exhibitor.category ? <span>{exhibitor.category}</span> : null}\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant=\"secondary\" className=\"uppercase\">\n {exhibitor.status}\n </Badge>\n <ActionMenu\n ariaLabel={`${exhibitor.name} actions`}\n entityName={exhibitor.name}\n onEdit={() => navigate(`/exhibitors/${exhibitor.id}/edit`)}\n onDelete={() => onDelete(exhibitor)}\n extraItems={[\n {\n key: 'add-lead',\n label: 'Add lead',\n icon: UserPlus,\n onSelect: () => setLeadTarget(exhibitor),\n },\n ]}\n />\n </div>\n </div>\n\n <div className=\"mt-4 grid grid-cols-1 gap-2 text-sm text-text-secondary sm:grid-cols-2\">\n <div className=\"min-w-0 truncate\">\n {exhibitor.contactName ? exhibitor.contactName : 'No contact set'}\n {exhibitor.contactEmail ? ` • ${exhibitor.contactEmail}` : ''}\n </div>\n {website ? (\n <SafeLink\n href={website}\n className=\"inline-flex items-center gap-1 text-text-link hover:underline\"\n fallbackClassName=\"text-text-secondary\"\n >\n <ExternalLink className=\"h-4 w-4\" />\n Website\n </SafeLink>\n ) : null}\n </div>\n </GlassCard>\n );\n })}\n </div>\n )}\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={exhibitors.length}\n total={total}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"exhibitors\"\n loading={loading}\n />\n\n {exhibitors.length > 0 ? (\n <EmphasisPanel className=\"flex items-center gap-3\">\n <LayoutGrid className=\"h-5 w-5 text-text-muted\" />\n <p className=\"text-sm text-text-secondary\">\n Use the row menu to edit a booth, capture a floor lead, or remove an exhibitor.\n </p>\n </EmphasisPanel>\n ) : null}\n\n {leadTarget ? (\n <LeadCaptureDialog\n open={Boolean(leadTarget)}\n onOpenChange={(next) => {\n if (!next) {\n setLeadTarget(null);\n }\n }}\n eventId={leadTarget.eventId}\n exhibitorId={leadTarget.id}\n contextLabel={leadTarget.name}\n />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
|