@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.
Files changed (41) hide show
  1. package/dist/comradecircle/components/Avatar.js +40 -17
  2. package/dist/comradecircle/components/Avatar.js.map +1 -1
  3. package/dist/comradecircle/components/AvatarUploadField.js +25 -14
  4. package/dist/comradecircle/components/AvatarUploadField.js.map +1 -1
  5. package/dist/comradecircle/components/CircleCard.js +54 -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/EventCard.js +84 -58
  10. package/dist/comradecircle/components/EventCard.js.map +1 -1
  11. package/dist/comradecircle/components/MemberIdentity.js +2 -1
  12. package/dist/comradecircle/components/MemberIdentity.js.map +1 -1
  13. package/dist/comradecircle/components/PollCard.js +65 -44
  14. package/dist/comradecircle/components/PollCard.js.map +1 -1
  15. package/dist/comradecircle/components/PostCard.js +1 -1
  16. package/dist/comradecircle/components/PostCard.js.map +1 -1
  17. package/dist/comradecircle/components/ReactionBar.js +1 -1
  18. package/dist/comradecircle/components/ReactionBar.js.map +1 -1
  19. package/dist/comradecircle/components/StateViews.js +1 -16
  20. package/dist/comradecircle/components/StateViews.js.map +1 -1
  21. package/dist/comradecircle/components/StatusBadge.js +1 -1
  22. package/dist/comradecircle/components/StatusBadge.js.map +1 -1
  23. package/dist/comradecircle/hooks/useComradeCircleApi.js +1 -1
  24. package/dist/comradecircle/hooks/useComradeCircleApi.js.map +1 -1
  25. package/dist/comradecircle/pages/FeedPage.js +79 -33
  26. package/dist/comradecircle/pages/FeedPage.js.map +1 -1
  27. package/dist/comradecircle/pages/circles/CircleDetailPage.js +354 -243
  28. package/dist/comradecircle/pages/circles/CircleDetailPage.js.map +1 -1
  29. package/dist/comradecircle/pages/circles/CirclesPage.js +97 -47
  30. package/dist/comradecircle/pages/circles/CirclesPage.js.map +1 -1
  31. package/dist/comradecircle/pages/events/EventDetailPage.js +193 -126
  32. package/dist/comradecircle/pages/events/EventDetailPage.js.map +1 -1
  33. package/dist/comradecircle/pages/events/EventsPage.js +74 -34
  34. package/dist/comradecircle/pages/events/EventsPage.js.map +1 -1
  35. package/dist/comradecircle/pages/members/MemberProfilePage.js +154 -82
  36. package/dist/comradecircle/pages/members/MemberProfilePage.js.map +1 -1
  37. package/dist/comradecircle/pages/members/MembersPage.js +140 -71
  38. package/dist/comradecircle/pages/members/MembersPage.js.map +1 -1
  39. package/dist/comradecircle/pages/profile/MyProfilePage.js +298 -202
  40. package/dist/comradecircle/pages/profile/MyProfilePage.js.map +1 -1
  41. package/package.json +1 -1
@@ -7,147 +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
143
  size: "lg",
92
- fileId: e.avatar?.id
93
- }), /* @__PURE__ */ x("div", {
144
+ fileId: e.avatar?.id,
145
+ seed: e.memberId
146
+ }), /* @__PURE__ */ S("div", {
94
147
  className: "min-w-0 flex-1",
95
148
  children: [
96
- /* @__PURE__ */ b("button", {
97
- type: "button",
98
- onClick: () => E(`members/${e.memberId}`),
99
- 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",
100
151
  children: e.displayName
101
152
  }),
102
- e.headline && /* @__PURE__ */ b("p", {
153
+ e.headline && /* @__PURE__ */ x("p", {
103
154
  className: "truncate text-sm text-text-secondary",
104
155
  children: e.headline
105
156
  }),
106
- /* @__PURE__ */ b("div", {
107
- className: "mt-1.5",
108
- 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
109
160
  })
110
161
  ]
111
162
  })]
112
163
  }),
113
- r.length > 0 && /* @__PURE__ */ b("div", {
164
+ i.length > 0 && /* @__PURE__ */ x("div", {
114
165
  className: "mt-3 flex flex-wrap gap-1.5",
115
- children: r.map((e) => /* @__PURE__ */ b("span", {
166
+ children: i.map((e) => /* @__PURE__ */ x("span", {
116
167
  className: "rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary",
117
168
  children: e
118
169
  }, e))
119
170
  }),
120
- !t && /* @__PURE__ */ b("div", {
171
+ !t && /* @__PURE__ */ x("div", {
121
172
  className: "mt-4 flex items-center justify-end border-t border-border-seam pt-3",
122
- children: n ? /* @__PURE__ */ x(S, {
173
+ children: n ? /* @__PURE__ */ x(C, {
123
174
  size: "sm",
124
175
  variant: "outline",
125
- onClick: () => U(e),
126
- disabled: j === e.memberId,
127
- children: [/* @__PURE__ */ b(_, { className: "mr-1.5 h-4 w-4" }), " Following"]
128
- }) : /* @__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, {
129
195
  size: "sm",
130
- onClick: () => U(e),
131
- disabled: j === e.memberId,
132
- 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"]
133
202
  })
134
203
  })
135
204
  ]
136
205
  }, e.id);
137
206
  })
138
- }),
139
- /* @__PURE__ */ b(p, {
140
- page: O.page,
141
- pageSize: T,
142
- itemCount: V.length,
143
- hasMore: N?.pageInfo.hasMore ?? !1,
144
- 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)
145
214
  })
146
215
  ]
147
216
  })
148
217
  });
149
218
  }
150
219
  //#endregion
151
- export { E as MembersPage };
220
+ export { A as MembersPage };
152
221
 
153
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\n name={p.displayName}\n presence={p.presence}\n size=\"lg\"\n fileId={p.avatar?.id}\n />\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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"}