@burdenoff/microfe-theculturepost 2026.704.2 → 2026.705.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.
Files changed (91) hide show
  1. package/dist/theculturepost/TheCulturePostRoot.js +63 -45
  2. package/dist/theculturepost/TheCulturePostRoot.js.map +1 -1
  3. package/dist/theculturepost/TheCulturePostRoutes.js +17 -9
  4. package/dist/theculturepost/TheCulturePostRoutes.js.map +1 -1
  5. package/dist/theculturepost/components/AddCitationDialog.js +131 -102
  6. package/dist/theculturepost/components/AddCitationDialog.js.map +1 -1
  7. package/dist/theculturepost/components/ArchiveItemCard.js +56 -43
  8. package/dist/theculturepost/components/ArchiveItemCard.js.map +1 -1
  9. package/dist/theculturepost/components/AudioPlayer.js +74 -0
  10. package/dist/theculturepost/components/AudioPlayer.js.map +1 -0
  11. package/dist/theculturepost/components/CitationList.js +215 -105
  12. package/dist/theculturepost/components/CitationList.js.map +1 -1
  13. package/dist/theculturepost/components/CollectionCard.js +32 -32
  14. package/dist/theculturepost/components/CollectionCard.js.map +1 -1
  15. package/dist/theculturepost/components/CreateArchiveItemDialog.js +133 -93
  16. package/dist/theculturepost/components/CreateArchiveItemDialog.js.map +1 -1
  17. package/dist/theculturepost/components/CreateCollectionDialog.js +91 -70
  18. package/dist/theculturepost/components/CreateCollectionDialog.js.map +1 -1
  19. package/dist/theculturepost/components/CreateStoryDialog.js +311 -132
  20. package/dist/theculturepost/components/CreateStoryDialog.js.map +1 -1
  21. package/dist/theculturepost/components/DecorativeCover.js +78 -0
  22. package/dist/theculturepost/components/DecorativeCover.js.map +1 -0
  23. package/dist/theculturepost/components/DecorativeDivider.js +45 -0
  24. package/dist/theculturepost/components/DecorativeDivider.js.map +1 -0
  25. package/dist/theculturepost/components/DiscussionCard.js +75 -60
  26. package/dist/theculturepost/components/DiscussionCard.js.map +1 -1
  27. package/dist/theculturepost/components/HistoryTimeline.js +115 -0
  28. package/dist/theculturepost/components/HistoryTimeline.js.map +1 -0
  29. package/dist/theculturepost/components/LifecycleStepper.js +33 -0
  30. package/dist/theculturepost/components/LifecycleStepper.js.map +1 -0
  31. package/dist/theculturepost/components/OpenDiscussionDialog.js +66 -56
  32. package/dist/theculturepost/components/OpenDiscussionDialog.js.map +1 -1
  33. package/dist/theculturepost/components/OralHistoryCard.js +6 -73
  34. package/dist/theculturepost/components/OverlayBadge.js +22 -0
  35. package/dist/theculturepost/components/OverlayBadge.js.map +1 -0
  36. package/dist/theculturepost/components/PageHero.js +62 -0
  37. package/dist/theculturepost/components/PageHero.js.map +1 -0
  38. package/dist/theculturepost/components/RecordOralHistoryDialog.js +306 -131
  39. package/dist/theculturepost/components/RecordOralHistoryDialog.js.map +1 -1
  40. package/dist/theculturepost/components/ReplyThread.js +268 -139
  41. package/dist/theculturepost/components/ReplyThread.js.map +1 -1
  42. package/dist/theculturepost/components/StatusBadge.js +9 -9
  43. package/dist/theculturepost/components/StatusBadge.js.map +1 -1
  44. package/dist/theculturepost/components/StoryCard.js +54 -49
  45. package/dist/theculturepost/components/StoryCard.js.map +1 -1
  46. package/dist/theculturepost/components/TopicCard.js +60 -41
  47. package/dist/theculturepost/components/TopicCard.js.map +1 -1
  48. package/dist/theculturepost/components/Waveform.js +31 -0
  49. package/dist/theculturepost/components/Waveform.js.map +1 -0
  50. package/dist/theculturepost/components/categoryMeta.js +20 -0
  51. package/dist/theculturepost/components/categoryMeta.js.map +1 -0
  52. package/dist/theculturepost/components/index.js +41 -0
  53. package/dist/theculturepost/components/viz/BarChart.js +53 -0
  54. package/dist/theculturepost/components/viz/BarChart.js.map +1 -0
  55. package/dist/theculturepost/components/viz/Donut.js +58 -0
  56. package/dist/theculturepost/components/viz/Donut.js.map +1 -0
  57. package/dist/theculturepost/components/viz/StatTile.js +35 -0
  58. package/dist/theculturepost/components/viz/StatTile.js.map +1 -0
  59. package/dist/theculturepost/components/viz/index.js +3 -0
  60. package/dist/theculturepost/hooks/useFiles.js +1 -1
  61. package/dist/theculturepost/hooks/useFiles.js.map +1 -1
  62. package/dist/theculturepost/pages/HomePage.js +247 -124
  63. package/dist/theculturepost/pages/HomePage.js.map +1 -1
  64. package/dist/theculturepost/pages/archive/ArchiveItemDetailPage.js +319 -127
  65. package/dist/theculturepost/pages/archive/ArchiveItemDetailPage.js.map +1 -1
  66. package/dist/theculturepost/pages/archive/ArchivePage.js +265 -180
  67. package/dist/theculturepost/pages/archive/ArchivePage.js.map +1 -1
  68. package/dist/theculturepost/pages/archive/CollectionDetailPage.js +158 -143
  69. package/dist/theculturepost/pages/archive/CollectionDetailPage.js.map +1 -1
  70. package/dist/theculturepost/pages/discussions/DiscussionDetailPage.js +155 -93
  71. package/dist/theculturepost/pages/discussions/DiscussionDetailPage.js.map +1 -1
  72. package/dist/theculturepost/pages/discussions/DiscussionsPage.js +16 -16
  73. package/dist/theculturepost/pages/discussions/DiscussionsPage.js.map +1 -1
  74. package/dist/theculturepost/pages/governance/GovernancePage.js +293 -0
  75. package/dist/theculturepost/pages/governance/GovernancePage.js.map +1 -0
  76. package/dist/theculturepost/pages/stories/StoriesPage.js +18 -18
  77. package/dist/theculturepost/pages/stories/StoriesPage.js.map +1 -1
  78. package/dist/theculturepost/pages/stories/StoryDetailPage.js +603 -285
  79. package/dist/theculturepost/pages/stories/StoryDetailPage.js.map +1 -1
  80. package/dist/theculturepost/pages/timeline/TimelinePage.js +162 -0
  81. package/dist/theculturepost/pages/timeline/TimelinePage.js.map +1 -0
  82. package/dist/theculturepost/pages/topics/TopicDetailPage.js +239 -163
  83. package/dist/theculturepost/pages/topics/TopicDetailPage.js.map +1 -1
  84. package/dist/theculturepost/pages/topics/TopicsPage.js +76 -74
  85. package/dist/theculturepost/pages/topics/TopicsPage.js.map +1 -1
  86. package/dist/theculturepost/styles/injectDisplayFont.js +11 -0
  87. package/dist/theculturepost/styles/injectDisplayFont.js.map +1 -0
  88. package/dist/theculturepost/utils/formatters.js +6 -1
  89. package/dist/theculturepost/utils/formatters.js.map +1 -1
  90. package/package.json +1 -1
  91. package/dist/theculturepost/components/OralHistoryCard.js.map +0 -1
@@ -1,245 +1,330 @@
1
1
  import { useTheCulturePost as e } from "../../context/TheCulturePostContext.js";
2
- import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { ErrorView as n, LoadingView as r } from "../../components/StateViews.js";
2
+ import { cn as t } from "../../utils/cn.js";
4
3
  import "../../context/index.js";
5
- import { formatEnumLabel as i } from "../../utils/formatters.js";
6
- import { CollectionCard as a } from "../../components/CollectionCard.js";
7
- import { EmptyState as o } from "../../components/EmptyState.js";
8
- import { useTcpArchiveItems as s, useTcpCollections as c, useTcpOralHistories as l } from "../../hooks/useTcpApi.js";
9
- import { useCursorPager as u } from "../../hooks/useCursorPager.js";
4
+ import { useFileUrl as n } from "../../hooks/useFiles.js";
5
+ import { PageHero as r } from "../../components/PageHero.js";
6
+ import { ErrorView as i, LoadingView as a } from "../../components/StateViews.js";
7
+ import { formatEnumLabel as o, initialsOf as s } from "../../utils/formatters.js";
8
+ import { StatusBadge as c } from "../../components/StatusBadge.js";
9
+ import { EmptyState as l } from "../../components/EmptyState.js";
10
+ import { useTcpArchiveItems as u, useTcpCollections as d, useTcpOralHistories as f } from "../../hooks/useTcpApi.js";
11
+ import { useCursorPager as p } from "../../hooks/useCursorPager.js";
10
12
  import "../../hooks/index.js";
11
- import { Tabs as d } from "../../components/Tabs.js";
12
- import { FilterTabs as f } from "../../components/FilterTabs.js";
13
- import { ArchiveItemCard as p } from "../../components/ArchiveItemCard.js";
14
- import { OralHistoryCard as m } from "../../components/OralHistoryCard.js";
15
- import { CreateCollectionDialog as h } from "../../components/CreateCollectionDialog.js";
16
- import { CreateArchiveItemDialog as g } from "../../components/CreateArchiveItemDialog.js";
17
- import { RecordOralHistoryDialog as _ } from "../../components/RecordOralHistoryDialog.js";
18
- import { Pagination as v } from "../../components/Pagination.js";
19
- import { useState as y } from "react";
20
- import { AudioLines as b, Boxes as x, Library as S, Plus as C } from "lucide-react";
21
- import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
22
- import { Button as D, Select as O, SelectContent as k, SelectItem as A, SelectTrigger as j, SelectValue as M } from "@burdenoff/fe-libs/ui";
13
+ import { KIND_ICON as m } from "../../components/kindIcon.js";
14
+ import { Tabs as h } from "../../components/Tabs.js";
15
+ import { AudioPlayer as g } from "../../components/AudioPlayer.js";
16
+ import { CollectionCard as _ } from "../../components/CollectionCard.js";
17
+ import { ArchiveItemCard as v } from "../../components/ArchiveItemCard.js";
18
+ import { RecordOralHistoryDialog as y } from "../../components/RecordOralHistoryDialog.js";
19
+ import { CreateCollectionDialog as b } from "../../components/CreateCollectionDialog.js";
20
+ import { CreateArchiveItemDialog as x } from "../../components/CreateArchiveItemDialog.js";
21
+ import { Pagination as S } from "../../components/Pagination.js";
22
+ import { createElement as C, useState as w } from "react";
23
+ import { AudioLines as T, Boxes as E, Globe as D, Layers as O, Library as k, Mic as A, Plus as j } from "lucide-react";
24
+ import { Fragment as M, jsx as N, jsxs as P } from "react/jsx-runtime";
25
+ import { Button as F, GlassCard as I, Select as L, SelectContent as R, SelectItem as z, SelectTrigger as B, SelectValue as V } from "@burdenoff/fe-libs/ui";
23
26
  //#region src/theculturepost/pages/archive/ArchivePage.tsx
24
- var N = [
27
+ var H = [
25
28
  {
26
29
  value: "collections",
27
30
  label: "Collections",
28
- icon: /* @__PURE__ */ T(S, { className: "h-4 w-4" })
31
+ icon: /* @__PURE__ */ N(k, { className: "h-4 w-4" })
29
32
  },
30
33
  {
31
34
  value: "artifacts",
32
35
  label: "Artifacts",
33
- icon: /* @__PURE__ */ T(x, { className: "h-4 w-4" })
36
+ icon: /* @__PURE__ */ N(E, { className: "h-4 w-4" })
34
37
  },
35
38
  {
36
39
  value: "oral-histories",
37
40
  label: "Oral Histories",
38
- icon: /* @__PURE__ */ T(b, { className: "h-4 w-4" })
41
+ icon: /* @__PURE__ */ N(T, { className: "h-4 w-4" })
39
42
  }
40
43
  ];
41
- function P() {
42
- let [e, n] = y("collections");
43
- return /* @__PURE__ */ E(t, {
44
- title: "Archive",
45
- description: "A living archive of manuscripts, photographs, recordings, maps and objects — grouped into collections.",
44
+ function U() {
45
+ let { navigateTo: t } = e(), [n, i] = w("collections"), [a, o] = w(!1), [s, c] = w(!1), [l, u] = w(!1);
46
+ return /* @__PURE__ */ P("div", {
47
+ className: "flex h-full flex-col",
46
48
  children: [
47
- /* @__PURE__ */ T(d, {
48
- items: N,
49
- value: e,
50
- onChange: n,
51
- className: "mb-6"
49
+ /* @__PURE__ */ N("div", {
50
+ className: "flex-1 overflow-auto",
51
+ children: /* @__PURE__ */ P("div", {
52
+ className: "mx-auto flex w-full max-w-6xl flex-col gap-6 p-4 sm:p-6",
53
+ children: [/* @__PURE__ */ N(r, {
54
+ eyebrow: "Cultural archive",
55
+ title: "Archive",
56
+ description: "A living archive of manuscripts, photographs, recordings, maps and objects — grouped into collections.",
57
+ actions: n === "collections" ? /* @__PURE__ */ P(F, {
58
+ onClick: () => o(!0),
59
+ children: [/* @__PURE__ */ N(j, { className: "mr-1.5 h-4 w-4" }), " New collection"]
60
+ }) : n === "artifacts" ? /* @__PURE__ */ P(F, {
61
+ onClick: () => c(!0),
62
+ children: [/* @__PURE__ */ N(j, { className: "mr-1.5 h-4 w-4" }), " Add artifact"]
63
+ }) : /* @__PURE__ */ P(F, {
64
+ onClick: () => u(!0),
65
+ children: [/* @__PURE__ */ N(A, { className: "mr-1.5 h-4 w-4" }), " Record"]
66
+ })
67
+ }), /* @__PURE__ */ P("div", { children: [
68
+ /* @__PURE__ */ N(h, {
69
+ items: H,
70
+ value: n,
71
+ onChange: i,
72
+ className: "mb-6"
73
+ }),
74
+ n === "collections" && /* @__PURE__ */ N(W, { onNew: () => o(!0) }),
75
+ n === "artifacts" && /* @__PURE__ */ N(J, { onNew: () => c(!0) }),
76
+ n === "oral-histories" && /* @__PURE__ */ N(Y, { onNew: () => u(!0) })
77
+ ] })]
78
+ })
79
+ }),
80
+ /* @__PURE__ */ N(b, {
81
+ open: a,
82
+ onOpenChange: o,
83
+ onCreated: (e) => t(`archive/collections/${e.id}`)
84
+ }),
85
+ /* @__PURE__ */ N(x, {
86
+ open: s,
87
+ onOpenChange: c,
88
+ onCreated: (e) => t(`archive/items/${e.id}`)
52
89
  }),
53
- e === "collections" && /* @__PURE__ */ T(F, {}),
54
- e === "artifacts" && /* @__PURE__ */ T(z, {}),
55
- e === "oral-histories" && /* @__PURE__ */ T(B, {})
90
+ /* @__PURE__ */ N(y, {
91
+ open: l,
92
+ onOpenChange: u
93
+ })
56
94
  ]
57
95
  });
58
96
  }
59
- function F() {
60
- let { navigateTo: t } = e(), { data: i, isLoading: s, isError: l, refetch: u } = c({ limit: 60 }), [d, f] = y(!1), p = i ?? [];
61
- return /* @__PURE__ */ E("div", { children: [
62
- /* @__PURE__ */ T("div", {
63
- className: "mb-4 flex items-center justify-end",
64
- children: /* @__PURE__ */ E(D, {
65
- onClick: () => f(!0),
66
- children: [/* @__PURE__ */ T(C, { className: "mr-1.5 h-4 w-4" }), " New collection"]
67
- })
68
- }),
69
- s ? /* @__PURE__ */ T(r, { label: "Loading collections…" }) : l ? /* @__PURE__ */ T(n, {
70
- message: "We couldn't load collections.",
71
- onRetry: () => u()
72
- }) : p.length === 0 ? /* @__PURE__ */ T(o, {
73
- illustration: "empty-files",
74
- icon: /* @__PURE__ */ T(S, { className: "h-10 w-10" }),
75
- title: "No collections yet",
76
- description: "Create a collection to begin grouping artifacts and oral histories.",
77
- action: /* @__PURE__ */ E(D, {
78
- onClick: () => f(!0),
79
- children: [/* @__PURE__ */ T(C, { className: "mr-1.5 h-4 w-4" }), " New collection"]
80
- })
81
- }) : /* @__PURE__ */ T("div", {
82
- className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
83
- children: p.map((e) => /* @__PURE__ */ T(a, {
84
- collection: e,
85
- onOpen: () => t(`archive/collections/${e.id}`)
86
- }, e.id))
87
- }),
88
- /* @__PURE__ */ T(h, {
89
- open: d,
90
- onOpenChange: f,
91
- onCreated: (e) => t(`archive/collections/${e.id}`)
97
+ function W({ onNew: t }) {
98
+ let { navigateTo: n } = e(), { data: r, isLoading: o, isError: s, refetch: c } = d({ limit: 60 }), u = r ?? [];
99
+ return o ? /* @__PURE__ */ N(a, { label: "Loading collections…" }) : s ? /* @__PURE__ */ N(i, {
100
+ message: "We couldn't load collections.",
101
+ onRetry: () => c()
102
+ }) : u.length === 0 ? /* @__PURE__ */ N(l, {
103
+ illustration: "empty-files",
104
+ icon: /* @__PURE__ */ N(k, { className: "h-10 w-10" }),
105
+ title: "No collections yet",
106
+ description: "Create a collection to begin grouping artifacts and oral histories.",
107
+ action: /* @__PURE__ */ P(F, {
108
+ onClick: t,
109
+ children: [/* @__PURE__ */ N(j, { className: "mr-1.5 h-4 w-4" }), " New collection"]
92
110
  })
93
- ] });
111
+ }) : /* @__PURE__ */ N("div", {
112
+ className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
113
+ children: u.map((e) => /* @__PURE__ */ N(_, {
114
+ collection: e,
115
+ onOpen: () => n(`archive/collections/${e.id}`)
116
+ }, e.id))
117
+ });
94
118
  }
95
- var I = 16, L = [
119
+ var G = 16, K = [
96
120
  {
97
121
  value: "ALL",
98
- label: "All kinds"
122
+ label: "All kinds",
123
+ icon: O
99
124
  },
100
125
  {
101
126
  value: "MANUSCRIPT",
102
- label: "Manuscripts"
127
+ label: "Manuscripts",
128
+ icon: m.MANUSCRIPT
103
129
  },
104
130
  {
105
131
  value: "PHOTOGRAPH",
106
- label: "Photographs"
132
+ label: "Photographs",
133
+ icon: m.PHOTOGRAPH
107
134
  },
108
135
  {
109
136
  value: "AUDIO",
110
- label: "Audio"
137
+ label: "Audio",
138
+ icon: m.AUDIO
111
139
  },
112
140
  {
113
141
  value: "VIDEO",
114
- label: "Video"
142
+ label: "Video",
143
+ icon: m.VIDEO
115
144
  },
116
145
  {
117
146
  value: "MAP",
118
- label: "Maps"
147
+ label: "Maps",
148
+ icon: m.MAP
119
149
  },
120
150
  {
121
151
  value: "OBJECT",
122
- label: "Objects"
152
+ label: "Objects",
153
+ icon: m.OBJECT
123
154
  },
124
155
  {
125
156
  value: "DOCUMENT",
126
- label: "Documents"
157
+ label: "Documents",
158
+ icon: m.DOCUMENT
127
159
  }
128
- ], R = [
160
+ ], q = [
129
161
  "PUBLIC",
130
162
  "COMMUNITY",
131
163
  "RESTRICTED",
132
164
  "EMBARGOED"
133
165
  ];
134
- function z() {
135
- let { navigateTo: t } = e(), a = u(), [c, l] = y("ALL"), [d, m] = y("ALL"), [h, _] = y(!1), { data: b, isLoading: S, isError: N, refetch: P } = s({
166
+ function J({ onNew: n }) {
167
+ let { navigateTo: r } = e(), s = p(), [c, d] = w("ALL"), [f, m] = w("ALL"), { data: h, isLoading: g, isError: _, refetch: y } = u({
136
168
  kind: c === "ALL" ? void 0 : c,
137
- accessLevel: d === "ALL" ? void 0 : d,
169
+ accessLevel: f === "ALL" ? void 0 : f,
138
170
  pagination: {
139
- limit: I,
140
- cursor: a.cursor
171
+ limit: G,
172
+ cursor: s.cursor
141
173
  }
142
- }), F = b?.items ?? [];
143
- return /* @__PURE__ */ E("div", { children: [
144
- /* @__PURE__ */ E("div", {
145
- className: "mb-4 flex flex-wrap items-center gap-3",
174
+ }), b = h?.items ?? [], x = (e) => {
175
+ d(e), s.reset();
176
+ };
177
+ return /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ P("div", {
178
+ className: "mb-6 flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between",
179
+ children: [/* @__PURE__ */ P("div", {
180
+ className: "flex flex-col gap-2",
181
+ children: [/* @__PURE__ */ N("span", {
182
+ id: "kind-filter-label",
183
+ className: "text-sm font-medium text-text-secondary",
184
+ children: "Kind"
185
+ }), /* @__PURE__ */ N("div", {
186
+ role: "tablist",
187
+ "aria-labelledby": "kind-filter-label",
188
+ className: "flex flex-wrap gap-2",
189
+ children: K.map((e) => {
190
+ let n = e.value === c;
191
+ return /* @__PURE__ */ P("button", {
192
+ type: "button",
193
+ role: "tab",
194
+ "aria-selected": n,
195
+ onClick: () => x(e.value),
196
+ className: t("inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-sm font-medium transition-colors", n ? "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"),
197
+ children: [C(e.icon, { className: "h-4 w-4" }), e.label]
198
+ }, e.value);
199
+ })
200
+ })]
201
+ }), /* @__PURE__ */ P("div", {
202
+ className: "flex flex-col gap-2 lg:items-end",
203
+ children: [/* @__PURE__ */ N("label", {
204
+ htmlFor: "access-filter",
205
+ className: "text-sm font-medium text-text-secondary",
206
+ children: "Access level"
207
+ }), /* @__PURE__ */ P(L, {
208
+ value: f,
209
+ onValueChange: (e) => {
210
+ m(e), s.reset();
211
+ },
212
+ children: [/* @__PURE__ */ N(B, {
213
+ id: "access-filter",
214
+ className: "w-full lg:w-[12rem]",
215
+ "aria-label": "Filter by access level",
216
+ children: /* @__PURE__ */ N(V, { placeholder: "All levels" })
217
+ }), /* @__PURE__ */ P(R, { children: [/* @__PURE__ */ N(z, {
218
+ value: "ALL",
219
+ children: "All levels"
220
+ }), q.map((e) => /* @__PURE__ */ N(z, {
221
+ value: e,
222
+ children: o(e)
223
+ }, e))] })]
224
+ })]
225
+ })]
226
+ }), g ? /* @__PURE__ */ N(a, { label: "Loading artifacts…" }) : _ ? /* @__PURE__ */ N(i, {
227
+ message: "We couldn't load artifacts.",
228
+ onRetry: () => y()
229
+ }) : b.length === 0 && s.page === 0 ? /* @__PURE__ */ N(l, {
230
+ illustration: "empty-files",
231
+ icon: /* @__PURE__ */ N(E, { className: "h-10 w-10" }),
232
+ title: c === "ALL" && f === "ALL" ? "No artifacts yet" : "No artifacts match these filters",
233
+ description: c === "ALL" && f === "ALL" ? "Add the first artifact to the archive." : "Try widening the filters, or add a new artifact.",
234
+ action: /* @__PURE__ */ P(F, {
235
+ onClick: n,
236
+ children: [/* @__PURE__ */ N(j, { className: "mr-1.5 h-4 w-4" }), " Add artifact"]
237
+ })
238
+ }) : /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N("div", {
239
+ className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
240
+ children: b.map((e) => /* @__PURE__ */ N(v, {
241
+ item: e,
242
+ onOpen: () => r(`archive/items/${e.id}`)
243
+ }, e.id))
244
+ }), /* @__PURE__ */ N(S, {
245
+ page: s.page,
246
+ pageSize: G,
247
+ itemCount: b.length,
248
+ hasMore: h?.pageInfo.hasMore ?? !1,
249
+ onPageChange: (e) => s.onPageChange(e, h?.pageInfo.cursor)
250
+ })] })] });
251
+ }
252
+ function Y({ onNew: e }) {
253
+ let { data: t, isLoading: n, isError: r, refetch: o } = f(), s = t ?? [];
254
+ return n ? /* @__PURE__ */ N(a, { label: "Loading oral histories…" }) : r ? /* @__PURE__ */ N(i, {
255
+ message: "We couldn't load oral histories.",
256
+ onRetry: () => o()
257
+ }) : s.length === 0 ? /* @__PURE__ */ N(l, {
258
+ illustration: "empty-data",
259
+ icon: /* @__PURE__ */ N(T, { className: "h-10 w-10" }),
260
+ title: "No oral histories yet",
261
+ description: "Record a first-person account to preserve it for the archive.",
262
+ action: /* @__PURE__ */ P(F, {
263
+ onClick: e,
264
+ children: [/* @__PURE__ */ N(A, { className: "mr-1.5 h-4 w-4" }), " Record oral history"]
265
+ })
266
+ }) : /* @__PURE__ */ N("div", {
267
+ className: "flex flex-col gap-4",
268
+ children: s.map((e) => /* @__PURE__ */ N(X, { oralHistory: e }, e.id))
269
+ });
270
+ }
271
+ function X({ oralHistory: e }) {
272
+ let { data: t } = n(e.recording?.id), r = e.narratorName?.trim(), i = e.summary?.trim() || e.transcript?.trim();
273
+ return /* @__PURE__ */ P(I, {
274
+ treatment: "plain",
275
+ className: "flex flex-col gap-4 p-4 sm:flex-row sm:items-start",
276
+ children: [/* @__PURE__ */ N("div", {
277
+ className: "flex h-14 w-14 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-[var(--color-accent-soft)] to-bg-sunken text-sm font-semibold text-text-primary",
278
+ "aria-hidden": "true",
279
+ children: r ? s(r) : /* @__PURE__ */ N(A, { className: "h-5 w-5" })
280
+ }), /* @__PURE__ */ P("div", {
281
+ className: "min-w-0 flex-1",
146
282
  children: [
147
- /* @__PURE__ */ T(f, {
148
- options: L,
149
- value: c,
150
- onChange: (e) => {
151
- l(e), a.reset();
152
- }
283
+ /* @__PURE__ */ P("div", {
284
+ className: "flex flex-wrap items-start justify-between gap-2",
285
+ children: [/* @__PURE__ */ P("div", {
286
+ className: "min-w-0",
287
+ children: [/* @__PURE__ */ N("h3", {
288
+ className: "font-display text-lg font-semibold leading-snug text-text-primary",
289
+ children: e.title
290
+ }), r && /* @__PURE__ */ N("p", {
291
+ className: "mt-0.5 text-sm text-text-secondary",
292
+ children: r
293
+ })]
294
+ }), /* @__PURE__ */ P("div", {
295
+ className: "flex flex-wrap items-center gap-1.5",
296
+ children: [e.language && /* @__PURE__ */ P("span", {
297
+ 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",
298
+ children: [
299
+ /* @__PURE__ */ N(D, {
300
+ className: "h-3 w-3",
301
+ "aria-hidden": "true"
302
+ }),
303
+ " ",
304
+ o(e.language)
305
+ ]
306
+ }), /* @__PURE__ */ N(c, { status: e.accessLevel })]
307
+ })]
153
308
  }),
154
- /* @__PURE__ */ E(O, {
155
- value: d,
156
- onValueChange: (e) => {
157
- m(e), a.reset();
158
- },
159
- children: [/* @__PURE__ */ T(j, {
160
- className: "w-[12rem]",
161
- "aria-label": "Filter by access level",
162
- children: /* @__PURE__ */ T(M, { placeholder: "All access" })
163
- }), /* @__PURE__ */ E(k, { children: [/* @__PURE__ */ T(A, {
164
- value: "ALL",
165
- children: "All access"
166
- }), R.map((e) => /* @__PURE__ */ T(A, {
167
- value: e,
168
- children: i(e)
169
- }, e))] })]
309
+ /* @__PURE__ */ N(g, {
310
+ className: "mt-3",
311
+ src: t,
312
+ seed: e.id || e.title,
313
+ durationSecs: e.durationSecs
170
314
  }),
171
- /* @__PURE__ */ E(D, {
172
- className: "ml-auto",
173
- onClick: () => _(!0),
174
- children: [/* @__PURE__ */ T(C, { className: "mr-1.5 h-4 w-4" }), " Add artifact"]
315
+ i && /* @__PURE__ */ P("p", {
316
+ className: "mt-3 border-l-2 border-[var(--color-accent-soft)] pl-3 text-sm italic leading-relaxed text-text-secondary line-clamp-2",
317
+ children: [
318
+ "“",
319
+ i,
320
+ "”"
321
+ ]
175
322
  })
176
323
  ]
177
- }),
178
- S ? /* @__PURE__ */ T(r, { label: "Loading artifacts…" }) : N ? /* @__PURE__ */ T(n, {
179
- message: "We couldn't load artifacts.",
180
- onRetry: () => P()
181
- }) : F.length === 0 && a.page === 0 ? /* @__PURE__ */ T(o, {
182
- illustration: "empty-files",
183
- icon: /* @__PURE__ */ T(x, { className: "h-10 w-10" }),
184
- title: c === "ALL" && d === "ALL" ? "No artifacts yet" : "No artifacts match these filters",
185
- description: c === "ALL" && d === "ALL" ? "Add the first artifact to the archive." : "Try widening the filters, or add a new artifact.",
186
- action: /* @__PURE__ */ E(D, {
187
- onClick: () => _(!0),
188
- children: [/* @__PURE__ */ T(C, { className: "mr-1.5 h-4 w-4" }), " Add artifact"]
189
- })
190
- }) : /* @__PURE__ */ E(w, { children: [/* @__PURE__ */ T("div", {
191
- className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
192
- children: F.map((e) => /* @__PURE__ */ T(p, {
193
- item: e,
194
- onOpen: () => t(`archive/items/${e.id}`)
195
- }, e.id))
196
- }), /* @__PURE__ */ T(v, {
197
- page: a.page,
198
- pageSize: I,
199
- itemCount: F.length,
200
- hasMore: b?.pageInfo.hasMore ?? !1,
201
- onPageChange: (e) => a.onPageChange(e, b?.pageInfo.cursor)
202
- })] }),
203
- /* @__PURE__ */ T(g, {
204
- open: h,
205
- onOpenChange: _,
206
- onCreated: (e) => t(`archive/items/${e.id}`)
207
- })
208
- ] });
209
- }
210
- function B() {
211
- let { data: e, isLoading: t, isError: i, refetch: a } = l(), [s, c] = y(!1), u = e ?? [];
212
- return /* @__PURE__ */ E("div", { children: [
213
- /* @__PURE__ */ T("div", {
214
- className: "mb-4 flex items-center justify-end",
215
- children: /* @__PURE__ */ E(D, {
216
- onClick: () => c(!0),
217
- children: [/* @__PURE__ */ T(C, { className: "mr-1.5 h-4 w-4" }), " Record oral history"]
218
- })
219
- }),
220
- t ? /* @__PURE__ */ T(r, { label: "Loading oral histories…" }) : i ? /* @__PURE__ */ T(n, {
221
- message: "We couldn't load oral histories.",
222
- onRetry: () => a()
223
- }) : u.length === 0 ? /* @__PURE__ */ T(o, {
224
- illustration: "empty-data",
225
- icon: /* @__PURE__ */ T(b, { className: "h-10 w-10" }),
226
- title: "No oral histories yet",
227
- description: "Record a first-person account to preserve it for the archive.",
228
- action: /* @__PURE__ */ E(D, {
229
- onClick: () => c(!0),
230
- children: [/* @__PURE__ */ T(C, { className: "mr-1.5 h-4 w-4" }), " Record oral history"]
231
- })
232
- }) : /* @__PURE__ */ T("div", {
233
- className: "grid gap-4 lg:grid-cols-2",
234
- children: u.map((e) => /* @__PURE__ */ T(m, { oralHistory: e }, e.id))
235
- }),
236
- /* @__PURE__ */ T(_, {
237
- open: s,
238
- onOpenChange: c
239
- })
240
- ] });
324
+ })]
325
+ });
241
326
  }
242
327
  //#endregion
243
- export { P as ArchivePage };
328
+ export { U as ArchivePage, X as OralHistoryPlayerRow };
244
329
 
245
330
  //# sourceMappingURL=ArchivePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ArchivePage.js","names":[],"sources":["../../../../src/theculturepost/pages/archive/ArchivePage.tsx"],"sourcesContent":["/**\n * ArchivePage — the cultural archive: collections, artifacts and oral histories.\n * @module theculturepost/pages/archive\n *\n * Three tabs, each backed by a real list field: `tcpListCollections`,\n * `tcpListArchiveItems` (filtered by kind + access level) and\n * `tcpListOralHistories`. Creation opens the matching dialog.\n */\n\nimport { useState } from 'react';\nimport { Library, Boxes, AudioLines, Plus } from 'lucide-react';\nimport {\n Button,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { Tabs, type TabItem } from '../../components/Tabs';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { CollectionCard } from '../../components/CollectionCard';\nimport { ArchiveItemCard } from '../../components/ArchiveItemCard';\nimport { OralHistoryCard } from '../../components/OralHistoryCard';\nimport { CreateCollectionDialog } from '../../components/CreateCollectionDialog';\nimport { CreateArchiveItemDialog } from '../../components/CreateArchiveItemDialog';\nimport { RecordOralHistoryDialog } from '../../components/RecordOralHistoryDialog';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport {\n useTcpCollections,\n useTcpArchiveItems,\n useTcpOralHistories,\n useCursorPager,\n} from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { formatEnumLabel } from '../../utils/formatters';\nimport type { TcpArchiveItemKind, TcpAccessLevel } from '../../types';\n\ntype TabKey = 'collections' | 'artifacts' | 'oral-histories';\n\nconst TABS: TabItem<TabKey>[] = [\n { value: 'collections', label: 'Collections', icon: <Library className=\"h-4 w-4\" /> },\n { value: 'artifacts', label: 'Artifacts', icon: <Boxes className=\"h-4 w-4\" /> },\n { value: 'oral-histories', label: 'Oral Histories', icon: <AudioLines className=\"h-4 w-4\" /> },\n];\n\nexport function ArchivePage() {\n const [tab, setTab] = useState<TabKey>('collections');\n\n return (\n <PageLayout\n title=\"Archive\"\n description=\"A living archive of manuscripts, photographs, recordings, maps and objects — grouped into collections.\"\n >\n <Tabs items={TABS} value={tab} onChange={setTab} className=\"mb-6\" />\n {tab === 'collections' && <CollectionsTab />}\n {tab === 'artifacts' && <ArtifactsTab />}\n {tab === 'oral-histories' && <OralHistoriesTab />}\n </PageLayout>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Collections\n// ---------------------------------------------------------------------------\n\nfunction CollectionsTab() {\n const { navigateTo } = useTheCulturePost();\n const { data, isLoading, isError, refetch } = useTcpCollections({ limit: 60 });\n const [createOpen, setCreateOpen] = useState(false);\n const collections = data ?? [];\n\n return (\n <div>\n <div className=\"mb-4 flex items-center justify-end\">\n <Button onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New collection\n </Button>\n </div>\n {isLoading ? (\n <LoadingView label=\"Loading collections…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load collections.\" onRetry={() => refetch()} />\n ) : collections.length === 0 ? (\n <EmptyState\n illustration=\"empty-files\"\n icon={<Library className=\"h-10 w-10\" />}\n title=\"No collections yet\"\n description=\"Create a collection to begin grouping artifacts and oral histories.\"\n action={\n <Button onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New collection\n </Button>\n }\n />\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {collections.map((collection) => (\n <CollectionCard\n key={collection.id}\n collection={collection}\n onOpen={() => navigateTo(`archive/collections/${collection.id}`)}\n />\n ))}\n </div>\n )}\n <CreateCollectionDialog\n open={createOpen}\n onOpenChange={setCreateOpen}\n onCreated={(collection) => navigateTo(`archive/collections/${collection.id}`)}\n />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Artifacts\n// ---------------------------------------------------------------------------\n\nconst PAGE_SIZE = 16;\n\ntype KindFilter = 'ALL' | TcpArchiveItemKind;\ntype AccessFilter = 'ALL' | TcpAccessLevel;\n\nconst KIND_FILTERS: FilterOption<KindFilter>[] = [\n { value: 'ALL', label: 'All kinds' },\n { value: 'MANUSCRIPT', label: 'Manuscripts' },\n { value: 'PHOTOGRAPH', label: 'Photographs' },\n { value: 'AUDIO', label: 'Audio' },\n { value: 'VIDEO', label: 'Video' },\n { value: 'MAP', label: 'Maps' },\n { value: 'OBJECT', label: 'Objects' },\n { value: 'DOCUMENT', label: 'Documents' },\n];\n\nconst ACCESS_LEVELS: TcpAccessLevel[] = ['PUBLIC', 'COMMUNITY', 'RESTRICTED', 'EMBARGOED'];\n\nfunction ArtifactsTab() {\n const { navigateTo } = useTheCulturePost();\n const pager = useCursorPager();\n const [kind, setKind] = useState<KindFilter>('ALL');\n const [accessLevel, setAccessLevel] = useState<AccessFilter>('ALL');\n const [createOpen, setCreateOpen] = useState(false);\n\n const { data, isLoading, isError, refetch } = useTcpArchiveItems({\n kind: kind === 'ALL' ? undefined : kind,\n accessLevel: accessLevel === 'ALL' ? undefined : accessLevel,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const items = data?.items ?? [];\n\n const changeKind = (next: KindFilter) => {\n setKind(next);\n pager.reset();\n };\n\n const changeAccess = (next: string) => {\n setAccessLevel(next as AccessFilter);\n pager.reset();\n };\n\n return (\n <div>\n <div className=\"mb-4 flex flex-wrap items-center gap-3\">\n <FilterTabs options={KIND_FILTERS} value={kind} onChange={changeKind} />\n <Select value={accessLevel} onValueChange={changeAccess}>\n <SelectTrigger className=\"w-[12rem]\" aria-label=\"Filter by access level\">\n <SelectValue placeholder=\"All access\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All access</SelectItem>\n {ACCESS_LEVELS.map((a) => (\n <SelectItem key={a} value={a}>\n {formatEnumLabel(a)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Button className=\"ml-auto\" onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Add artifact\n </Button>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading artifacts…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load artifacts.\" onRetry={() => refetch()} />\n ) : items.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-files\"\n icon={<Boxes className=\"h-10 w-10\" />}\n title={\n kind === 'ALL' && accessLevel === 'ALL'\n ? 'No artifacts yet'\n : 'No artifacts match these filters'\n }\n description={\n kind === 'ALL' && accessLevel === 'ALL'\n ? 'Add the first artifact to the archive.'\n : 'Try widening the filters, or add a new artifact.'\n }\n action={\n <Button onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Add artifact\n </Button>\n }\n />\n ) : (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {items.map((item) => (\n <ArchiveItemCard\n key={item.id}\n item={item}\n onOpen={() => navigateTo(`archive/items/${item.id}`)}\n />\n ))}\n </div>\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={items.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </>\n )}\n\n <CreateArchiveItemDialog\n open={createOpen}\n onOpenChange={setCreateOpen}\n onCreated={(item) => navigateTo(`archive/items/${item.id}`)}\n />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Oral histories\n// ---------------------------------------------------------------------------\n\nfunction OralHistoriesTab() {\n const { data, isLoading, isError, refetch } = useTcpOralHistories();\n const [createOpen, setCreateOpen] = useState(false);\n const oralHistories = data ?? [];\n\n return (\n <div>\n <div className=\"mb-4 flex items-center justify-end\">\n <Button onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record oral history\n </Button>\n </div>\n {isLoading ? (\n <LoadingView label=\"Loading oral histories…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load oral histories.\" onRetry={() => refetch()} />\n ) : oralHistories.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<AudioLines className=\"h-10 w-10\" />}\n title=\"No oral histories yet\"\n description=\"Record a first-person account to preserve it for the archive.\"\n action={\n <Button onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record oral history\n </Button>\n }\n />\n ) : (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n {oralHistories.map((oralHistory) => (\n <OralHistoryCard key={oralHistory.id} oralHistory={oralHistory} />\n ))}\n </div>\n )}\n <RecordOralHistoryDialog open={createOpen} onOpenChange={setCreateOpen} />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ArchivePage.js","names":[],"sources":["../../../../src/theculturepost/pages/archive/ArchivePage.tsx"],"sourcesContent":["/**\n * ArchivePage — the cultural archive: collections, artifacts and oral histories.\n * @module theculturepost/pages/archive\n *\n * Three tabs, each backed by a real list field: `tcpListCollections`,\n * `tcpListArchiveItems` (filtered by kind + access level) and\n * `tcpListOralHistories`. The primary action lives in the editorial {@link PageHero}\n * and switches with the active tab; creation opens the matching dialog.\n */\n\nimport { createElement, useState } from 'react';\nimport {\n Library,\n Boxes,\n AudioLines,\n Plus,\n Mic,\n Layers,\n Globe,\n type LucideIcon,\n} from 'lucide-react';\nimport {\n Button,\n GlassCard,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport { PageHero } from '../../components/PageHero';\nimport { Tabs, type TabItem } from '../../components/Tabs';\nimport { AudioPlayer } from '../../components/AudioPlayer';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { CollectionCard } from '../../components/CollectionCard';\nimport { ArchiveItemCard } from '../../components/ArchiveItemCard';\nimport { CreateCollectionDialog } from '../../components/CreateCollectionDialog';\nimport { CreateArchiveItemDialog } from '../../components/CreateArchiveItemDialog';\nimport { RecordOralHistoryDialog } from '../../components/RecordOralHistoryDialog';\nimport { KIND_ICON } from '../../components/kindIcon';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport {\n useTcpCollections,\n useTcpArchiveItems,\n useTcpOralHistories,\n useCursorPager,\n useFileUrl,\n} from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { cn } from '../../utils/cn';\nimport { formatEnumLabel, initialsOf } from '../../utils/formatters';\nimport type { TcpArchiveItemKind, TcpAccessLevel, TcpOralHistory } from '../../types';\n\ntype TabKey = 'collections' | 'artifacts' | 'oral-histories';\n\nconst TABS: TabItem<TabKey>[] = [\n { value: 'collections', label: 'Collections', icon: <Library className=\"h-4 w-4\" /> },\n { value: 'artifacts', label: 'Artifacts', icon: <Boxes className=\"h-4 w-4\" /> },\n { value: 'oral-histories', label: 'Oral Histories', icon: <AudioLines className=\"h-4 w-4\" /> },\n];\n\nexport function ArchivePage() {\n const { navigateTo } = useTheCulturePost();\n const [tab, setTab] = useState<TabKey>('collections');\n const [collectionOpen, setCollectionOpen] = useState(false);\n const [artifactOpen, setArtifactOpen] = useState(false);\n const [recordOpen, setRecordOpen] = useState(false);\n\n const heroAction =\n tab === 'collections' ? (\n <Button onClick={() => setCollectionOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New collection\n </Button>\n ) : tab === 'artifacts' ? (\n <Button onClick={() => setArtifactOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Add artifact\n </Button>\n ) : (\n <Button onClick={() => setRecordOpen(true)}>\n <Mic className=\"mr-1.5 h-4 w-4\" /> Record\n </Button>\n );\n\n return (\n <div className=\"flex h-full flex-col\">\n <div className=\"flex-1 overflow-auto\">\n <div className=\"mx-auto flex w-full max-w-6xl flex-col gap-6 p-4 sm:p-6\">\n <PageHero\n eyebrow=\"Cultural archive\"\n title=\"Archive\"\n description=\"A living archive of manuscripts, photographs, recordings, maps and objects — grouped into collections.\"\n actions={heroAction}\n />\n\n <div>\n <Tabs items={TABS} value={tab} onChange={setTab} className=\"mb-6\" />\n {tab === 'collections' && <CollectionsTab onNew={() => setCollectionOpen(true)} />}\n {tab === 'artifacts' && <ArtifactsTab onNew={() => setArtifactOpen(true)} />}\n {tab === 'oral-histories' && <OralHistoriesTab onNew={() => setRecordOpen(true)} />}\n </div>\n </div>\n </div>\n\n <CreateCollectionDialog\n open={collectionOpen}\n onOpenChange={setCollectionOpen}\n onCreated={(collection) => navigateTo(`archive/collections/${collection.id}`)}\n />\n <CreateArchiveItemDialog\n open={artifactOpen}\n onOpenChange={setArtifactOpen}\n onCreated={(item) => navigateTo(`archive/items/${item.id}`)}\n />\n <RecordOralHistoryDialog open={recordOpen} onOpenChange={setRecordOpen} />\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Collections\n// ---------------------------------------------------------------------------\n\nfunction CollectionsTab({ onNew }: { onNew: () => void }) {\n const { navigateTo } = useTheCulturePost();\n const { data, isLoading, isError, refetch } = useTcpCollections({ limit: 60 });\n const collections = data ?? [];\n\n if (isLoading) return <LoadingView label=\"Loading collections…\" />;\n if (isError)\n return <ErrorView message=\"We couldn't load collections.\" onRetry={() => refetch()} />;\n if (collections.length === 0) {\n return (\n <EmptyState\n illustration=\"empty-files\"\n icon={<Library className=\"h-10 w-10\" />}\n title=\"No collections yet\"\n description=\"Create a collection to begin grouping artifacts and oral histories.\"\n action={\n <Button onClick={onNew}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New collection\n </Button>\n }\n />\n );\n }\n\n return (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {collections.map((collection) => (\n <CollectionCard\n key={collection.id}\n collection={collection}\n onOpen={() => navigateTo(`archive/collections/${collection.id}`)}\n />\n ))}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Artifacts\n// ---------------------------------------------------------------------------\n\nconst PAGE_SIZE = 16;\n\ntype KindFilter = 'ALL' | TcpArchiveItemKind;\ntype AccessFilter = 'ALL' | TcpAccessLevel;\n\nconst KIND_FILTERS: { value: KindFilter; label: string; icon: LucideIcon }[] = [\n { value: 'ALL', label: 'All kinds', icon: Layers },\n { value: 'MANUSCRIPT', label: 'Manuscripts', icon: KIND_ICON.MANUSCRIPT },\n { value: 'PHOTOGRAPH', label: 'Photographs', icon: KIND_ICON.PHOTOGRAPH },\n { value: 'AUDIO', label: 'Audio', icon: KIND_ICON.AUDIO },\n { value: 'VIDEO', label: 'Video', icon: KIND_ICON.VIDEO },\n { value: 'MAP', label: 'Maps', icon: KIND_ICON.MAP },\n { value: 'OBJECT', label: 'Objects', icon: KIND_ICON.OBJECT },\n { value: 'DOCUMENT', label: 'Documents', icon: KIND_ICON.DOCUMENT },\n];\n\nconst ACCESS_LEVELS: TcpAccessLevel[] = ['PUBLIC', 'COMMUNITY', 'RESTRICTED', 'EMBARGOED'];\n\nfunction ArtifactsTab({ onNew }: { onNew: () => void }) {\n const { navigateTo } = useTheCulturePost();\n const pager = useCursorPager();\n const [kind, setKind] = useState<KindFilter>('ALL');\n const [accessLevel, setAccessLevel] = useState<AccessFilter>('ALL');\n\n const { data, isLoading, isError, refetch } = useTcpArchiveItems({\n kind: kind === 'ALL' ? undefined : kind,\n accessLevel: accessLevel === 'ALL' ? undefined : accessLevel,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const items = data?.items ?? [];\n\n const changeKind = (next: KindFilter) => {\n setKind(next);\n pager.reset();\n };\n\n const changeAccess = (next: string) => {\n setAccessLevel(next as AccessFilter);\n pager.reset();\n };\n\n return (\n <div>\n <div className=\"mb-6 flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between\">\n <div className=\"flex flex-col gap-2\">\n <span id=\"kind-filter-label\" className=\"text-sm font-medium text-text-secondary\">\n Kind\n </span>\n <div role=\"tablist\" aria-labelledby=\"kind-filter-label\" className=\"flex flex-wrap gap-2\">\n {KIND_FILTERS.map((opt) => {\n const active = opt.value === kind;\n return (\n <button\n key={opt.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => changeKind(opt.value)}\n className={cn(\n 'inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-sm font-medium transition-colors',\n active\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 {createElement(opt.icon, { className: 'h-4 w-4' })}\n {opt.label}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 lg:items-end\">\n <label htmlFor=\"access-filter\" className=\"text-sm font-medium text-text-secondary\">\n Access level\n </label>\n <Select value={accessLevel} onValueChange={changeAccess}>\n <SelectTrigger\n id=\"access-filter\"\n className=\"w-full lg:w-[12rem]\"\n aria-label=\"Filter by access level\"\n >\n <SelectValue placeholder=\"All levels\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All levels</SelectItem>\n {ACCESS_LEVELS.map((a) => (\n <SelectItem key={a} value={a}>\n {formatEnumLabel(a)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading artifacts…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load artifacts.\" onRetry={() => refetch()} />\n ) : items.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-files\"\n icon={<Boxes className=\"h-10 w-10\" />}\n title={\n kind === 'ALL' && accessLevel === 'ALL'\n ? 'No artifacts yet'\n : 'No artifacts match these filters'\n }\n description={\n kind === 'ALL' && accessLevel === 'ALL'\n ? 'Add the first artifact to the archive.'\n : 'Try widening the filters, or add a new artifact.'\n }\n action={\n <Button onClick={onNew}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Add artifact\n </Button>\n }\n />\n ) : (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {items.map((item) => (\n <ArchiveItemCard\n key={item.id}\n item={item}\n onOpen={() => navigateTo(`archive/items/${item.id}`)}\n />\n ))}\n </div>\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={items.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Oral histories\n// ---------------------------------------------------------------------------\n\nfunction OralHistoriesTab({ onNew }: { onNew: () => void }) {\n const { data, isLoading, isError, refetch } = useTcpOralHistories();\n const oralHistories = data ?? [];\n\n if (isLoading) return <LoadingView label=\"Loading oral histories…\" />;\n if (isError)\n return <ErrorView message=\"We couldn't load oral histories.\" onRetry={() => refetch()} />;\n if (oralHistories.length === 0) {\n return (\n <EmptyState\n illustration=\"empty-data\"\n icon={<AudioLines className=\"h-10 w-10\" />}\n title=\"No oral histories yet\"\n description=\"Record a first-person account to preserve it for the archive.\"\n action={\n <Button onClick={onNew}>\n <Mic className=\"mr-1.5 h-4 w-4\" /> Record oral history\n </Button>\n }\n />\n );\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n {oralHistories.map((oralHistory) => (\n <OralHistoryPlayerRow key={oralHistory.id} oralHistory={oralHistory} />\n ))}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// OralHistoryPlayerRow — an inline listenable oral-history row (reused by the\n// collection detail page). Uses the foundation AudioPlayer for play/seek. Real\n// fields only: narrator is a plain string, there is NO portrait or age.\n// ---------------------------------------------------------------------------\n\nexport function OralHistoryPlayerRow({ oralHistory }: { oralHistory: TcpOralHistory }) {\n const { data: recordingUrl } = useFileUrl(oralHistory.recording?.id);\n const narrator = oralHistory.narratorName?.trim();\n const excerpt = oralHistory.summary?.trim() || oralHistory.transcript?.trim();\n\n return (\n <GlassCard treatment=\"plain\" className=\"flex flex-col gap-4 p-4 sm:flex-row sm:items-start\">\n <div\n className=\"flex h-14 w-14 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-[var(--color-accent-soft)] to-bg-sunken text-sm font-semibold text-text-primary\"\n aria-hidden=\"true\"\n >\n {narrator ? initialsOf(narrator) : <Mic className=\"h-5 w-5\" />}\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <h3 className=\"font-display text-lg font-semibold leading-snug text-text-primary\">\n {oralHistory.title}\n </h3>\n {narrator && <p className=\"mt-0.5 text-sm text-text-secondary\">{narrator}</p>}\n </div>\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {oralHistory.language && (\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 <Globe className=\"h-3 w-3\" aria-hidden=\"true\" />{' '}\n {formatEnumLabel(oralHistory.language)}\n </span>\n )}\n <StatusBadge status={oralHistory.accessLevel} />\n </div>\n </div>\n\n <AudioPlayer\n className=\"mt-3\"\n src={recordingUrl}\n seed={oralHistory.id || oralHistory.title}\n durationSecs={oralHistory.durationSecs}\n />\n\n {excerpt && (\n <p className=\"mt-3 border-l-2 border-[var(--color-accent-soft)] pl-3 text-sm italic leading-relaxed text-text-secondary line-clamp-2\">\n “{excerpt}”\n </p>\n )}\n </div>\n </GlassCard>\n );\n}\n"],"mappings":"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"}