@burdenoff/microfe-comradecircle 2026.512.1 → 2026.704.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/comradecircle/ComradeCircleRoot.js +75 -95
- package/dist/comradecircle/ComradeCircleRoot.js.map +1 -1
- package/dist/comradecircle/ComradeCircleRoutes.js +58 -37
- package/dist/comradecircle/ComradeCircleRoutes.js.map +1 -1
- package/dist/comradecircle/components/Avatar.js +35 -0
- package/dist/comradecircle/components/Avatar.js.map +1 -0
- package/dist/comradecircle/components/CircleCard.js +117 -0
- package/dist/comradecircle/components/CircleCard.js.map +1 -0
- package/dist/comradecircle/components/CommentThread.js +105 -0
- package/dist/comradecircle/components/CommentThread.js.map +1 -0
- package/dist/comradecircle/components/CreateCircleDialog.js +148 -0
- package/dist/comradecircle/components/CreateCircleDialog.js.map +1 -0
- package/dist/comradecircle/components/CreateEventDialog.js +210 -0
- package/dist/comradecircle/components/CreateEventDialog.js.map +1 -0
- package/dist/comradecircle/components/EmptyState.js +35 -0
- package/dist/comradecircle/components/EmptyState.js.map +1 -0
- package/dist/comradecircle/components/EventCard.js +93 -0
- package/dist/comradecircle/components/EventCard.js.map +1 -0
- package/dist/comradecircle/components/FilterTabs.js +27 -0
- package/dist/comradecircle/components/FilterTabs.js.map +1 -0
- package/dist/comradecircle/components/MemberIdentity.js +43 -0
- package/dist/comradecircle/components/MemberIdentity.js.map +1 -0
- package/dist/comradecircle/components/MiniBar.js +22 -0
- package/dist/comradecircle/components/MiniBar.js.map +1 -0
- package/dist/comradecircle/components/PageLayout.js +38 -0
- package/dist/comradecircle/components/PageLayout.js.map +1 -0
- package/dist/comradecircle/components/Pagination.js +50 -0
- package/dist/comradecircle/components/Pagination.js.map +1 -0
- package/dist/comradecircle/components/PollCard.js +97 -0
- package/dist/comradecircle/components/PollCard.js.map +1 -0
- package/dist/comradecircle/components/PostCard.js +170 -0
- package/dist/comradecircle/components/PostCard.js.map +1 -0
- package/dist/comradecircle/components/PostComposer.js +77 -0
- package/dist/comradecircle/components/PostComposer.js.map +1 -0
- package/dist/comradecircle/components/ReactionBar.js +122 -0
- package/dist/comradecircle/components/ReactionBar.js.map +1 -0
- package/dist/comradecircle/components/StateViews.js +49 -0
- package/dist/comradecircle/components/StateViews.js.map +1 -0
- package/dist/comradecircle/components/StatusBadge.js +68 -0
- package/dist/comradecircle/components/StatusBadge.js.map +1 -0
- package/dist/comradecircle/components/Tabs.js +31 -0
- package/dist/comradecircle/components/Tabs.js.map +1 -0
- package/dist/comradecircle/components/TagInput.js +49 -0
- package/dist/comradecircle/components/TagInput.js.map +1 -0
- package/dist/comradecircle/context/ComradeCircleContext.js +85 -0
- package/dist/comradecircle/context/ComradeCircleContext.js.map +1 -0
- package/dist/comradecircle/context/index.js +1 -0
- package/dist/comradecircle/hooks/index.js +2 -0
- package/dist/comradecircle/hooks/useComradeCircleApi.js +416 -0
- package/dist/comradecircle/hooks/useComradeCircleApi.js.map +1 -0
- package/dist/comradecircle/hooks/useCursorPager.js +25 -0
- package/dist/comradecircle/hooks/useCursorPager.js.map +1 -0
- package/dist/comradecircle/index.js +5 -2
- package/dist/comradecircle/lib/toast.js +39 -0
- package/dist/comradecircle/lib/toast.js.map +1 -0
- package/dist/comradecircle/pages/FeedPage.js +65 -0
- package/dist/comradecircle/pages/FeedPage.js.map +1 -0
- package/dist/comradecircle/pages/circles/CircleDetailPage.js +650 -0
- package/dist/comradecircle/pages/circles/CircleDetailPage.js.map +1 -0
- package/dist/comradecircle/pages/circles/CirclesPage.js +129 -0
- package/dist/comradecircle/pages/circles/CirclesPage.js.map +1 -0
- package/dist/comradecircle/pages/events/EventDetailPage.js +276 -0
- package/dist/comradecircle/pages/events/EventDetailPage.js.map +1 -0
- package/dist/comradecircle/pages/events/EventsPage.js +102 -0
- package/dist/comradecircle/pages/events/EventsPage.js.map +1 -0
- package/dist/comradecircle/pages/members/MemberProfilePage.js +137 -0
- package/dist/comradecircle/pages/members/MemberProfilePage.js.map +1 -0
- package/dist/comradecircle/pages/members/MembersPage.js +152 -0
- package/dist/comradecircle/pages/members/MembersPage.js.map +1 -0
- package/dist/comradecircle/pages/profile/MyProfilePage.js +255 -0
- package/dist/comradecircle/pages/profile/MyProfilePage.js.map +1 -0
- package/dist/comradecircle/utils/cn.js +10 -0
- package/dist/comradecircle/utils/cn.js.map +1 -0
- package/dist/comradecircle/utils/formatters.js +51 -0
- package/dist/comradecircle/utils/formatters.js.map +1 -0
- package/dist/comradecircle/utils/navigation.js +2 -1
- package/dist/comradecircle/utils/navigation.js.map +1 -1
- package/dist/comradecircle/utils/slug.js +8 -0
- package/dist/comradecircle/utils/slug.js.map +1 -0
- package/dist/index.js +6 -4
- package/dist/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/sonner/dist/index.js +163 -0
- package/dist/node_modules/sonner/dist/index.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/package.json +3 -2
- package/dist/comradecircle/ComradeCircleRoot.d.ts +0 -5
- package/dist/comradecircle/ComradeCircleRoot.d.ts.map +0 -1
- package/dist/comradecircle/ComradeCircleRoutes.d.ts +0 -2
- package/dist/comradecircle/ComradeCircleRoutes.d.ts.map +0 -1
- package/dist/comradecircle/index.d.ts +0 -5
- package/dist/comradecircle/index.d.ts.map +0 -1
- package/dist/comradecircle/pages/CommunitiesPage.d.ts +0 -2
- package/dist/comradecircle/pages/CommunitiesPage.d.ts.map +0 -1
- package/dist/comradecircle/pages/CommunitiesPage.js +0 -299
- package/dist/comradecircle/pages/CommunitiesPage.js.map +0 -1
- package/dist/comradecircle/pages/CreatorPage.d.ts +0 -2
- package/dist/comradecircle/pages/CreatorPage.d.ts.map +0 -1
- package/dist/comradecircle/pages/CreatorPage.js +0 -399
- package/dist/comradecircle/pages/CreatorPage.js.map +0 -1
- package/dist/comradecircle/pages/DashboardPage.d.ts +0 -2
- package/dist/comradecircle/pages/DashboardPage.d.ts.map +0 -1
- package/dist/comradecircle/pages/DashboardPage.js +0 -265
- package/dist/comradecircle/pages/DashboardPage.js.map +0 -1
- package/dist/comradecircle/providers/ComradeCircleProvider.d.ts +0 -6
- package/dist/comradecircle/providers/ComradeCircleProvider.d.ts.map +0 -1
- package/dist/comradecircle/providers/ComradeCircleProvider.js +0 -27
- package/dist/comradecircle/providers/ComradeCircleProvider.js.map +0 -1
- package/dist/comradecircle/store/comradecircleStore.d.ts +0 -28
- package/dist/comradecircle/store/comradecircleStore.d.ts.map +0 -1
- package/dist/comradecircle/store/comradecircleStore.js +0 -345
- package/dist/comradecircle/store/comradecircleStore.js.map +0 -1
- package/dist/comradecircle/types/index.d.ts +0 -162
- package/dist/comradecircle/types/index.d.ts.map +0 -1
- package/dist/comradecircle/utils/cn.d.ts +0 -4
- package/dist/comradecircle/utils/cn.d.ts.map +0 -1
- package/dist/comradecircle/utils/navigation.d.ts +0 -2
- package/dist/comradecircle/utils/navigation.d.ts.map +0 -1
- package/dist/dev/main.d.ts +0 -2
- package/dist/dev/main.d.ts.map +0 -1
- package/dist/generated/global-operations.d.ts +0 -2
- package/dist/generated/global-operations.d.ts.map +0 -1
- package/dist/generated/global-types.d.ts +0 -18199
- package/dist/generated/global-types.d.ts.map +0 -1
- package/dist/generated/wspace-operations.d.ts +0 -2
- package/dist/generated/wspace-operations.d.ts.map +0 -1
- package/dist/generated/wspace-types.d.ts +0 -43046
- package/dist/generated/wspace-types.d.ts.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { cn as e } from "../utils/cn.js";
|
|
2
|
+
import { useComAddComment as t, useComComments as n } from "../hooks/useComradeCircleApi.js";
|
|
3
|
+
import "../hooks/index.js";
|
|
4
|
+
import { MemberIdentity as r } from "./MemberIdentity.js";
|
|
5
|
+
import { describeError as i, notify as a } from "../lib/toast.js";
|
|
6
|
+
import { formatRelativeTime as o } from "../utils/formatters.js";
|
|
7
|
+
import { useMemo as s, useState as c } from "react";
|
|
8
|
+
import { CornerDownRight as l, Send as u } from "lucide-react";
|
|
9
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
10
|
+
import { Button as p, Spinner as m, Textarea as h } from "@burdenoff/fe-libs/ui";
|
|
11
|
+
//#region src/comradecircle/components/CommentThread.tsx
|
|
12
|
+
function g({ postId: g }) {
|
|
13
|
+
let { data: _, isLoading: v } = n(g), y = t(), [b, x] = c(""), [S, C] = c(null), { roots: w, repliesByParent: T } = s(() => {
|
|
14
|
+
let e = _ ?? [], t = /* @__PURE__ */ new Map(), n = [];
|
|
15
|
+
for (let r of e) if (r.parentId) {
|
|
16
|
+
let e = t.get(r.parentId) ?? [];
|
|
17
|
+
e.push(r), t.set(r.parentId, e);
|
|
18
|
+
} else n.push(r);
|
|
19
|
+
return {
|
|
20
|
+
roots: n,
|
|
21
|
+
repliesByParent: t
|
|
22
|
+
};
|
|
23
|
+
}, [_]), E = async () => {
|
|
24
|
+
let e = b.trim();
|
|
25
|
+
if (e) try {
|
|
26
|
+
await y.mutateAsync({
|
|
27
|
+
postId: g,
|
|
28
|
+
body: e,
|
|
29
|
+
parentId: S?.id ?? null
|
|
30
|
+
}), x(""), C(null);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
a.error("Could not add comment", i(e));
|
|
33
|
+
}
|
|
34
|
+
}, D = (t, n = !1) => /* @__PURE__ */ f("div", {
|
|
35
|
+
className: e("flex flex-col gap-1", n && "ml-8"),
|
|
36
|
+
children: [/* @__PURE__ */ f("div", {
|
|
37
|
+
className: "rounded-xl bg-bg-sunken/60 px-3 py-2",
|
|
38
|
+
children: [/* @__PURE__ */ f("div", {
|
|
39
|
+
className: "flex items-center justify-between gap-2",
|
|
40
|
+
children: [/* @__PURE__ */ d(r, {
|
|
41
|
+
memberId: t.authorId,
|
|
42
|
+
size: "xs",
|
|
43
|
+
suffix: o(t.createdAt)
|
|
44
|
+
}), !n && /* @__PURE__ */ f("button", {
|
|
45
|
+
type: "button",
|
|
46
|
+
onClick: () => C(t),
|
|
47
|
+
className: "inline-flex items-center gap-1 text-xs text-text-tertiary transition-colors hover:text-text-primary",
|
|
48
|
+
children: [/* @__PURE__ */ d(l, { className: "h-3 w-3" }), " Reply"]
|
|
49
|
+
})]
|
|
50
|
+
}), /* @__PURE__ */ d("p", {
|
|
51
|
+
className: "mt-1 whitespace-pre-wrap break-words text-sm text-text-primary",
|
|
52
|
+
children: t.body
|
|
53
|
+
})]
|
|
54
|
+
}), (T.get(t.id) ?? []).map((e) => D(e, !0))]
|
|
55
|
+
}, t.id);
|
|
56
|
+
return /* @__PURE__ */ f("div", {
|
|
57
|
+
className: "mt-3 border-t border-border-seam pt-3",
|
|
58
|
+
children: [v ? /* @__PURE__ */ d("div", {
|
|
59
|
+
className: "flex justify-center py-4",
|
|
60
|
+
children: /* @__PURE__ */ d(m, { size: "sm" })
|
|
61
|
+
}) : w.length === 0 ? /* @__PURE__ */ d("p", {
|
|
62
|
+
className: "py-2 text-center text-sm text-text-tertiary",
|
|
63
|
+
children: "No comments yet. Start the conversation."
|
|
64
|
+
}) : /* @__PURE__ */ d("div", {
|
|
65
|
+
className: "flex flex-col gap-3",
|
|
66
|
+
children: w.map((e) => D(e))
|
|
67
|
+
}), /* @__PURE__ */ f("div", {
|
|
68
|
+
className: "mt-3 flex flex-col gap-2",
|
|
69
|
+
children: [S && /* @__PURE__ */ f("div", {
|
|
70
|
+
className: "flex items-center justify-between rounded-lg bg-bg-sunken px-3 py-1.5 text-xs text-text-secondary",
|
|
71
|
+
children: [/* @__PURE__ */ d("span", {
|
|
72
|
+
className: "truncate",
|
|
73
|
+
children: "Replying to a comment"
|
|
74
|
+
}), /* @__PURE__ */ d("button", {
|
|
75
|
+
type: "button",
|
|
76
|
+
onClick: () => C(null),
|
|
77
|
+
className: "text-text-tertiary hover:text-text-primary",
|
|
78
|
+
children: "Cancel"
|
|
79
|
+
})]
|
|
80
|
+
}), /* @__PURE__ */ f("div", {
|
|
81
|
+
className: "flex items-end gap-2",
|
|
82
|
+
children: [/* @__PURE__ */ d(h, {
|
|
83
|
+
value: b,
|
|
84
|
+
onChange: (e) => x(e.target.value),
|
|
85
|
+
placeholder: "Add a comment…",
|
|
86
|
+
rows: 1,
|
|
87
|
+
className: "min-h-[40px] resize-none",
|
|
88
|
+
onKeyDown: (e) => {
|
|
89
|
+
e.key === "Enter" && (e.metaKey || e.ctrlKey) && (e.preventDefault(), E());
|
|
90
|
+
}
|
|
91
|
+
}), /* @__PURE__ */ d(p, {
|
|
92
|
+
size: "sm",
|
|
93
|
+
onClick: E,
|
|
94
|
+
disabled: !b.trim() || y.isPending,
|
|
95
|
+
"aria-label": "Post comment",
|
|
96
|
+
children: /* @__PURE__ */ d(u, { className: "h-4 w-4" })
|
|
97
|
+
})]
|
|
98
|
+
})]
|
|
99
|
+
})]
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { g as CommentThread };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=CommentThread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentThread.js","names":[],"sources":["../../../src/comradecircle/components/CommentThread.tsx"],"sourcesContent":["/**\n * CommentThread — threaded comments for a post.\n * @module comradecircle/components\n *\n * Reads `comListComments(postId)`; writes `comAddComment`. Top-level comments\n * (parentId == null) render replies one level deep. Author identity comes from\n * `ComProfile` via {@link MemberIdentity}.\n */\n\nimport { useMemo, useState } from 'react';\nimport { CornerDownRight, Send } from 'lucide-react';\nimport { Button, Textarea, Spinner } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { useComComments, useComAddComment } from '../hooks';\nimport { MemberIdentity } from './MemberIdentity';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { ComComment } from '../types';\n\ninterface CommentThreadProps {\n postId: string;\n}\n\nexport function CommentThread({ postId }: CommentThreadProps) {\n const { data: comments, isLoading } = useComComments(postId);\n const addComment = useComAddComment();\n const [body, setBody] = useState('');\n const [replyTo, setReplyTo] = useState<ComComment | null>(null);\n\n const { roots, repliesByParent } = useMemo(() => {\n const list = comments ?? [];\n const repliesMap = new Map<string, ComComment[]>();\n const top: ComComment[] = [];\n for (const c of list) {\n if (c.parentId) {\n const arr = repliesMap.get(c.parentId) ?? [];\n arr.push(c);\n repliesMap.set(c.parentId, arr);\n } else {\n top.push(c);\n }\n }\n return { roots: top, repliesByParent: repliesMap };\n }, [comments]);\n\n const submit = async () => {\n const text = body.trim();\n if (!text) return;\n try {\n await addComment.mutateAsync({ postId, body: text, parentId: replyTo?.id ?? null });\n setBody('');\n setReplyTo(null);\n } catch (err) {\n notify.error('Could not add comment', describeError(err));\n }\n };\n\n const renderComment = (c: ComComment, isReply = false) => (\n <div key={c.id} className={cn('flex flex-col gap-1', isReply && 'ml-8')}>\n <div className=\"rounded-xl bg-bg-sunken/60 px-3 py-2\">\n <div className=\"flex items-center justify-between gap-2\">\n <MemberIdentity\n memberId={c.authorId}\n size=\"xs\"\n suffix={formatRelativeTime(c.createdAt)}\n />\n {!isReply && (\n <button\n type=\"button\"\n onClick={() => setReplyTo(c)}\n className=\"inline-flex items-center gap-1 text-xs text-text-tertiary transition-colors hover:text-text-primary\"\n >\n <CornerDownRight className=\"h-3 w-3\" /> Reply\n </button>\n )}\n </div>\n <p className=\"mt-1 whitespace-pre-wrap break-words text-sm text-text-primary\">{c.body}</p>\n </div>\n {(repliesByParent.get(c.id) ?? []).map((r) => renderComment(r, true))}\n </div>\n );\n\n return (\n <div className=\"mt-3 border-t border-border-seam pt-3\">\n {isLoading ? (\n <div className=\"flex justify-center py-4\">\n <Spinner size=\"sm\" />\n </div>\n ) : roots.length === 0 ? (\n <p className=\"py-2 text-center text-sm text-text-tertiary\">\n No comments yet. Start the conversation.\n </p>\n ) : (\n <div className=\"flex flex-col gap-3\">{roots.map((c) => renderComment(c))}</div>\n )}\n\n <div className=\"mt-3 flex flex-col gap-2\">\n {replyTo && (\n <div className=\"flex items-center justify-between rounded-lg bg-bg-sunken px-3 py-1.5 text-xs text-text-secondary\">\n <span className=\"truncate\">Replying to a comment</span>\n <button\n type=\"button\"\n onClick={() => setReplyTo(null)}\n className=\"text-text-tertiary hover:text-text-primary\"\n >\n Cancel\n </button>\n </div>\n )}\n <div className=\"flex items-end gap-2\">\n <Textarea\n value={body}\n onChange={(e) => setBody(e.target.value)}\n placeholder=\"Add a comment…\"\n rows={1}\n className=\"min-h-[40px] resize-none\"\n onKeyDown={(e) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n void submit();\n }\n }}\n />\n <Button\n size=\"sm\"\n onClick={submit}\n disabled={!body.trim() || addComment.isPending}\n aria-label=\"Post comment\"\n >\n <Send className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;AAuBA,SAAgB,EAAc,EAAE,aAA8B;CAC5D,IAAM,EAAE,MAAM,GAAU,iBAAc,EAAe,EAAO,EACtD,IAAa,GAAkB,EAC/B,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAS,KAAc,EAA4B,KAAK,EAEzD,EAAE,UAAO,uBAAoB,QAAc;EAC/C,IAAM,IAAO,KAAY,EAAE,EACrB,oBAAa,IAAI,KAA2B,EAC5C,IAAoB,EAAE;AAC5B,OAAK,IAAM,KAAK,EACd,KAAI,EAAE,UAAU;GACd,IAAM,IAAM,EAAW,IAAI,EAAE,SAAS,IAAI,EAAE;AAE5C,GADA,EAAI,KAAK,EAAE,EACX,EAAW,IAAI,EAAE,UAAU,EAAI;QAE/B,GAAI,KAAK,EAAE;AAGf,SAAO;GAAE,OAAO;GAAK,iBAAiB;GAAY;IACjD,CAAC,EAAS,CAAC,EAER,IAAS,YAAY;EACzB,IAAM,IAAO,EAAK,MAAM;AACnB,QACL,KAAI;AAGF,GAFA,MAAM,EAAW,YAAY;IAAE;IAAQ,MAAM;IAAM,UAAU,GAAS,MAAM;IAAM,CAAC,EACnF,EAAQ,GAAG,EACX,EAAW,KAAK;WACT,GAAK;AACZ,KAAO,MAAM,yBAAyB,EAAc,EAAI,CAAC;;IAIvD,KAAiB,GAAe,IAAU,OAC9C,kBAAC,OAAD;EAAgB,WAAW,EAAG,uBAAuB,KAAW,OAAO;YAAvE,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,UAAU,EAAE;KACZ,MAAK;KACL,QAAQ,EAAmB,EAAE,UAAU;KACvC,CAAA,EACD,CAAC,KACA,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAW,EAAE;KAC5B,WAAU;eAHZ,CAKE,kBAAC,GAAD,EAAiB,WAAU,WAAY,CAAA,EAAA,SAChC;OAEP;OACN,kBAAC,KAAD;IAAG,WAAU;cAAkE,EAAE;IAAS,CAAA,CACtF;OACJ,EAAgB,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,MAAM,EAAc,GAAG,GAAK,CAAC,CACjE;IArBI,EAAE,GAqBN;AAGR,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,IACC,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA;GACjB,CAAA,GACJ,EAAM,WAAW,IACnB,kBAAC,KAAD;GAAG,WAAU;aAA8C;GAEvD,CAAA,GAEJ,kBAAC,OAAD;GAAK,WAAU;aAAuB,EAAM,KAAK,MAAM,EAAc,EAAE,CAAC;GAAO,CAAA,EAGjF,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;eAAW;KAA4B,CAAA,EACvD,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAW,KAAK;KAC/B,WAAU;eACX;KAEQ,CAAA,CACL;OAER,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,OAAO;KACP,WAAW,MAAM,EAAQ,EAAE,OAAO,MAAM;KACxC,aAAY;KACZ,MAAM;KACN,WAAU;KACV,YAAY,MAAM;AAChB,MAAI,EAAE,QAAQ,YAAY,EAAE,WAAW,EAAE,aACvC,EAAE,gBAAgB,EACb,GAAQ;;KAGjB,CAAA,EACF,kBAAC,GAAD;KACE,MAAK;KACL,SAAS;KACT,UAAU,CAAC,EAAK,MAAM,IAAI,EAAW;KACrC,cAAW;eAEX,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;KACrB,CAAA,CACL;MACF;KACF"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { useComCreateCircle as e } from "../hooks/useComradeCircleApi.js";
|
|
2
|
+
import "../hooks/index.js";
|
|
3
|
+
import { describeError as t, notify as n } from "../lib/toast.js";
|
|
4
|
+
import { formatEnumLabel as r } from "../utils/formatters.js";
|
|
5
|
+
import { slugify as i } from "../utils/slug.js";
|
|
6
|
+
import { TagInput as a } from "./TagInput.js";
|
|
7
|
+
import { useState as o } from "react";
|
|
8
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
9
|
+
import { Button as l, Input as u, Label as d, ResponsiveDialog as f, ResponsiveDialogContent as p, ResponsiveDialogDescription as m, ResponsiveDialogFooter as h, ResponsiveDialogHeader as g, ResponsiveDialogTitle as _, Select as v, SelectContent as y, SelectItem as b, SelectTrigger as x, SelectValue as S, Textarea as C } from "@burdenoff/fe-libs/ui";
|
|
10
|
+
//#region src/comradecircle/components/CreateCircleDialog.tsx
|
|
11
|
+
var w = [
|
|
12
|
+
"PUBLIC",
|
|
13
|
+
"PRIVATE",
|
|
14
|
+
"SECRET"
|
|
15
|
+
];
|
|
16
|
+
function T({ open: T, onOpenChange: E, onCreated: D }) {
|
|
17
|
+
let O = e(), [k, A] = o(""), [j, M] = o(""), [N, P] = o(!1), [F, I] = o(""), [L, R] = o(""), [z, B] = o("PUBLIC"), [V, H] = o([]), [U, W] = o(null), G = N ? j : i(k), K = () => {
|
|
18
|
+
A(""), M(""), P(!1), I(""), R(""), B("PUBLIC"), H([]), W(null);
|
|
19
|
+
};
|
|
20
|
+
return /* @__PURE__ */ s(f, {
|
|
21
|
+
open: T,
|
|
22
|
+
onOpenChange: E,
|
|
23
|
+
children: /* @__PURE__ */ c(p, {
|
|
24
|
+
className: "sm:max-w-lg",
|
|
25
|
+
children: [
|
|
26
|
+
/* @__PURE__ */ c(g, { children: [/* @__PURE__ */ s(_, { children: "Create a circle" }), /* @__PURE__ */ s(m, { children: "A circle is a community space with its own channels, members, events, and polls." })] }),
|
|
27
|
+
/* @__PURE__ */ c("div", {
|
|
28
|
+
className: "flex flex-col gap-4 py-2",
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ c("div", {
|
|
31
|
+
className: "grid gap-1.5",
|
|
32
|
+
children: [/* @__PURE__ */ s(d, {
|
|
33
|
+
htmlFor: "circle-name",
|
|
34
|
+
children: "Name"
|
|
35
|
+
}), /* @__PURE__ */ s(u, {
|
|
36
|
+
id: "circle-name",
|
|
37
|
+
value: k,
|
|
38
|
+
onChange: (e) => A(e.target.value),
|
|
39
|
+
placeholder: "e.g. Product Guild"
|
|
40
|
+
})]
|
|
41
|
+
}),
|
|
42
|
+
/* @__PURE__ */ c("div", {
|
|
43
|
+
className: "grid gap-1.5",
|
|
44
|
+
children: [/* @__PURE__ */ s(d, {
|
|
45
|
+
htmlFor: "circle-slug",
|
|
46
|
+
children: "URL slug"
|
|
47
|
+
}), /* @__PURE__ */ s(u, {
|
|
48
|
+
id: "circle-slug",
|
|
49
|
+
value: G,
|
|
50
|
+
onChange: (e) => {
|
|
51
|
+
P(!0), M(i(e.target.value));
|
|
52
|
+
},
|
|
53
|
+
placeholder: "product-guild"
|
|
54
|
+
})]
|
|
55
|
+
}),
|
|
56
|
+
/* @__PURE__ */ c("div", {
|
|
57
|
+
className: "grid gap-1.5",
|
|
58
|
+
children: [/* @__PURE__ */ s(d, {
|
|
59
|
+
htmlFor: "circle-topic",
|
|
60
|
+
children: "Topic"
|
|
61
|
+
}), /* @__PURE__ */ s(u, {
|
|
62
|
+
id: "circle-topic",
|
|
63
|
+
value: F,
|
|
64
|
+
onChange: (e) => I(e.target.value),
|
|
65
|
+
placeholder: "A short one-line topic"
|
|
66
|
+
})]
|
|
67
|
+
}),
|
|
68
|
+
/* @__PURE__ */ c("div", {
|
|
69
|
+
className: "grid gap-1.5",
|
|
70
|
+
children: [/* @__PURE__ */ s(d, {
|
|
71
|
+
htmlFor: "circle-desc",
|
|
72
|
+
children: "Description"
|
|
73
|
+
}), /* @__PURE__ */ s(C, {
|
|
74
|
+
id: "circle-desc",
|
|
75
|
+
value: L,
|
|
76
|
+
onChange: (e) => R(e.target.value),
|
|
77
|
+
placeholder: "What is this circle about?",
|
|
78
|
+
rows: 3
|
|
79
|
+
})]
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ c("div", {
|
|
82
|
+
className: "grid gap-1.5",
|
|
83
|
+
children: [/* @__PURE__ */ s(d, { children: "Visibility" }), /* @__PURE__ */ c(v, {
|
|
84
|
+
value: z,
|
|
85
|
+
onValueChange: (e) => B(e),
|
|
86
|
+
children: [/* @__PURE__ */ s(x, { children: /* @__PURE__ */ s(S, {}) }), /* @__PURE__ */ s(y, { children: w.map((e) => /* @__PURE__ */ s(b, {
|
|
87
|
+
value: e,
|
|
88
|
+
children: r(e)
|
|
89
|
+
}, e)) })]
|
|
90
|
+
})]
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ c("div", {
|
|
93
|
+
className: "grid gap-1.5",
|
|
94
|
+
children: [/* @__PURE__ */ s(d, {
|
|
95
|
+
htmlFor: "circle-tags",
|
|
96
|
+
children: "Tags"
|
|
97
|
+
}), /* @__PURE__ */ s(a, {
|
|
98
|
+
id: "circle-tags",
|
|
99
|
+
value: V,
|
|
100
|
+
onChange: H,
|
|
101
|
+
placeholder: "Add tags…"
|
|
102
|
+
})]
|
|
103
|
+
}),
|
|
104
|
+
U && /* @__PURE__ */ s("p", {
|
|
105
|
+
className: "text-sm text-status-error-text",
|
|
106
|
+
children: U
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
}),
|
|
110
|
+
/* @__PURE__ */ c(h, { children: [/* @__PURE__ */ s(l, {
|
|
111
|
+
variant: "outline",
|
|
112
|
+
onClick: () => E(!1),
|
|
113
|
+
children: "Cancel"
|
|
114
|
+
}), /* @__PURE__ */ s(l, {
|
|
115
|
+
onClick: async () => {
|
|
116
|
+
if (!k.trim()) {
|
|
117
|
+
W("Circle name is required.");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!G) {
|
|
121
|
+
W("A URL slug is required.");
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
let e = await O.mutateAsync({
|
|
126
|
+
name: k.trim(),
|
|
127
|
+
slug: G,
|
|
128
|
+
topic: F.trim() || null,
|
|
129
|
+
description: L.trim() || null,
|
|
130
|
+
visibility: z,
|
|
131
|
+
tags: V.length ? V : null
|
|
132
|
+
});
|
|
133
|
+
n.success("Circle created", `${e.name} is ready.`), E(!1), K(), D?.(e);
|
|
134
|
+
} catch (e) {
|
|
135
|
+
W(t(e));
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
disabled: O.isPending,
|
|
139
|
+
children: "Create circle"
|
|
140
|
+
})] })
|
|
141
|
+
]
|
|
142
|
+
})
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
//#endregion
|
|
146
|
+
export { T as CreateCircleDialog };
|
|
147
|
+
|
|
148
|
+
//# sourceMappingURL=CreateCircleDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateCircleDialog.js","names":[],"sources":["../../../src/comradecircle/components/CreateCircleDialog.tsx"],"sourcesContent":["/**\n * CreateCircleDialog — create a new community circle.\n * @module comradecircle/components\n *\n * Writes `comCreateCircle`. Slug auto-derives from the name (editable).\n */\n\nimport { useState } from 'react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { TagInput } from './TagInput';\nimport { useComCreateCircle } from '../hooks';\nimport { slugify } from '../utils/slug';\nimport { formatEnumLabel } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { ComCircle, ComCircleVisibility } from '../types';\n\nconst VISIBILITIES: ComCircleVisibility[] = ['PUBLIC', 'PRIVATE', 'SECRET'];\n\ninterface CreateCircleDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreated?: (circle: ComCircle) => void;\n}\n\nexport function CreateCircleDialog({ open, onOpenChange, onCreated }: CreateCircleDialogProps) {\n const createCircle = useComCreateCircle();\n const [name, setName] = useState('');\n const [slug, setSlug] = useState('');\n const [slugTouched, setSlugTouched] = useState(false);\n const [topic, setTopic] = useState('');\n const [description, setDescription] = useState('');\n const [visibility, setVisibility] = useState<ComCircleVisibility>('PUBLIC');\n const [tags, setTags] = useState<string[]>([]);\n const [error, setError] = useState<string | null>(null);\n\n const effectiveSlug = slugTouched ? slug : slugify(name);\n\n const reset = () => {\n setName('');\n setSlug('');\n setSlugTouched(false);\n setTopic('');\n setDescription('');\n setVisibility('PUBLIC');\n setTags([]);\n setError(null);\n };\n\n const submit = async () => {\n if (!name.trim()) {\n setError('Circle name is required.');\n return;\n }\n if (!effectiveSlug) {\n setError('A URL slug is required.');\n return;\n }\n try {\n const created = await createCircle.mutateAsync({\n name: name.trim(),\n slug: effectiveSlug,\n topic: topic.trim() || null,\n description: description.trim() || null,\n visibility,\n tags: tags.length ? tags : null,\n });\n notify.success('Circle created', `${created.name} is ready.`);\n onOpenChange(false);\n reset();\n onCreated?.(created);\n } catch (err) {\n setError(describeError(err));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Create a circle</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n A circle is a community space with its own channels, members, events, and polls.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex flex-col gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"circle-name\">Name</Label>\n <Input\n id=\"circle-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. Product Guild\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"circle-slug\">URL slug</Label>\n <Input\n id=\"circle-slug\"\n value={effectiveSlug}\n onChange={(e) => {\n setSlugTouched(true);\n setSlug(slugify(e.target.value));\n }}\n placeholder=\"product-guild\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"circle-topic\">Topic</Label>\n <Input\n id=\"circle-topic\"\n value={topic}\n onChange={(e) => setTopic(e.target.value)}\n placeholder=\"A short one-line topic\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"circle-desc\">Description</Label>\n <Textarea\n id=\"circle-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"What is this circle about?\"\n rows={3}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label>Visibility</Label>\n <Select\n value={visibility}\n onValueChange={(v) => setVisibility(v as ComCircleVisibility)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {VISIBILITIES.map((v) => (\n <SelectItem key={v} value={v}>\n {formatEnumLabel(v)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"circle-tags\">Tags</Label>\n <TagInput id=\"circle-tags\" value={tags} onChange={setTags} placeholder=\"Add tags…\" />\n </div>\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={createCircle.isPending}>\n Create circle\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { useComCircles as e, useComCreateEvent as t } from "../hooks/useComradeCircleApi.js";
|
|
2
|
+
import "../hooks/index.js";
|
|
3
|
+
import { describeError as n, notify as r } from "../lib/toast.js";
|
|
4
|
+
import { formatEnumLabel as i } from "../utils/formatters.js";
|
|
5
|
+
import { TagInput as a } from "./TagInput.js";
|
|
6
|
+
import { useState as o } from "react";
|
|
7
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
8
|
+
import { Button as l, Input as u, Label as d, ResponsiveDialog as f, ResponsiveDialogContent as p, ResponsiveDialogDescription as ee, ResponsiveDialogFooter as m, ResponsiveDialogHeader as h, ResponsiveDialogTitle as g, Select as _, SelectContent as v, SelectItem as y, SelectTrigger as b, SelectValue as x, Textarea as S } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
//#region src/comradecircle/components/CreateEventDialog.tsx
|
|
10
|
+
var C = [
|
|
11
|
+
"ONLINE",
|
|
12
|
+
"IN_PERSON",
|
|
13
|
+
"HYBRID"
|
|
14
|
+
], w = (e) => {
|
|
15
|
+
if (!e) return null;
|
|
16
|
+
let t = new Date(e);
|
|
17
|
+
return Number.isNaN(t.getTime()) ? null : t.toISOString();
|
|
18
|
+
};
|
|
19
|
+
function T({ open: T, onOpenChange: E, circleId: D, onCreated: O }) {
|
|
20
|
+
let k = t(), A = e({ status: "ACTIVE" }), [j, M] = o(""), [N, P] = o(""), [F, I] = o(""), [L, R] = o("ONLINE"), [z, B] = o(""), [V, H] = o(""), [U, W] = o(""), [G, K] = o(""), [q, J] = o(""), [Y, X] = o([]), [Z, Q] = o(null), $ = D ?? j, te = () => {
|
|
21
|
+
M(""), P(""), I(""), R("ONLINE"), B(""), H(""), W(""), K(""), J(""), X([]), Q(null);
|
|
22
|
+
};
|
|
23
|
+
return /* @__PURE__ */ s(f, {
|
|
24
|
+
open: T,
|
|
25
|
+
onOpenChange: E,
|
|
26
|
+
children: /* @__PURE__ */ c(p, {
|
|
27
|
+
className: "sm:max-w-lg",
|
|
28
|
+
children: [
|
|
29
|
+
/* @__PURE__ */ c(h, { children: [/* @__PURE__ */ s(g, { children: "Schedule an event" }), /* @__PURE__ */ s(ee, { children: "Host a gathering for your circle — online, in person, or hybrid." })] }),
|
|
30
|
+
/* @__PURE__ */ c("div", {
|
|
31
|
+
className: "flex max-h-[60vh] flex-col gap-4 overflow-y-auto py-2",
|
|
32
|
+
children: [
|
|
33
|
+
!D && /* @__PURE__ */ c("div", {
|
|
34
|
+
className: "grid gap-1.5",
|
|
35
|
+
children: [/* @__PURE__ */ s(d, { children: "Circle" }), /* @__PURE__ */ c(_, {
|
|
36
|
+
value: j,
|
|
37
|
+
onValueChange: M,
|
|
38
|
+
children: [/* @__PURE__ */ s(b, { children: /* @__PURE__ */ s(x, { placeholder: "Choose a circle" }) }), /* @__PURE__ */ s(v, { children: (A.data?.items ?? []).map((e) => /* @__PURE__ */ s(y, {
|
|
39
|
+
value: e.id,
|
|
40
|
+
children: e.name
|
|
41
|
+
}, e.id)) })]
|
|
42
|
+
})]
|
|
43
|
+
}),
|
|
44
|
+
/* @__PURE__ */ c("div", {
|
|
45
|
+
className: "grid gap-1.5",
|
|
46
|
+
children: [/* @__PURE__ */ s(d, {
|
|
47
|
+
htmlFor: "event-title",
|
|
48
|
+
children: "Title"
|
|
49
|
+
}), /* @__PURE__ */ s(u, {
|
|
50
|
+
id: "event-title",
|
|
51
|
+
value: N,
|
|
52
|
+
onChange: (e) => P(e.target.value),
|
|
53
|
+
placeholder: "e.g. Monthly community call"
|
|
54
|
+
})]
|
|
55
|
+
}),
|
|
56
|
+
/* @__PURE__ */ c("div", {
|
|
57
|
+
className: "grid gap-1.5",
|
|
58
|
+
children: [/* @__PURE__ */ s(d, {
|
|
59
|
+
htmlFor: "event-desc",
|
|
60
|
+
children: "Description"
|
|
61
|
+
}), /* @__PURE__ */ s(S, {
|
|
62
|
+
id: "event-desc",
|
|
63
|
+
value: F,
|
|
64
|
+
onChange: (e) => I(e.target.value),
|
|
65
|
+
rows: 2
|
|
66
|
+
})]
|
|
67
|
+
}),
|
|
68
|
+
/* @__PURE__ */ c("div", {
|
|
69
|
+
className: "grid grid-cols-2 gap-3",
|
|
70
|
+
children: [/* @__PURE__ */ c("div", {
|
|
71
|
+
className: "grid gap-1.5",
|
|
72
|
+
children: [/* @__PURE__ */ s(d, { children: "Mode" }), /* @__PURE__ */ c(_, {
|
|
73
|
+
value: L,
|
|
74
|
+
onValueChange: (e) => R(e),
|
|
75
|
+
children: [/* @__PURE__ */ s(b, { children: /* @__PURE__ */ s(x, {}) }), /* @__PURE__ */ s(v, { children: C.map((e) => /* @__PURE__ */ s(y, {
|
|
76
|
+
value: e,
|
|
77
|
+
children: i(e)
|
|
78
|
+
}, e)) })]
|
|
79
|
+
})]
|
|
80
|
+
}), /* @__PURE__ */ c("div", {
|
|
81
|
+
className: "grid gap-1.5",
|
|
82
|
+
children: [/* @__PURE__ */ s(d, {
|
|
83
|
+
htmlFor: "event-capacity",
|
|
84
|
+
children: "Capacity"
|
|
85
|
+
}), /* @__PURE__ */ s(u, {
|
|
86
|
+
id: "event-capacity",
|
|
87
|
+
type: "number",
|
|
88
|
+
min: 0,
|
|
89
|
+
value: U,
|
|
90
|
+
onChange: (e) => W(e.target.value),
|
|
91
|
+
placeholder: "Optional"
|
|
92
|
+
})]
|
|
93
|
+
})]
|
|
94
|
+
}),
|
|
95
|
+
L !== "ONLINE" && /* @__PURE__ */ c("div", {
|
|
96
|
+
className: "grid gap-1.5",
|
|
97
|
+
children: [/* @__PURE__ */ s(d, {
|
|
98
|
+
htmlFor: "event-location",
|
|
99
|
+
children: "Location"
|
|
100
|
+
}), /* @__PURE__ */ s(u, {
|
|
101
|
+
id: "event-location",
|
|
102
|
+
value: z,
|
|
103
|
+
onChange: (e) => B(e.target.value),
|
|
104
|
+
placeholder: "Venue / address"
|
|
105
|
+
})]
|
|
106
|
+
}),
|
|
107
|
+
L !== "IN_PERSON" && /* @__PURE__ */ c("div", {
|
|
108
|
+
className: "grid gap-1.5",
|
|
109
|
+
children: [/* @__PURE__ */ s(d, {
|
|
110
|
+
htmlFor: "event-join",
|
|
111
|
+
children: "Join URL"
|
|
112
|
+
}), /* @__PURE__ */ s(u, {
|
|
113
|
+
id: "event-join",
|
|
114
|
+
value: V,
|
|
115
|
+
onChange: (e) => H(e.target.value),
|
|
116
|
+
placeholder: "https://…"
|
|
117
|
+
})]
|
|
118
|
+
}),
|
|
119
|
+
/* @__PURE__ */ c("div", {
|
|
120
|
+
className: "grid grid-cols-2 gap-3",
|
|
121
|
+
children: [/* @__PURE__ */ c("div", {
|
|
122
|
+
className: "grid gap-1.5",
|
|
123
|
+
children: [/* @__PURE__ */ s(d, {
|
|
124
|
+
htmlFor: "event-start",
|
|
125
|
+
children: "Starts"
|
|
126
|
+
}), /* @__PURE__ */ s(u, {
|
|
127
|
+
id: "event-start",
|
|
128
|
+
type: "datetime-local",
|
|
129
|
+
value: G,
|
|
130
|
+
onChange: (e) => K(e.target.value)
|
|
131
|
+
})]
|
|
132
|
+
}), /* @__PURE__ */ c("div", {
|
|
133
|
+
className: "grid gap-1.5",
|
|
134
|
+
children: [/* @__PURE__ */ s(d, {
|
|
135
|
+
htmlFor: "event-end",
|
|
136
|
+
children: "Ends"
|
|
137
|
+
}), /* @__PURE__ */ s(u, {
|
|
138
|
+
id: "event-end",
|
|
139
|
+
type: "datetime-local",
|
|
140
|
+
value: q,
|
|
141
|
+
onChange: (e) => J(e.target.value)
|
|
142
|
+
})]
|
|
143
|
+
})]
|
|
144
|
+
}),
|
|
145
|
+
/* @__PURE__ */ c("div", {
|
|
146
|
+
className: "grid gap-1.5",
|
|
147
|
+
children: [/* @__PURE__ */ s(d, {
|
|
148
|
+
htmlFor: "event-tags",
|
|
149
|
+
children: "Tags"
|
|
150
|
+
}), /* @__PURE__ */ s(a, {
|
|
151
|
+
id: "event-tags",
|
|
152
|
+
value: Y,
|
|
153
|
+
onChange: X,
|
|
154
|
+
placeholder: "Add tags…"
|
|
155
|
+
})]
|
|
156
|
+
}),
|
|
157
|
+
Z && /* @__PURE__ */ s("p", {
|
|
158
|
+
className: "text-sm text-status-error-text",
|
|
159
|
+
children: Z
|
|
160
|
+
})
|
|
161
|
+
]
|
|
162
|
+
}),
|
|
163
|
+
/* @__PURE__ */ c(m, { children: [/* @__PURE__ */ s(l, {
|
|
164
|
+
variant: "outline",
|
|
165
|
+
onClick: () => E(!1),
|
|
166
|
+
children: "Cancel"
|
|
167
|
+
}), /* @__PURE__ */ s(l, {
|
|
168
|
+
onClick: async () => {
|
|
169
|
+
if (!$) {
|
|
170
|
+
Q("Please choose a circle for this event.");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (!N.trim()) {
|
|
174
|
+
Q("Event title is required.");
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
let e = w(G);
|
|
178
|
+
if (!e) {
|
|
179
|
+
Q("A valid start date & time is required.");
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
let t = await k.mutateAsync({
|
|
184
|
+
circleId: $,
|
|
185
|
+
title: N.trim(),
|
|
186
|
+
description: F.trim() || null,
|
|
187
|
+
mode: L,
|
|
188
|
+
location: z.trim() || null,
|
|
189
|
+
joinUrl: V.trim() || null,
|
|
190
|
+
capacity: U ? Number(U) : null,
|
|
191
|
+
startsAt: e,
|
|
192
|
+
endsAt: w(q),
|
|
193
|
+
tags: Y.length ? Y : null
|
|
194
|
+
});
|
|
195
|
+
r.success("Event scheduled", t.title), E(!1), te(), O?.(t);
|
|
196
|
+
} catch (e) {
|
|
197
|
+
Q(n(e));
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
disabled: k.isPending,
|
|
201
|
+
children: "Schedule event"
|
|
202
|
+
})] })
|
|
203
|
+
]
|
|
204
|
+
})
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
export { T as CreateEventDialog };
|
|
209
|
+
|
|
210
|
+
//# sourceMappingURL=CreateEventDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateEventDialog.js","names":[],"sources":["../../../src/comradecircle/components/CreateEventDialog.tsx"],"sourcesContent":["/**\n * CreateEventDialog — schedule a new event in a circle.\n * @module comradecircle/components\n *\n * Writes `comCreateEvent`. When no `circleId` is fixed by the caller, a circle\n * picker (active circles) is shown. Datetime-local inputs are converted to ISO\n * strings for the `DateTime` scalar.\n */\n\nimport { useState } from 'react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { TagInput } from './TagInput';\nimport { useComCreateEvent, useComCircles } from '../hooks';\nimport { formatEnumLabel } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { ComEvent, ComEventMode } from '../types';\n\nconst MODES: ComEventMode[] = ['ONLINE', 'IN_PERSON', 'HYBRID'];\n\nconst toIso = (local: string): string | null => {\n if (!local) return null;\n const d = new Date(local);\n return Number.isNaN(d.getTime()) ? null : d.toISOString();\n};\n\ninterface CreateEventDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Fixed circle — when omitted the dialog shows an active-circle picker. */\n circleId?: string;\n onCreated?: (event: ComEvent) => void;\n}\n\nexport function CreateEventDialog({\n open,\n onOpenChange,\n circleId,\n onCreated,\n}: CreateEventDialogProps) {\n const createEvent = useComCreateEvent();\n const circlesQuery = useComCircles({ status: 'ACTIVE' });\n const [pickedCircle, setPickedCircle] = useState('');\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState('');\n const [mode, setMode] = useState<ComEventMode>('ONLINE');\n const [location, setLocation] = useState('');\n const [joinUrl, setJoinUrl] = useState('');\n const [capacity, setCapacity] = useState('');\n const [startsAt, setStartsAt] = useState('');\n const [endsAt, setEndsAt] = useState('');\n const [tags, setTags] = useState<string[]>([]);\n const [error, setError] = useState<string | null>(null);\n\n const effectiveCircle = circleId ?? pickedCircle;\n\n const reset = () => {\n setPickedCircle('');\n setTitle('');\n setDescription('');\n setMode('ONLINE');\n setLocation('');\n setJoinUrl('');\n setCapacity('');\n setStartsAt('');\n setEndsAt('');\n setTags([]);\n setError(null);\n };\n\n const submit = async () => {\n if (!effectiveCircle) {\n setError('Please choose a circle for this event.');\n return;\n }\n if (!title.trim()) {\n setError('Event title is required.');\n return;\n }\n const startIso = toIso(startsAt);\n if (!startIso) {\n setError('A valid start date & time is required.');\n return;\n }\n try {\n const created = await createEvent.mutateAsync({\n circleId: effectiveCircle,\n title: title.trim(),\n description: description.trim() || null,\n mode,\n location: location.trim() || null,\n joinUrl: joinUrl.trim() || null,\n capacity: capacity ? Number(capacity) : null,\n startsAt: startIso,\n endsAt: toIso(endsAt),\n tags: tags.length ? tags : null,\n });\n notify.success('Event scheduled', created.title);\n onOpenChange(false);\n reset();\n onCreated?.(created);\n } catch (err) {\n setError(describeError(err));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Schedule an event</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Host a gathering for your circle — online, in person, or hybrid.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[60vh] flex-col gap-4 overflow-y-auto py-2\">\n {!circleId && (\n <div className=\"grid gap-1.5\">\n <Label>Circle</Label>\n <Select value={pickedCircle} onValueChange={setPickedCircle}>\n <SelectTrigger>\n <SelectValue placeholder=\"Choose a circle\" />\n </SelectTrigger>\n <SelectContent>\n {(circlesQuery.data?.items ?? []).map((c) => (\n <SelectItem key={c.id} value={c.id}>\n {c.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"event-title\">Title</Label>\n <Input\n id=\"event-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. Monthly community call\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"event-desc\">Description</Label>\n <Textarea\n id=\"event-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n />\n </div>\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"grid gap-1.5\">\n <Label>Mode</Label>\n <Select value={mode} onValueChange={(v) => setMode(v as ComEventMode)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {MODES.map((m) => (\n <SelectItem key={m} value={m}>\n {formatEnumLabel(m)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"event-capacity\">Capacity</Label>\n <Input\n id=\"event-capacity\"\n type=\"number\"\n min={0}\n value={capacity}\n onChange={(e) => setCapacity(e.target.value)}\n placeholder=\"Optional\"\n />\n </div>\n </div>\n {mode !== 'ONLINE' && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"event-location\">Location</Label>\n <Input\n id=\"event-location\"\n value={location}\n onChange={(e) => setLocation(e.target.value)}\n placeholder=\"Venue / address\"\n />\n </div>\n )}\n {mode !== 'IN_PERSON' && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"event-join\">Join URL</Label>\n <Input\n id=\"event-join\"\n value={joinUrl}\n onChange={(e) => setJoinUrl(e.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n )}\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"event-start\">Starts</Label>\n <Input\n id=\"event-start\"\n type=\"datetime-local\"\n value={startsAt}\n onChange={(e) => setStartsAt(e.target.value)}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"event-end\">Ends</Label>\n <Input\n id=\"event-end\"\n type=\"datetime-local\"\n value={endsAt}\n onChange={(e) => setEndsAt(e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"event-tags\">Tags</Label>\n <TagInput id=\"event-tags\" value={tags} onChange={setTags} placeholder=\"Add tags…\" />\n </div>\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={createEvent.isPending}>\n Schedule event\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cn as e } from "../utils/cn.js";
|
|
2
|
+
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
3
|
+
import { IllustratedEmptyState as r } from "@burdenoff/fe-libs/ui";
|
|
4
|
+
//#region src/comradecircle/components/EmptyState.tsx
|
|
5
|
+
var i = ({ icon: i, illustration: a, title: o, description: s, action: c, className: l }) => a ? /* @__PURE__ */ t(r, {
|
|
6
|
+
illustration: a,
|
|
7
|
+
title: o,
|
|
8
|
+
description: s,
|
|
9
|
+
action: c,
|
|
10
|
+
className: l
|
|
11
|
+
}) : /* @__PURE__ */ n("div", {
|
|
12
|
+
className: e("flex flex-col items-center justify-center py-12 px-4 text-center", l),
|
|
13
|
+
children: [
|
|
14
|
+
i && /* @__PURE__ */ t("div", {
|
|
15
|
+
className: "mb-4 text-text-secondary opacity-50",
|
|
16
|
+
children: i
|
|
17
|
+
}),
|
|
18
|
+
/* @__PURE__ */ t("h3", {
|
|
19
|
+
className: "text-lg font-medium text-text-primary",
|
|
20
|
+
children: o
|
|
21
|
+
}),
|
|
22
|
+
s && /* @__PURE__ */ t("p", {
|
|
23
|
+
className: "mt-2 text-sm text-text-secondary max-w-sm",
|
|
24
|
+
children: s
|
|
25
|
+
}),
|
|
26
|
+
c && /* @__PURE__ */ t("div", {
|
|
27
|
+
className: "mt-6",
|
|
28
|
+
children: c
|
|
29
|
+
})
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
//#endregion
|
|
33
|
+
export { i as EmptyState };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=EmptyState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/comradecircle/components/EmptyState.tsx"],"sourcesContent":["/**\n * Empty State Component\n * @module comradecircle/components\n *\n * Boff UI 2.0 zero-state. When an `illustration` name is provided it renders the\n * fe-libs {@link IllustratedEmptyState} (on-brand glass illustration); otherwise\n * it falls back to the icon-based layout.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface EmptyStateProps {\n icon?: ReactNode;\n /**\n * On-brand illustration name → `/illustrations/<name>.webp`. Standard names:\n * empty-data, empty-search, empty-files, empty-people, empty-notifications,\n * onboarding, empty-generic.\n */\n illustration?: string;\n title: string;\n description?: string;\n action?: ReactNode;\n className?: string;\n}\n\nexport const EmptyState: FC<EmptyStateProps> = ({\n icon,\n illustration,\n title,\n description,\n action,\n className,\n}) => {\n if (illustration) {\n return (\n <IllustratedEmptyState\n illustration={illustration}\n title={title}\n description={description}\n action={action}\n className={className}\n />\n );\n }\n\n return (\n <div\n className={cn('flex flex-col items-center justify-center py-12 px-4 text-center', className)}\n >\n {icon && <div className=\"mb-4 text-text-secondary opacity-50\">{icon}</div>}\n <h3 className=\"text-lg font-medium text-text-primary\">{title}</h3>\n {description && <p className=\"mt-2 text-sm text-text-secondary max-w-sm\">{description}</p>}\n {action && <div className=\"mt-6\">{action}</div>}\n </div>\n );\n};\n"],"mappings":";;;;AA2BA,IAAa,KAAmC,EAC9C,SACA,iBACA,UACA,gBACA,WACA,mBAEI,IAEA,kBAAC,GAAD;CACgB;CACP;CACM;CACL;CACG;CACX,CAAA,GAKJ,kBAAC,OAAD;CACE,WAAW,EAAG,oEAAoE,EAAU;WAD9F;EAGG,KAAQ,kBAAC,OAAD;GAAK,WAAU;aAAuC;GAAW,CAAA;EAC1E,kBAAC,MAAD;GAAI,WAAU;aAAyC;GAAW,CAAA;EACjE,KAAe,kBAAC,KAAD;GAAG,WAAU;aAA6C;GAAgB,CAAA;EACzF,KAAU,kBAAC,OAAD;GAAK,WAAU;aAAQ;GAAa,CAAA;EAC3C"}
|