@burdenoff/microfe-theculturepost 2026.1112.1 → 2026.1112.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/theculturepost/components/CreateStoryDialog.js +2 -1
- package/dist/theculturepost/components/CreateStoryDialog.js.map +1 -1
- package/dist/theculturepost/hooks/index.js +7 -7
- package/dist/theculturepost/hooks/useTcpApi.d.ts +5 -0
- package/dist/theculturepost/hooks/useTcpApi.js +53 -45
- package/dist/theculturepost/hooks/useTcpApi.js.map +1 -1
- package/dist/theculturepost/lib/toast.js +1 -1
- package/dist/theculturepost/pages/stories/StoryDetailPage.js +263 -276
- package/dist/theculturepost/pages/stories/StoryDetailPage.js.map +1 -1
- package/dist/theculturepost/utils/nativeBridge.js +1 -2
- package/dist/theculturepost/utils/nativeBridge.js.map +1 -1
- package/dist/theculturepost/utils/storyTransitions.d.ts +9 -0
- package/dist/theculturepost/utils/storyTransitions.js +31 -0
- package/dist/theculturepost/utils/storyTransitions.js.map +1 -0
- package/package.json +1 -1
- package/dist/node_modules/sonner/dist/index.js +0 -169
- package/dist/node_modules/sonner/dist/index.js.map +0 -1
|
@@ -360,7 +360,8 @@ function P({ open: t, onOpenChange: n, topicId: r, onCreated: u }) {
|
|
|
360
360
|
});
|
|
361
361
|
l.success("Story created", e.title), n(!1), ue(), u?.(e);
|
|
362
362
|
} catch (e) {
|
|
363
|
-
|
|
363
|
+
let t = c(e);
|
|
364
|
+
Q(t), l.error("Could not create the story", t);
|
|
364
365
|
}
|
|
365
366
|
},
|
|
366
367
|
disabled: p.isPending,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateStoryDialog.js","names":["_Fragment","Fragment$1","FORMATS","SUMMARY_MAX","COVER_MAX_MB","CoverDropzone","inputRef","useRef","uploading","setUploading","useState","dragActive","setDragActive","previewUrl","setPreviewUrl","fileName","setFileName","handleFile","file","uploaded","uploadImageToFiles","FILE_FOLDERS","onUploaded","notify","err","describeError","onInputChange","event","onDrop","clear","onCleared","hiddenInput","X","coverFileId","FileCheck2","cn","Loader2","UploadCloud","Button","CreateStoryDialog","createStory","useTcpCreateStory","topicsQuery","useTcpTopics","title","setTitle","slug","setSlug","slugTouched","setSlugTouched","summary","setSummary","body","setBody","format","setFormat","pickedTopic","setPickedTopic","topicId","languages","setLanguages","tags","setTags","readingMins","setReadingMins","setCoverFileId","error","setError","resetNonce","setResetNonce","effectiveSlug","slugify","reset","n","ResponsiveDialog","ResponsiveDialogContent","ResponsiveDialogHeader","ResponsiveDialogTitle","ResponsiveDialogDescription","Label","Input","CheckCircle2","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","f","formatEnumLabel","topic","Textarea","TagInput","ResponsiveDialogFooter","onOpenChange","created","onCreated"],"sources":["../../../src/theculturepost/components/CreateStoryDialog.tsx"],"sourcesContent":["/**\n * CreateStoryDialog — draft a new story.\n * @module theculturepost/components\n *\n * Writes `tcpCreateStory`. A wide, two-column composer that mirrors the editorial\n * \"Draft a story\" surface: a real drag-and-drop cover dropzone (uploads to\n * wspace-files-svc and keeps the returned `coverFileId`), a title with an\n * auto-derived URL slug + uniqueness hint, char counters on summary/body, and\n * chip multiselects for languages/tags. New stories begin at the start of the\n * editorial lifecycle (IDEA/DRAFT on the svc). Every field maps to a real\n * `TcpCreateStoryInput` field — no bookmarks, no fabricated metadata.\n */\n\nimport { useRef, useState, type ChangeEvent, type DragEvent } from 'react';\nimport { UploadCloud, Loader2, X, CheckCircle2, FileCheck2 } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { TagInput } from './TagInput';\nimport { cn } from '../utils/cn';\nimport { useTcpCreateStory, useTcpTopics, uploadImageToFiles, FILE_FOLDERS } from '../hooks';\nimport { slugify } from '../utils/slug';\nimport { formatEnumLabel } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { TcpStory, TcpStoryFormat } from '../types';\n\nconst FORMATS: TcpStoryFormat[] = [\n 'ARTICLE',\n 'ESSAY',\n 'EXPLAINER',\n 'ORAL_HISTORY',\n 'PHOTO_STORY',\n 'TIMELINE',\n];\n\nconst SUMMARY_MAX = 200;\nconst COVER_MAX_MB = 25;\n\n// ---------------------------------------------------------------------------\n// Cover dropzone (real drag-and-drop → wspace-files-svc)\n// ---------------------------------------------------------------------------\n\ninterface CoverDropzoneProps {\n coverFileId: string | null;\n onUploaded: (fileId: string) => void;\n onCleared: () => void;\n}\n\nfunction CoverDropzone({ coverFileId, onUploaded, onCleared }: CoverDropzoneProps) {\n const inputRef = useRef<HTMLInputElement | null>(null);\n const [uploading, setUploading] = useState(false);\n const [dragActive, setDragActive] = useState(false);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const [fileName, setFileName] = useState<string | null>(null);\n\n const handleFile = async (file: File) => {\n if (!file.type.startsWith('image/')) {\n notify.error('Unsupported file', 'Please choose an image (JPG or PNG).');\n return;\n }\n if (file.size > COVER_MAX_MB * 1024 * 1024) {\n notify.error('File too large', `Please choose an image under ${COVER_MAX_MB} MB.`);\n return;\n }\n setUploading(true);\n try {\n const uploaded = await uploadImageToFiles(file, FILE_FOLDERS.covers);\n setPreviewUrl(uploaded.url);\n setFileName(uploaded.name);\n onUploaded(uploaded.id);\n notify.success('Cover uploaded', uploaded.name);\n } catch (err) {\n notify.error('Upload failed', describeError(err));\n } finally {\n setUploading(false);\n }\n };\n\n const onInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n event.target.value = '';\n if (file) void handleFile(file);\n };\n\n const onDrop = (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setDragActive(false);\n if (uploading) return;\n const file = event.dataTransfer.files?.[0];\n if (file) void handleFile(file);\n };\n\n const clear = () => {\n setPreviewUrl(null);\n setFileName(null);\n onCleared();\n };\n\n const hiddenInput = (\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"sr-only\"\n onChange={onInputChange}\n disabled={uploading}\n aria-label=\"Upload cover image\"\n />\n );\n\n // Uploaded image preview\n if (previewUrl) {\n return (\n <div className=\"relative overflow-hidden rounded-2xl border border-border-seam\">\n {hiddenInput}\n <img src={previewUrl} alt=\"Cover preview\" className=\"max-h-52 w-full object-cover\" />\n <div className=\"absolute right-2 top-2 flex gap-1.5\">\n <button\n type=\"button\"\n onClick={() => inputRef.current?.click()}\n className=\"rounded-full bg-bg-canvas/85 px-2.5 py-1 text-xs font-medium text-text-primary backdrop-blur-sm hover:bg-bg-canvas\"\n >\n Replace\n </button>\n <button\n type=\"button\"\n onClick={clear}\n aria-label=\"Remove cover\"\n className=\"rounded-full bg-bg-canvas/85 p-1.5 text-text-primary backdrop-blur-sm hover:bg-bg-canvas\"\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </div>\n </div>\n );\n }\n\n // Cover set but no local preview (defensive)\n if (coverFileId) {\n return (\n <div className=\"flex items-center justify-between gap-2 rounded-2xl border border-border-seam bg-bg-surface px-3 py-2.5 text-sm\">\n {hiddenInput}\n <span className=\"inline-flex min-w-0 items-center gap-2 text-text-primary\">\n <FileCheck2 className=\"h-4 w-4 shrink-0 text-status-success-text\" aria-hidden=\"true\" />\n <span className=\"truncate\">{fileName ?? 'Cover selected'}</span>\n </span>\n <button\n type=\"button\"\n onClick={clear}\n aria-label=\"Remove cover\"\n className=\"text-text-tertiary hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </div>\n );\n }\n\n // Empty dropzone\n return (\n <div\n onDragOver={(event) => {\n event.preventDefault();\n if (!uploading) setDragActive(true);\n }}\n onDragLeave={(event) => {\n event.preventDefault();\n setDragActive(false);\n }}\n onDrop={onDrop}\n className={cn(\n 'rounded-2xl border-2 border-dashed px-4 py-6 text-center transition-colors',\n dragActive\n ? 'border-accent bg-[var(--color-accent-soft)]'\n : 'border-border-seam bg-bg-sunken/40'\n )}\n >\n {hiddenInput}\n {uploading ? (\n <div className=\"flex items-center justify-center gap-2 text-sm text-text-secondary\">\n <Loader2 className=\"h-5 w-5 animate-spin\" aria-hidden=\"true\" /> Uploading cover…\n </div>\n ) : (\n <div className=\"flex flex-col items-center justify-center gap-3 sm:flex-row\">\n <UploadCloud className=\"h-8 w-8 text-accent\" aria-hidden=\"true\" />\n <p className=\"text-sm text-text-secondary\">Drag and drop an image here, or</p>\n <Button type=\"button\" size=\"sm\" onClick={() => inputRef.current?.click()}>\n Upload cover\n </Button>\n </div>\n )}\n <p className=\"mt-3 text-xs text-text-tertiary\">\n Recommended: 16:9 ratio, min 1200×675px. JPG or PNG, up to {COVER_MAX_MB} MB.\n </p>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dialog\n// ---------------------------------------------------------------------------\n\ninterface CreateStoryDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Pre-select a topic (e.g. from a topic detail page). */\n topicId?: string;\n onCreated?: (story: TcpStory) => void;\n}\n\nexport function CreateStoryDialog({\n open,\n onOpenChange,\n topicId,\n onCreated,\n}: CreateStoryDialogProps) {\n const createStory = useTcpCreateStory();\n const topicsQuery = useTcpTopics({ pagination: { limit: 100 } });\n\n const [title, setTitle] = useState('');\n const [slug, setSlug] = useState('');\n const [slugTouched, setSlugTouched] = useState(false);\n const [summary, setSummary] = useState('');\n const [body, setBody] = useState('');\n const [format, setFormat] = useState<TcpStoryFormat>('ARTICLE');\n const [pickedTopic, setPickedTopic] = useState(topicId ?? '');\n const [languages, setLanguages] = useState<string[]>([]);\n const [tags, setTags] = useState<string[]>([]);\n const [readingMins, setReadingMins] = useState('');\n const [coverFileId, setCoverFileId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n // Bumped on reset to force the cover dropzone to drop its local preview state.\n const [resetNonce, setResetNonce] = useState(0);\n\n const effectiveSlug = slugTouched ? slug : slugify(title);\n\n const reset = () => {\n setTitle('');\n setSlug('');\n setSlugTouched(false);\n setSummary('');\n setBody('');\n setFormat('ARTICLE');\n setPickedTopic(topicId ?? '');\n setLanguages([]);\n setTags([]);\n setReadingMins('');\n setCoverFileId(null);\n setError(null);\n setResetNonce((n) => n + 1);\n };\n\n const submit = async () => {\n if (!title.trim()) {\n setError('A title is required.');\n return;\n }\n if (!effectiveSlug) {\n setError('A URL slug is required.');\n return;\n }\n try {\n const created = await createStory.mutateAsync({\n title: title.trim(),\n slug: effectiveSlug,\n summary: summary.trim() || null,\n body: body.trim() || null,\n format,\n topicId: pickedTopic || null,\n languages: languages.length ? languages : null,\n tags: tags.length ? tags : null,\n readingMins: readingMins ? Number(readingMins) : null,\n coverFileId,\n });\n notify.success('Story created', created.title);\n onOpenChange(false);\n reset();\n onCreated?.(created);\n } catch (err) {\n setError(describeError(err));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-3xl\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle className=\"font-display\">Draft a story</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Begin a new piece — it enters the editorial lifecycle as a draft you can refine and\n publish later.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[64vh] flex-col gap-5 overflow-y-auto py-2\">\n {/* Cover image */}\n <div className=\"grid gap-1.5\">\n <Label>Cover image</Label>\n <CoverDropzone\n key={resetNonce}\n coverFileId={coverFileId}\n onUploaded={setCoverFileId}\n onCleared={() => setCoverFileId(null)}\n />\n </div>\n\n {/* Title + slug */}\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-title\">Title</Label>\n <Input\n id=\"story-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. The Weavers of the Coromandel Coast\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-slug\">URL slug</Label>\n <div className=\"relative\">\n <Input\n id=\"story-slug\"\n value={effectiveSlug}\n onChange={(e) => {\n setSlugTouched(true);\n setSlug(slugify(e.target.value));\n }}\n placeholder=\"the-weavers-of-the-coromandel-coast\"\n className={effectiveSlug ? 'pr-9' : undefined}\n />\n {effectiveSlug && (\n <CheckCircle2\n className=\"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-status-success-text\"\n aria-hidden=\"true\"\n />\n )}\n </div>\n <p className=\"text-xs text-text-tertiary\">\n Auto-derived from the title — used in the story’s URL, so keep it unique.\n </p>\n </div>\n </div>\n\n {/* Format + reading time */}\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label>Format</Label>\n <Select value={format} onValueChange={(v) => setFormat(v as TcpStoryFormat)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FORMATS.map((f) => (\n <SelectItem key={f} value={f}>\n {formatEnumLabel(f)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-reading\">Reading time (min)</Label>\n <Input\n id=\"story-reading\"\n type=\"number\"\n min={0}\n value={readingMins}\n onChange={(e) => setReadingMins(e.target.value)}\n placeholder=\"Optional\"\n />\n </div>\n </div>\n\n {/* Topic */}\n <div className=\"grid gap-1.5\">\n <Label>Topic</Label>\n <Select value={pickedTopic} onValueChange={setPickedTopic}>\n <SelectTrigger>\n <SelectValue placeholder=\"Choose a topic (optional)\" />\n </SelectTrigger>\n <SelectContent>\n {(topicsQuery.data?.items ?? []).map((topic) => (\n <SelectItem key={topic.id} value={topic.id}>\n {topic.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Summary */}\n <div className=\"grid gap-1.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <Label htmlFor=\"story-summary\">Summary</Label>\n <span className=\"text-xs tabular-nums text-text-tertiary\">\n {summary.length}/{SUMMARY_MAX}\n </span>\n </div>\n <Textarea\n id=\"story-summary\"\n value={summary}\n onChange={(e) => setSummary(e.target.value.slice(0, SUMMARY_MAX))}\n maxLength={SUMMARY_MAX}\n placeholder=\"A short standfirst that introduces the story.\"\n rows={2}\n />\n </div>\n\n {/* Body */}\n <div className=\"grid gap-1.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <Label htmlFor=\"story-body\">Body</Label>\n <span className=\"text-xs tabular-nums text-text-tertiary\">\n {body.length} {body.length === 1 ? 'character' : 'characters'}\n </span>\n </div>\n <Textarea\n id=\"story-body\"\n value={body}\n onChange={(e) => setBody(e.target.value)}\n placeholder=\"Write the story… (line breaks are preserved)\"\n rows={5}\n />\n </div>\n\n {/* Languages + tags */}\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-langs\">Languages</Label>\n <TagInput\n id=\"story-langs\"\n value={languages}\n onChange={setLanguages}\n placeholder=\"e.g. English, Tamil…\"\n preserveCase\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-tags\">Tags</Label>\n <TagInput id=\"story-tags\" value={tags} onChange={setTags} placeholder=\"Add tags…\" />\n </div>\n </div>\n\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={createStory.isPending}>\n {createStory.isPending ? (\n <>\n <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" aria-hidden=\"true\" /> Creating…\n </>\n ) : (\n 'Create story'\n )}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CreateStoryDialog.js","names":["_Fragment","Fragment$1","FORMATS","SUMMARY_MAX","COVER_MAX_MB","CoverDropzone","inputRef","useRef","uploading","setUploading","useState","dragActive","setDragActive","previewUrl","setPreviewUrl","fileName","setFileName","handleFile","file","uploaded","uploadImageToFiles","FILE_FOLDERS","onUploaded","notify","err","describeError","onInputChange","event","onDrop","clear","onCleared","hiddenInput","X","coverFileId","FileCheck2","cn","Loader2","UploadCloud","Button","CreateStoryDialog","createStory","useTcpCreateStory","topicsQuery","useTcpTopics","title","setTitle","slug","setSlug","slugTouched","setSlugTouched","summary","setSummary","body","setBody","format","setFormat","pickedTopic","setPickedTopic","topicId","languages","setLanguages","tags","setTags","readingMins","setReadingMins","setCoverFileId","error","setError","resetNonce","setResetNonce","effectiveSlug","slugify","reset","n","ResponsiveDialog","ResponsiveDialogContent","ResponsiveDialogHeader","ResponsiveDialogTitle","ResponsiveDialogDescription","Label","Input","CheckCircle2","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","f","formatEnumLabel","topic","Textarea","TagInput","ResponsiveDialogFooter","onOpenChange","created","onCreated","message"],"sources":["../../../src/theculturepost/components/CreateStoryDialog.tsx"],"sourcesContent":["/**\n * CreateStoryDialog — draft a new story.\n * @module theculturepost/components\n *\n * Writes `tcpCreateStory`. A wide, two-column composer that mirrors the editorial\n * \"Draft a story\" surface: a real drag-and-drop cover dropzone (uploads to\n * wspace-files-svc and keeps the returned `coverFileId`), a title with an\n * auto-derived URL slug + uniqueness hint, char counters on summary/body, and\n * chip multiselects for languages/tags. New stories begin at the start of the\n * editorial lifecycle (IDEA/DRAFT on the svc). Every field maps to a real\n * `TcpCreateStoryInput` field — no bookmarks, no fabricated metadata.\n */\n\nimport { useRef, useState, type ChangeEvent, type DragEvent } from 'react';\nimport { UploadCloud, Loader2, X, CheckCircle2, FileCheck2 } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { TagInput } from './TagInput';\nimport { cn } from '../utils/cn';\nimport { useTcpCreateStory, useTcpTopics, uploadImageToFiles, FILE_FOLDERS } from '../hooks';\nimport { slugify } from '../utils/slug';\nimport { formatEnumLabel } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { TcpStory, TcpStoryFormat } from '../types';\n\nconst FORMATS: TcpStoryFormat[] = [\n 'ARTICLE',\n 'ESSAY',\n 'EXPLAINER',\n 'ORAL_HISTORY',\n 'PHOTO_STORY',\n 'TIMELINE',\n];\n\nconst SUMMARY_MAX = 200;\nconst COVER_MAX_MB = 25;\n\n// ---------------------------------------------------------------------------\n// Cover dropzone (real drag-and-drop → wspace-files-svc)\n// ---------------------------------------------------------------------------\n\ninterface CoverDropzoneProps {\n coverFileId: string | null;\n onUploaded: (fileId: string) => void;\n onCleared: () => void;\n}\n\nfunction CoverDropzone({ coverFileId, onUploaded, onCleared }: CoverDropzoneProps) {\n const inputRef = useRef<HTMLInputElement | null>(null);\n const [uploading, setUploading] = useState(false);\n const [dragActive, setDragActive] = useState(false);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const [fileName, setFileName] = useState<string | null>(null);\n\n const handleFile = async (file: File) => {\n if (!file.type.startsWith('image/')) {\n notify.error('Unsupported file', 'Please choose an image (JPG or PNG).');\n return;\n }\n if (file.size > COVER_MAX_MB * 1024 * 1024) {\n notify.error('File too large', `Please choose an image under ${COVER_MAX_MB} MB.`);\n return;\n }\n setUploading(true);\n try {\n const uploaded = await uploadImageToFiles(file, FILE_FOLDERS.covers);\n setPreviewUrl(uploaded.url);\n setFileName(uploaded.name);\n onUploaded(uploaded.id);\n notify.success('Cover uploaded', uploaded.name);\n } catch (err) {\n notify.error('Upload failed', describeError(err));\n } finally {\n setUploading(false);\n }\n };\n\n const onInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n event.target.value = '';\n if (file) void handleFile(file);\n };\n\n const onDrop = (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setDragActive(false);\n if (uploading) return;\n const file = event.dataTransfer.files?.[0];\n if (file) void handleFile(file);\n };\n\n const clear = () => {\n setPreviewUrl(null);\n setFileName(null);\n onCleared();\n };\n\n const hiddenInput = (\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"sr-only\"\n onChange={onInputChange}\n disabled={uploading}\n aria-label=\"Upload cover image\"\n />\n );\n\n // Uploaded image preview\n if (previewUrl) {\n return (\n <div className=\"relative overflow-hidden rounded-2xl border border-border-seam\">\n {hiddenInput}\n <img src={previewUrl} alt=\"Cover preview\" className=\"max-h-52 w-full object-cover\" />\n <div className=\"absolute right-2 top-2 flex gap-1.5\">\n <button\n type=\"button\"\n onClick={() => inputRef.current?.click()}\n className=\"rounded-full bg-bg-canvas/85 px-2.5 py-1 text-xs font-medium text-text-primary backdrop-blur-sm hover:bg-bg-canvas\"\n >\n Replace\n </button>\n <button\n type=\"button\"\n onClick={clear}\n aria-label=\"Remove cover\"\n className=\"rounded-full bg-bg-canvas/85 p-1.5 text-text-primary backdrop-blur-sm hover:bg-bg-canvas\"\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </div>\n </div>\n );\n }\n\n // Cover set but no local preview (defensive)\n if (coverFileId) {\n return (\n <div className=\"flex items-center justify-between gap-2 rounded-2xl border border-border-seam bg-bg-surface px-3 py-2.5 text-sm\">\n {hiddenInput}\n <span className=\"inline-flex min-w-0 items-center gap-2 text-text-primary\">\n <FileCheck2 className=\"h-4 w-4 shrink-0 text-status-success-text\" aria-hidden=\"true\" />\n <span className=\"truncate\">{fileName ?? 'Cover selected'}</span>\n </span>\n <button\n type=\"button\"\n onClick={clear}\n aria-label=\"Remove cover\"\n className=\"text-text-tertiary hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </div>\n );\n }\n\n // Empty dropzone\n return (\n <div\n onDragOver={(event) => {\n event.preventDefault();\n if (!uploading) setDragActive(true);\n }}\n onDragLeave={(event) => {\n event.preventDefault();\n setDragActive(false);\n }}\n onDrop={onDrop}\n className={cn(\n 'rounded-2xl border-2 border-dashed px-4 py-6 text-center transition-colors',\n dragActive\n ? 'border-accent bg-[var(--color-accent-soft)]'\n : 'border-border-seam bg-bg-sunken/40'\n )}\n >\n {hiddenInput}\n {uploading ? (\n <div className=\"flex items-center justify-center gap-2 text-sm text-text-secondary\">\n <Loader2 className=\"h-5 w-5 animate-spin\" aria-hidden=\"true\" /> Uploading cover…\n </div>\n ) : (\n <div className=\"flex flex-col items-center justify-center gap-3 sm:flex-row\">\n <UploadCloud className=\"h-8 w-8 text-accent\" aria-hidden=\"true\" />\n <p className=\"text-sm text-text-secondary\">Drag and drop an image here, or</p>\n <Button type=\"button\" size=\"sm\" onClick={() => inputRef.current?.click()}>\n Upload cover\n </Button>\n </div>\n )}\n <p className=\"mt-3 text-xs text-text-tertiary\">\n Recommended: 16:9 ratio, min 1200×675px. JPG or PNG, up to {COVER_MAX_MB} MB.\n </p>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dialog\n// ---------------------------------------------------------------------------\n\ninterface CreateStoryDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Pre-select a topic (e.g. from a topic detail page). */\n topicId?: string;\n onCreated?: (story: TcpStory) => void;\n}\n\nexport function CreateStoryDialog({\n open,\n onOpenChange,\n topicId,\n onCreated,\n}: CreateStoryDialogProps) {\n const createStory = useTcpCreateStory();\n const topicsQuery = useTcpTopics({ pagination: { limit: 100 } });\n\n const [title, setTitle] = useState('');\n const [slug, setSlug] = useState('');\n const [slugTouched, setSlugTouched] = useState(false);\n const [summary, setSummary] = useState('');\n const [body, setBody] = useState('');\n const [format, setFormat] = useState<TcpStoryFormat>('ARTICLE');\n const [pickedTopic, setPickedTopic] = useState(topicId ?? '');\n const [languages, setLanguages] = useState<string[]>([]);\n const [tags, setTags] = useState<string[]>([]);\n const [readingMins, setReadingMins] = useState('');\n const [coverFileId, setCoverFileId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n // Bumped on reset to force the cover dropzone to drop its local preview state.\n const [resetNonce, setResetNonce] = useState(0);\n\n const effectiveSlug = slugTouched ? slug : slugify(title);\n\n const reset = () => {\n setTitle('');\n setSlug('');\n setSlugTouched(false);\n setSummary('');\n setBody('');\n setFormat('ARTICLE');\n setPickedTopic(topicId ?? '');\n setLanguages([]);\n setTags([]);\n setReadingMins('');\n setCoverFileId(null);\n setError(null);\n setResetNonce((n) => n + 1);\n };\n\n const submit = async () => {\n if (!title.trim()) {\n setError('A title is required.');\n return;\n }\n if (!effectiveSlug) {\n setError('A URL slug is required.');\n return;\n }\n try {\n const created = await createStory.mutateAsync({\n title: title.trim(),\n slug: effectiveSlug,\n summary: summary.trim() || null,\n body: body.trim() || null,\n format,\n topicId: pickedTopic || null,\n languages: languages.length ? languages : null,\n tags: tags.length ? tags : null,\n readingMins: readingMins ? Number(readingMins) : null,\n coverFileId,\n });\n notify.success('Story created', created.title);\n onOpenChange(false);\n reset();\n onCreated?.(created);\n } catch (err) {\n // Keep the dialog open with the entered values and surface the failure in\n // both the inline alert and a toast, so a failed create is never silent.\n const message = describeError(err);\n setError(message);\n notify.error('Could not create the story', message);\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-3xl\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle className=\"font-display\">Draft a story</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Begin a new piece — it enters the editorial lifecycle as a draft you can refine and\n publish later.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[64vh] flex-col gap-5 overflow-y-auto py-2\">\n {/* Cover image */}\n <div className=\"grid gap-1.5\">\n <Label>Cover image</Label>\n <CoverDropzone\n key={resetNonce}\n coverFileId={coverFileId}\n onUploaded={setCoverFileId}\n onCleared={() => setCoverFileId(null)}\n />\n </div>\n\n {/* Title + slug */}\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-title\">Title</Label>\n <Input\n id=\"story-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. The Weavers of the Coromandel Coast\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-slug\">URL slug</Label>\n <div className=\"relative\">\n <Input\n id=\"story-slug\"\n value={effectiveSlug}\n onChange={(e) => {\n setSlugTouched(true);\n setSlug(slugify(e.target.value));\n }}\n placeholder=\"the-weavers-of-the-coromandel-coast\"\n className={effectiveSlug ? 'pr-9' : undefined}\n />\n {effectiveSlug && (\n <CheckCircle2\n className=\"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-status-success-text\"\n aria-hidden=\"true\"\n />\n )}\n </div>\n <p className=\"text-xs text-text-tertiary\">\n Auto-derived from the title — used in the story’s URL, so keep it unique.\n </p>\n </div>\n </div>\n\n {/* Format + reading time */}\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label>Format</Label>\n <Select value={format} onValueChange={(v) => setFormat(v as TcpStoryFormat)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FORMATS.map((f) => (\n <SelectItem key={f} value={f}>\n {formatEnumLabel(f)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-reading\">Reading time (min)</Label>\n <Input\n id=\"story-reading\"\n type=\"number\"\n min={0}\n value={readingMins}\n onChange={(e) => setReadingMins(e.target.value)}\n placeholder=\"Optional\"\n />\n </div>\n </div>\n\n {/* Topic */}\n <div className=\"grid gap-1.5\">\n <Label>Topic</Label>\n <Select value={pickedTopic} onValueChange={setPickedTopic}>\n <SelectTrigger>\n <SelectValue placeholder=\"Choose a topic (optional)\" />\n </SelectTrigger>\n <SelectContent>\n {(topicsQuery.data?.items ?? []).map((topic) => (\n <SelectItem key={topic.id} value={topic.id}>\n {topic.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Summary */}\n <div className=\"grid gap-1.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <Label htmlFor=\"story-summary\">Summary</Label>\n <span className=\"text-xs tabular-nums text-text-tertiary\">\n {summary.length}/{SUMMARY_MAX}\n </span>\n </div>\n <Textarea\n id=\"story-summary\"\n value={summary}\n onChange={(e) => setSummary(e.target.value.slice(0, SUMMARY_MAX))}\n maxLength={SUMMARY_MAX}\n placeholder=\"A short standfirst that introduces the story.\"\n rows={2}\n />\n </div>\n\n {/* Body */}\n <div className=\"grid gap-1.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <Label htmlFor=\"story-body\">Body</Label>\n <span className=\"text-xs tabular-nums text-text-tertiary\">\n {body.length} {body.length === 1 ? 'character' : 'characters'}\n </span>\n </div>\n <Textarea\n id=\"story-body\"\n value={body}\n onChange={(e) => setBody(e.target.value)}\n placeholder=\"Write the story… (line breaks are preserved)\"\n rows={5}\n />\n </div>\n\n {/* Languages + tags */}\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-langs\">Languages</Label>\n <TagInput\n id=\"story-langs\"\n value={languages}\n onChange={setLanguages}\n placeholder=\"e.g. English, Tamil…\"\n preserveCase\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"story-tags\">Tags</Label>\n <TagInput id=\"story-tags\" value={tags} onChange={setTags} placeholder=\"Add tags…\" />\n </div>\n </div>\n\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={createStory.isPending}>\n {createStory.isPending ? (\n <>\n <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" aria-hidden=\"true\" /> Creating…\n </>\n ) : (\n 'Create story'\n )}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAwCA,IAAME,KAA4B;CAChC;CACA;CACA;CACA;CACA;CACA;AACF,GAEMC,IAAc,KACdC,IAAe;AAYrB,SAASC,GAAc,EAAE,gBAAa,eAAY,gBAAiC;CACjF,IAAMC,IAAWC,EAAgC,IAAI,GAC/C,CAACC,GAAWC,KAAgBC,EAAS,EAAK,GAC1C,CAACC,GAAYC,KAAiBF,EAAS,EAAK,GAC5C,CAACG,GAAYC,KAAiBJ,EAAwB,IAAI,GAC1D,CAACK,GAAUC,KAAeN,EAAwB,IAAI,GAEtDO,IAAa,OAAO,MAAe;EACvC,IAAI,CAACC,EAAK,KAAK,WAAW,QAAQ,GAChC,EAAO,MAAM,oBAAoB,sCAAsC;OAGzE,IAAIA,EAAK,OAAOd,IAAe,OAAO,MACpC,EAAO,MAAM,kBAAkB,gCAAgCA,EAAa,KAAK;OAGnF;KAAa,EAAI;GACjB,IAAI;IACF,IAAMe,IAAW,MAAMC,EAAmBF,GAAMG,EAAa,MAAM;IAInE,AAHAP,EAAcK,EAAS,GAAG,GAC1BH,EAAYG,EAAS,IAAI,GACzBG,EAAWH,EAAS,EAAE,GACtBI,EAAO,QAAQ,kBAAkBJ,EAAS,IAAI;GAChD,SAASK,GAAK;IACZ,EAAO,MAAM,iBAAiBC,EAAcD,CAAG,CAAC;GAClD,UAAU;IACR,EAAa,EAAK;GACpB;EAXiB;CAYnB,GAEME,KAAiB,MAAyC;EAC9D,IAAMR,IAAOS,EAAM,OAAO,QAAQ;EAElC,AADA,EAAM,OAAO,QAAQ,IACjBT,KAAMD,EAAgBC,CAAI;CAChC,GAEMU,KAAU,MAAqC;EAGnD,IAFAD,EAAM,eAAe,GACrBf,EAAc,EAAK,GACfJ,GAAW;EACf,IAAMU,IAAOS,EAAM,aAAa,QAAQ;EACxC,AAAIT,KAAMD,EAAgBC,CAAI;CAChC,GAEMW,UAAc;EAGlB,AAFAf,EAAc,IAAI,GAClBE,EAAY,IAAI,GAChBc,EAAU;CACZ,GAEMC,IACJ,kBAAC,SAAD;EACE,KAAKzB;EACL,MAAK;EACL,QAAO;EACP,WAAU;EACV,UAAUoB;EACV,UAAUlB;EACV,cAAW;CACZ,CAAA;CAoDH,OAhDIK,IAEA,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACGkB;GACD,kBAAC,OAAD;IAAK,KAAKlB;IAAY,KAAI;IAAgB,WAAU;GAAgC,CAAA;GACpF,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,UAAD;KACE,MAAK;KACL,eAAeP,EAAS,SAAS,MAAM;KACvC,WAAU;KACX,UAAA;IAEO,CAAA,GACR,kBAAC,UAAD;KACE,MAAK;KACL,SAASuB;KACT,cAAW;KACX,WAAU;KAEV,UAAA,kBAACG,GAAD;MAAG,WAAU;MAAU,eAAY;KAAQ,CAAA;IACrC,CAAA,CACL;;EACF;C,KAKLC,IAEA,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACGF;GACD,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CACE,kBAACG,GAAD;KAAY,WAAU;KAA4C,eAAY;IAAQ,CAAA,GACtF,kBAAC,QAAD;KAAM,WAAU;KAAY,UAAAnB,KAAY;IAAuB,CAAA,CAC3D;;GACN,kBAAC,UAAD;IACE,MAAK;IACL,SAASc;IACT,cAAW;IACX,WAAU;IAEV,UAAA,kBAACG,GAAD;KAAG,WAAU;KAAU,eAAY;IAAQ,CAAA;GACrC,CAAA;EACL;C,KAMP,kBAAC,OAAD;EACE,aAAa,MAAU;GAErB,AADAL,EAAM,eAAe,GAChBnB,KAAWI,EAAc,EAAI;EACpC;EACA,cAAc,MAAU;GAEtB,AADAe,EAAM,eAAe,GACrBf,EAAc,EAAK;EACrB;EACQ;EACR,WAAWuB,EACT,8EACAxB,IACI,gDACA,oCACN;EAfF,UAAA;GAiBGoB;GACAvB,IACC,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC4B,IAAD;KAAS,WAAU;KAAuB,eAAY;IAAQ,CAAA,GAAC,mBAC5D;GAEL,CAAA,IAAA,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,kBAACC,IAAD;MAAa,WAAU;MAAsB,eAAY;KAAQ,CAAA;KACjE,kBAAC,KAAD;MAAG,WAAU;MAA8B,UAAA;KAAkC,CAAA;KAC7E,kBAACC,GAAD;MAAQ,MAAK;MAAS,MAAK;MAAK,eAAehC,EAAS,SAAS,MAAM;MAAG,UAAA;KAElE,CAAA;IACL;;GAEP,kBAAC,KAAD;IAAG,WAAU;IAAb,UAAA;KAA+C;KACeF;KAAa;IACxE;;EACA;;AAET;AAcA,SAAgBmC,EAAkB,EAChC,SACA,iBACA,YACA,gBACyB;CACzB,IAAMC,IAAcC,EAAkB,GAChCC,KAAcC,EAAa,EAAE,YAAY,EAAE,OAAO,IAAI,EAAE,CAAC,GAEzD,CAACC,GAAOC,KAAYnC,EAAS,EAAE,GAC/B,CAACoC,GAAMC,KAAWrC,EAAS,EAAE,GAC7B,CAACsC,IAAaC,KAAkBvC,EAAS,EAAK,GAC9C,CAACwC,GAASC,KAAczC,EAAS,EAAE,GACnC,CAAC0C,GAAMC,KAAW3C,EAAS,EAAE,GAC7B,CAAC4C,GAAQC,MAAa7C,EAAyB,SAAS,GACxD,CAAC8C,GAAaC,KAAkB/C,EAASgD,KAAW,EAAE,GACtD,CAACC,GAAWC,KAAgBlD,EAAmB,CAAC,CAAC,GACjD,CAACmD,GAAMC,KAAWpD,EAAmB,CAAC,CAAC,GACvC,CAACqD,GAAaC,KAAkBtD,EAAS,EAAE,GAC3C,CAACuB,GAAagC,KAAkBvD,EAAwB,IAAI,GAC5D,CAACwD,IAAOC,KAAYzD,EAAwB,IAAI,GAEhD,CAAC0D,IAAYC,MAAiB3D,EAAS,CAAC,GAExC4D,IAAgBtB,KAAcF,IAAOyB,EAAQ3B,CAAK,GAElD4B,WAAc;EAalB,AAZA3B,EAAS,EAAE,GACXE,EAAQ,EAAE,GACVE,EAAe,EAAK,GACpBE,EAAW,EAAE,GACbE,EAAQ,EAAE,GACVE,GAAU,SAAS,GACnBE,EAAeC,KAAW,EAAE,GAC5BE,EAAa,CAAC,CAAC,GACfE,EAAQ,CAAC,CAAC,GACVE,EAAe,EAAE,GACjBC,EAAe,IAAI,GACnBE,EAAS,IAAI,GACbE,IAAe,MAAMI,IAAI,CAAC;CAC5B;CAqCA,OACE,kBAACC,GAAD;EAAwB;EAAoB;EAC1C,UAAA,kBAACC,GAAD;GAAyB,WAAU;GAAnC,UAAA;IACE,kBAACC,GAAD,EAAA,UAAA,CACE,kBAACC,GAAD;KAAuB,WAAU;KAAe,UAAA;IAAoC,CAAA,GACpF,kBAACC,GAAD,EAAA,UAA6B,qGAGA,CAAA,CACP,EAAA,CAAA;IAExB,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MAEE,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAACC,GAAD,EAAA,UAAO,cAAkB,CAAA,GACzB,kBAAC1E,IAAD;QAEe;QACb,YAAY4D;QACZ,iBAAiBA,EAAe,IAAI;OACrC,GAJMG,EAIN,CACE;;MAGL,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACW,GAAD;SAAO,SAAQ;SAAc,UAAA;QAAY,CAAA,GACzC,kBAACC,GAAD;SACE,IAAG;SACH,OAAOpC;SACP,WAAW,MAAMC,EAAS,EAAE,OAAO,KAAK;SACxC,aAAY;QACb,CAAA,CACE;OACL,CAAA,GAAA,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA;SACE,kBAACkC,GAAD;UAAO,SAAQ;UAAa,UAAA;SAAe,CAAA;SAC3C,kBAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CACE,kBAACC,GAAD;WACE,IAAG;WACH,OAAOV;WACP,WAAW,MAAM;YAEf,AADArB,EAAe,EAAI,GACnBF,EAAQwB,EAAQ,EAAE,OAAO,KAAK,CAAC;WACjC;WACA,aAAY;WACZ,WAAWD,IAAgB,SAAS,KAAA;UACrC,CAAA,GACAA,KACC,kBAACW,GAAD;WACE,WAAU;WACV,eAAY;UACb,CAAA,CAEA;;SACL,kBAAC,KAAD;UAAG,WAAU;UAA6B,UAAA;SAEvC,CAAA;QACA;OACF,CAAA,CAAA;;MAGL,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACF,GAAD,EAAA,UAAO,SAAa,CAAA,GACpB,kBAACG,GAAD;SAAQ,OAAO5B;SAAQ,gBAAgB,MAAMC,GAAU4B,CAAmB;SAA1E,UAAA,CACE,kBAACC,IAAD,EAAA,UACE,kBAACC,GAAD,CAAc,CAAA,EACD,CAAA,GACf,kBAACC,GAAD,EAAA,UACGpF,GAAQ,KAAK,MACZ,kBAACqF,GAAD;UAAoB,OAAOC;UACxB,UAAAC,EAAgBD,CAAC;SACR,GAFKA,CAEL,CACb,EACY,CAAA,CACT;QACL,CAAA,CAAA;OACL,CAAA,GAAA,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACT,GAAD;SAAO,SAAQ;SAAgB,UAAA;QAAyB,CAAA,GACxD,kBAACC,GAAD;SACE,IAAG;SACH,MAAK;SACL,KAAK;SACL,OAAOjB;SACP,WAAW,MAAMC,EAAe,EAAE,OAAO,KAAK;SAC9C,aAAY;QACb,CAAA,CACE;OACF,CAAA,CAAA;;MAGL,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAACe,GAAD,EAAA,UAAO,QAAY,CAAA,GACnB,kBAACG,GAAD;QAAQ,OAAO1B;QAAa,eAAeC;QAA3C,UAAA,CACE,kBAAC2B,IAAD,EAAA,UACE,kBAACC,GAAD,EAAa,aAAY,4BAA6B,CAAA,EACzC,CAAA,GACf,kBAACC,GAAD,EAAA,WACI5C,GAAY,MAAM,SAAS,CAAC,EAAA,CAAG,KAAK,MACpC,kBAAC6C,GAAD;SAA2B,OAAOG,EAAM;SACrC,UAAAA,EAAM;QACG,GAFKA,EAAM,EAEX,CACb,EACY,CAAA,CACT;OACL,CAAA,CAAA;;MAGL,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACX,GAAD;SAAO,SAAQ;SAAgB,UAAA;QAAc,CAAA,GAC7C,kBAAC,QAAD;SAAM,WAAU;SAAhB,UAAA;UACG7B,EAAQ;UAAO;UAAE/C;SACd;QACH,CAAA,CAAA;OACL,CAAA,GAAA,kBAACwF,GAAD;QACE,IAAG;QACH,OAAOzC;QACP,WAAW,MAAMC,EAAW,EAAE,OAAO,MAAM,MAAM,GAAGhD,CAAW,CAAC;QAChE,WAAWA;QACX,aAAY;QACZ,MAAM;OACP,CAAA,CACE;;MAGL,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAAC4E,GAAD;SAAO,SAAQ;SAAa,UAAA;QAAW,CAAA,GACvC,kBAAC,QAAD;SAAM,WAAU;SAAhB,UAAA;UACG3B,EAAK;UAAO;UAAEA,EAAK,WAAW,IAAI,cAAc;SAC7C;QACH,CAAA,CAAA;OACL,CAAA,GAAA,kBAACuC,GAAD;QACE,IAAG;QACH,OAAOvC;QACP,WAAW,MAAMC,EAAQ,EAAE,OAAO,KAAK;QACvC,aAAY;QACZ,MAAM;OACP,CAAA,CACE;;MAGL,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAAC0B,GAAD;SAAO,SAAQ;SAAc,UAAA;QAAgB,CAAA,GAC7C,kBAACa,GAAD;SACE,IAAG;SACH,OAAOjC;SACP,UAAUC;SACV,aAAY;SACZ,cAAA;QACD,CAAA,CACE;OACL,CAAA,GAAA,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACmB,GAAD;SAAO,SAAQ;SAAa,UAAA;QAAW,CAAA,GACvC,kBAACa,GAAD;SAAU,IAAG;SAAa,OAAO/B;SAAM,UAAUC;SAAS,aAAY;QAAa,CAAA,CAChF;OACF,CAAA,CAAA;;MAEJI,MAAS,kBAAC,KAAD;OAAG,WAAU;OAAkC,UAAAA;MAAS,CAAA;KAC/D;;IAEL,kBAAC2B,GAAD,EAAA,UAAA,CACE,kBAACvD,GAAD;KAAQ,SAAQ;KAAU,eAAewD,EAAa,EAAK;KAAG,UAAA;IAEtD,CAAA,GACR,kBAACxD,GAAD;KAAQ,SAAS,YA1ME;MACzB,IAAI,CAACM,EAAM,KAAK,GACd,EAAS,sBAAsB;WAGjC,IAAI,CAAC0B,GACH,EAAS,yBAAyB;WAGpC,IAAI;OACF,IAAMyB,IAAU,MAAMvD,EAAY,YAAY;QAC5C,OAAOI,EAAM,KAAK;QAClB,MAAM0B;QACN,SAASpB,EAAQ,KAAK,KAAK;QAC3B,MAAME,EAAK,KAAK,KAAK;QACrB;QACA,SAASI,KAAe;QACxB,WAAWG,EAAU,SAASA,IAAY;QAC1C,MAAME,EAAK,SAASA,IAAO;QAC3B,aAAaE,IAAc,OAAOA,CAAW,IAAI;QACjD;OACF,CAAC;OAID,AAHAxC,EAAO,QAAQ,iBAAiBwE,EAAQ,KAAK,GAC7CD,EAAa,EAAK,GAClBtB,GAAM,GACNwB,IAAYD,CAAO;MACrB,SAASvE,GAAK;OAGZ,IAAMyE,IAAUxE,EAAcD,CAAG;OAEjC,AADA2C,EAAS8B,CAAO,GAChB1E,EAAO,MAAM,8BAA8B0E,CAAO;MACpD;KACF;KAyKiC,UAAUzD,EAAY;KAC5C,UAAAA,EAAY,YACX,kBAAAxC,GAAA,EAAA,UAAA,CACE,kBAACoC,IAAD;MAAS,WAAU;MAA8B,eAAY;KAAQ,CAAA,GAAC,YACtE,EAAA,CAAA,IAEF;IAEI,CAAA,CACc,EAAA,CAAA;GACD;;CACT,CAAA;AAEtB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useCursorPager as
|
|
3
|
-
import { FILE_FOLDERS as
|
|
4
|
-
import { stripBasePath as
|
|
5
|
-
import { useTr as
|
|
6
|
-
import { usePendingOralHistorySync as
|
|
7
|
-
export {
|
|
1
|
+
import { TcpApiError as e, useTcpAddCitation as t, useTcpAddStoryClaim as n, useTcpAiContextRuns as r, useTcpArchiveItem as i, useTcpArchiveItems as a, useTcpArchiveTopic as o, useTcpCitations as s, useTcpCollection as c, useTcpCollections as l, useTcpCreateArchiveItem as u, useTcpCreateCollection as d, useTcpCreateStory as f, useTcpCreateTopic as p, useTcpDiscussion as m, useTcpDiscussions as h, useTcpGenerateAiContext as g, useTcpLinkCitationToClaim as _, useTcpLockDiscussion as v, useTcpModerateReply as y, useTcpMySavedStories as b, useTcpOpenDiscussion as x, useTcpOralHistories as S, useTcpPostReply as C, useTcpRecordOralHistory as w, useTcpRemoveStoryClaim as T, useTcpReplies as E, useTcpReviewAiContext as D, useTcpStories as O, useTcpStory as k, useTcpStoryClaims as A, useTcpToggleStoryBookmark as j, useTcpTopic as M, useTcpTopics as N, useTcpTransitionStory as P, useTcpUpdateStory as F, useTcpUpdateStoryClaim as I, useTcpUpdateTopic as L, useTcpVerifyCitation as R } from "./useTcpApi.js";
|
|
2
|
+
import { useCursorPager as z } from "./useCursorPager.js";
|
|
3
|
+
import { FILE_FOLDERS as B, uploadImageToFiles as V, useFileUrl as H } from "./useFiles.js";
|
|
4
|
+
import { stripBasePath as U, usePageAnalytics as W } from "./usePageAnalytics.js";
|
|
5
|
+
import { useTr as G } from "./useTr.js";
|
|
6
|
+
import { usePendingOralHistorySync as K } from "./usePendingOralHistorySync.js";
|
|
7
|
+
export { B as FILE_FOLDERS, e as TcpApiError, U as stripBasePath, V as uploadImageToFiles, z as useCursorPager, H as useFileUrl, W as usePageAnalytics, K as usePendingOralHistorySync, t as useTcpAddCitation, n as useTcpAddStoryClaim, r as useTcpAiContextRuns, i as useTcpArchiveItem, a as useTcpArchiveItems, o as useTcpArchiveTopic, s as useTcpCitations, c as useTcpCollection, l as useTcpCollections, u as useTcpCreateArchiveItem, d as useTcpCreateCollection, f as useTcpCreateStory, p as useTcpCreateTopic, m as useTcpDiscussion, h as useTcpDiscussions, g as useTcpGenerateAiContext, _ as useTcpLinkCitationToClaim, v as useTcpLockDiscussion, y as useTcpModerateReply, b as useTcpMySavedStories, x as useTcpOpenDiscussion, S as useTcpOralHistories, C as useTcpPostReply, w as useTcpRecordOralHistory, T as useTcpRemoveStoryClaim, E as useTcpReplies, D as useTcpReviewAiContext, O as useTcpStories, k as useTcpStory, A as useTcpStoryClaims, j as useTcpToggleStoryBookmark, M as useTcpTopic, N as useTcpTopics, P as useTcpTransitionStory, F as useTcpUpdateStory, I as useTcpUpdateStoryClaim, L as useTcpUpdateTopic, R as useTcpVerifyCitation, G as useTr };
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { TcpConnection, TcpStory, TcpStoryStatus, TcpTopic, TcpTopicCategory, TcpCitation, TcpVerificationStatus, TcpDiscussion, TcpReply, TcpModerationStatus, TcpCollection, TcpArchiveItem, TcpArchiveItemKind, TcpAccessLevel, TcpOralHistory, TcpCreateStoryInput, TcpUpdateStoryInput, TcpCreateTopicInput, TcpUpdateTopicInput, TcpCreateCitationInput, TcpStoryClaim, TcpCreateStoryClaimInput, TcpUpdateStoryClaimInput, TcpCreateDiscussionInput, TcpCreateReplyInput, TcpCreateCollectionInput, TcpCreateArchiveItemInput, TcpUpdateArchiveItemInput, TcpCreateOralHistoryInput, TcpAgentRun, TcpGenerateAiContextInput, PaginationInput } from '../types';
|
|
2
|
+
/** A GraphQL failure carrying the server's `extensions.code` so callers can map it to friendly copy. */
|
|
3
|
+
export declare class TcpApiError extends Error {
|
|
4
|
+
readonly code: string | null;
|
|
5
|
+
constructor(message: string, code: string | null);
|
|
6
|
+
}
|
|
2
7
|
export interface StoryFilters {
|
|
3
8
|
status?: TcpStoryStatus;
|
|
4
9
|
topicId?: string;
|
|
@@ -7,8 +7,13 @@ import { clearGraphqlResponseCache as r } from "../lib/graphql-cache.js";
|
|
|
7
7
|
import { useMutation as i, useQuery as a, useQueryClient as o } from "@tanstack/react-query";
|
|
8
8
|
import { graphqlFetch as s } from "@burdenoff/fe-libs/shared/graphql";
|
|
9
9
|
// src/theculturepost/hooks/useTcpApi.ts
|
|
10
|
-
var c =
|
|
11
|
-
|
|
10
|
+
var c = class extends Error {
|
|
11
|
+
code;
|
|
12
|
+
constructor(e, t) {
|
|
13
|
+
super(e), this.name = "TcpApiError", this.code = t;
|
|
14
|
+
}
|
|
15
|
+
}, ee = (e) => /^\s*mutation\b/.test(e), l = async (e, t, n) => {
|
|
16
|
+
let i = ee(e);
|
|
12
17
|
i && r();
|
|
13
18
|
let a = await s({
|
|
14
19
|
gateway: "workspace",
|
|
@@ -17,7 +22,10 @@ var c = (e) => /^\s*mutation\b/.test(e), l = async (e, t, n) => {
|
|
|
17
22
|
variables: t,
|
|
18
23
|
workspaceToken: !0
|
|
19
24
|
});
|
|
20
|
-
if (i && r(), a.errors?.length)
|
|
25
|
+
if (i && r(), a.errors?.length) {
|
|
26
|
+
let e = a.errors[0], t = e?.extensions?.code;
|
|
27
|
+
throw new c(e?.message ?? "GraphQL request failed", typeof t == "string" ? t : null);
|
|
28
|
+
}
|
|
21
29
|
if (!a.data) throw Error("GraphQL response did not include data");
|
|
22
30
|
return a.data;
|
|
23
31
|
}, u = {
|
|
@@ -95,7 +103,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
95
103
|
status: e.tcpModerationStatus ?? "PENDING",
|
|
96
104
|
createdAt: e.createdAt,
|
|
97
105
|
updatedAt: e.tcpModeratedAt ?? e.updatedAt
|
|
98
|
-
}), S = "\n id workspaceId title description kind accessLevel collectionId file { id }\n provenance origin languages tags datedAt createdAt updatedAt\n", C = "\n id workspaceId title summary transcript narratorName language accessLevel collectionId\n recording { id } durationSecs recordedAt consentGiven tags createdAt updatedAt\n", w = "\n id workspaceId name slug description tradition cover { id } itemCount createdAt updatedAt\n", T = "\n id workspaceId actorId actorType trigger useCase storyId collectionId oralHistoryId\n provider model promptSummary groundingRefs { kind refId title }\n content uncertainty status error reviewStatus reviewNotes reviewedAt reviewedBy\n costUsd latencyMs tokensIn tokensOut createdAt\n",
|
|
106
|
+
}), S = "\n id workspaceId title description kind accessLevel collectionId file { id }\n provenance origin languages tags datedAt createdAt updatedAt\n", C = "\n id workspaceId title summary transcript narratorName language accessLevel collectionId\n recording { id } durationSecs recordedAt consentGiven tags createdAt updatedAt\n", w = "\n id workspaceId name slug description tradition cover { id } itemCount createdAt updatedAt\n", T = "\n id workspaceId actorId actorType trigger useCase storyId collectionId oralHistoryId\n provider model promptSummary groundingRefs { kind refId title }\n content uncertainty status error reviewStatus reviewNotes reviewedAt reviewedBy\n costUsd latencyMs tokensIn tokensOut createdAt\n", E = (t = {}) => {
|
|
99
107
|
let { apiGatewayUrl: n } = e();
|
|
100
108
|
return a({
|
|
101
109
|
queryKey: [...u.stories, t],
|
|
@@ -111,7 +119,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
111
119
|
pagination: f(t.pagination)
|
|
112
120
|
}, n)).tcpListStories
|
|
113
121
|
});
|
|
114
|
-
},
|
|
122
|
+
}, D = (t) => {
|
|
115
123
|
let { apiGatewayUrl: n } = e();
|
|
116
124
|
return a({
|
|
117
125
|
queryKey: u.story(t ?? ""),
|
|
@@ -120,35 +128,35 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
120
128
|
tcpStory(id: $id) { ${_} }
|
|
121
129
|
}`, { id: t }, n)).tcpStory)
|
|
122
130
|
});
|
|
123
|
-
},
|
|
131
|
+
}, O = () => {
|
|
124
132
|
let { apiGatewayUrl: r } = e(), a = o(), s = n();
|
|
125
133
|
return i({
|
|
126
134
|
mutationFn: async (e) => v((await l(`mutation TcpCreateStory($input: TcpCreateStoryInput!) {
|
|
127
135
|
tcpCreateStory(input: $input) { ${_} }
|
|
128
136
|
}`, { input: e }, r)).tcpCreateStory),
|
|
129
|
-
onSuccess: (e) => (s(t.storyDraftCreated(e)), a.invalidateQueries({ queryKey: u.stories }))
|
|
137
|
+
onSuccess: (e) => (s(t.storyDraftCreated(e)), a.setQueryData(u.story(e.id), e), a.invalidateQueries({ queryKey: u.stories }))
|
|
130
138
|
});
|
|
131
|
-
},
|
|
139
|
+
}, k = () => {
|
|
132
140
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
133
141
|
return i({
|
|
134
142
|
mutationFn: async (e) => v((await l(`mutation TcpUpdateStory($id: ID!, $input: TcpUpdateStoryInput!) {
|
|
135
143
|
tcpUpdateStory(id: $id, input: $input) { ${_} }
|
|
136
144
|
}`, e, t)).tcpUpdateStory),
|
|
137
145
|
onSuccess: (e) => {
|
|
138
|
-
n.invalidateQueries({ queryKey: u.stories }), n.invalidateQueries({ queryKey: u.story(e.id) });
|
|
146
|
+
n.setQueryData(u.story(e.id), e), n.invalidateQueries({ queryKey: u.stories }), n.invalidateQueries({ queryKey: u.story(e.id) });
|
|
139
147
|
}
|
|
140
148
|
});
|
|
141
|
-
},
|
|
149
|
+
}, A = () => {
|
|
142
150
|
let { apiGatewayUrl: r } = e(), a = o(), s = n();
|
|
143
151
|
return i({
|
|
144
152
|
mutationFn: async (e) => v((await l(`mutation TcpTransitionStory($id: ID!, $status: TcpStoryStatus!) {
|
|
145
153
|
tcpTransitionStory(id: $id, status: $status) { ${_} }
|
|
146
154
|
}`, e, r)).tcpTransitionStory),
|
|
147
155
|
onSuccess: (e) => {
|
|
148
|
-
e.status === "PUBLISHED" && s(t.storyPublished(e)), a.invalidateQueries({ queryKey: u.stories }), a.invalidateQueries({ queryKey: u.story(e.id) });
|
|
156
|
+
e.status === "PUBLISHED" && s(t.storyPublished(e)), a.setQueryData(u.story(e.id), e), a.invalidateQueries({ queryKey: u.stories }), a.invalidateQueries({ queryKey: u.story(e.id) });
|
|
149
157
|
}
|
|
150
158
|
});
|
|
151
|
-
},
|
|
159
|
+
}, j = (t) => {
|
|
152
160
|
let { apiGatewayUrl: n } = e();
|
|
153
161
|
return a({
|
|
154
162
|
queryKey: [
|
|
@@ -163,7 +171,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
163
171
|
}
|
|
164
172
|
}`, { pagination: f(t) }, n)).tcpMySavedStories
|
|
165
173
|
});
|
|
166
|
-
},
|
|
174
|
+
}, M = () => {
|
|
167
175
|
let { apiGatewayUrl: r, workspaceId: a } = e(), s = o(), c = n();
|
|
168
176
|
return i({
|
|
169
177
|
mutationFn: async (e) => (await l("mutation TcpToggleStoryBookmark($storyId: ID!) { tcpToggleStoryBookmark(storyId: $storyId) }", { storyId: e }, r)).tcpToggleStoryBookmark,
|
|
@@ -171,7 +179,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
171
179
|
e && c(t.storySaved(a, n)), s.invalidateQueries({ queryKey: u.stories }), s.invalidateQueries({ queryKey: u.story(n) });
|
|
172
180
|
}
|
|
173
181
|
});
|
|
174
|
-
},
|
|
182
|
+
}, N = (t) => {
|
|
175
183
|
let { apiGatewayUrl: n } = e();
|
|
176
184
|
return a({
|
|
177
185
|
queryKey: u.citations(t ?? ""),
|
|
@@ -180,7 +188,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
180
188
|
tcpListCitations(storyId: $storyId) { items { ${h} } pageInfo { cursor hasMore } }
|
|
181
189
|
}`, { storyId: t }, n)).tcpListCitations.items
|
|
182
190
|
});
|
|
183
|
-
},
|
|
191
|
+
}, P = () => {
|
|
184
192
|
let { apiGatewayUrl: r } = e(), a = o(), s = n();
|
|
185
193
|
return i({
|
|
186
194
|
mutationFn: async (e) => (await l(`mutation TcpAddCitation($input: TcpCreateCitationInput!) {
|
|
@@ -190,7 +198,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
190
198
|
s(t.citationAttached(e)), a.invalidateQueries({ queryKey: u.citations(e.storyId) }), a.invalidateQueries({ queryKey: u.claims(e.storyId) }), a.invalidateQueries({ queryKey: u.story(e.storyId) });
|
|
191
199
|
}
|
|
192
200
|
});
|
|
193
|
-
},
|
|
201
|
+
}, F = () => {
|
|
194
202
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
195
203
|
return i({
|
|
196
204
|
mutationFn: async (e) => (await l(`mutation TcpVerifyCitation($id: ID!, $verification: TcpVerificationStatus!) {
|
|
@@ -200,7 +208,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
200
208
|
n.invalidateQueries({ queryKey: u.citations(e.storyId) }), n.invalidateQueries({ queryKey: u.claims(e.storyId) }), n.invalidateQueries({ queryKey: u.story(e.storyId) });
|
|
201
209
|
}
|
|
202
210
|
});
|
|
203
|
-
},
|
|
211
|
+
}, I = () => {
|
|
204
212
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
205
213
|
return i({
|
|
206
214
|
mutationFn: async (e) => (await l(`mutation TcpLinkCitationToClaim($citationId: ID!, $claimId: ID) {
|
|
@@ -210,7 +218,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
210
218
|
n.invalidateQueries({ queryKey: u.citations(e.storyId) }), n.invalidateQueries({ queryKey: u.claims(e.storyId) });
|
|
211
219
|
}
|
|
212
220
|
});
|
|
213
|
-
},
|
|
221
|
+
}, L = (t) => {
|
|
214
222
|
let { apiGatewayUrl: n } = e();
|
|
215
223
|
return a({
|
|
216
224
|
queryKey: u.claims(t ?? ""),
|
|
@@ -219,7 +227,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
219
227
|
tcpListStoryClaims(storyId: $storyId) { ${g} }
|
|
220
228
|
}`, { storyId: t }, n)).tcpListStoryClaims
|
|
221
229
|
});
|
|
222
|
-
},
|
|
230
|
+
}, R = () => {
|
|
223
231
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
224
232
|
return i({
|
|
225
233
|
mutationFn: async (e) => (await l(`mutation TcpAddStoryClaim($input: TcpCreateStoryClaimInput!) {
|
|
@@ -229,7 +237,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
229
237
|
n.invalidateQueries({ queryKey: u.claims(e.storyId) });
|
|
230
238
|
}
|
|
231
239
|
});
|
|
232
|
-
},
|
|
240
|
+
}, z = () => {
|
|
233
241
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
234
242
|
return i({
|
|
235
243
|
mutationFn: async (e) => (await l(`mutation TcpUpdateStoryClaim($id: ID!, $input: TcpUpdateStoryClaimInput!) {
|
|
@@ -239,7 +247,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
239
247
|
n.invalidateQueries({ queryKey: u.claims(e.storyId) });
|
|
240
248
|
}
|
|
241
249
|
});
|
|
242
|
-
},
|
|
250
|
+
}, B = () => {
|
|
243
251
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
244
252
|
return i({
|
|
245
253
|
mutationFn: async (e) => (await l("mutation TcpRemoveStoryClaim($id: ID!) { tcpRemoveStoryClaim(id: $id) }", { id: e.id }, t)).tcpRemoveStoryClaim,
|
|
@@ -247,7 +255,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
247
255
|
n.invalidateQueries({ queryKey: u.claims(t.storyId) }), n.invalidateQueries({ queryKey: u.citations(t.storyId) });
|
|
248
256
|
}
|
|
249
257
|
});
|
|
250
|
-
},
|
|
258
|
+
}, V = (t = {}) => {
|
|
251
259
|
let { apiGatewayUrl: n } = e();
|
|
252
260
|
return a({
|
|
253
261
|
queryKey: [...u.topics, t],
|
|
@@ -261,7 +269,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
261
269
|
pagination: f(t.pagination)
|
|
262
270
|
}, n)).tcpListTopics
|
|
263
271
|
});
|
|
264
|
-
},
|
|
272
|
+
}, te = (t) => {
|
|
265
273
|
let { apiGatewayUrl: n } = e();
|
|
266
274
|
return a({
|
|
267
275
|
queryKey: u.topic(t ?? ""),
|
|
@@ -279,7 +287,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
279
287
|
} : null;
|
|
280
288
|
}
|
|
281
289
|
});
|
|
282
|
-
},
|
|
290
|
+
}, H = () => {
|
|
283
291
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
284
292
|
return i({
|
|
285
293
|
mutationFn: async (e) => (await l(`mutation TcpCreateTopic($input: TcpCreateTopicInput!) {
|
|
@@ -287,7 +295,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
287
295
|
}`, { input: e }, t)).tcpCreateTopic,
|
|
288
296
|
onSuccess: () => n.invalidateQueries({ queryKey: u.topics })
|
|
289
297
|
});
|
|
290
|
-
},
|
|
298
|
+
}, U = () => {
|
|
291
299
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
292
300
|
return i({
|
|
293
301
|
mutationFn: async (e) => (await l(`mutation TcpUpdateTopic($id: ID!, $input: TcpUpdateTopicInput!) {
|
|
@@ -297,7 +305,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
297
305
|
n.invalidateQueries({ queryKey: u.topics }), n.invalidateQueries({ queryKey: u.topic(e.id) });
|
|
298
306
|
}
|
|
299
307
|
});
|
|
300
|
-
},
|
|
308
|
+
}, W = () => {
|
|
301
309
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
302
310
|
return i({
|
|
303
311
|
mutationFn: async (e) => (await l("mutation TcpArchiveTopic($id: ID!) { tcpArchiveTopic(id: $id) }", { id: e }, t)).tcpArchiveTopic,
|
|
@@ -305,7 +313,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
305
313
|
n.invalidateQueries({ queryKey: u.topics }), n.invalidateQueries({ queryKey: u.topic(t) });
|
|
306
314
|
}
|
|
307
315
|
});
|
|
308
|
-
},
|
|
316
|
+
}, G = (t = {}) => {
|
|
309
317
|
let { apiGatewayUrl: n } = e();
|
|
310
318
|
return a({
|
|
311
319
|
queryKey: [...u.discussions, t],
|
|
@@ -320,7 +328,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
320
328
|
pagination: f(t.pagination)
|
|
321
329
|
}, n)).tcpListDiscussions
|
|
322
330
|
});
|
|
323
|
-
},
|
|
331
|
+
}, K = (t) => {
|
|
324
332
|
let { apiGatewayUrl: n } = e();
|
|
325
333
|
return a({
|
|
326
334
|
queryKey: u.discussion(t ?? ""),
|
|
@@ -338,7 +346,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
338
346
|
} : null;
|
|
339
347
|
}
|
|
340
348
|
});
|
|
341
|
-
},
|
|
349
|
+
}, q = (t, n) => {
|
|
342
350
|
let { apiGatewayUrl: r } = e();
|
|
343
351
|
return a({
|
|
344
352
|
queryKey: [...u.replies(t ?? ""), n ?? "all"],
|
|
@@ -350,7 +358,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
350
358
|
status: n
|
|
351
359
|
}, r)).tcpListReplies.items.map(x)
|
|
352
360
|
});
|
|
353
|
-
},
|
|
361
|
+
}, J = () => {
|
|
354
362
|
let { apiGatewayUrl: r } = e(), a = o(), s = n();
|
|
355
363
|
return i({
|
|
356
364
|
mutationFn: async (e) => (await l(`mutation TcpOpenDiscussion($input: TcpCreateDiscussionInput!) {
|
|
@@ -358,7 +366,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
358
366
|
}`, { input: e }, r)).tcpOpenDiscussion,
|
|
359
367
|
onSuccess: (e) => (s(t.discussionOpened(e)), a.invalidateQueries({ queryKey: u.discussions }))
|
|
360
368
|
});
|
|
361
|
-
},
|
|
369
|
+
}, Y = () => {
|
|
362
370
|
let { apiGatewayUrl: r } = e(), a = o(), s = n();
|
|
363
371
|
return i({
|
|
364
372
|
mutationFn: async (e) => x((await l(`mutation TcpPostReply($input: TcpCreateReplyInput!) {
|
|
@@ -368,7 +376,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
368
376
|
s(t.discussionReplied(e)), a.invalidateQueries({ queryKey: u.replies(e.discussionId) }), a.invalidateQueries({ queryKey: u.discussion(e.discussionId) }), a.invalidateQueries({ queryKey: u.discussions });
|
|
369
377
|
}
|
|
370
378
|
});
|
|
371
|
-
},
|
|
379
|
+
}, X = () => {
|
|
372
380
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
373
381
|
return i({
|
|
374
382
|
mutationFn: async (e) => x((await l(`mutation TcpModerateReply($id: ID!, $status: TcpModerationStatus!) {
|
|
@@ -378,7 +386,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
378
386
|
n.invalidateQueries({ queryKey: u.replies(e.discussionId) }), n.invalidateQueries({ queryKey: u.discussion(e.discussionId) });
|
|
379
387
|
}
|
|
380
388
|
});
|
|
381
|
-
},
|
|
389
|
+
}, Z = () => {
|
|
382
390
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
383
391
|
return i({
|
|
384
392
|
mutationFn: async (e) => (await l(`mutation TcpLockDiscussion($id: ID!) {
|
|
@@ -388,7 +396,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
388
396
|
n.invalidateQueries({ queryKey: u.discussions }), n.invalidateQueries({ queryKey: u.discussion(e.id) });
|
|
389
397
|
}
|
|
390
398
|
});
|
|
391
|
-
},
|
|
399
|
+
}, Q = (t) => {
|
|
392
400
|
let { apiGatewayUrl: n } = e();
|
|
393
401
|
return a({
|
|
394
402
|
queryKey: [...u.collections, t],
|
|
@@ -396,7 +404,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
396
404
|
tcpListCollections(pagination: $pagination) { items { ${w} } pageInfo { cursor hasMore } }
|
|
397
405
|
}`, { pagination: f(t) }, n)).tcpListCollections.items
|
|
398
406
|
});
|
|
399
|
-
},
|
|
407
|
+
}, ne = (t) => {
|
|
400
408
|
let { apiGatewayUrl: n } = e();
|
|
401
409
|
return a({
|
|
402
410
|
queryKey: u.collection(t ?? ""),
|
|
@@ -416,7 +424,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
416
424
|
} : null;
|
|
417
425
|
}
|
|
418
426
|
});
|
|
419
|
-
},
|
|
427
|
+
}, re = () => {
|
|
420
428
|
let { apiGatewayUrl: r } = e(), a = o(), s = n();
|
|
421
429
|
return i({
|
|
422
430
|
mutationFn: async (e) => (await l(`mutation TcpCreateCollection($input: TcpCreateCollectionInput!) {
|
|
@@ -424,7 +432,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
424
432
|
}`, { input: e }, r)).tcpCreateCollection,
|
|
425
433
|
onSuccess: (e) => (s(t.collectionCreated(e)), a.invalidateQueries({ queryKey: u.collections }))
|
|
426
434
|
});
|
|
427
|
-
},
|
|
435
|
+
}, ie = (t = {}) => {
|
|
428
436
|
let { apiGatewayUrl: n } = e();
|
|
429
437
|
return a({
|
|
430
438
|
queryKey: [...u.archiveItems, t],
|
|
@@ -440,7 +448,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
440
448
|
pagination: f(t.pagination)
|
|
441
449
|
}, n)).tcpListArchiveItems
|
|
442
450
|
});
|
|
443
|
-
},
|
|
451
|
+
}, ae = (t) => {
|
|
444
452
|
let { apiGatewayUrl: n } = e();
|
|
445
453
|
return a({
|
|
446
454
|
queryKey: u.archiveItem(t ?? ""),
|
|
@@ -452,7 +460,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
452
460
|
}
|
|
453
461
|
}`, { id: t }, n)).tcpArchiveItem
|
|
454
462
|
});
|
|
455
|
-
},
|
|
463
|
+
}, oe = () => {
|
|
456
464
|
let { apiGatewayUrl: r } = e(), a = o(), s = n();
|
|
457
465
|
return i({
|
|
458
466
|
mutationFn: async (e) => (await l(`mutation TcpCreateArchiveItem($input: TcpCreateArchiveItemInput!) {
|
|
@@ -462,7 +470,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
462
470
|
s(t.archiveItemUploaded(e)), a.invalidateQueries({ queryKey: u.archiveItems }), e.collectionId && a.invalidateQueries({ queryKey: u.collection(e.collectionId) });
|
|
463
471
|
}
|
|
464
472
|
});
|
|
465
|
-
},
|
|
473
|
+
}, $ = (t) => {
|
|
466
474
|
let { apiGatewayUrl: n } = e();
|
|
467
475
|
return a({
|
|
468
476
|
queryKey: [...u.oralHistories, t ?? "all"],
|
|
@@ -470,7 +478,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
470
478
|
tcpListOralHistories(collectionId: $collectionId) { items { ${C} } pageInfo { cursor hasMore } }
|
|
471
479
|
}`, { collectionId: t }, n)).tcpListOralHistories.items
|
|
472
480
|
});
|
|
473
|
-
},
|
|
481
|
+
}, se = () => {
|
|
474
482
|
let { apiGatewayUrl: r } = e(), a = o(), s = n();
|
|
475
483
|
return i({
|
|
476
484
|
mutationFn: async (e) => (await l(`mutation TcpRecordOralHistory($input: TcpCreateOralHistoryInput!) {
|
|
@@ -480,7 +488,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
480
488
|
s(t.oralHistoryRecorded(e)), a.invalidateQueries({ queryKey: u.oralHistories }), e.collectionId && a.invalidateQueries({ queryKey: u.collection(e.collectionId) });
|
|
481
489
|
}
|
|
482
490
|
});
|
|
483
|
-
},
|
|
491
|
+
}, ce = (t = {}) => {
|
|
484
492
|
let { apiGatewayUrl: n } = e();
|
|
485
493
|
return a({
|
|
486
494
|
queryKey: [...u.aiRuns, t],
|
|
@@ -496,7 +504,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
496
504
|
pagination: f(t.pagination)
|
|
497
505
|
}, n)).tcpAiContextRuns
|
|
498
506
|
});
|
|
499
|
-
},
|
|
507
|
+
}, le = () => {
|
|
500
508
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
501
509
|
return i({
|
|
502
510
|
mutationFn: async (e) => (await l(`mutation TcpGenerateAiContext($input: TcpGenerateAiContextInput!) {
|
|
@@ -506,7 +514,7 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
506
514
|
n.invalidateQueries({ queryKey: u.aiRuns });
|
|
507
515
|
}
|
|
508
516
|
});
|
|
509
|
-
},
|
|
517
|
+
}, ue = () => {
|
|
510
518
|
let { apiGatewayUrl: t } = e(), n = o();
|
|
511
519
|
return i({
|
|
512
520
|
mutationFn: async (e) => (await l(`mutation TcpReviewAiContext($id: ID!, $approved: Boolean!, $reviewNotes: String) {
|
|
@@ -517,6 +525,6 @@ var y = "\n id workspaceId title prompt storyId openedById isInterfaith isLocke
|
|
|
517
525
|
}
|
|
518
526
|
});
|
|
519
527
|
};
|
|
520
|
-
export {
|
|
528
|
+
export { c as TcpApiError, P as useTcpAddCitation, R as useTcpAddStoryClaim, ce as useTcpAiContextRuns, ae as useTcpArchiveItem, ie as useTcpArchiveItems, W as useTcpArchiveTopic, N as useTcpCitations, ne as useTcpCollection, Q as useTcpCollections, oe as useTcpCreateArchiveItem, re as useTcpCreateCollection, O as useTcpCreateStory, H as useTcpCreateTopic, K as useTcpDiscussion, G as useTcpDiscussions, le as useTcpGenerateAiContext, I as useTcpLinkCitationToClaim, Z as useTcpLockDiscussion, X as useTcpModerateReply, j as useTcpMySavedStories, J as useTcpOpenDiscussion, $ as useTcpOralHistories, Y as useTcpPostReply, se as useTcpRecordOralHistory, B as useTcpRemoveStoryClaim, q as useTcpReplies, ue as useTcpReviewAiContext, E as useTcpStories, D as useTcpStory, L as useTcpStoryClaims, M as useTcpToggleStoryBookmark, te as useTcpTopic, V as useTcpTopics, A as useTcpTransitionStory, k as useTcpUpdateStory, z as useTcpUpdateStoryClaim, U as useTcpUpdateTopic, F as useTcpVerifyCitation };
|
|
521
529
|
|
|
522
530
|
//# sourceMappingURL=useTcpApi.js.map
|