@burdenoff/microfe-comradecircle 2026.819.1 → 2026.830.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/comradecircle/components/AvatarUploadField.js +8 -8
- package/dist/comradecircle/components/CircleCard.js +4 -4
- package/dist/comradecircle/components/CommentThread.d.ts.map +1 -1
- package/dist/comradecircle/components/CommentThread.js +66 -61
- package/dist/comradecircle/components/CommentThread.js.map +1 -1
- package/dist/comradecircle/components/CreateCircleDialog.d.ts.map +1 -1
- package/dist/comradecircle/components/CreateCircleDialog.js +89 -88
- package/dist/comradecircle/components/CreateCircleDialog.js.map +1 -1
- package/dist/comradecircle/components/CreateEventDialog.d.ts.map +1 -1
- package/dist/comradecircle/components/CreateEventDialog.js +28 -27
- package/dist/comradecircle/components/CreateEventDialog.js.map +1 -1
- package/dist/comradecircle/components/DraftsPanel.d.ts +32 -0
- package/dist/comradecircle/components/DraftsPanel.d.ts.map +1 -0
- package/dist/comradecircle/components/DraftsPanel.js +176 -0
- package/dist/comradecircle/components/DraftsPanel.js.map +1 -0
- package/dist/comradecircle/components/EventCard.js +5 -5
- package/dist/comradecircle/components/FileImage.js +5 -5
- package/dist/comradecircle/components/ImageAttachments.js +21 -21
- package/dist/comradecircle/components/MemberIdentity.js +4 -4
- package/dist/comradecircle/components/MobileBottomNav.d.ts.map +1 -1
- package/dist/comradecircle/components/MobileBottomNav.js +37 -30
- package/dist/comradecircle/components/MobileBottomNav.js.map +1 -1
- package/dist/comradecircle/components/Pagination.d.ts.map +1 -1
- package/dist/comradecircle/components/Pagination.js +37 -28
- package/dist/comradecircle/components/Pagination.js.map +1 -1
- package/dist/comradecircle/components/PollCard.js +13 -13
- package/dist/comradecircle/components/PostCard.d.ts.map +1 -1
- package/dist/comradecircle/components/PostCard.js +102 -89
- package/dist/comradecircle/components/PostCard.js.map +1 -1
- package/dist/comradecircle/components/PostComposer.d.ts +11 -5
- package/dist/comradecircle/components/PostComposer.d.ts.map +1 -1
- package/dist/comradecircle/components/PostComposer.js +60 -48
- package/dist/comradecircle/components/PostComposer.js.map +1 -1
- package/dist/comradecircle/components/ReactionBar.d.ts.map +1 -1
- package/dist/comradecircle/components/ReactionBar.js +65 -55
- package/dist/comradecircle/components/ReactionBar.js.map +1 -1
- package/dist/comradecircle/components/StateViews.d.ts.map +1 -1
- package/dist/comradecircle/components/StateViews.js +38 -30
- package/dist/comradecircle/components/StateViews.js.map +1 -1
- package/dist/comradecircle/components/UpcomingEvents.d.ts +26 -0
- package/dist/comradecircle/components/UpcomingEvents.d.ts.map +1 -0
- package/dist/comradecircle/components/UpcomingEvents.js +126 -0
- package/dist/comradecircle/components/UpcomingEvents.js.map +1 -0
- package/dist/comradecircle/components/index.d.ts +2 -0
- package/dist/comradecircle/components/index.d.ts.map +1 -1
- package/dist/comradecircle/hooks/index.d.ts +1 -0
- package/dist/comradecircle/hooks/index.d.ts.map +1 -1
- package/dist/comradecircle/hooks/index.js +1 -0
- package/dist/comradecircle/hooks/useTr.d.ts +18 -0
- package/dist/comradecircle/hooks/useTr.d.ts.map +1 -0
- package/dist/comradecircle/hooks/useTr.js +12 -0
- package/dist/comradecircle/hooks/useTr.js.map +1 -0
- package/dist/comradecircle/pages/FeedPage.d.ts +5 -0
- package/dist/comradecircle/pages/FeedPage.d.ts.map +1 -1
- package/dist/comradecircle/pages/FeedPage.js +76 -62
- package/dist/comradecircle/pages/FeedPage.js.map +1 -1
- package/dist/comradecircle/pages/circles/CircleDetailPage.d.ts.map +1 -1
- package/dist/comradecircle/pages/circles/CircleDetailPage.js +454 -409
- package/dist/comradecircle/pages/circles/CircleDetailPage.js.map +1 -1
- package/dist/comradecircle/pages/circles/CirclesPage.d.ts.map +1 -1
- package/dist/comradecircle/pages/circles/CirclesPage.js +124 -117
- package/dist/comradecircle/pages/circles/CirclesPage.js.map +1 -1
- package/dist/comradecircle/pages/events/EventDetailPage.d.ts.map +1 -1
- package/dist/comradecircle/pages/events/EventDetailPage.js +182 -153
- package/dist/comradecircle/pages/events/EventDetailPage.js.map +1 -1
- package/dist/comradecircle/pages/events/EventsPage.d.ts.map +1 -1
- package/dist/comradecircle/pages/events/EventsPage.js +100 -91
- package/dist/comradecircle/pages/events/EventsPage.js.map +1 -1
- package/dist/comradecircle/pages/members/MemberProfilePage.d.ts.map +1 -1
- package/dist/comradecircle/pages/members/MemberProfilePage.js +172 -159
- package/dist/comradecircle/pages/members/MemberProfilePage.js.map +1 -1
- package/dist/comradecircle/pages/members/MembersPage.d.ts.map +1 -1
- package/dist/comradecircle/pages/members/MembersPage.js +103 -104
- package/dist/comradecircle/pages/members/MembersPage.js.map +1 -1
- package/dist/comradecircle/pages/monetization/MonetizationPage.d.ts.map +1 -1
- package/dist/comradecircle/pages/monetization/MonetizationPage.js +319 -297
- package/dist/comradecircle/pages/monetization/MonetizationPage.js.map +1 -1
- package/dist/comradecircle/pages/posts/PostThreadPage.d.ts.map +1 -1
- package/dist/comradecircle/pages/posts/PostThreadPage.js +37 -32
- package/dist/comradecircle/pages/posts/PostThreadPage.js.map +1 -1
- package/dist/comradecircle/pages/profile/MyProfilePage.d.ts.map +1 -1
- package/dist/comradecircle/pages/profile/MyProfilePage.js +182 -177
- package/dist/comradecircle/pages/profile/MyProfilePage.js.map +1 -1
- package/dist/comradecircle/utils/i18n.js +15 -0
- package/dist/comradecircle/utils/i18n.js.map +1 -0
- package/dist/comradecircle/utils/pageContext.d.ts.map +1 -1
- package/dist/comradecircle/utils/pageContext.js +3 -1
- package/dist/comradecircle/utils/pageContext.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,111 +1,121 @@
|
|
|
1
1
|
import { useComradeCircle as e } from "../context/ComradeCircleContext.js";
|
|
2
2
|
import "../context/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { useComReactToPost as t } from "../hooks/useComradeCircleApi.js";
|
|
4
|
+
import { useTr as n } from "../hooks/useTr.js";
|
|
5
5
|
import "../hooks/index.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
6
|
+
import { cn as r } from "../utils/cn.js";
|
|
7
|
+
import { describeError as i, notify as a } from "../lib/toast.js";
|
|
8
|
+
import { useState as o } from "react";
|
|
9
|
+
import { SmilePlus as s } from "lucide-react";
|
|
10
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
11
|
+
import { Popover as u, PopoverContent as d, PopoverTrigger as f } from "@burdenoff/fe-libs/ui";
|
|
11
12
|
//#region src/comradecircle/components/ReactionBar.tsx
|
|
12
|
-
var
|
|
13
|
+
var p = [
|
|
13
14
|
{
|
|
14
15
|
type: "LIKE",
|
|
15
16
|
emoji: "👍",
|
|
16
|
-
|
|
17
|
+
key: "comradecircle.components.reactionBar.like",
|
|
18
|
+
fallback: "Like"
|
|
17
19
|
},
|
|
18
20
|
{
|
|
19
21
|
type: "LOVE",
|
|
20
22
|
emoji: "❤️",
|
|
21
|
-
|
|
23
|
+
key: "comradecircle.components.reactionBar.love",
|
|
24
|
+
fallback: "Love"
|
|
22
25
|
},
|
|
23
26
|
{
|
|
24
27
|
type: "CELEBRATE",
|
|
25
28
|
emoji: "🎉",
|
|
26
|
-
|
|
29
|
+
key: "comradecircle.components.reactionBar.celebrate",
|
|
30
|
+
fallback: "Celebrate"
|
|
27
31
|
},
|
|
28
32
|
{
|
|
29
33
|
type: "INSIGHTFUL",
|
|
30
34
|
emoji: "💡",
|
|
31
|
-
|
|
35
|
+
key: "comradecircle.components.reactionBar.insightful",
|
|
36
|
+
fallback: "Insightful"
|
|
32
37
|
},
|
|
33
38
|
{
|
|
34
39
|
type: "LAUGH",
|
|
35
40
|
emoji: "😄",
|
|
36
|
-
|
|
41
|
+
key: "comradecircle.components.reactionBar.funny",
|
|
42
|
+
fallback: "Funny"
|
|
37
43
|
},
|
|
38
44
|
{
|
|
39
45
|
type: "SUPPORT",
|
|
40
46
|
emoji: "🤝",
|
|
41
|
-
|
|
47
|
+
key: "comradecircle.components.reactionBar.support",
|
|
48
|
+
fallback: "Support"
|
|
42
49
|
}
|
|
43
50
|
];
|
|
44
|
-
function
|
|
45
|
-
let { currentUser:
|
|
46
|
-
for (let e of
|
|
47
|
-
let t =
|
|
51
|
+
function m({ post: m }) {
|
|
52
|
+
let { currentUser: h } = e(), g = t(), _ = n(), [v, y] = o(!1), b = h?.id, x = /* @__PURE__ */ new Map();
|
|
53
|
+
for (let e of m.reactions ?? []) {
|
|
54
|
+
let t = x.get(e.type) ?? {
|
|
48
55
|
count: 0,
|
|
49
56
|
mine: !1
|
|
50
57
|
};
|
|
51
|
-
t.count += 1,
|
|
58
|
+
t.count += 1, b && e.memberId === b && (t.mine = !0), x.set(e.type, t);
|
|
52
59
|
}
|
|
53
|
-
let
|
|
54
|
-
|
|
60
|
+
let S = async (e) => {
|
|
61
|
+
y(!1);
|
|
55
62
|
try {
|
|
56
|
-
await
|
|
57
|
-
postId:
|
|
63
|
+
await g.mutateAsync({
|
|
64
|
+
postId: m.id,
|
|
58
65
|
type: e
|
|
59
66
|
});
|
|
60
67
|
} catch (e) {
|
|
61
|
-
|
|
68
|
+
a.error(_("comradecircle.components.reactionBar.reactError", "Could not react"), i(e));
|
|
62
69
|
}
|
|
63
70
|
};
|
|
64
|
-
return /* @__PURE__ */
|
|
71
|
+
return /* @__PURE__ */ l("div", {
|
|
65
72
|
className: "flex flex-wrap items-center gap-1.5",
|
|
66
|
-
children: [
|
|
67
|
-
let
|
|
68
|
-
return /* @__PURE__ */
|
|
73
|
+
children: [p.filter((e) => (x.get(e.type)?.count ?? 0) > 0).map((e) => {
|
|
74
|
+
let t = x.get(e.type);
|
|
75
|
+
return /* @__PURE__ */ l("button", {
|
|
69
76
|
type: "button",
|
|
70
|
-
onClick: () =>
|
|
71
|
-
disabled:
|
|
72
|
-
"aria-pressed":
|
|
73
|
-
"aria-label":
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
onClick: () => S(e.type),
|
|
78
|
+
disabled: g.isPending,
|
|
79
|
+
"aria-pressed": t.mine,
|
|
80
|
+
"aria-label": _("comradecircle.components.reactionBar.reactionAriaLabel", "{{label}} ({{count}})", {
|
|
81
|
+
label: _(e.key, e.fallback),
|
|
82
|
+
count: t.count
|
|
83
|
+
}),
|
|
84
|
+
className: r("inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-transform duration-150 active:scale-90", t.mine ? "border-accent bg-[var(--color-accent-soft)] text-text-primary shadow-[0_0_0_2px_var(--color-accent-soft)]" : "border-border-seam bg-bg-surface text-text-secondary hover:-translate-y-px hover:bg-bg-sunken"),
|
|
85
|
+
children: [/* @__PURE__ */ c("span", {
|
|
76
86
|
"aria-hidden": "true",
|
|
77
87
|
children: e.emoji
|
|
78
|
-
}), /* @__PURE__ */
|
|
88
|
+
}), /* @__PURE__ */ c("span", {
|
|
79
89
|
className: "tabular-nums",
|
|
80
|
-
children:
|
|
90
|
+
children: t.count
|
|
81
91
|
})]
|
|
82
92
|
}, e.type);
|
|
83
|
-
}), /* @__PURE__ */
|
|
84
|
-
open:
|
|
85
|
-
onOpenChange:
|
|
86
|
-
children: [/* @__PURE__ */
|
|
93
|
+
}), /* @__PURE__ */ l(u, {
|
|
94
|
+
open: v,
|
|
95
|
+
onOpenChange: y,
|
|
96
|
+
children: [/* @__PURE__ */ c(f, {
|
|
87
97
|
asChild: !0,
|
|
88
|
-
children: /* @__PURE__ */
|
|
98
|
+
children: /* @__PURE__ */ c("button", {
|
|
89
99
|
type: "button",
|
|
90
|
-
"aria-label": "Add reaction",
|
|
100
|
+
"aria-label": _("comradecircle.components.reactionBar.addReactionAriaLabel", "Add reaction"),
|
|
91
101
|
className: "inline-flex items-center gap-1 rounded-full border border-border-seam bg-bg-surface px-2 py-0.5 text-xs text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary",
|
|
92
|
-
children: /* @__PURE__ */ s
|
|
102
|
+
children: /* @__PURE__ */ c(s, { className: "h-3.5 w-3.5" })
|
|
93
103
|
})
|
|
94
|
-
}), /* @__PURE__ */
|
|
104
|
+
}), /* @__PURE__ */ c(d, {
|
|
95
105
|
className: "w-auto p-1.5",
|
|
96
106
|
align: "start",
|
|
97
|
-
children: /* @__PURE__ */
|
|
107
|
+
children: /* @__PURE__ */ c("div", {
|
|
98
108
|
className: "flex items-center gap-0.5",
|
|
99
|
-
children:
|
|
100
|
-
let
|
|
101
|
-
return /* @__PURE__ */
|
|
109
|
+
children: p.map((e) => {
|
|
110
|
+
let t = x.get(e.type)?.mine ?? !1, n = _(e.key, e.fallback);
|
|
111
|
+
return /* @__PURE__ */ c("button", {
|
|
102
112
|
type: "button",
|
|
103
|
-
onClick: () =>
|
|
104
|
-
disabled:
|
|
105
|
-
title:
|
|
106
|
-
"aria-label":
|
|
107
|
-
className:
|
|
108
|
-
children: /* @__PURE__ */
|
|
113
|
+
onClick: () => S(e.type),
|
|
114
|
+
disabled: g.isPending,
|
|
115
|
+
title: n,
|
|
116
|
+
"aria-label": n,
|
|
117
|
+
className: r("flex h-9 w-9 items-center justify-center rounded-lg text-lg transition-transform hover:scale-110 hover:bg-bg-sunken", t && "bg-[var(--color-accent-soft)]"),
|
|
118
|
+
children: /* @__PURE__ */ c("span", {
|
|
109
119
|
"aria-hidden": "true",
|
|
110
120
|
children: e.emoji
|
|
111
121
|
})
|
|
@@ -117,6 +127,6 @@ function p({ post: p }) {
|
|
|
117
127
|
});
|
|
118
128
|
}
|
|
119
129
|
//#endregion
|
|
120
|
-
export {
|
|
130
|
+
export { m as ReactionBar };
|
|
121
131
|
|
|
122
132
|
//# sourceMappingURL=ReactionBar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReactionBar.js","names":[],"sources":["../../../src/comradecircle/components/ReactionBar.tsx"],"sourcesContent":["/**\n * ReactionBar — Slack-style multi-reaction control for a post.\n * @module comradecircle/components\n *\n * `comReactToPost(postId, type)` is an idempotent toggle for one typed reaction,\n * so a member may hold several distinct reactions on a post. We render a chip\n * per reaction type that has a count (highlighted when the caller reacted) plus\n * a popover to add any of the six types.\n */\n\nimport { useState } from 'react';\nimport { SmilePlus } from 'lucide-react';\nimport { Popover, PopoverContent, PopoverTrigger } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { useComReactToPost } from '../hooks';\nimport { useComradeCircle } from '../context';\nimport { notify, describeError } from '../lib/toast';\nimport type { ComPost, ComReactionType } from '../types';\n\nconst REACTIONS: { type: ComReactionType; emoji: string;
|
|
1
|
+
{"version":3,"file":"ReactionBar.js","names":[],"sources":["../../../src/comradecircle/components/ReactionBar.tsx"],"sourcesContent":["/**\n * ReactionBar — Slack-style multi-reaction control for a post.\n * @module comradecircle/components\n *\n * `comReactToPost(postId, type)` is an idempotent toggle for one typed reaction,\n * so a member may hold several distinct reactions on a post. We render a chip\n * per reaction type that has a count (highlighted when the caller reacted) plus\n * a popover to add any of the six types.\n */\n\nimport { useState } from 'react';\nimport { SmilePlus } from 'lucide-react';\nimport { Popover, PopoverContent, PopoverTrigger } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { useComReactToPost, useTr } from '../hooks';\nimport { useComradeCircle } from '../context';\nimport { notify, describeError } from '../lib/toast';\nimport type { ComPost, ComReactionType } from '../types';\n\nconst REACTIONS: { type: ComReactionType; emoji: string; key: string; fallback: string }[] = [\n { type: 'LIKE', emoji: '👍', key: 'comradecircle.components.reactionBar.like', fallback: 'Like' },\n { type: 'LOVE', emoji: '❤️', key: 'comradecircle.components.reactionBar.love', fallback: 'Love' },\n {\n type: 'CELEBRATE',\n emoji: '🎉',\n key: 'comradecircle.components.reactionBar.celebrate',\n fallback: 'Celebrate',\n },\n {\n type: 'INSIGHTFUL',\n emoji: '💡',\n key: 'comradecircle.components.reactionBar.insightful',\n fallback: 'Insightful',\n },\n {\n type: 'LAUGH',\n emoji: '😄',\n key: 'comradecircle.components.reactionBar.funny',\n fallback: 'Funny',\n },\n {\n type: 'SUPPORT',\n emoji: '🤝',\n key: 'comradecircle.components.reactionBar.support',\n fallback: 'Support',\n },\n];\n\ninterface ReactionBarProps {\n post: ComPost;\n}\n\nexport function ReactionBar({ post }: ReactionBarProps) {\n const { currentUser } = useComradeCircle();\n const react = useComReactToPost();\n const tr = useTr();\n const [open, setOpen] = useState(false);\n\n const meId = currentUser?.id;\n const counts = new Map<ComReactionType, { count: number; mine: boolean }>();\n for (const r of post.reactions ?? []) {\n const cur = counts.get(r.type) ?? { count: 0, mine: false };\n cur.count += 1;\n if (meId && r.memberId === meId) cur.mine = true;\n counts.set(r.type, cur);\n }\n\n const toggle = async (type: ComReactionType) => {\n setOpen(false);\n try {\n await react.mutateAsync({ postId: post.id, type });\n } catch (err) {\n notify.error(\n tr('comradecircle.components.reactionBar.reactError', 'Could not react'),\n describeError(err)\n );\n }\n };\n\n const active = REACTIONS.filter((r) => (counts.get(r.type)?.count ?? 0) > 0);\n\n return (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {active.map((r) => {\n const info = counts.get(r.type)!;\n return (\n <button\n key={r.type}\n type=\"button\"\n onClick={() => toggle(r.type)}\n disabled={react.isPending}\n aria-pressed={info.mine}\n aria-label={tr(\n 'comradecircle.components.reactionBar.reactionAriaLabel',\n '{{label}} ({{count}})',\n {\n label: tr(r.key, r.fallback),\n count: info.count,\n }\n )}\n className={cn(\n 'inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-transform duration-150 active:scale-90',\n info.mine\n ? 'border-accent bg-[var(--color-accent-soft)] text-text-primary shadow-[0_0_0_2px_var(--color-accent-soft)]'\n : 'border-border-seam bg-bg-surface text-text-secondary hover:-translate-y-px hover:bg-bg-sunken'\n )}\n >\n <span aria-hidden=\"true\">{r.emoji}</span>\n <span className=\"tabular-nums\">{info.count}</span>\n </button>\n );\n })}\n\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={tr(\n 'comradecircle.components.reactionBar.addReactionAriaLabel',\n 'Add reaction'\n )}\n className=\"inline-flex items-center gap-1 rounded-full border border-border-seam bg-bg-surface px-2 py-0.5 text-xs text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <SmilePlus className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-1.5\" align=\"start\">\n <div className=\"flex items-center gap-0.5\">\n {REACTIONS.map((r) => {\n const mine = counts.get(r.type)?.mine ?? false;\n const label = tr(r.key, r.fallback);\n return (\n <button\n key={r.type}\n type=\"button\"\n onClick={() => toggle(r.type)}\n disabled={react.isPending}\n title={label}\n aria-label={label}\n className={cn(\n 'flex h-9 w-9 items-center justify-center rounded-lg text-lg transition-transform hover:scale-110 hover:bg-bg-sunken',\n mine && 'bg-[var(--color-accent-soft)]'\n )}\n >\n <span aria-hidden=\"true\">{r.emoji}</span>\n </button>\n );\n })}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAmBA,IAAM,IAAuF;CAC3F;EAAE,MAAM;EAAQ,OAAO;EAAM,KAAK;EAA6C,UAAU;CAAO;CAChG;EAAE,MAAM;EAAQ,OAAO;EAAM,KAAK;EAA6C,UAAU;CAAO;CAChG;EACE,MAAM;EACN,OAAO;EACP,KAAK;EACL,UAAU;CACZ;CACA;EACE,MAAM;EACN,OAAO;EACP,KAAK;EACL,UAAU;CACZ;CACA;EACE,MAAM;EACN,OAAO;EACP,KAAK;EACL,UAAU;CACZ;CACA;EACE,MAAM;EACN,OAAO;EACP,KAAK;EACL,UAAU;CACZ;AACF;AAMA,SAAgB,EAAY,EAAE,WAA0B;CACtD,IAAM,EAAE,mBAAgB,EAAiB,GACnC,IAAQ,EAAkB,GAC1B,IAAK,EAAM,GACX,CAAC,GAAM,KAAW,EAAS,EAAK,GAEhC,IAAO,GAAa,IACpB,oBAAS,IAAI,IAAuD;CAC1E,KAAK,IAAM,KAAK,EAAK,aAAa,CAAC,GAAG;EACpC,IAAM,IAAM,EAAO,IAAI,EAAE,IAAI,KAAK;GAAE,OAAO;GAAG,MAAM;EAAM;EAG1D,AAFA,EAAI,SAAS,GACT,KAAQ,EAAE,aAAa,MAAM,EAAI,OAAO,KAC5C,EAAO,IAAI,EAAE,MAAM,CAAG;CACxB;CAEA,IAAM,IAAS,OAAO,MAA0B;EAC9C,EAAQ,EAAK;EACb,IAAI;GACF,MAAM,EAAM,YAAY;IAAE,QAAQ,EAAK;IAAI;GAAK,CAAC;EACnD,SAAS,GAAK;GACZ,EAAO,MACL,EAAG,mDAAmD,iBAAiB,GACvE,EAAc,CAAG,CACnB;EACF;CACF;CAIA,OACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CAHa,EAAU,QAAQ,OAAO,EAAO,IAAI,EAAE,IAAI,GAAG,SAAS,KAAK,CAIrE,EAAO,KAAK,MAAM;GACjB,IAAM,IAAO,EAAO,IAAI,EAAE,IAAI;GAC9B,OACE,kBAAC,UAAD;IAEE,MAAK;IACL,eAAe,EAAO,EAAE,IAAI;IAC5B,UAAU,EAAM;IAChB,gBAAc,EAAK;IACnB,cAAY,EACV,0DACA,yBACA;KACE,OAAO,EAAG,EAAE,KAAK,EAAE,QAAQ;KAC3B,OAAO,EAAK;IACd,CACF;IACA,WAAW,EACT,wIACA,EAAK,OACD,8GACA,+FACN;cAnBF,CAqBE,kBAAC,QAAD;KAAM,eAAY;eAAQ,EAAE;IAAY,CAAA,GACxC,kBAAC,QAAD;KAAM,WAAU;eAAgB,EAAK;IAAY,CAAA,CAC3C;MAtBD,EAAE,IAsBD;EAEZ,CAAC,GAED,kBAAC,GAAD;GAAe;GAAM,cAAc;aAAnC,CACE,kBAAC,GAAD;IAAgB,SAAA;cACd,kBAAC,UAAD;KACE,MAAK;KACL,cAAY,EACV,6DACA,cACF;KACA,WAAU;eAEV,kBAAC,GAAD,EAAW,WAAU,cAAe,CAAA;IAC9B,CAAA;GACM,CAAA,GAChB,kBAAC,GAAD;IAAgB,WAAU;IAAe,OAAM;cAC7C,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAU,KAAK,MAAM;MACpB,IAAM,IAAO,EAAO,IAAI,EAAE,IAAI,GAAG,QAAQ,IACnC,IAAQ,EAAG,EAAE,KAAK,EAAE,QAAQ;MAClC,OACE,kBAAC,UAAD;OAEE,MAAK;OACL,eAAe,EAAO,EAAE,IAAI;OAC5B,UAAU,EAAM;OAChB,OAAO;OACP,cAAY;OACZ,WAAW,EACT,uHACA,KAAQ,+BACV;iBAEA,kBAAC,QAAD;QAAM,eAAY;kBAAQ,EAAE;OAAY,CAAA;MAClC,GAZD,EAAE,IAYD;KAEZ,CAAC;IACE,CAAA;GACS,CAAA,CACT;IACN;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StateViews.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/components/StateViews.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"StateViews.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/components/StateViews.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAM3C,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAU5C,CAAC;AAEF,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CA2BxC,CAAC;AAEF,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAWpC,CAAC"}
|
|
@@ -1,34 +1,42 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { useTr as e } from "../hooks/useTr.js";
|
|
2
|
+
import "../hooks/index.js";
|
|
3
|
+
import { cn as t } from "../utils/cn.js";
|
|
4
|
+
import { AlertCircle as n } from "lucide-react";
|
|
5
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
6
|
+
import { Spinner as a } from "@burdenoff/fe-libs/ui";
|
|
5
7
|
//#region src/comradecircle/components/StateViews.tsx
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
className: "
|
|
10
|
-
children:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
className: "
|
|
21
|
-
children:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
8
|
+
var o = ({ label: n, className: o }) => {
|
|
9
|
+
let s = e();
|
|
10
|
+
return /* @__PURE__ */ i("div", {
|
|
11
|
+
className: t("flex min-h-[40vh] flex-col items-center justify-center gap-3", o),
|
|
12
|
+
children: [/* @__PURE__ */ r(a, { size: "lg" }), /* @__PURE__ */ r("p", {
|
|
13
|
+
className: "text-sm text-text-secondary",
|
|
14
|
+
children: n ?? s("comradecircle.components.stateViews.loading", "Loading…")
|
|
15
|
+
})]
|
|
16
|
+
});
|
|
17
|
+
}, s = ({ title: a, message: o, onRetry: s, className: c }) => {
|
|
18
|
+
let l = e();
|
|
19
|
+
return /* @__PURE__ */ i("div", {
|
|
20
|
+
className: t("flex min-h-[40vh] flex-col items-center justify-center gap-4 text-center", c),
|
|
21
|
+
children: [
|
|
22
|
+
/* @__PURE__ */ r(n, { className: "h-10 w-10 text-status-error-text" }),
|
|
23
|
+
/* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("h2", {
|
|
24
|
+
className: "text-lg font-semibold text-text-primary",
|
|
25
|
+
children: a ?? l("comradecircle.components.stateViews.errorTitle", "Something went wrong")
|
|
26
|
+
}), o && /* @__PURE__ */ r("p", {
|
|
27
|
+
className: "mt-1 max-w-md text-sm text-text-secondary",
|
|
28
|
+
children: o
|
|
29
|
+
})] }),
|
|
30
|
+
s && /* @__PURE__ */ r("button", {
|
|
31
|
+
type: "button",
|
|
32
|
+
onClick: s,
|
|
33
|
+
className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
|
|
34
|
+
children: l("comradecircle.components.stateViews.retry", "Retry")
|
|
35
|
+
})
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
};
|
|
31
39
|
//#endregion
|
|
32
|
-
export {
|
|
40
|
+
export { s as ErrorView, o as LoadingView };
|
|
33
41
|
|
|
34
42
|
//# sourceMappingURL=StateViews.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StateViews.js","names":[],"sources":["../../../src/comradecircle/components/StateViews.tsx"],"sourcesContent":["/**\n * Shared loading / error / section state views\n * @module comradecircle/components\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { AlertCircle } from 'lucide-react';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface LoadingViewProps {\n label?: string;\n className?: string;\n}\n\nexport const LoadingView: FC<LoadingViewProps> = ({ label
|
|
1
|
+
{"version":3,"file":"StateViews.js","names":[],"sources":["../../../src/comradecircle/components/StateViews.tsx"],"sourcesContent":["/**\n * Shared loading / error / section state views\n * @module comradecircle/components\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { AlertCircle } from 'lucide-react';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { useTr } from '../hooks';\nimport { cn } from '../utils/cn';\n\ninterface LoadingViewProps {\n label?: string;\n className?: string;\n}\n\nexport const LoadingView: FC<LoadingViewProps> = ({ label, className }) => {\n const tr = useTr();\n return (\n <div className={cn('flex min-h-[40vh] flex-col items-center justify-center gap-3', className)}>\n <Spinner size=\"lg\" />\n <p className=\"text-sm text-text-secondary\">\n {label ?? tr('comradecircle.components.stateViews.loading', 'Loading…')}\n </p>\n </div>\n );\n};\n\ninterface ErrorViewProps {\n title?: string;\n message?: string;\n onRetry?: () => void;\n className?: string;\n}\n\nexport const ErrorView: FC<ErrorViewProps> = ({ title, message, onRetry, className }) => {\n const tr = useTr();\n return (\n <div\n className={cn(\n 'flex min-h-[40vh] flex-col items-center justify-center gap-4 text-center',\n className\n )}\n >\n <AlertCircle className=\"h-10 w-10 text-status-error-text\" />\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {title ?? tr('comradecircle.components.stateViews.errorTitle', 'Something went wrong')}\n </h2>\n {message && <p className=\"mt-1 max-w-md text-sm text-text-secondary\">{message}</p>}\n </div>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n {tr('comradecircle.components.stateViews.retry', 'Retry')}\n </button>\n )}\n </div>\n );\n};\n\ninterface SectionProps {\n title: string;\n description?: string;\n action?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nexport const Section: FC<SectionProps> = ({ title, description, action, children, className }) => (\n <section className={cn('mt-8 first:mt-0', className)}>\n <div className=\"mb-3 flex items-end justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">{title}</h2>\n {description && <p className=\"mt-0.5 text-sm text-text-secondary\">{description}</p>}\n </div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n {children}\n </section>\n);\n"],"mappings":";;;;;;;AAgBA,IAAa,KAAqC,EAAE,UAAO,mBAAgB;CACzE,IAAM,IAAK,EAAM;CACjB,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,gEAAgE,CAAS;YAA5F,CACE,kBAAC,GAAD,EAAS,MAAK,KAAM,CAAA,GACpB,kBAAC,KAAD;GAAG,WAAU;aACV,KAAS,EAAG,+CAA+C,UAAU;EACrE,CAAA,CACA;;AAET,GASa,KAAiC,EAAE,UAAO,YAAS,YAAS,mBAAgB;CACvF,IAAM,IAAK,EAAM;CACjB,OACE,kBAAC,OAAD;EACE,WAAW,EACT,4EACA,CACF;YAJF;GAME,kBAAC,GAAD,EAAa,WAAU,mCAAoC,CAAA;GAC3D,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cACX,KAAS,EAAG,kDAAkD,sBAAsB;GACnF,CAAA,GACH,KAAW,kBAAC,KAAD;IAAG,WAAU;cAA6C;GAAW,CAAA,CAC9E,EAAA,CAAA;GACJ,KACC,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,WAAU;cAET,EAAG,6CAA6C,OAAO;GAClD,CAAA;EAEP;;AAET"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UpcomingEvents — a compact "what's next" strip for the home feed.
|
|
3
|
+
* @module comradecircle/components
|
|
4
|
+
*
|
|
5
|
+
* Reads `comListEvents(status: SCHEDULED)` — the same root field the Events page
|
|
6
|
+
* already uses — and writes `comRsvpEvent(eventId, status)` straight from the
|
|
7
|
+
* row, so the member can commit to the next gathering without leaving home.
|
|
8
|
+
* Every value shown (`title`, `startsAt`, `mode`, `location`, `rsvpCount`,
|
|
9
|
+
* `capacity`) comes from that query's own selection set.
|
|
10
|
+
*
|
|
11
|
+
* Why the client-side date filter: the svc orders `comListEvents` by
|
|
12
|
+
* `startsAt: 'asc'` and does NOT drop events whose start time has passed, so an
|
|
13
|
+
* event left in `SCHEDULED` after its slot sorts *ahead* of genuinely upcoming
|
|
14
|
+
* ones. The rail therefore reads a window of the ordered list and keeps only
|
|
15
|
+
* rows still in the future. If that window is entirely historical the strip
|
|
16
|
+
* renders nothing at all — it never claims "no upcoming events", because one
|
|
17
|
+
* page of a list is not evidence that none exist.
|
|
18
|
+
*/
|
|
19
|
+
interface UpcomingEventsProps {
|
|
20
|
+
/** Rows to render once past events are filtered out. */
|
|
21
|
+
limit?: number;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function UpcomingEvents({ limit, className }: UpcomingEventsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=UpcomingEvents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpcomingEvents.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/components/UpcomingEvents.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAgCH,UAAU,mBAAmB;IAC3B,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAS,EAAE,SAAS,EAAE,EAAE,mBAAmB,kDAgD3E"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { useComradeCircle as e } from "../context/ComradeCircleContext.js";
|
|
2
|
+
import "../context/index.js";
|
|
3
|
+
import { useComEvents as t, useComRsvpEvent as n } from "../hooks/useComradeCircleApi.js";
|
|
4
|
+
import "../hooks/index.js";
|
|
5
|
+
import { cn as r } from "../utils/cn.js";
|
|
6
|
+
import { describeError as i, notify as a } from "../lib/toast.js";
|
|
7
|
+
import { formatDateTime as o, formatNumber as s } from "../utils/formatters.js";
|
|
8
|
+
import { useEffect as c, useMemo as l, useState as u } from "react";
|
|
9
|
+
import { ArrowRight as d, CalendarDays as f, Check as p, MapPin as m, Users as h, Video as g } from "lucide-react";
|
|
10
|
+
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
11
|
+
import { Button as b } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
//#region src/comradecircle/components/UpcomingEvents.tsx
|
|
13
|
+
var x = 50, S = 6e4;
|
|
14
|
+
function C(e = S) {
|
|
15
|
+
let [t, n] = u(() => Date.now());
|
|
16
|
+
return c(() => {
|
|
17
|
+
let t = setInterval(() => n(Date.now()), e);
|
|
18
|
+
return () => clearInterval(t);
|
|
19
|
+
}, [e]), t;
|
|
20
|
+
}
|
|
21
|
+
function w({ limit: n = 3, className: i }) {
|
|
22
|
+
let { navigateTo: a } = e(), o = C(), { data: s, isLoading: c, isError: u } = t({
|
|
23
|
+
status: "SCHEDULED",
|
|
24
|
+
pagination: { limit: x }
|
|
25
|
+
}), p = l(() => (s?.items ?? []).filter((e) => new Date(e.startsAt).getTime() >= o).slice(0, n), [
|
|
26
|
+
s,
|
|
27
|
+
o,
|
|
28
|
+
n
|
|
29
|
+
]);
|
|
30
|
+
return c || u || p.length === 0 ? null : /* @__PURE__ */ y("section", {
|
|
31
|
+
className: r("mx-auto w-full max-w-2xl", i),
|
|
32
|
+
"aria-labelledby": "cc-upcoming",
|
|
33
|
+
children: [/* @__PURE__ */ y("div", {
|
|
34
|
+
className: "mb-2 flex items-center justify-between gap-3",
|
|
35
|
+
children: [/* @__PURE__ */ y("h2", {
|
|
36
|
+
id: "cc-upcoming",
|
|
37
|
+
className: "inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-text-tertiary",
|
|
38
|
+
children: [/* @__PURE__ */ v(f, { className: "h-3.5 w-3.5" }), " Upcoming events"]
|
|
39
|
+
}), /* @__PURE__ */ y("button", {
|
|
40
|
+
type: "button",
|
|
41
|
+
onClick: () => a("events"),
|
|
42
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-text-secondary transition-colors hover:text-text-primary",
|
|
43
|
+
children: ["View all ", /* @__PURE__ */ v(d, { className: "h-3 w-3" })]
|
|
44
|
+
})]
|
|
45
|
+
}), /* @__PURE__ */ v("ul", {
|
|
46
|
+
className: "overflow-hidden rounded-2xl border border-border-seam bg-bg-surface",
|
|
47
|
+
children: p.map((e) => /* @__PURE__ */ v("li", {
|
|
48
|
+
className: "border-b border-border-seam last:border-b-0",
|
|
49
|
+
children: /* @__PURE__ */ v(T, { event: e })
|
|
50
|
+
}, e.id))
|
|
51
|
+
})]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function T({ event: t }) {
|
|
55
|
+
let { navigateTo: c } = e(), l = n(), [d, x] = u(null), S = d === "GOING", C = t.mode === "IN_PERSON" ? m : g, w = t.mode === "IN_PERSON" ? t.location || "In person" : t.mode === "HYBRID" ? `Hybrid${t.location ? ` · ${t.location}` : ""}` : "Online", T = async () => {
|
|
56
|
+
try {
|
|
57
|
+
await l.mutateAsync({
|
|
58
|
+
eventId: t.id,
|
|
59
|
+
status: "GOING"
|
|
60
|
+
}), x("GOING"), a.success("RSVP: Going", t.title);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
a.error("Could not RSVP", i(e));
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
return /* @__PURE__ */ y("div", {
|
|
66
|
+
className: "flex items-center gap-3 px-4 py-3",
|
|
67
|
+
children: [
|
|
68
|
+
/* @__PURE__ */ v("span", {
|
|
69
|
+
"aria-hidden": "true",
|
|
70
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-accent",
|
|
71
|
+
children: /* @__PURE__ */ v(f, { className: "h-5 w-5" })
|
|
72
|
+
}),
|
|
73
|
+
/* @__PURE__ */ y("div", {
|
|
74
|
+
className: "min-w-0 flex-1",
|
|
75
|
+
children: [/* @__PURE__ */ v("button", {
|
|
76
|
+
type: "button",
|
|
77
|
+
onClick: () => c(`events/${t.id}`),
|
|
78
|
+
className: "block max-w-full truncate text-left text-sm font-semibold text-text-primary transition-colors hover:text-accent",
|
|
79
|
+
children: t.title
|
|
80
|
+
}), /* @__PURE__ */ y("div", {
|
|
81
|
+
className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-text-tertiary",
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ v("span", { children: o(t.startsAt) }),
|
|
84
|
+
/* @__PURE__ */ v("span", {
|
|
85
|
+
"aria-hidden": "true",
|
|
86
|
+
children: "·"
|
|
87
|
+
}),
|
|
88
|
+
/* @__PURE__ */ y("span", {
|
|
89
|
+
className: "inline-flex items-center gap-1",
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ v(C, { className: "h-3 w-3" }),
|
|
92
|
+
" ",
|
|
93
|
+
w
|
|
94
|
+
]
|
|
95
|
+
}),
|
|
96
|
+
/* @__PURE__ */ v("span", {
|
|
97
|
+
"aria-hidden": "true",
|
|
98
|
+
children: "·"
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ y("span", {
|
|
101
|
+
className: "inline-flex items-center gap-1",
|
|
102
|
+
children: [
|
|
103
|
+
/* @__PURE__ */ v(h, { className: "h-3 w-3" }),
|
|
104
|
+
s(t.rsvpCount),
|
|
105
|
+
t.capacity ? ` / ${s(t.capacity)}` : ""
|
|
106
|
+
]
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
})]
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ v(b, {
|
|
112
|
+
size: "sm",
|
|
113
|
+
variant: S ? "outline" : "default",
|
|
114
|
+
onClick: () => void T(),
|
|
115
|
+
disabled: l.isPending,
|
|
116
|
+
"aria-pressed": S,
|
|
117
|
+
className: r("shrink-0", S && "text-accent"),
|
|
118
|
+
children: S ? /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(p, { className: "mr-1 h-3.5 w-3.5" }), " Going"] }) : "RSVP"
|
|
119
|
+
})
|
|
120
|
+
]
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
//#endregion
|
|
124
|
+
export { w as UpcomingEvents };
|
|
125
|
+
|
|
126
|
+
//# sourceMappingURL=UpcomingEvents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpcomingEvents.js","names":[],"sources":["../../../src/comradecircle/components/UpcomingEvents.tsx"],"sourcesContent":["/**\n * UpcomingEvents — a compact \"what's next\" strip for the home feed.\n * @module comradecircle/components\n *\n * Reads `comListEvents(status: SCHEDULED)` — the same root field the Events page\n * already uses — and writes `comRsvpEvent(eventId, status)` straight from the\n * row, so the member can commit to the next gathering without leaving home.\n * Every value shown (`title`, `startsAt`, `mode`, `location`, `rsvpCount`,\n * `capacity`) comes from that query's own selection set.\n *\n * Why the client-side date filter: the svc orders `comListEvents` by\n * `startsAt: 'asc'` and does NOT drop events whose start time has passed, so an\n * event left in `SCHEDULED` after its slot sorts *ahead* of genuinely upcoming\n * ones. The rail therefore reads a window of the ordered list and keeps only\n * rows still in the future. If that window is entirely historical the strip\n * renders nothing at all — it never claims \"no upcoming events\", because one\n * page of a list is not evidence that none exist.\n */\n\nimport { useEffect, useMemo, useState } from 'react';\nimport { ArrowRight, CalendarDays, Check, MapPin, Users, Video } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { useComEvents, useComRsvpEvent } from '../hooks';\nimport { useComradeCircle } from '../context';\nimport { formatDateTime, formatNumber } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { ComEvent, ComRsvpStatus } from '../types';\n\n/** How far down the `startsAt`-ascending list to look for future events. */\nconst LOOKAHEAD = 50;\n\n/** How often the \"is it still in the future?\" cut-off is re-evaluated. */\nconst TICK_MS = 60_000;\n\n/**\n * A wall-clock reading that advances on its own, so a row whose start time\n * passes while the page is open drops out without waiting for a refetch.\n * Reading the clock in an effect (never in render) keeps the component pure.\n */\nfunction useNow(intervalMs: number = TICK_MS): number {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), intervalMs);\n return () => clearInterval(id);\n }, [intervalMs]);\n return now;\n}\n\ninterface UpcomingEventsProps {\n /** Rows to render once past events are filtered out. */\n limit?: number;\n className?: string;\n}\n\nexport function UpcomingEvents({ limit = 3, className }: UpcomingEventsProps) {\n const { navigateTo } = useComradeCircle();\n const now = useNow();\n const { data, isLoading, isError } = useComEvents({\n status: 'SCHEDULED',\n pagination: { limit: LOOKAHEAD },\n });\n\n const upcoming = useMemo(\n () =>\n (data?.items ?? [])\n .filter((event) => new Date(event.startsAt).getTime() >= now)\n .slice(0, limit),\n [data, now, limit]\n );\n\n // A supplementary strip above the feed: while it loads, or if it fails, the\n // feed below is the page — the rail simply stays out of the layout rather\n // than pushing the posts down for a section that may turn out to be empty.\n if (isLoading || isError || upcoming.length === 0) return null;\n\n return (\n <section className={cn('mx-auto w-full max-w-2xl', className)} aria-labelledby=\"cc-upcoming\">\n <div className=\"mb-2 flex items-center justify-between gap-3\">\n <h2\n id=\"cc-upcoming\"\n className=\"inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-text-tertiary\"\n >\n <CalendarDays className=\"h-3.5 w-3.5\" /> Upcoming events\n </h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('events')}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-text-secondary transition-colors hover:text-text-primary\"\n >\n View all <ArrowRight className=\"h-3 w-3\" />\n </button>\n </div>\n\n <ul className=\"overflow-hidden rounded-2xl border border-border-seam bg-bg-surface\">\n {upcoming.map((event) => (\n <li key={event.id} className=\"border-b border-border-seam last:border-b-0\">\n <UpcomingEventRow event={event} />\n </li>\n ))}\n </ul>\n </section>\n );\n}\n\nfunction UpcomingEventRow({ event }: { event: ComEvent }) {\n const { navigateTo } = useComradeCircle();\n const rsvp = useComRsvpEvent();\n // `comListEvents` returns aggregate `rsvpCount`, not the caller's own RSVP, so\n // the confirmed cue reflects this session's mutation only — the same contract\n // EventCard documents.\n const [myStatus, setMyStatus] = useState<ComRsvpStatus | null>(null);\n\n const going = myStatus === 'GOING';\n const ModeIcon = event.mode === 'IN_PERSON' ? MapPin : Video;\n const where =\n event.mode === 'IN_PERSON'\n ? event.location || 'In person'\n : event.mode === 'HYBRID'\n ? `Hybrid${event.location ? ` · ${event.location}` : ''}`\n : 'Online';\n\n const doRsvp = async () => {\n try {\n await rsvp.mutateAsync({ eventId: event.id, status: 'GOING' });\n setMyStatus('GOING');\n notify.success('RSVP: Going', event.title);\n } catch (err) {\n notify.error('Could not RSVP', describeError(err));\n }\n };\n\n return (\n <div className=\"flex items-center gap-3 px-4 py-3\">\n <span\n aria-hidden=\"true\"\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-accent\"\n >\n <CalendarDays className=\"h-5 w-5\" />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`events/${event.id}`)}\n className=\"block max-w-full truncate text-left text-sm font-semibold text-text-primary transition-colors hover:text-accent\"\n >\n {event.title}\n </button>\n <div className=\"mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-text-tertiary\">\n <span>{formatDateTime(event.startsAt)}</span>\n <span aria-hidden=\"true\">·</span>\n <span className=\"inline-flex items-center gap-1\">\n <ModeIcon className=\"h-3 w-3\" /> {where}\n </span>\n <span aria-hidden=\"true\">·</span>\n <span className=\"inline-flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {formatNumber(event.rsvpCount)}\n {event.capacity ? ` / ${formatNumber(event.capacity)}` : ''}\n </span>\n </div>\n </div>\n\n <Button\n size=\"sm\"\n variant={going ? 'outline' : 'default'}\n onClick={() => void doRsvp()}\n disabled={rsvp.isPending}\n aria-pressed={going}\n className={cn('shrink-0', going && 'text-accent')}\n >\n {going ? (\n <>\n <Check className=\"mr-1 h-3.5 w-3.5\" /> Going\n </>\n ) : (\n 'RSVP'\n )}\n </Button>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -22,7 +22,9 @@ export { TagInput } from './TagInput';
|
|
|
22
22
|
export { ReactionBar } from './ReactionBar';
|
|
23
23
|
export { CommentThread } from './CommentThread';
|
|
24
24
|
export { PostComposer } from './PostComposer';
|
|
25
|
+
export { DraftsPanel } from './DraftsPanel';
|
|
25
26
|
export { PostCard } from './PostCard';
|
|
27
|
+
export { UpcomingEvents } from './UpcomingEvents';
|
|
26
28
|
export { CircleCard } from './CircleCard';
|
|
27
29
|
export { EventCard } from './EventCard';
|
|
28
30
|
export { PollCard } from './PollCard';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/components/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/components/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTr — translation hook with fallback semantics.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `useI18n().t()` so that when a key has no translation (i.e. the
|
|
5
|
+
* provider returns the key itself), the caller's English fallback is used
|
|
6
|
+
* instead. This keeps consumer call sites consistent and avoids leaking
|
|
7
|
+
* untranslated keys into the UI.
|
|
8
|
+
*
|
|
9
|
+
* Supports optional interpolation params using `{{key}}` placeholders.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const tr = useTr();
|
|
13
|
+
* return <h1>{tr('comradecircle.pages.feed.title', 'Home')}</h1>;
|
|
14
|
+
* return <p>{tr('comradecircle.components.pagination.showing', 'Showing {{from}}–{{to}}', { from: 1, to: 10 })}</p>;
|
|
15
|
+
*/
|
|
16
|
+
export type TranslationParams = Record<string, string | number>;
|
|
17
|
+
export declare function useTr(): (key: string, fallback: string, params?: TranslationParams) => string;
|
|
18
|
+
//# sourceMappingURL=useTr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTr.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/hooks/useTr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEhE,wBAAgB,KAAK,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,iBAAiB,KAAK,MAAM,CAQ7F"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { tWithFallback as e } from "../utils/i18n.js";
|
|
2
|
+
import { useCallback as t } from "react";
|
|
3
|
+
import { useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
4
|
+
//#region src/comradecircle/hooks/useTr.ts
|
|
5
|
+
function r() {
|
|
6
|
+
let { t: r } = n();
|
|
7
|
+
return t((t, n, i) => e(r, t, n, i), [r]);
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { r as useTr };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=useTr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTr.js","names":[],"sources":["../../../src/comradecircle/hooks/useTr.ts"],"sourcesContent":["/**\n * useTr — translation hook with fallback semantics.\n *\n * Wraps `useI18n().t()` so that when a key has no translation (i.e. the\n * provider returns the key itself), the caller's English fallback is used\n * instead. This keeps consumer call sites consistent and avoids leaking\n * untranslated keys into the UI.\n *\n * Supports optional interpolation params using `{{key}}` placeholders.\n *\n * @example\n * const tr = useTr();\n * return <h1>{tr('comradecircle.pages.feed.title', 'Home')}</h1>;\n * return <p>{tr('comradecircle.components.pagination.showing', 'Showing {{from}}–{{to}}', { from: 1, to: 10 })}</p>;\n */\n\nimport { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\n\nexport type TranslationParams = Record<string, string | number>;\n\nexport function useTr(): (key: string, fallback: string, params?: TranslationParams) => string {\n const { t } = useI18n();\n\n return useCallback(\n (key: string, fallback: string, params?: TranslationParams): string =>\n tWithFallback(t, key, fallback, params),\n [t]\n );\n}\n"],"mappings":";;;;AAsBA,SAAgB,IAA+E;CAC7F,IAAM,EAAE,SAAM,EAAQ;CAEtB,OAAO,GACJ,GAAa,GAAkB,MAC9B,EAAc,GAAG,GAAK,GAAU,CAAM,GACxC,CAAC,CAAC,CACJ;AACF"}
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
* Reads `comMyFeed` (published posts from every channel, member, and circle the
|
|
6
6
|
* caller follows, newest first). A new member with no follows sees a guided
|
|
7
7
|
* empty state pointing at circle & member discovery.
|
|
8
|
+
*
|
|
9
|
+
* Above the post column sits {@link UpcomingEvents} — the mobile home mock
|
|
10
|
+
* shows the home surface carrying the member's next gathering (with an RSVP
|
|
11
|
+
* affordance), not posts alone. It is a separate `comListEvents` read because
|
|
12
|
+
* `comMyFeed` returns `ComPost` rows only.
|
|
8
13
|
*/
|
|
9
14
|
export declare function FeedPage(): import("react/jsx-runtime").JSX.Element;
|
|
10
15
|
//# sourceMappingURL=FeedPage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeedPage.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/pages/FeedPage.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"FeedPage.d.ts","sourceRoot":"","sources":["../../../src/comradecircle/pages/FeedPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAkEH,wBAAgB,QAAQ,4CAgFvB"}
|