@burdenoff/microfe-theculturepost 2026.705.2 → 2026.709.2
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/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +18199 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +43046 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -1
- package/dist/services/assistantApi.d.ts +15 -0
- package/dist/services/assistantApi.d.ts.map +1 -0
- package/dist/services/assistantApi.js +204 -0
- package/dist/services/assistantApi.js.map +1 -0
- package/dist/services/createSandboxAssistantTransport.d.ts +26 -0
- package/dist/services/createSandboxAssistantTransport.d.ts.map +1 -0
- package/dist/services/createSandboxAssistantTransport.js +126 -0
- package/dist/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/theculturepost/TheCulturePostRoot.d.ts +5 -0
- package/dist/theculturepost/TheCulturePostRoot.d.ts.map +1 -0
- package/dist/theculturepost/TheCulturePostRoutes.d.ts +4 -0
- package/dist/theculturepost/TheCulturePostRoutes.d.ts.map +1 -0
- package/dist/theculturepost/TheCulturePostRoutes.js +73 -40
- package/dist/theculturepost/TheCulturePostRoutes.js.map +1 -1
- package/dist/theculturepost/components/AddCitationDialog.d.ts +11 -0
- package/dist/theculturepost/components/AddCitationDialog.d.ts.map +1 -0
- package/dist/theculturepost/components/ArchiveItemCard.d.ts +9 -0
- package/dist/theculturepost/components/ArchiveItemCard.d.ts.map +1 -0
- package/dist/theculturepost/components/AudioPlayer.d.ts +22 -0
- package/dist/theculturepost/components/AudioPlayer.d.ts.map +1 -0
- package/dist/theculturepost/components/AuthorLabel.d.ts +16 -0
- package/dist/theculturepost/components/AuthorLabel.d.ts.map +1 -0
- package/dist/theculturepost/components/AuthorLabel.js +1 -1
- package/dist/theculturepost/components/CitationList.d.ts +27 -0
- package/dist/theculturepost/components/CitationList.d.ts.map +1 -0
- package/dist/theculturepost/components/CollectionCard.d.ts +9 -0
- package/dist/theculturepost/components/CollectionCard.d.ts.map +1 -0
- package/dist/theculturepost/components/CoverImage.d.ts +13 -0
- package/dist/theculturepost/components/CoverImage.d.ts.map +1 -0
- package/dist/theculturepost/components/CreateArchiveItemDialog.d.ts +12 -0
- package/dist/theculturepost/components/CreateArchiveItemDialog.d.ts.map +1 -0
- package/dist/theculturepost/components/CreateCollectionDialog.d.ts +10 -0
- package/dist/theculturepost/components/CreateCollectionDialog.d.ts.map +1 -0
- package/dist/theculturepost/components/CreateStoryDialog.d.ts +12 -0
- package/dist/theculturepost/components/CreateStoryDialog.d.ts.map +1 -0
- package/dist/theculturepost/components/CreateTopicDialog.d.ts +10 -0
- package/dist/theculturepost/components/CreateTopicDialog.d.ts.map +1 -0
- package/dist/theculturepost/components/DecorativeCover.d.ts +17 -0
- package/dist/theculturepost/components/DecorativeCover.d.ts.map +1 -0
- package/dist/theculturepost/components/DecorativeDivider.d.ts +14 -0
- package/dist/theculturepost/components/DecorativeDivider.d.ts.map +1 -0
- package/dist/theculturepost/components/DiscussionCard.d.ts +9 -0
- package/dist/theculturepost/components/DiscussionCard.d.ts.map +1 -0
- package/dist/theculturepost/components/EmptyState.d.ts +18 -0
- package/dist/theculturepost/components/EmptyState.d.ts.map +1 -0
- package/dist/theculturepost/components/FileImage.d.ts +18 -0
- package/dist/theculturepost/components/FileImage.d.ts.map +1 -0
- package/dist/theculturepost/components/FileUploadField.d.ts +29 -0
- package/dist/theculturepost/components/FileUploadField.d.ts.map +1 -0
- package/dist/theculturepost/components/FilterTabs.d.ts +18 -0
- package/dist/theculturepost/components/FilterTabs.d.ts.map +1 -0
- package/dist/theculturepost/components/HistoryTimeline.d.ts +20 -0
- package/dist/theculturepost/components/HistoryTimeline.d.ts.map +1 -0
- package/dist/theculturepost/components/LifecycleStepper.d.ts +11 -0
- package/dist/theculturepost/components/LifecycleStepper.d.ts.map +1 -0
- package/dist/theculturepost/components/OpenDiscussionDialog.d.ts +12 -0
- package/dist/theculturepost/components/OpenDiscussionDialog.d.ts.map +1 -0
- package/dist/theculturepost/components/OralHistoryCard.d.ts +8 -0
- package/dist/theculturepost/components/OralHistoryCard.d.ts.map +1 -0
- package/dist/theculturepost/components/OverlayBadge.d.ts +15 -0
- package/dist/theculturepost/components/OverlayBadge.d.ts.map +1 -0
- package/dist/theculturepost/components/PageHero.d.ts +26 -0
- package/dist/theculturepost/components/PageHero.d.ts.map +1 -0
- package/dist/theculturepost/components/PageLayout.d.ts +16 -0
- package/dist/theculturepost/components/PageLayout.d.ts.map +1 -0
- package/dist/theculturepost/components/Pagination.d.ts +22 -0
- package/dist/theculturepost/components/Pagination.d.ts.map +1 -0
- package/dist/theculturepost/components/RecordOralHistoryDialog.d.ts +47 -0
- package/dist/theculturepost/components/RecordOralHistoryDialog.d.ts.map +1 -0
- package/dist/theculturepost/components/ReplyThread.d.ts +20 -0
- package/dist/theculturepost/components/ReplyThread.d.ts.map +1 -0
- package/dist/theculturepost/components/ReplyThread.js +1 -1
- package/dist/theculturepost/components/StateViews.d.ts +24 -0
- package/dist/theculturepost/components/StateViews.d.ts.map +1 -0
- package/dist/theculturepost/components/StatusBadge.d.ts +11 -0
- package/dist/theculturepost/components/StatusBadge.d.ts.map +1 -0
- package/dist/theculturepost/components/StoryCard.d.ts +11 -0
- package/dist/theculturepost/components/StoryCard.d.ts.map +1 -0
- package/dist/theculturepost/components/Tabs.d.ts +17 -0
- package/dist/theculturepost/components/Tabs.d.ts.map +1 -0
- package/dist/theculturepost/components/TagInput.d.ts +20 -0
- package/dist/theculturepost/components/TagInput.d.ts.map +1 -0
- package/dist/theculturepost/components/TopicCard.d.ts +9 -0
- package/dist/theculturepost/components/TopicCard.d.ts.map +1 -0
- package/dist/theculturepost/components/Waveform.d.ts +23 -0
- package/dist/theculturepost/components/Waveform.d.ts.map +1 -0
- package/dist/theculturepost/components/categoryMeta.d.ts +14 -0
- package/dist/theculturepost/components/categoryMeta.d.ts.map +1 -0
- package/dist/theculturepost/components/index.d.ts +43 -0
- package/dist/theculturepost/components/index.d.ts.map +1 -0
- package/dist/theculturepost/components/kindIcon.d.ts +7 -0
- package/dist/theculturepost/components/kindIcon.d.ts.map +1 -0
- package/dist/theculturepost/components/viz/BarChart.d.ts +23 -0
- package/dist/theculturepost/components/viz/BarChart.d.ts.map +1 -0
- package/dist/theculturepost/components/viz/Donut.d.ts +25 -0
- package/dist/theculturepost/components/viz/Donut.d.ts.map +1 -0
- package/dist/theculturepost/components/viz/StatTile.d.ts +14 -0
- package/dist/theculturepost/components/viz/StatTile.d.ts.map +1 -0
- package/dist/theculturepost/components/viz/index.d.ts +11 -0
- package/dist/theculturepost/components/viz/index.d.ts.map +1 -0
- package/dist/theculturepost/context/TheCulturePostContext.d.ts +16 -0
- package/dist/theculturepost/context/TheCulturePostContext.d.ts.map +1 -0
- package/dist/theculturepost/context/index.d.ts +6 -0
- package/dist/theculturepost/context/index.d.ts.map +1 -0
- package/dist/theculturepost/hooks/index.d.ts +10 -0
- package/dist/theculturepost/hooks/index.d.ts.map +1 -0
- package/dist/theculturepost/hooks/index.js +2 -0
- package/dist/theculturepost/hooks/useCursorPager.d.ts +32 -0
- package/dist/theculturepost/hooks/useCursorPager.d.ts.map +1 -0
- package/dist/theculturepost/hooks/useFiles.d.ts +31 -0
- package/dist/theculturepost/hooks/useFiles.d.ts.map +1 -0
- package/dist/theculturepost/hooks/usePageAnalytics.d.ts +9 -0
- package/dist/theculturepost/hooks/usePageAnalytics.d.ts.map +1 -0
- package/dist/theculturepost/hooks/usePageAnalytics.js +34 -0
- package/dist/theculturepost/hooks/usePageAnalytics.js.map +1 -0
- package/dist/theculturepost/hooks/useTcpApi.d.ts +74 -0
- package/dist/theculturepost/hooks/useTcpApi.d.ts.map +1 -0
- package/dist/theculturepost/hooks/useTr.d.ts +8 -0
- package/dist/theculturepost/hooks/useTr.d.ts.map +1 -0
- package/dist/theculturepost/hooks/useTr.js +14 -0
- package/dist/theculturepost/hooks/useTr.js.map +1 -0
- package/dist/theculturepost/index.d.ts +9 -0
- package/dist/theculturepost/index.d.ts.map +1 -0
- package/dist/theculturepost/index.js +2 -1
- package/dist/theculturepost/lib/graphql-cache.d.ts +26 -0
- package/dist/theculturepost/lib/graphql-cache.d.ts.map +1 -0
- package/dist/theculturepost/lib/toast.d.ts +23 -0
- package/dist/theculturepost/lib/toast.d.ts.map +1 -0
- package/dist/theculturepost/pages/HomePage.d.ts +16 -0
- package/dist/theculturepost/pages/HomePage.d.ts.map +1 -0
- package/dist/theculturepost/pages/HomePage.js +83 -68
- package/dist/theculturepost/pages/HomePage.js.map +1 -1
- package/dist/theculturepost/pages/archive/ArchiveItemDetailPage.d.ts +12 -0
- package/dist/theculturepost/pages/archive/ArchiveItemDetailPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/archive/ArchiveItemDetailPage.js +21 -21
- package/dist/theculturepost/pages/archive/ArchivePage.d.ts +7 -0
- package/dist/theculturepost/pages/archive/ArchivePage.d.ts.map +1 -0
- package/dist/theculturepost/pages/archive/ArchivePage.js +144 -125
- package/dist/theculturepost/pages/archive/ArchivePage.js.map +1 -1
- package/dist/theculturepost/pages/archive/CollectionDetailPage.d.ts +12 -0
- package/dist/theculturepost/pages/archive/CollectionDetailPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/discussions/DiscussionDetailPage.d.ts +12 -0
- package/dist/theculturepost/pages/discussions/DiscussionDetailPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/discussions/DiscussionDetailPage.js +78 -70
- package/dist/theculturepost/pages/discussions/DiscussionDetailPage.js.map +1 -1
- package/dist/theculturepost/pages/discussions/DiscussionsPage.d.ts +10 -0
- package/dist/theculturepost/pages/discussions/DiscussionsPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/discussions/DiscussionsPage.js +63 -56
- package/dist/theculturepost/pages/discussions/DiscussionsPage.js.map +1 -1
- package/dist/theculturepost/pages/governance/GovernancePage.d.ts +20 -0
- package/dist/theculturepost/pages/governance/GovernancePage.d.ts.map +1 -0
- package/dist/theculturepost/pages/stories/StoriesPage.d.ts +9 -0
- package/dist/theculturepost/pages/stories/StoriesPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/stories/StoriesPage.js +65 -58
- package/dist/theculturepost/pages/stories/StoriesPage.js.map +1 -1
- package/dist/theculturepost/pages/stories/StoryDetailPage.d.ts +18 -0
- package/dist/theculturepost/pages/stories/StoryDetailPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/stories/StoryDetailPage.js +249 -229
- package/dist/theculturepost/pages/stories/StoryDetailPage.js.map +1 -1
- package/dist/theculturepost/pages/timeline/TimelinePage.d.ts +17 -0
- package/dist/theculturepost/pages/timeline/TimelinePage.d.ts.map +1 -0
- package/dist/theculturepost/pages/topics/TopicDetailPage.d.ts +12 -0
- package/dist/theculturepost/pages/topics/TopicDetailPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/topics/TopicsPage.d.ts +12 -0
- package/dist/theculturepost/pages/topics/TopicsPage.d.ts.map +1 -0
- package/dist/theculturepost/pages/topics/TopicsPage.js +61 -52
- package/dist/theculturepost/pages/topics/TopicsPage.js.map +1 -1
- package/dist/theculturepost/styles/injectDisplayFont.d.ts +14 -0
- package/dist/theculturepost/styles/injectDisplayFont.d.ts.map +1 -0
- package/dist/theculturepost/translations/ar.d.ts +50 -0
- package/dist/theculturepost/translations/ar.d.ts.map +1 -0
- package/dist/theculturepost/translations/ar.js +54 -0
- package/dist/theculturepost/translations/ar.js.map +1 -0
- package/dist/theculturepost/translations/en.d.ts +50 -0
- package/dist/theculturepost/translations/en.d.ts.map +1 -0
- package/dist/theculturepost/translations/en.js +54 -0
- package/dist/theculturepost/translations/en.js.map +1 -0
- package/dist/theculturepost/translations/es.d.ts +50 -0
- package/dist/theculturepost/translations/es.d.ts.map +1 -0
- package/dist/theculturepost/translations/es.js +54 -0
- package/dist/theculturepost/translations/es.js.map +1 -0
- package/dist/theculturepost/translations/hi.d.ts +50 -0
- package/dist/theculturepost/translations/hi.d.ts.map +1 -0
- package/dist/theculturepost/translations/hi.js +54 -0
- package/dist/theculturepost/translations/hi.js.map +1 -0
- package/dist/theculturepost/translations/index.d.ts +7 -0
- package/dist/theculturepost/translations/index.d.ts.map +1 -0
- package/dist/theculturepost/translations/ta.d.ts +50 -0
- package/dist/theculturepost/translations/ta.d.ts.map +1 -0
- package/dist/theculturepost/translations/ta.js +54 -0
- package/dist/theculturepost/translations/ta.js.map +1 -0
- package/dist/theculturepost/translations/zh.d.ts +50 -0
- package/dist/theculturepost/translations/zh.d.ts.map +1 -0
- package/dist/theculturepost/translations/zh.js +54 -0
- package/dist/theculturepost/translations/zh.js.map +1 -0
- package/dist/theculturepost/types/index.d.ts +333 -0
- package/dist/theculturepost/types/index.d.ts.map +1 -0
- package/dist/theculturepost/utils/cn.d.ts +4 -0
- package/dist/theculturepost/utils/cn.d.ts.map +1 -0
- package/dist/theculturepost/utils/formatters.d.ts +19 -0
- package/dist/theculturepost/utils/formatters.d.ts.map +1 -0
- package/dist/theculturepost/utils/i18n.d.ts +6 -0
- package/dist/theculturepost/utils/i18n.d.ts.map +1 -0
- package/dist/theculturepost/utils/index.d.ts +11 -0
- package/dist/theculturepost/utils/index.d.ts.map +1 -0
- package/dist/theculturepost/utils/index.js +6 -0
- package/dist/theculturepost/utils/nativeBridge.d.ts +47 -0
- package/dist/theculturepost/utils/nativeBridge.d.ts.map +1 -0
- package/dist/theculturepost/utils/nativeBridge.js +60 -0
- package/dist/theculturepost/utils/nativeBridge.js.map +1 -0
- package/dist/theculturepost/utils/navigation.d.ts +14 -0
- package/dist/theculturepost/utils/navigation.d.ts.map +1 -0
- package/dist/theculturepost/utils/slug.d.ts +6 -0
- package/dist/theculturepost/utils/slug.d.ts.map +1 -0
- package/dist/types/assistant.d.ts +56 -0
- package/dist/types/assistant.d.ts.map +1 -0
- package/dist/utils/pageContext.d.ts +27 -0
- package/dist/utils/pageContext.d.ts.map +1 -0
- package/dist/utils/pageContext.js +47 -0
- package/dist/utils/pageContext.js.map +1 -0
- package/package.json +29 -1
|
@@ -7,170 +7,178 @@ import { AuthorLabel as o } from "../../components/AuthorLabel.js";
|
|
|
7
7
|
import { useTcpDiscussion as s, useTcpLockDiscussion as c } from "../../hooks/useTcpApi.js";
|
|
8
8
|
import "../../hooks/index.js";
|
|
9
9
|
import { describeError as l, notify as u } from "../../lib/toast.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
10
|
+
import { impact as d, nativeConfirm as f } from "../../utils/nativeBridge.js";
|
|
11
|
+
import { PageLayout as p } from "../../components/PageLayout.js";
|
|
12
|
+
import { ReplyThread as m } from "../../components/ReplyThread.js";
|
|
13
|
+
import { ArrowLeft as h, BookOpen as g, CheckCircle2 as _, Clock as v, ExternalLink as y, Flag as b, HeartHandshake as x, Lock as S, MessagesSquare as C, Quote as w, Trash2 as T, Unlock as E } from "lucide-react";
|
|
14
|
+
import { useParams as D } from "react-router-dom";
|
|
15
|
+
import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
|
|
16
|
+
import { Button as j, GlassCard as M } from "@burdenoff/fe-libs/ui";
|
|
16
17
|
//#region src/theculturepost/pages/discussions/DiscussionDetailPage.tsx
|
|
17
|
-
function
|
|
18
|
+
function N(e) {
|
|
18
19
|
let t = "h-3 w-3";
|
|
19
20
|
switch (e) {
|
|
20
|
-
case "APPROVED": return /* @__PURE__ */
|
|
21
|
+
case "APPROVED": return /* @__PURE__ */ k(_, {
|
|
21
22
|
className: t,
|
|
22
23
|
"aria-hidden": "true"
|
|
23
24
|
});
|
|
24
|
-
case "PENDING": return /* @__PURE__ */
|
|
25
|
+
case "PENDING": return /* @__PURE__ */ k(v, {
|
|
25
26
|
className: t,
|
|
26
27
|
"aria-hidden": "true"
|
|
27
28
|
});
|
|
28
|
-
case "FLAGGED": return /* @__PURE__ */
|
|
29
|
+
case "FLAGGED": return /* @__PURE__ */ k(b, {
|
|
29
30
|
className: t,
|
|
30
31
|
"aria-hidden": "true"
|
|
31
32
|
});
|
|
32
|
-
case "REMOVED": return /* @__PURE__ */
|
|
33
|
+
case "REMOVED": return /* @__PURE__ */ k(T, {
|
|
33
34
|
className: t,
|
|
34
35
|
"aria-hidden": "true"
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
|
-
function
|
|
39
|
-
let { id:
|
|
39
|
+
function P() {
|
|
40
|
+
let { id: _ } = D(), { navigateTo: v } = e(), { data: b, isLoading: T, isError: P, refetch: F } = s(_), I = c(), L = /* @__PURE__ */ A(j, {
|
|
40
41
|
variant: "ghost",
|
|
41
42
|
size: "sm",
|
|
42
|
-
onClick: () =>
|
|
43
|
-
children: [/* @__PURE__ */
|
|
43
|
+
onClick: () => v("discussions"),
|
|
44
|
+
children: [/* @__PURE__ */ k(h, { className: "mr-1.5 h-4 w-4" }), " Back"]
|
|
44
45
|
});
|
|
45
|
-
return
|
|
46
|
+
return T ? /* @__PURE__ */ k(p, {
|
|
46
47
|
title: "Discussion",
|
|
47
|
-
actions:
|
|
48
|
-
children: /* @__PURE__ */
|
|
49
|
-
}) :
|
|
48
|
+
actions: L,
|
|
49
|
+
children: /* @__PURE__ */ k(n, { label: "Loading discussion…" })
|
|
50
|
+
}) : P || !b ? /* @__PURE__ */ k(p, {
|
|
50
51
|
title: "Discussion",
|
|
51
|
-
actions:
|
|
52
|
-
children: /* @__PURE__ */
|
|
52
|
+
actions: L,
|
|
53
|
+
children: /* @__PURE__ */ k(t, {
|
|
53
54
|
title: "Discussion not found",
|
|
54
55
|
message: "This discussion may have been removed, or you may not have access.",
|
|
55
|
-
onRetry: () =>
|
|
56
|
+
onRetry: () => F()
|
|
56
57
|
})
|
|
57
|
-
}) : /* @__PURE__ */
|
|
58
|
+
}) : /* @__PURE__ */ k(p, {
|
|
58
59
|
title: "Discussion",
|
|
59
|
-
actions:
|
|
60
|
-
children: /* @__PURE__ */
|
|
60
|
+
actions: L,
|
|
61
|
+
children: /* @__PURE__ */ A("div", {
|
|
61
62
|
className: "mx-auto flex max-w-3xl flex-col gap-6",
|
|
62
|
-
children: [/* @__PURE__ */
|
|
63
|
+
children: [/* @__PURE__ */ A(M, {
|
|
63
64
|
treatment: "plain",
|
|
64
65
|
className: "flex flex-col gap-4 p-5 sm:p-6",
|
|
65
66
|
children: [
|
|
66
|
-
/* @__PURE__ */
|
|
67
|
+
/* @__PURE__ */ A("div", {
|
|
67
68
|
className: "flex items-start justify-between gap-3",
|
|
68
|
-
children: [/* @__PURE__ */
|
|
69
|
+
children: [/* @__PURE__ */ k("h1", {
|
|
69
70
|
className: "font-display text-2xl font-semibold leading-tight text-text-primary sm:text-3xl",
|
|
70
|
-
children:
|
|
71
|
-
}), /* @__PURE__ */
|
|
71
|
+
children: b.title
|
|
72
|
+
}), /* @__PURE__ */ k(j, {
|
|
72
73
|
variant: "outline",
|
|
73
74
|
size: "sm",
|
|
74
75
|
onClick: async () => {
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
await d("light");
|
|
77
|
+
let e = b.isLocked ? "unlock" : "lock";
|
|
78
|
+
if (await f({
|
|
79
|
+
title: `${e === "lock" ? "Lock" : "Unlock"} discussion`,
|
|
80
|
+
message: `Are you sure you want to ${e} this discussion?`,
|
|
81
|
+
okButtonTitle: e === "lock" ? "Lock" : "Unlock",
|
|
82
|
+
cancelButtonTitle: "Cancel"
|
|
83
|
+
})) try {
|
|
84
|
+
await I.mutateAsync(b.id), u.success(b.isLocked ? "Discussion unlocked" : "Discussion locked");
|
|
77
85
|
} catch (e) {
|
|
78
86
|
u.error("Could not update the discussion", l(e));
|
|
79
87
|
}
|
|
80
88
|
},
|
|
81
|
-
disabled:
|
|
89
|
+
disabled: I.isPending,
|
|
82
90
|
className: "shrink-0",
|
|
83
|
-
children:
|
|
91
|
+
children: b.isLocked ? /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(E, { className: "mr-1.5 h-4 w-4" }), " Unlock"] }) : /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(S, { className: "mr-1.5 h-4 w-4" }), " Lock"] })
|
|
84
92
|
})]
|
|
85
93
|
}),
|
|
86
|
-
/* @__PURE__ */
|
|
94
|
+
/* @__PURE__ */ A("div", {
|
|
87
95
|
className: "flex flex-wrap items-center gap-x-4 gap-y-2",
|
|
88
|
-
children: [/* @__PURE__ */
|
|
96
|
+
children: [/* @__PURE__ */ A("div", {
|
|
89
97
|
className: "flex flex-wrap items-center gap-1.5",
|
|
90
98
|
children: [
|
|
91
|
-
/* @__PURE__ */
|
|
92
|
-
status:
|
|
93
|
-
icon:
|
|
99
|
+
/* @__PURE__ */ k(a, {
|
|
100
|
+
status: b.status,
|
|
101
|
+
icon: N(b.status)
|
|
94
102
|
}),
|
|
95
|
-
|
|
103
|
+
b.isInterfaith && /* @__PURE__ */ A("span", {
|
|
96
104
|
className: "inline-flex items-center gap-1 rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-xs font-medium text-text-primary",
|
|
97
|
-
children: [/* @__PURE__ */
|
|
105
|
+
children: [/* @__PURE__ */ k(x, {
|
|
98
106
|
className: "h-3 w-3",
|
|
99
107
|
"aria-hidden": "true"
|
|
100
108
|
}), " Interfaith"]
|
|
101
109
|
}),
|
|
102
|
-
|
|
110
|
+
b.isLocked && /* @__PURE__ */ A("span", {
|
|
103
111
|
className: "inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
|
|
104
|
-
children: [/* @__PURE__ */
|
|
112
|
+
children: [/* @__PURE__ */ k(S, {
|
|
105
113
|
className: "h-3 w-3",
|
|
106
114
|
"aria-hidden": "true"
|
|
107
115
|
}), " Locked"]
|
|
108
116
|
})
|
|
109
117
|
]
|
|
110
|
-
}),
|
|
118
|
+
}), b.tags.length > 0 && /* @__PURE__ */ k("div", {
|
|
111
119
|
className: "flex flex-wrap items-center gap-1.5 sm:ml-auto",
|
|
112
|
-
children:
|
|
120
|
+
children: b.tags.map((e) => /* @__PURE__ */ A("span", {
|
|
113
121
|
className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
|
|
114
122
|
children: ["#", e]
|
|
115
123
|
}, e))
|
|
116
124
|
})]
|
|
117
125
|
}),
|
|
118
|
-
/* @__PURE__ */
|
|
126
|
+
/* @__PURE__ */ A("div", {
|
|
119
127
|
className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-text-tertiary",
|
|
120
128
|
children: [
|
|
121
|
-
/* @__PURE__ */
|
|
122
|
-
actorId:
|
|
129
|
+
/* @__PURE__ */ k(o, {
|
|
130
|
+
actorId: b.openedById,
|
|
123
131
|
prefix: "Opened by"
|
|
124
132
|
}),
|
|
125
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ k("span", {
|
|
126
134
|
"aria-hidden": "true",
|
|
127
135
|
children: "·"
|
|
128
136
|
}),
|
|
129
|
-
/* @__PURE__ */
|
|
137
|
+
/* @__PURE__ */ A("span", {
|
|
130
138
|
className: "inline-flex items-center gap-1",
|
|
131
139
|
children: [
|
|
132
|
-
/* @__PURE__ */
|
|
140
|
+
/* @__PURE__ */ k(C, {
|
|
133
141
|
className: "h-3.5 w-3.5",
|
|
134
142
|
"aria-hidden": "true"
|
|
135
143
|
}),
|
|
136
|
-
r(
|
|
144
|
+
r(b.replyCount),
|
|
137
145
|
" ",
|
|
138
|
-
|
|
146
|
+
b.replyCount === 1 ? "reply" : "replies"
|
|
139
147
|
]
|
|
140
148
|
}),
|
|
141
|
-
/* @__PURE__ */
|
|
149
|
+
/* @__PURE__ */ k("span", {
|
|
142
150
|
"aria-hidden": "true",
|
|
143
151
|
children: "·"
|
|
144
152
|
}),
|
|
145
|
-
/* @__PURE__ */
|
|
153
|
+
/* @__PURE__ */ A("span", { children: ["Started ", i(b.createdAt)] })
|
|
146
154
|
]
|
|
147
155
|
}),
|
|
148
|
-
(
|
|
156
|
+
(b.prompt || b.storyId) && /* @__PURE__ */ A("div", {
|
|
149
157
|
className: "flex flex-col gap-3 rounded-xl border border-border-seam bg-[var(--color-accent-soft)] p-4 sm:flex-row sm:items-start sm:justify-between",
|
|
150
|
-
children: [
|
|
158
|
+
children: [b.prompt ? /* @__PURE__ */ A("div", {
|
|
151
159
|
className: "flex min-w-0 items-start gap-3",
|
|
152
|
-
children: [/* @__PURE__ */
|
|
160
|
+
children: [/* @__PURE__ */ k("span", {
|
|
153
161
|
className: "mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-canvas/70 text-accent",
|
|
154
162
|
"aria-hidden": "true",
|
|
155
|
-
children: /* @__PURE__ */
|
|
156
|
-
}), /* @__PURE__ */
|
|
163
|
+
children: /* @__PURE__ */ k(w, { className: "h-4 w-4" })
|
|
164
|
+
}), /* @__PURE__ */ k("p", {
|
|
157
165
|
className: "min-w-0 whitespace-pre-wrap text-sm leading-relaxed text-text-primary",
|
|
158
|
-
children:
|
|
166
|
+
children: b.prompt
|
|
159
167
|
})]
|
|
160
|
-
}) : /* @__PURE__ */
|
|
168
|
+
}) : /* @__PURE__ */ k("span", {
|
|
161
169
|
className: "text-sm text-text-secondary",
|
|
162
170
|
children: "Anchored to a story."
|
|
163
|
-
}),
|
|
171
|
+
}), b.storyId && /* @__PURE__ */ A("button", {
|
|
164
172
|
type: "button",
|
|
165
|
-
onClick: () =>
|
|
173
|
+
onClick: () => v(`stories/${b.storyId}`),
|
|
166
174
|
className: "inline-flex shrink-0 items-center gap-1.5 self-start rounded-lg px-1 text-sm font-medium text-accent hover:underline",
|
|
167
175
|
children: [
|
|
168
|
-
/* @__PURE__ */
|
|
176
|
+
/* @__PURE__ */ k(g, {
|
|
169
177
|
className: "h-4 w-4",
|
|
170
178
|
"aria-hidden": "true"
|
|
171
179
|
}),
|
|
172
180
|
" View linked story",
|
|
173
|
-
/* @__PURE__ */
|
|
181
|
+
/* @__PURE__ */ k(y, {
|
|
174
182
|
className: "h-3.5 w-3.5",
|
|
175
183
|
"aria-hidden": "true"
|
|
176
184
|
})
|
|
@@ -178,14 +186,14 @@ function M() {
|
|
|
178
186
|
})]
|
|
179
187
|
})
|
|
180
188
|
]
|
|
181
|
-
}), /* @__PURE__ */
|
|
182
|
-
discussionId:
|
|
183
|
-
isLocked:
|
|
189
|
+
}), /* @__PURE__ */ k(m, {
|
|
190
|
+
discussionId: b.id,
|
|
191
|
+
isLocked: b.isLocked
|
|
184
192
|
})]
|
|
185
193
|
})
|
|
186
194
|
});
|
|
187
195
|
}
|
|
188
196
|
//#endregion
|
|
189
|
-
export {
|
|
197
|
+
export { P as DiscussionDetailPage };
|
|
190
198
|
|
|
191
199
|
//# sourceMappingURL=DiscussionDetailPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiscussionDetailPage.js","names":[],"sources":["../../../../src/theculturepost/pages/discussions/DiscussionDetailPage.tsx"],"sourcesContent":["/**\n * DiscussionDetailPage — a single discussion and its moderated replies.\n * @module theculturepost/pages/discussions\n *\n * Reads `tcpDiscussion`. Writes `tcpLockDiscussion` and, via {@link ReplyThread},\n * `tcpPostReply` / `tcpModerateReply`. When anchored to a story, a link back to\n * the story is shown. The header is an editorial card: display-serif title, a\n * moderation-status + interfaith badge row, tag chips, an \"opened by\" byline and\n * a framed prompt callout.\n */\n\nimport type { ReactNode } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n Lock,\n Unlock,\n HeartHandshake,\n BookOpen,\n MessagesSquare,\n Quote,\n CheckCircle2,\n Clock,\n Flag,\n Trash2,\n ExternalLink,\n} from 'lucide-react';\nimport { Button, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { AuthorLabel } from '../../components/AuthorLabel';\nimport { ReplyThread } from '../../components/ReplyThread';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useTcpDiscussion, useTcpLockDiscussion } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { formatNumber, formatRelativeTime } from '../../utils/formatters';\nimport { notify, describeError } from '../../lib/toast';\nimport type { TcpModerationStatus } from '../../types';\n\n/** Leading icon for a moderation-status badge (token colours come from StatusBadge). */\nfunction statusIcon(status: TcpModerationStatus): ReactNode {\n const className = 'h-3 w-3';\n switch (status) {\n case 'APPROVED':\n return <CheckCircle2 className={className} aria-hidden=\"true\" />;\n case 'PENDING':\n return <Clock className={className} aria-hidden=\"true\" />;\n case 'FLAGGED':\n return <Flag className={className} aria-hidden=\"true\" />;\n case 'REMOVED':\n return <Trash2 className={className} aria-hidden=\"true\" />;\n }\n}\n\nexport function DiscussionDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useTheCulturePost();\n const { data: discussion, isLoading, isError, refetch } = useTcpDiscussion(id);\n const lock = useTcpLockDiscussion();\n\n const backButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('discussions')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <LoadingView label=\"Loading discussion…\" />\n </PageLayout>\n );\n }\n\n if (isError || !discussion) {\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <ErrorView\n title=\"Discussion not found\"\n message=\"This discussion may have been removed, or you may not have access.\"\n onRetry={() => refetch()}\n />\n </PageLayout>\n );\n }\n\n const doLock = async () => {\n try {\n await lock.mutateAsync(discussion.id);\n notify.success(discussion.isLocked ? 'Discussion unlocked' : 'Discussion locked');\n } catch (err) {\n notify.error('Could not update the discussion', describeError(err));\n }\n };\n\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <div className=\"mx-auto flex max-w-3xl flex-col gap-6\">\n <GlassCard treatment=\"plain\" className=\"flex flex-col gap-4 p-5 sm:p-6\">\n {/* Title + lock/unlock */}\n <div className=\"flex items-start justify-between gap-3\">\n <h1 className=\"font-display text-2xl font-semibold leading-tight text-text-primary sm:text-3xl\">\n {discussion.title}\n </h1>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={doLock}\n disabled={lock.isPending}\n className=\"shrink-0\"\n >\n {discussion.isLocked ? (\n <>\n <Unlock className=\"mr-1.5 h-4 w-4\" /> Unlock\n </>\n ) : (\n <>\n <Lock className=\"mr-1.5 h-4 w-4\" /> Lock\n </>\n )}\n </Button>\n </div>\n\n {/* Moderation status + interfaith / locked signals, with tags to the right */}\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={discussion.status} icon={statusIcon(discussion.status)} />\n {discussion.isInterfaith && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-xs font-medium text-text-primary\">\n <HeartHandshake className=\"h-3 w-3\" aria-hidden=\"true\" /> Interfaith\n </span>\n )}\n {discussion.isLocked && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n <Lock className=\"h-3 w-3\" aria-hidden=\"true\" /> Locked\n </span>\n )}\n </div>\n {discussion.tags.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-1.5 sm:ml-auto\">\n {discussion.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n #{tag}\n </span>\n ))}\n </div>\n )}\n </div>\n\n {/* Byline */}\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-text-tertiary\">\n <AuthorLabel actorId={discussion.openedById} prefix=\"Opened by\" />\n <span aria-hidden=\"true\">·</span>\n <span className=\"inline-flex items-center gap-1\">\n <MessagesSquare className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n {formatNumber(discussion.replyCount)}{' '}\n {discussion.replyCount === 1 ? 'reply' : 'replies'}\n </span>\n <span aria-hidden=\"true\">·</span>\n <span>Started {formatRelativeTime(discussion.createdAt)}</span>\n </div>\n\n {/* Prompt callout + linked story */}\n {(discussion.prompt || discussion.storyId) && (\n <div className=\"flex flex-col gap-3 rounded-xl border border-border-seam bg-[var(--color-accent-soft)] p-4 sm:flex-row sm:items-start sm:justify-between\">\n {discussion.prompt ? (\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-canvas/70 text-accent\"\n aria-hidden=\"true\"\n >\n <Quote className=\"h-4 w-4\" />\n </span>\n <p className=\"min-w-0 whitespace-pre-wrap text-sm leading-relaxed text-text-primary\">\n {discussion.prompt}\n </p>\n </div>\n ) : (\n <span className=\"text-sm text-text-secondary\">Anchored to a story.</span>\n )}\n {discussion.storyId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`stories/${discussion.storyId}`)}\n className=\"inline-flex shrink-0 items-center gap-1.5 self-start rounded-lg px-1 text-sm font-medium text-accent hover:underline\"\n >\n <BookOpen className=\"h-4 w-4\" aria-hidden=\"true\" /> View linked story\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </button>\n )}\n </div>\n )}\n </GlassCard>\n\n <ReplyThread discussionId={discussion.id} isLocked={discussion.isLocked} />\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DiscussionDetailPage.js","names":[],"sources":["../../../../src/theculturepost/pages/discussions/DiscussionDetailPage.tsx"],"sourcesContent":["/**\n * DiscussionDetailPage — a single discussion and its moderated replies.\n * @module theculturepost/pages/discussions\n *\n * Reads `tcpDiscussion`. Writes `tcpLockDiscussion` and, via {@link ReplyThread},\n * `tcpPostReply` / `tcpModerateReply`. When anchored to a story, a link back to\n * the story is shown. The header is an editorial card: display-serif title, a\n * moderation-status + interfaith badge row, tag chips, an \"opened by\" byline and\n * a framed prompt callout.\n */\n\nimport type { ReactNode } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n Lock,\n Unlock,\n HeartHandshake,\n BookOpen,\n MessagesSquare,\n Quote,\n CheckCircle2,\n Clock,\n Flag,\n Trash2,\n ExternalLink,\n} from 'lucide-react';\nimport { Button, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { AuthorLabel } from '../../components/AuthorLabel';\nimport { ReplyThread } from '../../components/ReplyThread';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useTcpDiscussion, useTcpLockDiscussion } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { formatNumber, formatRelativeTime } from '../../utils/formatters';\nimport { notify, describeError } from '../../lib/toast';\nimport { impact, nativeConfirm } from '../../utils/nativeBridge';\nimport type { TcpModerationStatus } from '../../types';\n\n/** Leading icon for a moderation-status badge (token colours come from StatusBadge). */\nfunction statusIcon(status: TcpModerationStatus): ReactNode {\n const className = 'h-3 w-3';\n switch (status) {\n case 'APPROVED':\n return <CheckCircle2 className={className} aria-hidden=\"true\" />;\n case 'PENDING':\n return <Clock className={className} aria-hidden=\"true\" />;\n case 'FLAGGED':\n return <Flag className={className} aria-hidden=\"true\" />;\n case 'REMOVED':\n return <Trash2 className={className} aria-hidden=\"true\" />;\n }\n}\n\nexport function DiscussionDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useTheCulturePost();\n const { data: discussion, isLoading, isError, refetch } = useTcpDiscussion(id);\n const lock = useTcpLockDiscussion();\n\n const backButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('discussions')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <LoadingView label=\"Loading discussion…\" />\n </PageLayout>\n );\n }\n\n if (isError || !discussion) {\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <ErrorView\n title=\"Discussion not found\"\n message=\"This discussion may have been removed, or you may not have access.\"\n onRetry={() => refetch()}\n />\n </PageLayout>\n );\n }\n\n const doLock = async () => {\n await impact('light');\n const action = discussion.isLocked ? 'unlock' : 'lock';\n const confirmed = await nativeConfirm({\n title: `${action === 'lock' ? 'Lock' : 'Unlock'} discussion`,\n message: `Are you sure you want to ${action} this discussion?`,\n okButtonTitle: action === 'lock' ? 'Lock' : 'Unlock',\n cancelButtonTitle: 'Cancel',\n });\n if (!confirmed) return;\n try {\n await lock.mutateAsync(discussion.id);\n notify.success(discussion.isLocked ? 'Discussion unlocked' : 'Discussion locked');\n } catch (err) {\n notify.error('Could not update the discussion', describeError(err));\n }\n };\n\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <div className=\"mx-auto flex max-w-3xl flex-col gap-6\">\n <GlassCard treatment=\"plain\" className=\"flex flex-col gap-4 p-5 sm:p-6\">\n {/* Title + lock/unlock */}\n <div className=\"flex items-start justify-between gap-3\">\n <h1 className=\"font-display text-2xl font-semibold leading-tight text-text-primary sm:text-3xl\">\n {discussion.title}\n </h1>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={doLock}\n disabled={lock.isPending}\n className=\"shrink-0\"\n >\n {discussion.isLocked ? (\n <>\n <Unlock className=\"mr-1.5 h-4 w-4\" /> Unlock\n </>\n ) : (\n <>\n <Lock className=\"mr-1.5 h-4 w-4\" /> Lock\n </>\n )}\n </Button>\n </div>\n\n {/* Moderation status + interfaith / locked signals, with tags to the right */}\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={discussion.status} icon={statusIcon(discussion.status)} />\n {discussion.isInterfaith && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-xs font-medium text-text-primary\">\n <HeartHandshake className=\"h-3 w-3\" aria-hidden=\"true\" /> Interfaith\n </span>\n )}\n {discussion.isLocked && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n <Lock className=\"h-3 w-3\" aria-hidden=\"true\" /> Locked\n </span>\n )}\n </div>\n {discussion.tags.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-1.5 sm:ml-auto\">\n {discussion.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n #{tag}\n </span>\n ))}\n </div>\n )}\n </div>\n\n {/* Byline */}\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-text-tertiary\">\n <AuthorLabel actorId={discussion.openedById} prefix=\"Opened by\" />\n <span aria-hidden=\"true\">·</span>\n <span className=\"inline-flex items-center gap-1\">\n <MessagesSquare className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n {formatNumber(discussion.replyCount)}{' '}\n {discussion.replyCount === 1 ? 'reply' : 'replies'}\n </span>\n <span aria-hidden=\"true\">·</span>\n <span>Started {formatRelativeTime(discussion.createdAt)}</span>\n </div>\n\n {/* Prompt callout + linked story */}\n {(discussion.prompt || discussion.storyId) && (\n <div className=\"flex flex-col gap-3 rounded-xl border border-border-seam bg-[var(--color-accent-soft)] p-4 sm:flex-row sm:items-start sm:justify-between\">\n {discussion.prompt ? (\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-canvas/70 text-accent\"\n aria-hidden=\"true\"\n >\n <Quote className=\"h-4 w-4\" />\n </span>\n <p className=\"min-w-0 whitespace-pre-wrap text-sm leading-relaxed text-text-primary\">\n {discussion.prompt}\n </p>\n </div>\n ) : (\n <span className=\"text-sm text-text-secondary\">Anchored to a story.</span>\n )}\n {discussion.storyId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`stories/${discussion.storyId}`)}\n className=\"inline-flex shrink-0 items-center gap-1.5 self-start rounded-lg px-1 text-sm font-medium text-accent hover:underline\"\n >\n <BookOpen className=\"h-4 w-4\" aria-hidden=\"true\" /> View linked story\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </button>\n )}\n </div>\n )}\n </GlassCard>\n\n <ReplyThread discussionId={discussion.id} isLocked={discussion.isLocked} />\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DiscussionsPage — browse moderated community discussions.
|
|
3
|
+
* @module theculturepost/pages/discussions
|
|
4
|
+
*
|
|
5
|
+
* Reads `tcpListDiscussions` (filtered by moderation status). The interfaith
|
|
6
|
+
* toggle is a client-side filter over the loaded page (the svc list field does
|
|
7
|
+
* not filter by interfaith). "Open Discussion" opens {@link OpenDiscussionDialog}.
|
|
8
|
+
*/
|
|
9
|
+
export declare function DiscussionsPage(): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=DiscussionsPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscussionsPage.d.ts","sourceRoot":"","sources":["../../../../src/theculturepost/pages/discussions/DiscussionsPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA6BH,wBAAgB,eAAe,4CA6G9B"}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { useTheCulturePost as e } from "../../context/TheCulturePostContext.js";
|
|
2
|
-
import { cn as t } from "../../utils/cn.js";
|
|
3
2
|
import "../../context/index.js";
|
|
3
|
+
import { cn as t } from "../../utils/cn.js";
|
|
4
4
|
import { ErrorView as n, LoadingView as r } from "../../components/StateViews.js";
|
|
5
5
|
import { EmptyState as i } from "../../components/EmptyState.js";
|
|
6
6
|
import { useTcpDiscussions as a } from "../../hooks/useTcpApi.js";
|
|
7
7
|
import { useCursorPager as o } from "../../hooks/useCursorPager.js";
|
|
8
|
+
import { useTr as s } from "../../hooks/useTr.js";
|
|
8
9
|
import "../../hooks/index.js";
|
|
9
|
-
import { Pagination as
|
|
10
|
-
import { PageLayout as
|
|
11
|
-
import { FilterTabs as
|
|
12
|
-
import { DiscussionCard as
|
|
13
|
-
import { OpenDiscussionDialog as
|
|
14
|
-
import { useState as
|
|
15
|
-
import { HeartHandshake as
|
|
16
|
-
import { Fragment as
|
|
17
|
-
import { Button as
|
|
10
|
+
import { Pagination as c } from "../../components/Pagination.js";
|
|
11
|
+
import { PageLayout as l } from "../../components/PageLayout.js";
|
|
12
|
+
import { FilterTabs as u } from "../../components/FilterTabs.js";
|
|
13
|
+
import { DiscussionCard as d } from "../../components/DiscussionCard.js";
|
|
14
|
+
import { OpenDiscussionDialog as f } from "../../components/OpenDiscussionDialog.js";
|
|
15
|
+
import { useState as p } from "react";
|
|
16
|
+
import { HeartHandshake as m, MessagesSquare as h, Plus as g } from "lucide-react";
|
|
17
|
+
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
18
|
+
import { Button as b } from "@burdenoff/fe-libs/ui";
|
|
18
19
|
//#region src/theculturepost/pages/discussions/DiscussionsPage.tsx
|
|
19
|
-
var
|
|
20
|
+
var x = 12, S = [
|
|
20
21
|
{
|
|
21
22
|
value: "ALL",
|
|
22
23
|
label: "All"
|
|
@@ -38,72 +39,78 @@ var b = 12, x = [
|
|
|
38
39
|
label: "Removed"
|
|
39
40
|
}
|
|
40
41
|
];
|
|
41
|
-
function
|
|
42
|
-
let { navigateTo:
|
|
43
|
-
status:
|
|
42
|
+
function C() {
|
|
43
|
+
let { navigateTo: C } = e(), w = s(), T = o(), [E, D] = p("ALL"), [O, k] = p(!1), [A, j] = p(!1), { data: M, isLoading: N, isError: P, refetch: F } = a({
|
|
44
|
+
status: E === "ALL" ? void 0 : E,
|
|
44
45
|
pagination: {
|
|
45
|
-
limit:
|
|
46
|
-
cursor:
|
|
46
|
+
limit: x,
|
|
47
|
+
cursor: T.cursor
|
|
47
48
|
}
|
|
48
|
-
}),
|
|
49
|
-
return /* @__PURE__ */
|
|
50
|
-
title: "Discussions",
|
|
51
|
-
description: "Respectful, moderated conversations — including interfaith spaces that welcome many traditions.",
|
|
52
|
-
actions: /* @__PURE__ */
|
|
53
|
-
onClick: () =>
|
|
54
|
-
|
|
49
|
+
}), I = M?.items ?? [], L = O ? I.filter((e) => e.isInterfaith) : I;
|
|
50
|
+
return /* @__PURE__ */ y(l, {
|
|
51
|
+
title: w("discussions.title", "Discussions"),
|
|
52
|
+
description: w("discussions.description", "Respectful, moderated conversations — including interfaith spaces that welcome many traditions."),
|
|
53
|
+
actions: /* @__PURE__ */ y(b, {
|
|
54
|
+
onClick: () => j(!0),
|
|
55
|
+
"data-tour": "theculturepost-discussions-create",
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ v(g, { className: "mr-1.5 h-4 w-4" }),
|
|
58
|
+
" ",
|
|
59
|
+
w("discussions.openDiscussion", "Open discussion")
|
|
60
|
+
]
|
|
55
61
|
}),
|
|
56
62
|
children: [
|
|
57
|
-
/* @__PURE__ */
|
|
63
|
+
/* @__PURE__ */ y("div", {
|
|
58
64
|
className: "mb-5 flex flex-wrap items-center gap-3",
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
"data-tour": "theculturepost-discussions-filters",
|
|
66
|
+
children: [/* @__PURE__ */ v(u, {
|
|
67
|
+
options: S,
|
|
68
|
+
value: E,
|
|
62
69
|
onChange: (e) => {
|
|
63
|
-
|
|
70
|
+
D(e), T.reset();
|
|
64
71
|
}
|
|
65
|
-
}), /* @__PURE__ */
|
|
72
|
+
}), /* @__PURE__ */ y("button", {
|
|
66
73
|
type: "button",
|
|
67
|
-
"aria-pressed":
|
|
68
|
-
onClick: () =>
|
|
69
|
-
className: t("inline-flex items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm font-medium transition-colors",
|
|
70
|
-
children: [/* @__PURE__ */
|
|
74
|
+
"aria-pressed": O,
|
|
75
|
+
onClick: () => k((e) => !e),
|
|
76
|
+
className: t("inline-flex items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm font-medium transition-colors", O ? "border-transparent bg-action-primary-bg text-action-primary-text" : "border-border-seam bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary"),
|
|
77
|
+
children: [/* @__PURE__ */ v(m, { className: "h-4 w-4" }), " Interfaith"]
|
|
71
78
|
})]
|
|
72
79
|
}),
|
|
73
|
-
|
|
80
|
+
N ? /* @__PURE__ */ v(r, { label: "Loading discussions…" }) : P ? /* @__PURE__ */ v(n, {
|
|
74
81
|
message: "We couldn't load discussions.",
|
|
75
|
-
onRetry: () =>
|
|
76
|
-
}) :
|
|
82
|
+
onRetry: () => F()
|
|
83
|
+
}) : L.length === 0 && T.page === 0 ? /* @__PURE__ */ v(i, {
|
|
77
84
|
illustration: "empty-notifications",
|
|
78
|
-
icon: /* @__PURE__ */
|
|
79
|
-
title:
|
|
80
|
-
description:
|
|
81
|
-
action: /* @__PURE__ */
|
|
82
|
-
onClick: () =>
|
|
83
|
-
children: [/* @__PURE__ */
|
|
85
|
+
icon: /* @__PURE__ */ v(h, { className: "h-10 w-10" }),
|
|
86
|
+
title: O ? "No interfaith discussions here" : E === "ALL" ? "No discussions yet" : "No discussions match this filter",
|
|
87
|
+
description: E === "ALL" && !O ? "Open a discussion to invite thoughtful, respectful perspectives." : "Try a different filter, or open a new discussion.",
|
|
88
|
+
action: /* @__PURE__ */ y(b, {
|
|
89
|
+
onClick: () => j(!0),
|
|
90
|
+
children: [/* @__PURE__ */ v(g, { className: "mr-1.5 h-4 w-4" }), " Open discussion"]
|
|
84
91
|
})
|
|
85
|
-
}) : /* @__PURE__ */
|
|
92
|
+
}) : /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("ul", {
|
|
86
93
|
className: "flex flex-col gap-3",
|
|
87
|
-
children:
|
|
94
|
+
children: L.map((e) => /* @__PURE__ */ v("li", { children: /* @__PURE__ */ v(d, {
|
|
88
95
|
discussion: e,
|
|
89
|
-
onOpen: () =>
|
|
96
|
+
onOpen: () => C(`discussions/${e.id}`)
|
|
90
97
|
}) }, e.id))
|
|
91
|
-
}), /* @__PURE__ */
|
|
92
|
-
page:
|
|
93
|
-
pageSize:
|
|
94
|
-
itemCount:
|
|
95
|
-
hasMore:
|
|
96
|
-
onPageChange: (e) =>
|
|
98
|
+
}), /* @__PURE__ */ v(c, {
|
|
99
|
+
page: T.page,
|
|
100
|
+
pageSize: x,
|
|
101
|
+
itemCount: I.length,
|
|
102
|
+
hasMore: M?.pageInfo.hasMore ?? !1,
|
|
103
|
+
onPageChange: (e) => T.onPageChange(e, M?.pageInfo.cursor)
|
|
97
104
|
})] }),
|
|
98
|
-
/* @__PURE__ */
|
|
99
|
-
open:
|
|
100
|
-
onOpenChange:
|
|
101
|
-
onCreated: (e) =>
|
|
105
|
+
/* @__PURE__ */ v(f, {
|
|
106
|
+
open: A,
|
|
107
|
+
onOpenChange: j,
|
|
108
|
+
onCreated: (e) => C(`discussions/${e.id}`)
|
|
102
109
|
})
|
|
103
110
|
]
|
|
104
111
|
});
|
|
105
112
|
}
|
|
106
113
|
//#endregion
|
|
107
|
-
export {
|
|
114
|
+
export { C as DiscussionsPage };
|
|
108
115
|
|
|
109
116
|
//# sourceMappingURL=DiscussionsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiscussionsPage.js","names":[],"sources":["../../../../src/theculturepost/pages/discussions/DiscussionsPage.tsx"],"sourcesContent":["/**\n * DiscussionsPage — browse moderated community discussions.\n * @module theculturepost/pages/discussions\n *\n * Reads `tcpListDiscussions` (filtered by moderation status). The interfaith\n * toggle is a client-side filter over the loaded page (the svc list field does\n * not filter by interfaith). \"Open Discussion\" opens {@link OpenDiscussionDialog}.\n */\n\nimport { useState } from 'react';\nimport { MessagesSquare, Plus, HeartHandshake } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { DiscussionCard } from '../../components/DiscussionCard';\nimport { OpenDiscussionDialog } from '../../components/OpenDiscussionDialog';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport { useTcpDiscussions, useCursorPager } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { cn } from '../../utils/cn';\nimport type { TcpModerationStatus } from '../../types';\n\nconst PAGE_SIZE = 12;\n\ntype StatusFilter = 'ALL' | TcpModerationStatus;\n\nconst STATUS_FILTERS: FilterOption<StatusFilter>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'APPROVED', label: 'Approved' },\n { value: 'PENDING', label: 'Pending' },\n { value: 'FLAGGED', label: 'Flagged' },\n { value: 'REMOVED', label: 'Removed' },\n];\n\nexport function DiscussionsPage() {\n const { navigateTo } = useTheCulturePost();\n const pager = useCursorPager();\n const [status, setStatus] = useState<StatusFilter>('ALL');\n const [interfaithOnly, setInterfaithOnly] = useState(false);\n const [createOpen, setCreateOpen] = useState(false);\n\n const { data, isLoading, isError, refetch } = useTcpDiscussions({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const allItems = data?.items ?? [];\n const discussions = interfaithOnly ? allItems.filter((d) => d.isInterfaith) : allItems;\n\n const changeStatus = (next: StatusFilter) => {\n setStatus(next);\n pager.reset();\n };\n\n return (\n <PageLayout\n title
|
|
1
|
+
{"version":3,"file":"DiscussionsPage.js","names":[],"sources":["../../../../src/theculturepost/pages/discussions/DiscussionsPage.tsx"],"sourcesContent":["/**\n * DiscussionsPage — browse moderated community discussions.\n * @module theculturepost/pages/discussions\n *\n * Reads `tcpListDiscussions` (filtered by moderation status). The interfaith\n * toggle is a client-side filter over the loaded page (the svc list field does\n * not filter by interfaith). \"Open Discussion\" opens {@link OpenDiscussionDialog}.\n */\n\nimport { useState } from 'react';\nimport { MessagesSquare, Plus, HeartHandshake } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { DiscussionCard } from '../../components/DiscussionCard';\nimport { OpenDiscussionDialog } from '../../components/OpenDiscussionDialog';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport { useTcpDiscussions, useCursorPager, useTr } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { cn } from '../../utils/cn';\nimport type { TcpModerationStatus } from '../../types';\n\nconst PAGE_SIZE = 12;\n\ntype StatusFilter = 'ALL' | TcpModerationStatus;\n\nconst STATUS_FILTERS: FilterOption<StatusFilter>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'APPROVED', label: 'Approved' },\n { value: 'PENDING', label: 'Pending' },\n { value: 'FLAGGED', label: 'Flagged' },\n { value: 'REMOVED', label: 'Removed' },\n];\n\nexport function DiscussionsPage() {\n const { navigateTo } = useTheCulturePost();\n const tr = useTr();\n const pager = useCursorPager();\n const [status, setStatus] = useState<StatusFilter>('ALL');\n const [interfaithOnly, setInterfaithOnly] = useState(false);\n const [createOpen, setCreateOpen] = useState(false);\n\n const { data, isLoading, isError, refetch } = useTcpDiscussions({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const allItems = data?.items ?? [];\n const discussions = interfaithOnly ? allItems.filter((d) => d.isInterfaith) : allItems;\n\n const changeStatus = (next: StatusFilter) => {\n setStatus(next);\n pager.reset();\n };\n\n return (\n <PageLayout\n title={tr('discussions.title', 'Discussions')}\n description={tr(\n 'discussions.description',\n 'Respectful, moderated conversations — including interfaith spaces that welcome many traditions.'\n )}\n actions={\n <Button onClick={() => setCreateOpen(true)} data-tour=\"theculturepost-discussions-create\">\n <Plus className=\"mr-1.5 h-4 w-4\" /> {tr('discussions.openDiscussion', 'Open discussion')}\n </Button>\n }\n >\n <div\n className=\"mb-5 flex flex-wrap items-center gap-3\"\n data-tour=\"theculturepost-discussions-filters\"\n >\n <FilterTabs options={STATUS_FILTERS} value={status} onChange={changeStatus} />\n <button\n type=\"button\"\n aria-pressed={interfaithOnly}\n onClick={() => setInterfaithOnly((v) => !v)}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm font-medium transition-colors',\n interfaithOnly\n ? 'border-transparent bg-action-primary-bg text-action-primary-text'\n : 'border-border-seam bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary'\n )}\n >\n <HeartHandshake className=\"h-4 w-4\" /> Interfaith\n </button>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading discussions…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load discussions.\" onRetry={() => refetch()} />\n ) : discussions.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<MessagesSquare className=\"h-10 w-10\" />}\n title={\n interfaithOnly\n ? 'No interfaith discussions here'\n : status === 'ALL'\n ? 'No discussions yet'\n : 'No discussions match this filter'\n }\n description={\n status === 'ALL' && !interfaithOnly\n ? 'Open a discussion to invite thoughtful, respectful perspectives.'\n : 'Try a different filter, or open a new discussion.'\n }\n action={\n <Button onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Open discussion\n </Button>\n }\n />\n ) : (\n <>\n <ul className=\"flex flex-col gap-3\">\n {discussions.map((discussion) => (\n <li key={discussion.id}>\n <DiscussionCard\n discussion={discussion}\n onOpen={() => navigateTo(`discussions/${discussion.id}`)}\n />\n </li>\n ))}\n </ul>\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={allItems.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </>\n )}\n\n <OpenDiscussionDialog\n open={createOpen}\n onOpenChange={setCreateOpen}\n onCreated={(discussion) => navigateTo(`discussions/${discussion.id}`)}\n />\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAwBA,IAAM,IAAY,IAIZ,IAA+C;CACnD;EAAE,OAAO;EAAO,OAAO;EAAO;CAC9B;EAAE,OAAO;EAAY,OAAO;EAAY;CACxC;EAAE,OAAO;EAAW,OAAO;EAAW;CACtC;EAAE,OAAO;EAAW,OAAO;EAAW;CACtC;EAAE,OAAO;EAAW,OAAO;EAAW;CACvC;AAED,SAAgB,IAAkB;CAChC,IAAM,EAAE,kBAAe,GAAmB,EACpC,IAAK,GAAO,EACZ,IAAQ,GAAgB,EACxB,CAAC,GAAQ,KAAa,EAAuB,MAAM,EACnD,CAAC,GAAgB,KAAqB,EAAS,GAAM,EACrD,CAAC,GAAY,KAAiB,EAAS,GAAM,EAE7C,EAAE,SAAM,cAAW,YAAS,eAAY,EAAkB;EAC9D,QAAQ,MAAW,QAAQ,KAAA,IAAY;EACvC,YAAY;GAAE,OAAO;GAAW,QAAQ,EAAM;GAAQ;EACvD,CAAC,EAEI,IAAW,GAAM,SAAS,EAAE,EAC5B,IAAc,IAAiB,EAAS,QAAQ,MAAM,EAAE,aAAa,GAAG;AAO9E,QACE,kBAAC,GAAD;EACE,OAAO,EAAG,qBAAqB,cAAc;EAC7C,aAAa,EACX,2BACA,kGACD;EACD,SACE,kBAAC,GAAD;GAAQ,eAAe,EAAc,GAAK;GAAE,aAAU;aAAtD;IACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA;;IAAE,EAAG,8BAA8B,kBAAkB;IACjF;;YATb;GAYE,kBAAC,OAAD;IACE,WAAU;IACV,aAAU;cAFZ,CAIE,kBAAC,GAAD;KAAY,SAAS;KAAgB,OAAO;KAAQ,WAtBpC,MAAuB;AAE3C,MADA,EAAU,EAAK,EACf,EAAM,OAAO;;KAoBqE,CAAA,EAC9E,kBAAC,UAAD;KACE,MAAK;KACL,gBAAc;KACd,eAAe,GAAmB,MAAM,CAAC,EAAE;KAC3C,WAAW,EACT,wGACA,IACI,qEACA,kGACL;eATH,CAWE,kBAAC,GAAD,EAAgB,WAAU,WAAY,CAAA,EAAA,cAC/B;OACL;;GAEL,IACC,kBAAC,GAAD,EAAa,OAAM,wBAAyB,CAAA,GAC1C,IACF,kBAAC,GAAD;IAAW,SAAQ;IAAgC,eAAe,GAAS;IAAI,CAAA,GAC7E,EAAY,WAAW,KAAK,EAAM,SAAS,IAC7C,kBAAC,GAAD;IACE,cAAa;IACb,MAAM,kBAAC,GAAD,EAAgB,WAAU,aAAc,CAAA;IAC9C,OACE,IACI,mCACA,MAAW,QACT,uBACA;IAER,aACE,MAAW,SAAS,CAAC,IACjB,qEACA;IAEN,QACE,kBAAC,GAAD;KAAQ,eAAe,EAAc,GAAK;eAA1C,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,mBAC5B;;IAEX,CAAA,GAEF,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cACX,EAAY,KAAK,MAChB,kBAAC,MAAD,EAAA,UACE,kBAAC,GAAD;KACc;KACZ,cAAc,EAAW,eAAe,EAAW,KAAK;KACxD,CAAA,EACC,EALI,EAAW,GAKf,CACL;IACC,CAAA,EACL,kBAAC,GAAD;IACE,MAAM,EAAM;IACZ,UAAU;IACV,WAAW,EAAS;IACpB,SAAS,GAAM,SAAS,WAAW;IACnC,eAAe,MAAW,EAAM,aAAa,GAAQ,GAAM,SAAS,OAAO;IAC3E,CAAA,CACD,EAAA,CAAA;GAGL,kBAAC,GAAD;IACE,MAAM;IACN,cAAc;IACd,YAAY,MAAe,EAAW,eAAe,EAAW,KAAK;IACrE,CAAA;GACS"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GovernancePage — the editorial / governance overview for TheCulturePost.
|
|
3
|
+
* @module theculturepost/pages/governance
|
|
4
|
+
*
|
|
5
|
+
* A data-honest dashboard computed entirely from real counts in the current
|
|
6
|
+
* workspace. There is NO historical series in the contract, so this surface
|
|
7
|
+
* carries NO trend deltas and NO time-series line chart (unlike the concept
|
|
8
|
+
* mockup). It also DROPS the "Contributors & Roles" table — actors are id-only
|
|
9
|
+
* federation stubs and roles are platform RBAC, neither of which this subgraph
|
|
10
|
+
* exposes.
|
|
11
|
+
*
|
|
12
|
+
* What it renders, all from live `tcp*` reads:
|
|
13
|
+
* - Status StatTiles: Published / In Review / Draft / Idea stories, plus a
|
|
14
|
+
* Discussions total and an Archive (artifacts) count.
|
|
15
|
+
* - "Content pipeline" {@link BarChart} across the lifecycle stages.
|
|
16
|
+
* - "Discussion health" {@link Donut} = share of discussions that are Approved.
|
|
17
|
+
* - "Recent activity" — the latest stories + discussions, newest first.
|
|
18
|
+
*/
|
|
19
|
+
export declare function GovernancePage(): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=GovernancePage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GovernancePage.d.ts","sourceRoot":"","sources":["../../../../src/theculturepost/pages/governance/GovernancePage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAuDH,wBAAgB,cAAc,4CAgS7B"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StoriesPage — browse the newsroom.
|
|
3
|
+
* @module theculturepost/pages/stories
|
|
4
|
+
*
|
|
5
|
+
* Reads `tcpListStories` (filtered by status + optional topic). "New Story"
|
|
6
|
+
* opens {@link CreateStoryDialog}. Cursor-paginated.
|
|
7
|
+
*/
|
|
8
|
+
export declare function StoriesPage(): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=StoriesPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StoriesPage.d.ts","sourceRoot":"","sources":["../../../../src/theculturepost/pages/stories/StoriesPage.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoCH,wBAAgB,WAAW,4CAiH1B"}
|