@burdenoff/microfe-comradecircle 2026.704.2 → 2026.704.3
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/comradecircle/components/Avatar.js +40 -17
- package/dist/comradecircle/components/Avatar.js.map +1 -1
- package/dist/comradecircle/components/AvatarUploadField.js +25 -14
- package/dist/comradecircle/components/AvatarUploadField.js.map +1 -1
- package/dist/comradecircle/components/CircleCard.js +54 -52
- package/dist/comradecircle/components/CircleCard.js.map +1 -1
- package/dist/comradecircle/components/CommentThread.js +80 -64
- package/dist/comradecircle/components/CommentThread.js.map +1 -1
- package/dist/comradecircle/components/EventCard.js +84 -58
- package/dist/comradecircle/components/EventCard.js.map +1 -1
- package/dist/comradecircle/components/MemberIdentity.js +2 -1
- package/dist/comradecircle/components/MemberIdentity.js.map +1 -1
- package/dist/comradecircle/components/PollCard.js +65 -44
- package/dist/comradecircle/components/PollCard.js.map +1 -1
- package/dist/comradecircle/components/PostCard.js +1 -1
- package/dist/comradecircle/components/PostCard.js.map +1 -1
- package/dist/comradecircle/components/ReactionBar.js +1 -1
- package/dist/comradecircle/components/ReactionBar.js.map +1 -1
- package/dist/comradecircle/components/StateViews.js +1 -16
- package/dist/comradecircle/components/StateViews.js.map +1 -1
- package/dist/comradecircle/components/StatusBadge.js +1 -1
- package/dist/comradecircle/components/StatusBadge.js.map +1 -1
- package/dist/comradecircle/hooks/useComradeCircleApi.js +1 -1
- package/dist/comradecircle/hooks/useComradeCircleApi.js.map +1 -1
- package/dist/comradecircle/pages/FeedPage.js +79 -33
- package/dist/comradecircle/pages/FeedPage.js.map +1 -1
- package/dist/comradecircle/pages/circles/CircleDetailPage.js +354 -243
- package/dist/comradecircle/pages/circles/CircleDetailPage.js.map +1 -1
- package/dist/comradecircle/pages/circles/CirclesPage.js +97 -47
- package/dist/comradecircle/pages/circles/CirclesPage.js.map +1 -1
- package/dist/comradecircle/pages/events/EventDetailPage.js +193 -126
- package/dist/comradecircle/pages/events/EventDetailPage.js.map +1 -1
- package/dist/comradecircle/pages/events/EventsPage.js +74 -34
- package/dist/comradecircle/pages/events/EventsPage.js.map +1 -1
- package/dist/comradecircle/pages/members/MemberProfilePage.js +154 -82
- package/dist/comradecircle/pages/members/MemberProfilePage.js.map +1 -1
- package/dist/comradecircle/pages/members/MembersPage.js +140 -71
- package/dist/comradecircle/pages/members/MembersPage.js.map +1 -1
- package/dist/comradecircle/pages/profile/MyProfilePage.js +298 -202
- package/dist/comradecircle/pages/profile/MyProfilePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { useComradeCircle as e } from "../../context/ComradeCircleContext.js";
|
|
2
|
-
import {
|
|
2
|
+
import { cn as t } from "../../utils/cn.js";
|
|
3
|
+
import { PageLayout as n } from "../../components/PageLayout.js";
|
|
3
4
|
import "../../context/index.js";
|
|
4
|
-
import { useComEvent as
|
|
5
|
+
import { useComEvent as ee, useComRsvpEvent as te, useComTransitionEvent as r } from "../../hooks/useComradeCircleApi.js";
|
|
5
6
|
import "../../hooks/index.js";
|
|
6
|
-
import { MemberIdentity as
|
|
7
|
-
import { describeError as
|
|
8
|
-
import { formatDateTime as
|
|
7
|
+
import { MemberIdentity as i } from "../../components/MemberIdentity.js";
|
|
8
|
+
import { describeError as a, notify as o } from "../../lib/toast.js";
|
|
9
|
+
import { formatDateTime as s, formatEnumLabel as c, formatNumber as l } from "../../utils/formatters.js";
|
|
10
|
+
import { EmptyState as u } from "../../components/EmptyState.js";
|
|
9
11
|
import { ErrorView as d, LoadingView as f } from "../../components/StateViews.js";
|
|
10
12
|
import { StatusBadge as p } from "../../components/StatusBadge.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { MiniBar as m } from "../../components/MiniBar.js";
|
|
14
|
+
import { ArrowLeft as h, Ban as ne, CalendarDays as re, Check as g, CheckCircle2 as _, MapPin as v, Radio as y, Tag as b, Users as x, Video as S } from "lucide-react";
|
|
15
|
+
import { useParams as C } from "react-router-dom";
|
|
16
|
+
import { Fragment as ie, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
17
|
+
import { Button as E, GlassCard as ae } from "@burdenoff/fe-libs/ui";
|
|
15
18
|
//#region src/comradecircle/pages/events/EventDetailPage.tsx
|
|
16
|
-
var
|
|
19
|
+
var oe = [
|
|
17
20
|
{
|
|
18
21
|
status: "GOING",
|
|
19
22
|
label: "Going"
|
|
@@ -30,139 +33,192 @@ var A = [
|
|
|
30
33
|
status: "NOT_GOING",
|
|
31
34
|
label: "Can't go"
|
|
32
35
|
}
|
|
36
|
+
], D = {
|
|
37
|
+
GOING: 0,
|
|
38
|
+
INTERESTED: 1,
|
|
39
|
+
WAITLISTED: 2,
|
|
40
|
+
NOT_GOING: 3
|
|
41
|
+
}, O = [
|
|
42
|
+
{
|
|
43
|
+
status: "GOING",
|
|
44
|
+
label: "going"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
status: "INTERESTED",
|
|
48
|
+
label: "interested"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
status: "WAITLISTED",
|
|
52
|
+
label: "waitlisted"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
status: "NOT_GOING",
|
|
56
|
+
label: "can't go"
|
|
57
|
+
}
|
|
33
58
|
];
|
|
34
|
-
function
|
|
35
|
-
let { id:
|
|
59
|
+
function k() {
|
|
60
|
+
let { id: k } = C(), { currentUser: A, navigateTo: j } = e(), { data: M, isLoading: N, isError: P, refetch: F } = ee(k), I = te(), L = r(), R = /* @__PURE__ */ T(E, {
|
|
36
61
|
variant: "ghost",
|
|
37
62
|
size: "sm",
|
|
38
|
-
onClick: () =>
|
|
39
|
-
children: [/* @__PURE__ */
|
|
63
|
+
onClick: () => j("events"),
|
|
64
|
+
children: [/* @__PURE__ */ w(h, { className: "mr-1.5 h-4 w-4" }), " Back"]
|
|
40
65
|
});
|
|
41
|
-
if (
|
|
66
|
+
if (N) return /* @__PURE__ */ w(n, {
|
|
42
67
|
title: "Event",
|
|
43
|
-
actions:
|
|
44
|
-
children: /* @__PURE__ */
|
|
68
|
+
actions: R,
|
|
69
|
+
children: /* @__PURE__ */ w(f, { label: "Loading event…" })
|
|
45
70
|
});
|
|
46
|
-
if (
|
|
71
|
+
if (P || !M) return /* @__PURE__ */ w(n, {
|
|
47
72
|
title: "Event",
|
|
48
|
-
actions:
|
|
49
|
-
children: /* @__PURE__ */
|
|
73
|
+
actions: R,
|
|
74
|
+
children: /* @__PURE__ */ w(d, {
|
|
50
75
|
title: "Event not found",
|
|
51
76
|
message: "This event may have been cancelled, or you may not have access to it.",
|
|
52
|
-
onRetry: () =>
|
|
77
|
+
onRetry: () => F()
|
|
53
78
|
})
|
|
54
79
|
});
|
|
55
|
-
let
|
|
80
|
+
let z = !!(A?.id && A.id === M.hostId), B = M.status === "LIVE", V = M.status === "SCHEDULED" || M.status === "LIVE", H = M.mode === "ONLINE" || M.mode === "HYBRID", U = M.mode === "IN_PERSON" || M.mode === "HYBRID", W = B && H && !!M.joinUrl, G = A?.id ? M.rsvps.find((e) => e.memberId === A.id) : void 0, K = M.capacity ?? null, q = K && K > 0 ? Math.min(100, M.rsvpCount / K * 100) : null, J = q != null && q >= 80, Y = q != null && q >= 100, X = q == null ? "" : Y ? "Full" : `${Math.round(q)}% full`, se = Y ? "bg-status-error-text" : J ? "bg-status-warning-text" : "bg-accent", ce = Y ? "text-status-error-text" : J ? "text-status-warning-text" : "text-text-tertiary", Z = M.rsvps.reduce((e, t) => (e[t.status] += 1, e), {
|
|
81
|
+
GOING: 0,
|
|
82
|
+
INTERESTED: 0,
|
|
83
|
+
WAITLISTED: 0,
|
|
84
|
+
NOT_GOING: 0
|
|
85
|
+
}), le = [...M.rsvps].sort((e, t) => D[e.status] - D[t.status]), Q = O.filter((e) => Z[e.status] > 0).map((e) => `${l(Z[e.status])} ${e.label}`).join(" · "), ue = async (e) => {
|
|
56
86
|
try {
|
|
57
|
-
await
|
|
58
|
-
eventId:
|
|
87
|
+
await I.mutateAsync({
|
|
88
|
+
eventId: M.id,
|
|
59
89
|
status: e
|
|
60
|
-
}),
|
|
90
|
+
}), o.success("RSVP updated", `${c(e)} · ${M.title}`);
|
|
61
91
|
} catch (e) {
|
|
62
|
-
|
|
92
|
+
o.error("Could not RSVP", a(e));
|
|
63
93
|
}
|
|
64
|
-
},
|
|
94
|
+
}, $ = async (e, t) => {
|
|
65
95
|
try {
|
|
66
|
-
await
|
|
67
|
-
id:
|
|
96
|
+
await L.mutateAsync({
|
|
97
|
+
id: M.id,
|
|
68
98
|
status: e
|
|
69
|
-
}),
|
|
99
|
+
}), o.success(t, M.title);
|
|
70
100
|
} catch (e) {
|
|
71
|
-
|
|
101
|
+
o.error("Could not update the event", a(e));
|
|
72
102
|
}
|
|
73
|
-
},
|
|
74
|
-
return /* @__PURE__ */
|
|
75
|
-
title:
|
|
76
|
-
actions:
|
|
77
|
-
children: /* @__PURE__ */
|
|
103
|
+
}, de = M.endsAt ? `${s(M.startsAt)} – ${s(M.endsAt)}` : s(M.startsAt);
|
|
104
|
+
return /* @__PURE__ */ w(n, {
|
|
105
|
+
title: M.title,
|
|
106
|
+
actions: R,
|
|
107
|
+
children: /* @__PURE__ */ T("div", {
|
|
78
108
|
className: "mx-auto flex max-w-3xl flex-col gap-6",
|
|
79
109
|
children: [
|
|
80
|
-
/* @__PURE__ */
|
|
110
|
+
/* @__PURE__ */ T(ae, {
|
|
81
111
|
treatment: "plain",
|
|
82
|
-
className: "flex flex-col gap-5 p-5 sm:p-6",
|
|
112
|
+
className: t("flex flex-col gap-5 p-5 sm:p-6", B && "ring-1 ring-[var(--color-accent-soft)]"),
|
|
83
113
|
children: [
|
|
84
|
-
/* @__PURE__ */
|
|
114
|
+
B && /* @__PURE__ */ w("span", {
|
|
115
|
+
"aria-hidden": "true",
|
|
116
|
+
className: "pointer-events-none absolute inset-0 rounded-card ring-2 ring-accent/60 motion-safe:animate-pulse"
|
|
117
|
+
}),
|
|
118
|
+
/* @__PURE__ */ T("div", {
|
|
85
119
|
className: "flex flex-wrap items-center gap-2",
|
|
86
|
-
children: [/* @__PURE__ */
|
|
120
|
+
children: [/* @__PURE__ */ w(p, { status: M.status }), /* @__PURE__ */ w(p, { status: M.mode })]
|
|
121
|
+
}),
|
|
122
|
+
W && M.joinUrl && /* @__PURE__ */ w(E, {
|
|
123
|
+
asChild: !0,
|
|
124
|
+
size: "lg",
|
|
125
|
+
className: "w-full justify-center sm:w-auto sm:self-start",
|
|
126
|
+
children: /* @__PURE__ */ T("a", {
|
|
127
|
+
href: M.joinUrl,
|
|
128
|
+
target: "_blank",
|
|
129
|
+
rel: "noreferrer noopener",
|
|
130
|
+
children: [/* @__PURE__ */ w(S, { className: "h-4 w-4" }), " Join the live event"]
|
|
131
|
+
})
|
|
87
132
|
}),
|
|
88
|
-
|
|
133
|
+
M.description && /* @__PURE__ */ w("p", {
|
|
89
134
|
className: "whitespace-pre-wrap text-sm text-text-secondary",
|
|
90
|
-
children:
|
|
135
|
+
children: M.description
|
|
91
136
|
}),
|
|
92
|
-
/* @__PURE__ */
|
|
137
|
+
/* @__PURE__ */ T("dl", {
|
|
93
138
|
className: "flex flex-col gap-3 text-sm",
|
|
94
139
|
children: [
|
|
95
|
-
/* @__PURE__ */
|
|
140
|
+
/* @__PURE__ */ T("div", {
|
|
96
141
|
className: "flex items-start gap-2.5",
|
|
97
|
-
children: [/* @__PURE__ */
|
|
142
|
+
children: [/* @__PURE__ */ w(re, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary" }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
|
|
98
143
|
className: "text-text-tertiary",
|
|
99
144
|
children: "When"
|
|
100
|
-
}), /* @__PURE__ */
|
|
145
|
+
}), /* @__PURE__ */ w("dd", {
|
|
101
146
|
className: "mt-0.5 text-text-primary",
|
|
102
|
-
children:
|
|
147
|
+
children: de
|
|
103
148
|
})] })]
|
|
104
149
|
}),
|
|
105
|
-
|
|
150
|
+
U && M.location && /* @__PURE__ */ T("div", {
|
|
106
151
|
className: "flex items-start gap-2.5",
|
|
107
|
-
children: [/* @__PURE__ */
|
|
152
|
+
children: [/* @__PURE__ */ w(v, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary" }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
|
|
108
153
|
className: "text-text-tertiary",
|
|
109
154
|
children: "Where"
|
|
110
|
-
}), /* @__PURE__ */
|
|
155
|
+
}), /* @__PURE__ */ w("dd", {
|
|
111
156
|
className: "mt-0.5 text-text-primary",
|
|
112
|
-
children:
|
|
157
|
+
children: M.location
|
|
113
158
|
})] })]
|
|
114
159
|
}),
|
|
115
|
-
|
|
160
|
+
H && /* @__PURE__ */ T("div", {
|
|
116
161
|
className: "flex items-start gap-2.5",
|
|
117
|
-
children: [/* @__PURE__ */
|
|
162
|
+
children: [/* @__PURE__ */ w(S, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary" }), /* @__PURE__ */ T("div", {
|
|
118
163
|
className: "min-w-0",
|
|
119
|
-
children: [/* @__PURE__ */
|
|
164
|
+
children: [/* @__PURE__ */ w("dt", {
|
|
120
165
|
className: "text-text-tertiary",
|
|
121
166
|
children: "Online"
|
|
122
|
-
}), /* @__PURE__ */
|
|
167
|
+
}), /* @__PURE__ */ w("dd", {
|
|
123
168
|
className: "mt-0.5 text-text-primary",
|
|
124
|
-
children:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
className: "inline-flex items-center gap-1 font-medium text-accent hover:underline",
|
|
129
|
-
children: ["Join the live event ", /* @__PURE__ */ E(v, { className: "h-3.5 w-3.5" })]
|
|
130
|
-
}) : /* @__PURE__ */ E("span", {
|
|
169
|
+
children: W ? /* @__PURE__ */ w("span", {
|
|
170
|
+
className: "font-medium text-accent",
|
|
171
|
+
children: "The join link is live — use the button above."
|
|
172
|
+
}) : /* @__PURE__ */ w("span", {
|
|
131
173
|
className: "text-text-secondary",
|
|
132
|
-
children:
|
|
174
|
+
children: B ? "A join link has not been provided." : "The join link becomes available when the event goes live."
|
|
133
175
|
})
|
|
134
176
|
})]
|
|
135
177
|
})]
|
|
136
178
|
}),
|
|
137
|
-
/* @__PURE__ */
|
|
179
|
+
/* @__PURE__ */ T("div", {
|
|
138
180
|
className: "flex items-start gap-2.5",
|
|
139
|
-
children: [/* @__PURE__ */
|
|
140
|
-
className: "
|
|
141
|
-
children:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
181
|
+
children: [/* @__PURE__ */ w(x, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary" }), /* @__PURE__ */ T("div", {
|
|
182
|
+
className: "min-w-0 flex-1",
|
|
183
|
+
children: [
|
|
184
|
+
/* @__PURE__ */ w("dt", {
|
|
185
|
+
className: "text-text-tertiary",
|
|
186
|
+
children: "Attending"
|
|
187
|
+
}),
|
|
188
|
+
/* @__PURE__ */ T("dd", {
|
|
189
|
+
className: "mt-0.5 flex flex-wrap items-baseline gap-x-2 text-text-primary",
|
|
190
|
+
children: [/* @__PURE__ */ T("span", { children: [l(M.rsvpCount), K ? ` / ${l(K)}` : ""] }), X && /* @__PURE__ */ w("span", {
|
|
191
|
+
className: t("text-xs font-semibold", ce),
|
|
192
|
+
children: X
|
|
193
|
+
})]
|
|
194
|
+
}),
|
|
195
|
+
q != null && /* @__PURE__ */ w(m, {
|
|
196
|
+
value: q,
|
|
197
|
+
barClassName: se,
|
|
198
|
+
className: "mt-2 max-w-xs"
|
|
199
|
+
})
|
|
200
|
+
]
|
|
201
|
+
})]
|
|
146
202
|
})
|
|
147
203
|
]
|
|
148
204
|
}),
|
|
149
|
-
|
|
205
|
+
M.tags.length > 0 && /* @__PURE__ */ T("div", {
|
|
150
206
|
className: "flex flex-wrap items-center gap-1.5",
|
|
151
|
-
children: [/* @__PURE__ */
|
|
207
|
+
children: [/* @__PURE__ */ w(b, {
|
|
152
208
|
className: "h-3.5 w-3.5 text-text-tertiary",
|
|
153
209
|
"aria-hidden": "true"
|
|
154
|
-
}),
|
|
210
|
+
}), M.tags.map((e) => /* @__PURE__ */ T("span", {
|
|
155
211
|
className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
|
|
156
212
|
children: ["#", e]
|
|
157
213
|
}, e))]
|
|
158
214
|
}),
|
|
159
|
-
/* @__PURE__ */
|
|
215
|
+
/* @__PURE__ */ T("div", {
|
|
160
216
|
className: "border-t border-border-seam pt-4",
|
|
161
|
-
children: [/* @__PURE__ */
|
|
217
|
+
children: [/* @__PURE__ */ w("p", {
|
|
162
218
|
className: "mb-2 text-xs font-semibold uppercase tracking-wide text-text-tertiary",
|
|
163
219
|
children: "Hosted by"
|
|
164
|
-
}), /* @__PURE__ */
|
|
165
|
-
memberId:
|
|
220
|
+
}), /* @__PURE__ */ w(i, {
|
|
221
|
+
memberId: M.hostId,
|
|
166
222
|
variant: "row",
|
|
167
223
|
size: "md",
|
|
168
224
|
showPresence: !0
|
|
@@ -170,98 +226,109 @@ function j() {
|
|
|
170
226
|
})
|
|
171
227
|
]
|
|
172
228
|
}),
|
|
173
|
-
|
|
229
|
+
V && /* @__PURE__ */ T("section", {
|
|
174
230
|
className: "rounded-2xl border border-border-seam bg-bg-surface p-5",
|
|
175
231
|
children: [
|
|
176
|
-
/* @__PURE__ */
|
|
232
|
+
/* @__PURE__ */ w("h2", {
|
|
177
233
|
className: "text-base font-semibold text-text-primary",
|
|
178
234
|
children: "Your RSVP"
|
|
179
235
|
}),
|
|
180
|
-
/* @__PURE__ */
|
|
236
|
+
/* @__PURE__ */ w("p", {
|
|
181
237
|
className: "mt-0.5 text-sm text-text-secondary",
|
|
182
238
|
children: "Let the host know whether you'll attend."
|
|
183
239
|
}),
|
|
184
|
-
/* @__PURE__ */
|
|
185
|
-
className: "mt-4 flex flex-
|
|
186
|
-
children:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
240
|
+
/* @__PURE__ */ w("div", {
|
|
241
|
+
className: "mt-4 flex flex-col gap-2 sm:flex-row sm:flex-wrap",
|
|
242
|
+
children: oe.map((e) => {
|
|
243
|
+
let n = G?.status === e.status;
|
|
244
|
+
return /* @__PURE__ */ T(E, {
|
|
245
|
+
variant: n ? "default" : "outline",
|
|
246
|
+
onClick: () => ue(e.status),
|
|
247
|
+
disabled: I.isPending,
|
|
248
|
+
"aria-pressed": n,
|
|
249
|
+
className: t("w-full justify-center sm:w-auto", n && "font-semibold shadow-elevation-1"),
|
|
250
|
+
children: [n && /* @__PURE__ */ w(g, { className: "h-4 w-4" }), e.label]
|
|
251
|
+
}, e.status);
|
|
252
|
+
})
|
|
193
253
|
})
|
|
194
254
|
]
|
|
195
255
|
}),
|
|
196
|
-
|
|
256
|
+
z && (M.status === "SCHEDULED" || M.status === "LIVE") && /* @__PURE__ */ T("section", {
|
|
197
257
|
className: "rounded-2xl border border-border-seam bg-bg-surface p-5",
|
|
198
258
|
children: [
|
|
199
|
-
/* @__PURE__ */
|
|
259
|
+
/* @__PURE__ */ w("h2", {
|
|
200
260
|
className: "text-base font-semibold text-text-primary",
|
|
201
261
|
children: "Host controls"
|
|
202
262
|
}),
|
|
203
|
-
/* @__PURE__ */
|
|
263
|
+
/* @__PURE__ */ w("p", {
|
|
204
264
|
className: "mt-0.5 text-sm text-text-secondary",
|
|
205
265
|
children: "Move this event through its lifecycle."
|
|
206
266
|
}),
|
|
207
|
-
/* @__PURE__ */
|
|
267
|
+
/* @__PURE__ */ T("div", {
|
|
208
268
|
className: "mt-4 flex flex-wrap gap-2",
|
|
209
|
-
children: [
|
|
269
|
+
children: [M.status === "SCHEDULED" && /* @__PURE__ */ T(ie, { children: [/* @__PURE__ */ T(E, {
|
|
210
270
|
size: "sm",
|
|
211
|
-
onClick: () =>
|
|
212
|
-
disabled:
|
|
213
|
-
children: [/* @__PURE__ */
|
|
214
|
-
}), /* @__PURE__ */
|
|
271
|
+
onClick: () => $("LIVE", "Event is now live"),
|
|
272
|
+
disabled: L.isPending,
|
|
273
|
+
children: [/* @__PURE__ */ w(y, { className: "mr-1.5 h-4 w-4" }), " Go live"]
|
|
274
|
+
}), /* @__PURE__ */ T(E, {
|
|
215
275
|
size: "sm",
|
|
216
276
|
variant: "destructive",
|
|
217
|
-
onClick: () =>
|
|
218
|
-
disabled:
|
|
219
|
-
children: [/* @__PURE__ */
|
|
220
|
-
})] }),
|
|
277
|
+
onClick: () => $("CANCELLED", "Event cancelled"),
|
|
278
|
+
disabled: L.isPending,
|
|
279
|
+
children: [/* @__PURE__ */ w(ne, { className: "mr-1.5 h-4 w-4" }), " Cancel"]
|
|
280
|
+
})] }), M.status === "LIVE" && /* @__PURE__ */ T(E, {
|
|
221
281
|
size: "sm",
|
|
222
|
-
onClick: () =>
|
|
223
|
-
disabled:
|
|
224
|
-
children: [/* @__PURE__ */
|
|
282
|
+
onClick: () => $("COMPLETED", "Event marked complete"),
|
|
283
|
+
disabled: L.isPending,
|
|
284
|
+
children: [/* @__PURE__ */ w(_, { className: "mr-1.5 h-4 w-4" }), " Mark complete"]
|
|
225
285
|
})]
|
|
226
286
|
})
|
|
227
287
|
]
|
|
228
288
|
}),
|
|
229
|
-
/* @__PURE__ */
|
|
289
|
+
/* @__PURE__ */ T("section", {
|
|
230
290
|
className: "rounded-2xl border border-border-seam bg-bg-surface p-5",
|
|
231
|
-
children: [/* @__PURE__ */
|
|
291
|
+
children: [/* @__PURE__ */ T("div", {
|
|
232
292
|
className: "mb-3 flex items-center justify-between gap-3",
|
|
233
|
-
children: [/* @__PURE__ */
|
|
234
|
-
className: "
|
|
235
|
-
children: "
|
|
236
|
-
|
|
237
|
-
|
|
293
|
+
children: [/* @__PURE__ */ T("div", {
|
|
294
|
+
className: "min-w-0",
|
|
295
|
+
children: [/* @__PURE__ */ w("h2", {
|
|
296
|
+
className: "text-base font-semibold text-text-primary",
|
|
297
|
+
children: "Attendees"
|
|
298
|
+
}), Q && /* @__PURE__ */ w("p", {
|
|
299
|
+
className: "mt-0.5 truncate text-xs text-text-tertiary",
|
|
300
|
+
children: Q
|
|
301
|
+
})]
|
|
302
|
+
}), /* @__PURE__ */ T("span", {
|
|
303
|
+
className: "inline-flex shrink-0 items-center gap-1 text-xs text-text-tertiary",
|
|
238
304
|
children: [
|
|
239
|
-
/* @__PURE__ */
|
|
305
|
+
/* @__PURE__ */ w(x, { className: "h-3.5 w-3.5" }),
|
|
240
306
|
" ",
|
|
241
|
-
|
|
307
|
+
l(M.rsvps.length)
|
|
242
308
|
]
|
|
243
309
|
})]
|
|
244
|
-
}),
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
310
|
+
}), M.rsvps.length === 0 ? /* @__PURE__ */ w(u, {
|
|
311
|
+
illustration: "empty-people",
|
|
312
|
+
title: "No RSVPs yet",
|
|
313
|
+
description: "Be the first to let the host know you're coming."
|
|
314
|
+
}) : /* @__PURE__ */ w("ul", {
|
|
248
315
|
className: "flex flex-col gap-2",
|
|
249
|
-
children:
|
|
250
|
-
className: "flex flex-wrap items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-sunken px-4 py-2.5",
|
|
251
|
-
children: [/* @__PURE__ */
|
|
316
|
+
children: le.map((e) => /* @__PURE__ */ T("li", {
|
|
317
|
+
className: "flex flex-wrap items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-sunken px-4 py-2.5 transition-colors hover:border-[var(--color-accent-soft)]",
|
|
318
|
+
children: [/* @__PURE__ */ w(i, {
|
|
252
319
|
memberId: e.memberId,
|
|
253
320
|
variant: "row",
|
|
254
321
|
size: "sm"
|
|
255
|
-
}), /* @__PURE__ */
|
|
322
|
+
}), /* @__PURE__ */ T("div", {
|
|
256
323
|
className: "flex min-w-0 items-center gap-2",
|
|
257
|
-
children: [e.note && /* @__PURE__ */
|
|
324
|
+
children: [e.note && /* @__PURE__ */ T("span", {
|
|
258
325
|
className: "max-w-[16rem] truncate text-xs text-text-tertiary",
|
|
259
326
|
children: [
|
|
260
327
|
"“",
|
|
261
328
|
e.note,
|
|
262
329
|
"”"
|
|
263
330
|
]
|
|
264
|
-
}), /* @__PURE__ */
|
|
331
|
+
}), /* @__PURE__ */ w(p, { status: e.status })]
|
|
265
332
|
})]
|
|
266
333
|
}, e.id))
|
|
267
334
|
})]
|
|
@@ -271,6 +338,6 @@ function j() {
|
|
|
271
338
|
});
|
|
272
339
|
}
|
|
273
340
|
//#endregion
|
|
274
|
-
export {
|
|
341
|
+
export { k as EventDetailPage };
|
|
275
342
|
|
|
276
343
|
//# sourceMappingURL=EventDetailPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventDetailPage.js","names":[],"sources":["../../../../src/comradecircle/pages/events/EventDetailPage.tsx"],"sourcesContent":["/**\n * EventDetailPage — a single community event.\n * @module comradecircle/pages/events\n *\n * Reads `comEvent` (with its RSVPs). Members RSVP (GOING / INTERESTED /\n * WAITLISTED / NOT_GOING) while the event is SCHEDULED or LIVE; the host drives\n * the lifecycle (SCHEDULED → LIVE → COMPLETED, or CANCELLED). Person references\n * always resolve through {@link MemberIdentity} — never a raw actor id.\n */\n\nimport {\n ArrowLeft,\n CalendarDays,\n MapPin,\n Video,\n Users,\n ExternalLink,\n Radio,\n CheckCircle2,\n Ban,\n Tag,\n} from 'lucide-react';\nimport { GlassCard, Button } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { MemberIdentity } from '../../components/MemberIdentity';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useComEvent, useComRsvpEvent, useComTransitionEvent } from '../../hooks';\nimport { useComradeCircle } from '../../context';\nimport { formatDateTime, formatNumber, formatEnumLabel } from '../../utils';\nimport { notify, describeError } from '../../lib/toast';\nimport { useParams } from 'react-router-dom';\nimport type { ComEventStatus, ComRsvpStatus } from '../../types';\n\nconst RSVP_OPTIONS: { status: ComRsvpStatus; label: string }[] = [\n { status: 'GOING', label: 'Going' },\n { status: 'INTERESTED', label: 'Interested' },\n { status: 'WAITLISTED', label: 'Waitlist' },\n { status: 'NOT_GOING', label: \"Can't go\" },\n];\n\nexport function EventDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { currentUser, navigateTo } = useComradeCircle();\n const { data: event, isLoading, isError, refetch } = useComEvent(id);\n const rsvp = useComRsvpEvent();\n const transition = useComTransitionEvent();\n\n const backButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('events')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Event\" actions={backButton}>\n <LoadingView label=\"Loading event…\" />\n </PageLayout>\n );\n }\n\n if (isError || !event) {\n return (\n <PageLayout title=\"Event\" actions={backButton}>\n <ErrorView\n title=\"Event not found\"\n message=\"This event may have been cancelled, or you may not have access to it.\"\n onRetry={() => refetch()}\n />\n </PageLayout>\n );\n }\n\n const isHost = Boolean(currentUser?.id && currentUser.id === event.hostId);\n const canRsvp = event.status === 'SCHEDULED' || event.status === 'LIVE';\n const isOnlineish = event.mode === 'ONLINE' || event.mode === 'HYBRID';\n const isInPersonish = event.mode === 'IN_PERSON' || event.mode === 'HYBRID';\n const showJoin = event.status === 'LIVE' && isOnlineish && Boolean(event.joinUrl);\n const myRsvp = currentUser?.id\n ? event.rsvps.find((r) => r.memberId === currentUser.id)\n : undefined;\n\n const doRsvp = async (status: ComRsvpStatus) => {\n try {\n await rsvp.mutateAsync({ eventId: event.id, status });\n notify.success('RSVP updated', `${formatEnumLabel(status)} · ${event.title}`);\n } catch (err) {\n notify.error('Could not RSVP', describeError(err));\n }\n };\n\n const doTransition = async (status: ComEventStatus, successMessage: string) => {\n try {\n await transition.mutateAsync({ id: event.id, status });\n notify.success(successMessage, event.title);\n } catch (err) {\n notify.error('Could not update the event', describeError(err));\n }\n };\n\n const scheduleText = event.endsAt\n ? `${formatDateTime(event.startsAt)} – ${formatDateTime(event.endsAt)}`\n : formatDateTime(event.startsAt);\n\n return (\n <PageLayout title={event.title} actions={backButton}>\n <div className=\"mx-auto flex max-w-3xl flex-col gap-6\">\n {/* Overview */}\n <GlassCard treatment=\"plain\" className=\"flex flex-col gap-5 p-5 sm:p-6\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge status={event.status} />\n <StatusBadge status={event.mode} />\n </div>\n\n {event.description && (\n <p className=\"whitespace-pre-wrap text-sm text-text-secondary\">{event.description}</p>\n )}\n\n <dl className=\"flex flex-col gap-3 text-sm\">\n {/* Schedule */}\n <div className=\"flex items-start gap-2.5\">\n <CalendarDays className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">When</dt>\n <dd className=\"mt-0.5 text-text-primary\">{scheduleText}</dd>\n </div>\n </div>\n\n {/* Location (in-person / hybrid) */}\n {isInPersonish && event.location && (\n <div className=\"flex items-start gap-2.5\">\n <MapPin className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">Where</dt>\n <dd className=\"mt-0.5 text-text-primary\">{event.location}</dd>\n </div>\n </div>\n )}\n\n {/* Online join link (online / hybrid) */}\n {isOnlineish && (\n <div className=\"flex items-start gap-2.5\">\n <Video className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div className=\"min-w-0\">\n <dt className=\"text-text-tertiary\">Online</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {showJoin && event.joinUrl ? (\n <a\n href={event.joinUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"inline-flex items-center gap-1 font-medium text-accent hover:underline\"\n >\n Join the live event <ExternalLink className=\"h-3.5 w-3.5\" />\n </a>\n ) : (\n <span className=\"text-text-secondary\">\n {event.status === 'LIVE'\n ? 'A join link has not been provided.'\n : 'The join link becomes available when the event goes live.'}\n </span>\n )}\n </dd>\n </div>\n </div>\n )}\n\n {/* Attendance */}\n <div className=\"flex items-start gap-2.5\">\n <Users className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">Attending</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {formatNumber(event.rsvpCount)}\n {event.capacity ? ` / ${formatNumber(event.capacity)}` : ''}\n </dd>\n </div>\n </div>\n </dl>\n\n {/* Tags */}\n {event.tags.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <Tag className=\"h-3.5 w-3.5 text-text-tertiary\" aria-hidden=\"true\" />\n {event.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n #{tag}\n </span>\n ))}\n </div>\n )}\n\n {/* Host */}\n <div className=\"border-t border-border-seam pt-4\">\n <p className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-tertiary\">\n Hosted by\n </p>\n <MemberIdentity memberId={event.hostId} variant=\"row\" size=\"md\" showPresence />\n </div>\n </GlassCard>\n\n {/* RSVP controls */}\n {canRsvp && (\n <section className=\"rounded-2xl border border-border-seam bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary\">Your RSVP</h2>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n Let the host know whether you'll attend.\n </p>\n <div className=\"mt-4 flex flex-wrap gap-2\">\n {RSVP_OPTIONS.map((opt) => {\n const active = myRsvp?.status === opt.status;\n return (\n <Button\n key={opt.status}\n size=\"sm\"\n variant={active ? 'default' : 'outline'}\n onClick={() => doRsvp(opt.status)}\n disabled={rsvp.isPending}\n >\n {opt.label}\n </Button>\n );\n })}\n </div>\n </section>\n )}\n\n {/* Host lifecycle controls */}\n {isHost && (event.status === 'SCHEDULED' || event.status === 'LIVE') && (\n <section className=\"rounded-2xl border border-border-seam bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary\">Host controls</h2>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n Move this event through its lifecycle.\n </p>\n <div className=\"mt-4 flex flex-wrap gap-2\">\n {event.status === 'SCHEDULED' && (\n <>\n <Button\n size=\"sm\"\n onClick={() => doTransition('LIVE', 'Event is now live')}\n disabled={transition.isPending}\n >\n <Radio className=\"mr-1.5 h-4 w-4\" /> Go live\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => doTransition('CANCELLED', 'Event cancelled')}\n disabled={transition.isPending}\n >\n <Ban className=\"mr-1.5 h-4 w-4\" /> Cancel\n </Button>\n </>\n )}\n {event.status === 'LIVE' && (\n <Button\n size=\"sm\"\n onClick={() => doTransition('COMPLETED', 'Event marked complete')}\n disabled={transition.isPending}\n >\n <CheckCircle2 className=\"mr-1.5 h-4 w-4\" /> Mark complete\n </Button>\n )}\n </div>\n </section>\n )}\n\n {/* Attendees */}\n <section className=\"rounded-2xl border border-border-seam bg-bg-surface p-5\">\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <h2 className=\"text-base font-semibold text-text-primary\">Attendees</h2>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-tertiary\">\n <Users className=\"h-3.5 w-3.5\" /> {formatNumber(event.rsvps.length)}\n </span>\n </div>\n {event.rsvps.length === 0 ? (\n <p className=\"py-4 text-center text-sm text-text-tertiary\">No RSVPs yet.</p>\n ) : (\n <ul className=\"flex flex-col gap-2\">\n {event.rsvps.map((r) => (\n <li\n key={r.id}\n className=\"flex flex-wrap items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-sunken px-4 py-2.5\"\n >\n <MemberIdentity memberId={r.memberId} variant=\"row\" size=\"sm\" />\n <div className=\"flex min-w-0 items-center gap-2\">\n {r.note && (\n <span className=\"max-w-[16rem] truncate text-xs text-text-tertiary\">\n “{r.note}”\n </span>\n )}\n <StatusBadge status={r.status} />\n </div>\n </li>\n ))}\n </ul>\n )}\n </section>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EventDetailPage.js","names":[],"sources":["../../../../src/comradecircle/pages/events/EventDetailPage.tsx"],"sourcesContent":["/**\n * EventDetailPage — a single community event.\n * @module comradecircle/pages/events\n *\n * Reads `comEvent` (with its RSVPs). Members RSVP (GOING / INTERESTED /\n * WAITLISTED / NOT_GOING) while the event is SCHEDULED or LIVE; the host drives\n * the lifecycle (SCHEDULED → LIVE → COMPLETED, or CANCELLED). Person references\n * always resolve through {@link MemberIdentity} — never a raw actor id.\n */\n\nimport {\n ArrowLeft,\n CalendarDays,\n MapPin,\n Video,\n Users,\n Radio,\n CheckCircle2,\n Check,\n Ban,\n Tag,\n} from 'lucide-react';\nimport { GlassCard, Button } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { MemberIdentity } from '../../components/MemberIdentity';\nimport { MiniBar } from '../../components/MiniBar';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useComEvent, useComRsvpEvent, useComTransitionEvent } from '../../hooks';\nimport { useComradeCircle } from '../../context';\nimport { formatDateTime, formatNumber, formatEnumLabel } from '../../utils';\nimport { cn } from '../../utils/cn';\nimport { notify, describeError } from '../../lib/toast';\nimport { useParams } from 'react-router-dom';\nimport type { ComEventStatus, ComRsvpStatus } from '../../types';\n\nconst RSVP_OPTIONS: { status: ComRsvpStatus; label: string }[] = [\n { status: 'GOING', label: 'Going' },\n { status: 'INTERESTED', label: 'Interested' },\n { status: 'WAITLISTED', label: 'Waitlist' },\n { status: 'NOT_GOING', label: \"Can't go\" },\n];\n\n/** Attendee display order: confirmed first, declines last. */\nconst RSVP_ORDER: Record<ComRsvpStatus, number> = {\n GOING: 0,\n INTERESTED: 1,\n WAITLISTED: 2,\n NOT_GOING: 3,\n};\n\n/** Facet labels for the one-line attendee summary. */\nconst RSVP_FACETS: { status: ComRsvpStatus; label: string }[] = [\n { status: 'GOING', label: 'going' },\n { status: 'INTERESTED', label: 'interested' },\n { status: 'WAITLISTED', label: 'waitlisted' },\n { status: 'NOT_GOING', label: \"can't go\" },\n];\n\nexport function EventDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { currentUser, navigateTo } = useComradeCircle();\n const { data: event, isLoading, isError, refetch } = useComEvent(id);\n const rsvp = useComRsvpEvent();\n const transition = useComTransitionEvent();\n\n const backButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('events')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Event\" actions={backButton}>\n <LoadingView label=\"Loading event…\" />\n </PageLayout>\n );\n }\n\n if (isError || !event) {\n return (\n <PageLayout title=\"Event\" actions={backButton}>\n <ErrorView\n title=\"Event not found\"\n message=\"This event may have been cancelled, or you may not have access to it.\"\n onRetry={() => refetch()}\n />\n </PageLayout>\n );\n }\n\n const isHost = Boolean(currentUser?.id && currentUser.id === event.hostId);\n const isLive = event.status === 'LIVE';\n const canRsvp = event.status === 'SCHEDULED' || event.status === 'LIVE';\n const isOnlineish = event.mode === 'ONLINE' || event.mode === 'HYBRID';\n const isInPersonish = event.mode === 'IN_PERSON' || event.mode === 'HYBRID';\n const showJoin = isLive && isOnlineish && Boolean(event.joinUrl);\n const myRsvp = currentUser?.id\n ? event.rsvps.find((r) => r.memberId === currentUser.id)\n : undefined;\n\n // Attendance / capacity — derived from real rsvpCount + capacity only.\n const capacity = event.capacity ?? null;\n const fillPct =\n capacity && capacity > 0 ? Math.min(100, (event.rsvpCount / capacity) * 100) : null;\n const nearFull = fillPct != null && fillPct >= 80;\n const isFull = fillPct != null && fillPct >= 100;\n const capacityLabel = fillPct == null ? '' : isFull ? 'Full' : `${Math.round(fillPct)}% full`;\n const capacityBar = isFull\n ? 'bg-status-error-text'\n : nearFull\n ? 'bg-status-warning-text'\n : 'bg-accent';\n const capacityTone = isFull\n ? 'text-status-error-text'\n : nearFull\n ? 'text-status-warning-text'\n : 'text-text-tertiary';\n\n // Attendees — sort GOING → INTERESTED → WAITLISTED → NOT_GOING; facet summary.\n const rsvpCounts = event.rsvps.reduce<Record<ComRsvpStatus, number>>(\n (acc, r) => {\n acc[r.status] += 1;\n return acc;\n },\n { GOING: 0, INTERESTED: 0, WAITLISTED: 0, NOT_GOING: 0 }\n );\n const sortedRsvps = [...event.rsvps].sort((a, b) => RSVP_ORDER[a.status] - RSVP_ORDER[b.status]);\n const facetSummary = RSVP_FACETS.filter((f) => rsvpCounts[f.status] > 0)\n .map((f) => `${formatNumber(rsvpCounts[f.status])} ${f.label}`)\n .join(' · ');\n\n const doRsvp = async (status: ComRsvpStatus) => {\n try {\n await rsvp.mutateAsync({ eventId: event.id, status });\n notify.success('RSVP updated', `${formatEnumLabel(status)} · ${event.title}`);\n } catch (err) {\n notify.error('Could not RSVP', describeError(err));\n }\n };\n\n const doTransition = async (status: ComEventStatus, successMessage: string) => {\n try {\n await transition.mutateAsync({ id: event.id, status });\n notify.success(successMessage, event.title);\n } catch (err) {\n notify.error('Could not update the event', describeError(err));\n }\n };\n\n const scheduleText = event.endsAt\n ? `${formatDateTime(event.startsAt)} – ${formatDateTime(event.endsAt)}`\n : formatDateTime(event.startsAt);\n\n return (\n <PageLayout title={event.title} actions={backButton}>\n <div className=\"mx-auto flex max-w-3xl flex-col gap-6\">\n {/* Overview */}\n <GlassCard\n treatment=\"plain\"\n className={cn(\n 'flex flex-col gap-5 p-5 sm:p-6',\n isLive && 'ring-1 ring-[var(--color-accent-soft)]'\n )}\n >\n {/* Motion-safe live ring — a pulsing accent halo, gated for reduced motion. */}\n {isLive && (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-0 rounded-card ring-2 ring-accent/60 motion-safe:animate-pulse\"\n />\n )}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge status={event.status} />\n <StatusBadge status={event.mode} />\n </div>\n\n {/* Prominent live-join CTA, promoted near the header. */}\n {showJoin && event.joinUrl && (\n <Button asChild size=\"lg\" className=\"w-full justify-center sm:w-auto sm:self-start\">\n <a href={event.joinUrl} target=\"_blank\" rel=\"noreferrer noopener\">\n <Video className=\"h-4 w-4\" /> Join the live event\n </a>\n </Button>\n )}\n\n {event.description && (\n <p className=\"whitespace-pre-wrap text-sm text-text-secondary\">{event.description}</p>\n )}\n\n <dl className=\"flex flex-col gap-3 text-sm\">\n {/* Schedule */}\n <div className=\"flex items-start gap-2.5\">\n <CalendarDays className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">When</dt>\n <dd className=\"mt-0.5 text-text-primary\">{scheduleText}</dd>\n </div>\n </div>\n\n {/* Location (in-person / hybrid) */}\n {isInPersonish && event.location && (\n <div className=\"flex items-start gap-2.5\">\n <MapPin className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">Where</dt>\n <dd className=\"mt-0.5 text-text-primary\">{event.location}</dd>\n </div>\n </div>\n )}\n\n {/* Online join link (online / hybrid) */}\n {isOnlineish && (\n <div className=\"flex items-start gap-2.5\">\n <Video className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div className=\"min-w-0\">\n <dt className=\"text-text-tertiary\">Online</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {showJoin ? (\n <span className=\"font-medium text-accent\">\n The join link is live — use the button above.\n </span>\n ) : (\n <span className=\"text-text-secondary\">\n {isLive\n ? 'A join link has not been provided.'\n : 'The join link becomes available when the event goes live.'}\n </span>\n )}\n </dd>\n </div>\n </div>\n )}\n\n {/* Attendance */}\n <div className=\"flex items-start gap-2.5\">\n <Users className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div className=\"min-w-0 flex-1\">\n <dt className=\"text-text-tertiary\">Attending</dt>\n <dd className=\"mt-0.5 flex flex-wrap items-baseline gap-x-2 text-text-primary\">\n <span>\n {formatNumber(event.rsvpCount)}\n {capacity ? ` / ${formatNumber(capacity)}` : ''}\n </span>\n {capacityLabel && (\n <span className={cn('text-xs font-semibold', capacityTone)}>\n {capacityLabel}\n </span>\n )}\n </dd>\n {fillPct != null && (\n <MiniBar value={fillPct} barClassName={capacityBar} className=\"mt-2 max-w-xs\" />\n )}\n </div>\n </div>\n </dl>\n\n {/* Tags */}\n {event.tags.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <Tag className=\"h-3.5 w-3.5 text-text-tertiary\" aria-hidden=\"true\" />\n {event.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n #{tag}\n </span>\n ))}\n </div>\n )}\n\n {/* Host */}\n <div className=\"border-t border-border-seam pt-4\">\n <p className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-tertiary\">\n Hosted by\n </p>\n <MemberIdentity memberId={event.hostId} variant=\"row\" size=\"md\" showPresence />\n </div>\n </GlassCard>\n\n {/* RSVP controls */}\n {canRsvp && (\n <section className=\"rounded-2xl border border-border-seam bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary\">Your RSVP</h2>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n Let the host know whether you'll attend.\n </p>\n <div className=\"mt-4 flex flex-col gap-2 sm:flex-row sm:flex-wrap\">\n {RSVP_OPTIONS.map((opt) => {\n const active = myRsvp?.status === opt.status;\n return (\n <Button\n key={opt.status}\n variant={active ? 'default' : 'outline'}\n onClick={() => doRsvp(opt.status)}\n disabled={rsvp.isPending}\n aria-pressed={active}\n className={cn(\n 'w-full justify-center sm:w-auto',\n active && 'font-semibold shadow-elevation-1'\n )}\n >\n {active && <Check className=\"h-4 w-4\" />}\n {opt.label}\n </Button>\n );\n })}\n </div>\n </section>\n )}\n\n {/* Host lifecycle controls */}\n {isHost && (event.status === 'SCHEDULED' || event.status === 'LIVE') && (\n <section className=\"rounded-2xl border border-border-seam bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary\">Host controls</h2>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n Move this event through its lifecycle.\n </p>\n <div className=\"mt-4 flex flex-wrap gap-2\">\n {event.status === 'SCHEDULED' && (\n <>\n <Button\n size=\"sm\"\n onClick={() => doTransition('LIVE', 'Event is now live')}\n disabled={transition.isPending}\n >\n <Radio className=\"mr-1.5 h-4 w-4\" /> Go live\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => doTransition('CANCELLED', 'Event cancelled')}\n disabled={transition.isPending}\n >\n <Ban className=\"mr-1.5 h-4 w-4\" /> Cancel\n </Button>\n </>\n )}\n {event.status === 'LIVE' && (\n <Button\n size=\"sm\"\n onClick={() => doTransition('COMPLETED', 'Event marked complete')}\n disabled={transition.isPending}\n >\n <CheckCircle2 className=\"mr-1.5 h-4 w-4\" /> Mark complete\n </Button>\n )}\n </div>\n </section>\n )}\n\n {/* Attendees */}\n <section className=\"rounded-2xl border border-border-seam bg-bg-surface p-5\">\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <h2 className=\"text-base font-semibold text-text-primary\">Attendees</h2>\n {facetSummary && (\n <p className=\"mt-0.5 truncate text-xs text-text-tertiary\">{facetSummary}</p>\n )}\n </div>\n <span className=\"inline-flex shrink-0 items-center gap-1 text-xs text-text-tertiary\">\n <Users className=\"h-3.5 w-3.5\" /> {formatNumber(event.rsvps.length)}\n </span>\n </div>\n {event.rsvps.length === 0 ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No RSVPs yet\"\n description=\"Be the first to let the host know you're coming.\"\n />\n ) : (\n <ul className=\"flex flex-col gap-2\">\n {sortedRsvps.map((r) => (\n <li\n key={r.id}\n className=\"flex flex-wrap items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-sunken px-4 py-2.5 transition-colors hover:border-[var(--color-accent-soft)]\"\n >\n <MemberIdentity memberId={r.memberId} variant=\"row\" size=\"sm\" />\n <div className=\"flex min-w-0 items-center gap-2\">\n {r.note && (\n <span className=\"max-w-[16rem] truncate text-xs text-text-tertiary\">\n “{r.note}”\n </span>\n )}\n <StatusBadge status={r.status} />\n </div>\n </li>\n ))}\n </ul>\n )}\n </section>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|