@burdenoff/microfe-comradecircle 2026.704.1 → 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.
Files changed (54) hide show
  1. package/dist/comradecircle/components/Avatar.js +52 -17
  2. package/dist/comradecircle/components/Avatar.js.map +1 -1
  3. package/dist/comradecircle/components/AvatarUploadField.js +91 -0
  4. package/dist/comradecircle/components/AvatarUploadField.js.map +1 -0
  5. package/dist/comradecircle/components/CircleCard.js +55 -52
  6. package/dist/comradecircle/components/CircleCard.js.map +1 -1
  7. package/dist/comradecircle/components/CommentThread.js +80 -64
  8. package/dist/comradecircle/components/CommentThread.js.map +1 -1
  9. package/dist/comradecircle/components/CreateCircleDialog.js +74 -63
  10. package/dist/comradecircle/components/CreateCircleDialog.js.map +1 -1
  11. package/dist/comradecircle/components/EventCard.js +84 -58
  12. package/dist/comradecircle/components/EventCard.js.map +1 -1
  13. package/dist/comradecircle/components/FileImage.js +20 -0
  14. package/dist/comradecircle/components/FileImage.js.map +1 -0
  15. package/dist/comradecircle/components/ImageAttachments.js +97 -0
  16. package/dist/comradecircle/components/ImageAttachments.js.map +1 -0
  17. package/dist/comradecircle/components/MemberIdentity.js +4 -2
  18. package/dist/comradecircle/components/MemberIdentity.js.map +1 -1
  19. package/dist/comradecircle/components/PollCard.js +65 -44
  20. package/dist/comradecircle/components/PollCard.js.map +1 -1
  21. package/dist/comradecircle/components/PostCard.js +8 -15
  22. package/dist/comradecircle/components/PostCard.js.map +1 -1
  23. package/dist/comradecircle/components/PostComposer.js +45 -35
  24. package/dist/comradecircle/components/PostComposer.js.map +1 -1
  25. package/dist/comradecircle/components/ReactionBar.js +1 -1
  26. package/dist/comradecircle/components/ReactionBar.js.map +1 -1
  27. package/dist/comradecircle/components/StateViews.js +1 -16
  28. package/dist/comradecircle/components/StateViews.js.map +1 -1
  29. package/dist/comradecircle/components/StatusBadge.js +1 -1
  30. package/dist/comradecircle/components/StatusBadge.js.map +1 -1
  31. package/dist/comradecircle/hooks/index.js +1 -0
  32. package/dist/comradecircle/hooks/useComradeCircleApi.js +244 -241
  33. package/dist/comradecircle/hooks/useComradeCircleApi.js.map +1 -1
  34. package/dist/comradecircle/hooks/useFiles.js +78 -0
  35. package/dist/comradecircle/hooks/useFiles.js.map +1 -0
  36. package/dist/comradecircle/lib/graphql-cache.js +9 -0
  37. package/dist/comradecircle/lib/graphql-cache.js.map +1 -0
  38. package/dist/comradecircle/pages/FeedPage.js +79 -33
  39. package/dist/comradecircle/pages/FeedPage.js.map +1 -1
  40. package/dist/comradecircle/pages/circles/CircleDetailPage.js +354 -242
  41. package/dist/comradecircle/pages/circles/CircleDetailPage.js.map +1 -1
  42. package/dist/comradecircle/pages/circles/CirclesPage.js +97 -47
  43. package/dist/comradecircle/pages/circles/CirclesPage.js.map +1 -1
  44. package/dist/comradecircle/pages/events/EventDetailPage.js +193 -126
  45. package/dist/comradecircle/pages/events/EventDetailPage.js.map +1 -1
  46. package/dist/comradecircle/pages/events/EventsPage.js +74 -34
  47. package/dist/comradecircle/pages/events/EventsPage.js.map +1 -1
  48. package/dist/comradecircle/pages/members/MemberProfilePage.js +154 -81
  49. package/dist/comradecircle/pages/members/MemberProfilePage.js.map +1 -1
  50. package/dist/comradecircle/pages/members/MembersPage.js +141 -71
  51. package/dist/comradecircle/pages/members/MembersPage.js.map +1 -1
  52. package/dist/comradecircle/pages/profile/MyProfilePage.js +298 -191
  53. package/dist/comradecircle/pages/profile/MyProfilePage.js.map +1 -1
  54. package/package.json +1 -1
@@ -7,146 +7,216 @@ import "../../hooks/index.js";
7
7
  import { Avatar as s } from "../../components/Avatar.js";
8
8
  import { describeError as c, notify as l } from "../../lib/toast.js";
9
9
  import { EmptyState as u } from "../../components/EmptyState.js";
10
- import { ErrorView as d, LoadingView as f } from "../../components/StateViews.js";
11
- import { Pagination as p } from "../../components/Pagination.js";
12
- import { StatusBadge as m } from "../../components/StatusBadge.js";
13
- import { useMemo as h, useState as g } from "react";
14
- import { Check as _, Search as v, UserPlus as y } from "lucide-react";
15
- import { jsx as b, jsxs as x } from "react/jsx-runtime";
16
- import { Button as S, GlassCard as C, Input as w } from "@burdenoff/fe-libs/ui";
10
+ import { ErrorView as d } from "../../components/StateViews.js";
11
+ import { Pagination as f } from "../../components/Pagination.js";
12
+ import { useMemo as p, useState as m } from "react";
13
+ import { Check as h, Loader2 as g, Search as _, UserMinus as v, UserPlus as y } from "lucide-react";
14
+ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
15
+ import { Button as C, GlassCard as w, Input as T, Skeleton as E } from "@burdenoff/fe-libs/ui";
17
16
  //#region src/comradecircle/pages/members/MembersPage.tsx
18
- var T = 12;
19
- function E() {
20
- let { navigateTo: E, currentUser: D } = e(), O = o(), [k, A] = g(""), [j, M] = g(null), { data: N, isLoading: P, isError: F, refetch: I } = i({
17
+ var D = 12, O = [
18
+ "s1",
19
+ "s2",
20
+ "s3",
21
+ "s4",
22
+ "s5",
23
+ "s6",
24
+ "s7",
25
+ "s8"
26
+ ];
27
+ function k() {
28
+ return /* @__PURE__ */ S(w, {
29
+ treatment: "plain",
30
+ className: "flex flex-col p-5",
31
+ children: [
32
+ /* @__PURE__ */ S("div", {
33
+ className: "flex items-start gap-3",
34
+ children: [/* @__PURE__ */ x(E, { className: "h-14 w-14 rounded-full" }), /* @__PURE__ */ S("div", {
35
+ className: "min-w-0 flex-1 space-y-2 py-1",
36
+ children: [
37
+ /* @__PURE__ */ x(E, { className: "h-4 w-2/3" }),
38
+ /* @__PURE__ */ x(E, { className: "h-3 w-1/2" }),
39
+ /* @__PURE__ */ x(E, { className: "h-3 w-4/5" })
40
+ ]
41
+ })]
42
+ }),
43
+ /* @__PURE__ */ S("div", {
44
+ className: "mt-3 flex flex-wrap gap-1.5",
45
+ children: [/* @__PURE__ */ x(E, { className: "h-5 w-16 rounded-full" }), /* @__PURE__ */ x(E, { className: "h-5 w-20 rounded-full" })]
46
+ }),
47
+ /* @__PURE__ */ x("div", {
48
+ className: "mt-4 flex justify-end border-t border-border-seam pt-3",
49
+ children: /* @__PURE__ */ x(E, { className: "h-8 w-28 rounded-button" })
50
+ })
51
+ ]
52
+ });
53
+ }
54
+ function A() {
55
+ let { navigateTo: A, currentUser: j } = e(), M = o(), [N, P] = m(""), [F, I] = m(null), { data: L, isLoading: R, isError: z, refetch: B } = i({
21
56
  discoverable: !0,
22
57
  pagination: {
23
- limit: T,
24
- cursor: O.cursor
58
+ limit: D,
59
+ cursor: M.cursor
25
60
  }
26
- }), { data: L } = r("MEMBER"), R = n(), z = a(), B = h(() => new Set((L ?? []).map((e) => e.targetId)), [L]), V = h(() => N?.items ?? [], [N]), H = h(() => {
27
- let e = k.trim().toLowerCase();
28
- return e ? V.filter((t) => [
61
+ }), { data: V } = r("MEMBER"), H = n(), U = a(), W = p(() => new Set((V ?? []).map((e) => e.targetId)), [V]), G = p(() => L?.items ?? [], [L]), K = p(() => {
62
+ let e = N.trim().toLowerCase();
63
+ return e ? G.filter((t) => [
29
64
  t.displayName,
30
65
  t.headline ?? "",
31
66
  ...t.skills,
32
67
  ...t.interests
33
- ].join(" ").toLowerCase().includes(e)) : V;
34
- }, [V, k]), U = async (e) => {
35
- let t = B.has(e.memberId), n = {
68
+ ].join(" ").toLowerCase().includes(e)) : G;
69
+ }, [G, N]), q = async (e) => {
70
+ let t = W.has(e.memberId), n = {
36
71
  targetId: e.memberId,
37
72
  targetType: "MEMBER"
38
73
  };
39
- M(e.memberId);
74
+ I(e.memberId);
40
75
  try {
41
- t ? (await z.mutateAsync(n), l.success("Unfollowed", e.displayName)) : (await R.mutateAsync(n), l.success("Following", e.displayName));
76
+ t ? (await U.mutateAsync(n), l.success("Unfollowed", e.displayName)) : (await H.mutateAsync(n), l.success("Following", e.displayName));
42
77
  } catch (e) {
43
78
  l.error(t ? "Could not unfollow" : "Could not follow", c(e));
44
79
  } finally {
45
- M(null);
80
+ I(null);
46
81
  }
47
82
  };
48
- return /* @__PURE__ */ b(t, {
83
+ return /* @__PURE__ */ x(t, {
49
84
  title: "Members",
50
85
  description: "Discover and follow people across your circles — search by name, headline, or skills.",
51
- children: P ? /* @__PURE__ */ b(f, { label: "Loading members…" }) : F ? /* @__PURE__ */ b(d, {
86
+ children: R ? /* @__PURE__ */ S("div", {
87
+ className: "flex flex-col gap-5",
88
+ children: [/* @__PURE__ */ x(E, { className: "h-9 w-full max-w-sm rounded-button" }), /* @__PURE__ */ x("div", {
89
+ className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4",
90
+ children: O.map((e) => /* @__PURE__ */ x(k, {}, e))
91
+ })]
92
+ }) : z ? /* @__PURE__ */ x(d, {
52
93
  message: "We couldn't load the member directory.",
53
- onRetry: () => I()
54
- }) : V.length === 0 && O.page === 0 ? /* @__PURE__ */ b(u, {
94
+ onRetry: () => B()
95
+ }) : G.length === 0 && M.page === 0 ? /* @__PURE__ */ x(u, {
55
96
  illustration: "empty-people",
56
97
  title: "No members to discover yet",
57
98
  description: "When members make their profiles discoverable, they'll show up here for you to follow."
58
- }) : /* @__PURE__ */ x("div", {
99
+ }) : /* @__PURE__ */ S("div", {
59
100
  className: "flex flex-col gap-5",
60
101
  children: [
61
- /* @__PURE__ */ x("div", {
102
+ /* @__PURE__ */ S("div", {
62
103
  className: "relative w-full max-w-sm",
63
- children: [/* @__PURE__ */ b(v, {
104
+ children: [/* @__PURE__ */ x(_, {
64
105
  className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary",
65
106
  "aria-hidden": "true"
66
- }), /* @__PURE__ */ b(w, {
67
- value: k,
68
- onChange: (e) => A(e.target.value),
107
+ }), /* @__PURE__ */ x(T, {
108
+ value: N,
109
+ onChange: (e) => P(e.target.value),
69
110
  placeholder: "Search by name, headline, or skills",
70
111
  "aria-label": "Search members",
71
112
  className: "pl-9"
72
113
  })]
73
114
  }),
74
- H.length === 0 ? /* @__PURE__ */ b(u, {
75
- icon: /* @__PURE__ */ b(v, { className: "h-9 w-9" }),
115
+ K.length === 0 ? /* @__PURE__ */ x(u, {
116
+ icon: /* @__PURE__ */ x(_, { className: "h-9 w-9" }),
76
117
  title: "No matches on this page",
77
118
  description: "No members on this page match your search. Try a different term or browse another page."
78
- }) : /* @__PURE__ */ b("div", {
79
- className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3",
80
- children: H.map((e) => {
81
- let t = !!(D?.id && e.memberId === D.id), n = B.has(e.memberId), r = Array.from(new Set([...e.skills, ...e.interests])).slice(0, 4);
82
- return /* @__PURE__ */ x(C, {
119
+ }) : /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ S("p", {
120
+ className: "text-xs font-medium text-text-tertiary",
121
+ children: [
122
+ "Showing ",
123
+ K.length,
124
+ " member",
125
+ K.length === 1 ? "" : "s"
126
+ ]
127
+ }), /* @__PURE__ */ x("div", {
128
+ className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4",
129
+ children: K.map((e) => {
130
+ let t = !!(j?.id && e.memberId === j.id), n = W.has(e.memberId), r = F === e.memberId, i = Array.from(new Set([...e.skills, ...e.interests])).slice(0, 4);
131
+ return /* @__PURE__ */ S(w, {
83
132
  treatment: "plain",
84
- className: "flex flex-col p-5",
133
+ className: "flex flex-col p-5 transition-all duration-200 motion-safe:hover:-translate-y-0.5 hover:border-[var(--color-accent-soft)]",
85
134
  children: [
86
- /* @__PURE__ */ x("div", {
87
- className: "flex items-start gap-3",
88
- children: [/* @__PURE__ */ b(s, {
135
+ /* @__PURE__ */ S("button", {
136
+ type: "button",
137
+ onClick: () => A(`members/${e.memberId}`),
138
+ "aria-label": `View ${e.displayName}'s profile`,
139
+ className: "group/head flex w-full items-start gap-3 rounded-lg text-left outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-focus-ring)]",
140
+ children: [/* @__PURE__ */ x(s, {
89
141
  name: e.displayName,
90
142
  presence: e.presence,
91
- size: "lg"
92
- }), /* @__PURE__ */ x("div", {
143
+ size: "lg",
144
+ fileId: e.avatar?.id,
145
+ seed: e.memberId
146
+ }), /* @__PURE__ */ S("div", {
93
147
  className: "min-w-0 flex-1",
94
148
  children: [
95
- /* @__PURE__ */ b("button", {
96
- type: "button",
97
- onClick: () => E(`members/${e.memberId}`),
98
- className: "block max-w-full truncate text-left text-base font-semibold text-text-primary hover:underline",
149
+ /* @__PURE__ */ x("span", {
150
+ className: "block max-w-full truncate text-base font-semibold text-text-primary group-hover/head:underline",
99
151
  children: e.displayName
100
152
  }),
101
- e.headline && /* @__PURE__ */ b("p", {
153
+ e.headline && /* @__PURE__ */ x("p", {
102
154
  className: "truncate text-sm text-text-secondary",
103
155
  children: e.headline
104
156
  }),
105
- /* @__PURE__ */ b("div", {
106
- className: "mt-1.5",
107
- children: /* @__PURE__ */ b(m, { status: e.presence })
157
+ e.bio && /* @__PURE__ */ x("p", {
158
+ className: "mt-0.5 line-clamp-1 text-xs text-text-tertiary",
159
+ children: e.bio
108
160
  })
109
161
  ]
110
162
  })]
111
163
  }),
112
- r.length > 0 && /* @__PURE__ */ b("div", {
164
+ i.length > 0 && /* @__PURE__ */ x("div", {
113
165
  className: "mt-3 flex flex-wrap gap-1.5",
114
- children: r.map((e) => /* @__PURE__ */ b("span", {
166
+ children: i.map((e) => /* @__PURE__ */ x("span", {
115
167
  className: "rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary",
116
168
  children: e
117
169
  }, e))
118
170
  }),
119
- !t && /* @__PURE__ */ b("div", {
171
+ !t && /* @__PURE__ */ x("div", {
120
172
  className: "mt-4 flex items-center justify-end border-t border-border-seam pt-3",
121
- children: n ? /* @__PURE__ */ x(S, {
173
+ children: n ? /* @__PURE__ */ x(C, {
122
174
  size: "sm",
123
175
  variant: "outline",
124
- onClick: () => U(e),
125
- disabled: j === e.memberId,
126
- children: [/* @__PURE__ */ b(_, { className: "mr-1.5 h-4 w-4" }), " Following"]
127
- }) : /* @__PURE__ */ x(S, {
176
+ onClick: (t) => {
177
+ t.stopPropagation(), q(e);
178
+ },
179
+ disabled: r,
180
+ "aria-label": `Following ${e.displayName}. Activate to unfollow.`,
181
+ className: "group/follow min-w-[7.5rem] justify-center hover:border-status-error-border hover:bg-status-error-bg-subtle hover:text-status-error-text",
182
+ children: r ? /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(g, { className: "motion-safe:animate-spin" }), /* @__PURE__ */ x("span", { children: "Following" })] }) : /* @__PURE__ */ S(b, { children: [
183
+ /* @__PURE__ */ x(h, { className: "group-hover/follow:hidden" }),
184
+ /* @__PURE__ */ x(v, { className: "hidden group-hover/follow:inline" }),
185
+ /* @__PURE__ */ x("span", {
186
+ className: "group-hover/follow:hidden",
187
+ children: "Following"
188
+ }),
189
+ /* @__PURE__ */ x("span", {
190
+ className: "hidden group-hover/follow:inline",
191
+ children: "Unfollow"
192
+ })
193
+ ] })
194
+ }) : /* @__PURE__ */ S(C, {
128
195
  size: "sm",
129
- onClick: () => U(e),
130
- disabled: j === e.memberId,
131
- children: [/* @__PURE__ */ b(y, { className: "mr-1.5 h-4 w-4" }), " Follow"]
196
+ onClick: (t) => {
197
+ t.stopPropagation(), q(e);
198
+ },
199
+ disabled: r,
200
+ className: "min-w-[7.5rem] justify-center",
201
+ children: [r ? /* @__PURE__ */ x(g, { className: "motion-safe:animate-spin" }) : /* @__PURE__ */ x(y, {}), "Follow"]
132
202
  })
133
203
  })
134
204
  ]
135
205
  }, e.id);
136
206
  })
137
- }),
138
- /* @__PURE__ */ b(p, {
139
- page: O.page,
140
- pageSize: T,
141
- itemCount: V.length,
142
- hasMore: N?.pageInfo.hasMore ?? !1,
143
- onPageChange: (e) => O.onPageChange(e, N?.pageInfo.cursor)
207
+ })] }),
208
+ /* @__PURE__ */ x(f, {
209
+ page: M.page,
210
+ pageSize: D,
211
+ itemCount: G.length,
212
+ hasMore: L?.pageInfo.hasMore ?? !1,
213
+ onPageChange: (e) => M.onPageChange(e, L?.pageInfo.cursor)
144
214
  })
145
215
  ]
146
216
  })
147
217
  });
148
218
  }
149
219
  //#endregion
150
- export { E as MembersPage };
220
+ export { A as MembersPage };
151
221
 
152
222
  //# sourceMappingURL=MembersPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MembersPage.js","names":[],"sources":["../../../../src/comradecircle/pages/members/MembersPage.tsx"],"sourcesContent":["/**\n * MembersPage — the discoverable member directory.\n * @module comradecircle/pages/members\n *\n * Reads `comListProfiles(discoverable: true)` — every member who has opted into\n * discovery via their {@link ComProfile}. Each card resolves display identity\n * from the social-identity layer (never a raw actor id), links to the member's\n * public profile, and offers a Follow/Following toggle wired to `comFollow` /\n * `comUnfollow` (targetType MEMBER). An optional client-side search narrows the\n * current page by name, headline, skills, or interests.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Search, UserPlus, Check } from 'lucide-react';\nimport { GlassCard, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { Avatar } from '../../components/Avatar';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport {\n useComProfiles,\n useComMyFollows,\n useComFollow,\n useComUnfollow,\n useCursorPager,\n} from '../../hooks';\nimport { useComradeCircle } from '../../context';\nimport { notify, describeError } from '../../lib/toast';\nimport type { ComProfile } from '../../types';\n\nconst PAGE_SIZE = 12;\n\nexport function MembersPage() {\n const { navigateTo, currentUser } = useComradeCircle();\n const pager = useCursorPager();\n const [search, setSearch] = useState('');\n const [pendingId, setPendingId] = useState<string | null>(null);\n\n const { data, isLoading, isError, refetch } = useComProfiles({\n discoverable: true,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const { data: follows } = useComMyFollows('MEMBER');\n const follow = useComFollow();\n const unfollow = useComUnfollow();\n\n const followSet = useMemo(() => new Set((follows ?? []).map((f) => f.targetId)), [follows]);\n\n const profiles = useMemo(() => data?.items ?? [], [data]);\n\n const visible = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return profiles;\n return profiles.filter((p) => {\n const haystack = [p.displayName, p.headline ?? '', ...p.skills, ...p.interests]\n .join(' ')\n .toLowerCase();\n return haystack.includes(q);\n });\n }, [profiles, search]);\n\n const toggleFollow = async (profile: ComProfile) => {\n const wasFollowing = followSet.has(profile.memberId);\n const input = { targetId: profile.memberId, targetType: 'MEMBER' as const };\n setPendingId(profile.memberId);\n try {\n if (wasFollowing) {\n await unfollow.mutateAsync(input);\n notify.success('Unfollowed', profile.displayName);\n } else {\n await follow.mutateAsync(input);\n notify.success('Following', profile.displayName);\n }\n } catch (err) {\n notify.error(wasFollowing ? 'Could not unfollow' : 'Could not follow', describeError(err));\n } finally {\n setPendingId(null);\n }\n };\n\n return (\n <PageLayout\n title=\"Members\"\n description=\"Discover and follow people across your circles — search by name, headline, or skills.\"\n >\n {isLoading ? (\n <LoadingView label=\"Loading members…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load the member directory.\" onRetry={() => refetch()} />\n ) : profiles.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No members to discover yet\"\n description=\"When members make their profiles discoverable, they'll show up here for you to follow.\"\n />\n ) : (\n <div className=\"flex flex-col gap-5\">\n <div className=\"relative w-full max-w-sm\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <Input\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search by name, headline, or skills\"\n aria-label=\"Search members\"\n className=\"pl-9\"\n />\n </div>\n\n {visible.length === 0 ? (\n <EmptyState\n icon={<Search className=\"h-9 w-9\" />}\n title=\"No matches on this page\"\n description=\"No members on this page match your search. Try a different term or browse another page.\"\n />\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3\">\n {visible.map((p) => {\n const isSelf = Boolean(currentUser?.id && p.memberId === currentUser.id);\n const isFollowing = followSet.has(p.memberId);\n const chips = Array.from(new Set([...p.skills, ...p.interests])).slice(0, 4);\n\n return (\n <GlassCard key={p.id} treatment=\"plain\" className=\"flex flex-col p-5\">\n <div className=\"flex items-start gap-3\">\n <Avatar name={p.displayName} presence={p.presence} size=\"lg\" />\n <div className=\"min-w-0 flex-1\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`members/${p.memberId}`)}\n className=\"block max-w-full truncate text-left text-base font-semibold text-text-primary hover:underline\"\n >\n {p.displayName}\n </button>\n {p.headline && (\n <p className=\"truncate text-sm text-text-secondary\">{p.headline}</p>\n )}\n <div className=\"mt-1.5\">\n <StatusBadge status={p.presence} />\n </div>\n </div>\n </div>\n\n {chips.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {chips.map((chip) => (\n <span\n key={chip}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\"\n >\n {chip}\n </span>\n ))}\n </div>\n )}\n\n {!isSelf && (\n <div className=\"mt-4 flex items-center justify-end border-t border-border-seam pt-3\">\n {isFollowing ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => toggleFollow(p)}\n disabled={pendingId === p.memberId}\n >\n <Check className=\"mr-1.5 h-4 w-4\" /> Following\n </Button>\n ) : (\n <Button\n size=\"sm\"\n onClick={() => toggleFollow(p)}\n disabled={pendingId === p.memberId}\n >\n <UserPlus className=\"mr-1.5 h-4 w-4\" /> Follow\n </Button>\n )}\n </div>\n )}\n </GlassCard>\n );\n })}\n </div>\n )}\n\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={profiles.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MembersPage.js","names":[],"sources":["../../../../src/comradecircle/pages/members/MembersPage.tsx"],"sourcesContent":["/**\n * MembersPage — the discoverable member directory.\n * @module comradecircle/pages/members\n *\n * Reads `comListProfiles(discoverable: true)` — every member who has opted into\n * discovery via their {@link ComProfile}. Each card resolves display identity\n * from the social-identity layer (never a raw actor id), links to the member's\n * public profile, and offers a Follow/Following toggle wired to `comFollow` /\n * `comUnfollow` (targetType MEMBER). An optional client-side search narrows the\n * current page by name, headline, skills, or interests.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Search, UserPlus, UserMinus, Check, Loader2 } from 'lucide-react';\nimport { GlassCard, Button, Input, Skeleton } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { Avatar } from '../../components/Avatar';\nimport { EmptyState } from '../../components/EmptyState';\nimport { ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport {\n useComProfiles,\n useComMyFollows,\n useComFollow,\n useComUnfollow,\n useCursorPager,\n} from '../../hooks';\nimport { useComradeCircle } from '../../context';\nimport { notify, describeError } from '../../lib/toast';\nimport type { ComProfile } from '../../types';\n\nconst PAGE_SIZE = 12;\n\nconst SKELETON_KEYS = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8'] as const;\n\n/** Card-shaped placeholder that mirrors the member card while the page loads. */\nfunction MemberCardSkeleton() {\n return (\n <GlassCard treatment=\"plain\" className=\"flex flex-col p-5\">\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"h-14 w-14 rounded-full\" />\n <div className=\"min-w-0 flex-1 space-y-2 py-1\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"h-3 w-1/2\" />\n <Skeleton className=\"h-3 w-4/5\" />\n </div>\n </div>\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n <Skeleton className=\"h-5 w-16 rounded-full\" />\n <Skeleton className=\"h-5 w-20 rounded-full\" />\n </div>\n <div className=\"mt-4 flex justify-end border-t border-border-seam pt-3\">\n <Skeleton className=\"h-8 w-28 rounded-button\" />\n </div>\n </GlassCard>\n );\n}\n\nexport function MembersPage() {\n const { navigateTo, currentUser } = useComradeCircle();\n const pager = useCursorPager();\n const [search, setSearch] = useState('');\n const [pendingId, setPendingId] = useState<string | null>(null);\n\n const { data, isLoading, isError, refetch } = useComProfiles({\n discoverable: true,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const { data: follows } = useComMyFollows('MEMBER');\n const follow = useComFollow();\n const unfollow = useComUnfollow();\n\n const followSet = useMemo(() => new Set((follows ?? []).map((f) => f.targetId)), [follows]);\n\n const profiles = useMemo(() => data?.items ?? [], [data]);\n\n const visible = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return profiles;\n return profiles.filter((p) => {\n const haystack = [p.displayName, p.headline ?? '', ...p.skills, ...p.interests]\n .join(' ')\n .toLowerCase();\n return haystack.includes(q);\n });\n }, [profiles, search]);\n\n const toggleFollow = async (profile: ComProfile) => {\n const wasFollowing = followSet.has(profile.memberId);\n const input = { targetId: profile.memberId, targetType: 'MEMBER' as const };\n setPendingId(profile.memberId);\n try {\n if (wasFollowing) {\n await unfollow.mutateAsync(input);\n notify.success('Unfollowed', profile.displayName);\n } else {\n await follow.mutateAsync(input);\n notify.success('Following', profile.displayName);\n }\n } catch (err) {\n notify.error(wasFollowing ? 'Could not unfollow' : 'Could not follow', describeError(err));\n } finally {\n setPendingId(null);\n }\n };\n\n return (\n <PageLayout\n title=\"Members\"\n description=\"Discover and follow people across your circles — search by name, headline, or skills.\"\n >\n {isLoading ? (\n <div className=\"flex flex-col gap-5\">\n <Skeleton className=\"h-9 w-full max-w-sm rounded-button\" />\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4\">\n {SKELETON_KEYS.map((key) => (\n <MemberCardSkeleton key={key} />\n ))}\n </div>\n </div>\n ) : isError ? (\n <ErrorView message=\"We couldn't load the member directory.\" onRetry={() => refetch()} />\n ) : profiles.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No members to discover yet\"\n description=\"When members make their profiles discoverable, they'll show up here for you to follow.\"\n />\n ) : (\n <div className=\"flex flex-col gap-5\">\n <div className=\"relative w-full max-w-sm\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <Input\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search by name, headline, or skills\"\n aria-label=\"Search members\"\n className=\"pl-9\"\n />\n </div>\n\n {visible.length === 0 ? (\n <EmptyState\n icon={<Search className=\"h-9 w-9\" />}\n title=\"No matches on this page\"\n description=\"No members on this page match your search. Try a different term or browse another page.\"\n />\n ) : (\n <>\n <p className=\"text-xs font-medium text-text-tertiary\">\n Showing {visible.length} member{visible.length === 1 ? '' : 's'}\n </p>\n\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4\">\n {visible.map((p) => {\n const isSelf = Boolean(currentUser?.id && p.memberId === currentUser.id);\n const isFollowing = followSet.has(p.memberId);\n const isPending = pendingId === p.memberId;\n const chips = Array.from(new Set([...p.skills, ...p.interests])).slice(0, 4);\n\n return (\n <GlassCard\n key={p.id}\n treatment=\"plain\"\n className=\"flex flex-col p-5 transition-all duration-200 motion-safe:hover:-translate-y-0.5 hover:border-[var(--color-accent-soft)]\"\n >\n <button\n type=\"button\"\n onClick={() => navigateTo(`members/${p.memberId}`)}\n aria-label={`View ${p.displayName}'s profile`}\n className=\"group/head flex w-full items-start gap-3 rounded-lg text-left outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <Avatar\n name={p.displayName}\n presence={p.presence}\n size=\"lg\"\n fileId={p.avatar?.id}\n seed={p.memberId}\n />\n <div className=\"min-w-0 flex-1\">\n <span className=\"block max-w-full truncate text-base font-semibold text-text-primary group-hover/head:underline\">\n {p.displayName}\n </span>\n {p.headline && (\n <p className=\"truncate text-sm text-text-secondary\">{p.headline}</p>\n )}\n {p.bio && (\n <p className=\"mt-0.5 line-clamp-1 text-xs text-text-tertiary\">\n {p.bio}\n </p>\n )}\n </div>\n </button>\n\n {chips.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {chips.map((chip) => (\n <span\n key={chip}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\"\n >\n {chip}\n </span>\n ))}\n </div>\n )}\n\n {!isSelf && (\n <div className=\"mt-4 flex items-center justify-end border-t border-border-seam pt-3\">\n {isFollowing ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n void toggleFollow(p);\n }}\n disabled={isPending}\n aria-label={`Following ${p.displayName}. Activate to unfollow.`}\n className=\"group/follow min-w-[7.5rem] justify-center hover:border-status-error-border hover:bg-status-error-bg-subtle hover:text-status-error-text\"\n >\n {isPending ? (\n <>\n <Loader2 className=\"motion-safe:animate-spin\" />\n <span>Following</span>\n </>\n ) : (\n <>\n <Check className=\"group-hover/follow:hidden\" />\n <UserMinus className=\"hidden group-hover/follow:inline\" />\n <span className=\"group-hover/follow:hidden\">Following</span>\n <span className=\"hidden group-hover/follow:inline\">Unfollow</span>\n </>\n )}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n void toggleFollow(p);\n }}\n disabled={isPending}\n className=\"min-w-[7.5rem] justify-center\"\n >\n {isPending ? (\n <Loader2 className=\"motion-safe:animate-spin\" />\n ) : (\n <UserPlus />\n )}\n Follow\n </Button>\n )}\n </div>\n )}\n </GlassCard>\n );\n })}\n </div>\n </>\n )}\n\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={profiles.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}