184 lines
6.7 KiB
TypeScript
184 lines
6.7 KiB
TypeScript
import { useParams, Link, useNavigate } from 'react-router-dom';
|
|
import { useState } from 'react';
|
|
import { WidePageLayout } from '../components/WidePageLayout';
|
|
import RichTextEditor from '../components/RichTextEditor';
|
|
import useWikis from '../hooks/useWikis';
|
|
import CheckSquareIcon from '../components/icons/CheckSquareIcon';
|
|
import type { CreateWikiRequest } from '../types/epic';
|
|
|
|
export function CreateWiki() {
|
|
const { id: boardId } = useParams<{ id: string }>();
|
|
const navigate = useNavigate();
|
|
const { createWiki } = useWikis(boardId || '0');
|
|
|
|
const [name, setName] = useState('');
|
|
const [slug, setSlug] = useState('');
|
|
const [summary, setSummary] = useState('');
|
|
const [category, setCategory] = useState('');
|
|
const [tags, setTags] = useState('');
|
|
const [content, setContent] = useState<any[]>([{ children: [{ text: '' }] }]);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
|
|
if (!name.trim()) {
|
|
return;
|
|
}
|
|
|
|
const wikiData: CreateWikiRequest = {
|
|
name: name.trim(),
|
|
slug: slug.trim() || undefined,
|
|
summary: summary.trim() || undefined,
|
|
content:
|
|
content.length > 1 || (content[0] as any).children[0].text !== ''
|
|
? (content as unknown as Record<string, unknown>)
|
|
: { children: [{ text: '' }] },
|
|
category: category.trim() || undefined,
|
|
tags: tags.trim() ? tags.split(',').map((t) => t.trim()) : undefined,
|
|
};
|
|
|
|
try {
|
|
const newWiki = await createWiki(wikiData);
|
|
navigate(`/boards/${boardId}/wikis/${newWiki.id}`);
|
|
} catch {
|
|
// Error is handled by hook
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<WidePageLayout>
|
|
<div>
|
|
<Link
|
|
to={`/boards/${boardId}/wikis`}
|
|
className="text-gray-400 hover:text-white transition-colors text-sm"
|
|
>
|
|
← Back to Wikis
|
|
</Link>
|
|
<h1 className="text-3xl font-bold text-white mt-2">Create Wiki</h1>
|
|
<p className="text-gray-400 mt-1">Create a new wiki for this board</p>
|
|
</div>
|
|
</WidePageLayout>
|
|
|
|
<WidePageLayout>
|
|
<form onSubmit={handleSubmit} className="bg-gray-800 rounded-lg border border-gray-700 p-6">
|
|
{/* Name */}
|
|
<div className="mb-6">
|
|
<label htmlFor="name" className="block text-white font-medium mb-2">
|
|
Wiki Name <span className="text-red-500">*</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="name"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
className="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 text-white focus:outline-none focus:border-blue-500"
|
|
placeholder="Enter wiki name..."
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
{/* Slug */}
|
|
<div className="mb-6">
|
|
<label htmlFor="slug" className="block text-white font-medium mb-2">
|
|
URL Slug (optional)
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="slug"
|
|
value={slug}
|
|
onChange={(e) => setSlug(e.target.value)}
|
|
className="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 text-white focus:outline-none focus:border-blue-500"
|
|
placeholder="url-friendly-slug"
|
|
/>
|
|
<p className="text-gray-500 text-xs mt-2">
|
|
Leave empty to auto-generate from name. Used in URLs.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Summary */}
|
|
<div className="mb-6">
|
|
<label htmlFor="summary" className="block text-white font-medium mb-2">
|
|
Summary
|
|
</label>
|
|
<textarea
|
|
id="summary"
|
|
value={summary}
|
|
onChange={(e) => setSummary(e.target.value)}
|
|
className="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 text-white focus:outline-none focus:border-blue-500 resize-none"
|
|
rows={3}
|
|
placeholder="Brief summary of this wiki..."
|
|
/>
|
|
</div>
|
|
|
|
{/* Category */}
|
|
<div className="mb-6">
|
|
<label htmlFor="category" className="block text-white font-medium mb-2">
|
|
Category
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="category"
|
|
value={category}
|
|
onChange={(e) => setCategory(e.target.value)}
|
|
className="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 text-white focus:outline-none focus:border-blue-500"
|
|
placeholder="e.g., Documentation, Guides, Tutorials"
|
|
/>
|
|
</div>
|
|
|
|
{/* Tags */}
|
|
<div className="mb-6">
|
|
<label htmlFor="tags" className="block text-white font-medium mb-2">
|
|
Tags
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="tags"
|
|
value={tags}
|
|
onChange={(e) => setTags(e.target.value)}
|
|
className="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 text-white focus:outline-none focus:border-blue-500"
|
|
placeholder="tag1, tag2, tag3"
|
|
/>
|
|
<p className="text-gray-500 text-xs mt-2">Separate multiple tags with commas.</p>
|
|
</div>
|
|
|
|
{/* Rich Text Content */}
|
|
<div className="mb-6">
|
|
<label className="block text-white font-medium mb-2">Wiki Content</label>
|
|
<RichTextEditor
|
|
value={content}
|
|
onChange={setContent}
|
|
placeholder="Add detailed information to your wiki..."
|
|
className="border-0"
|
|
/>
|
|
<p className="text-gray-500 text-xs mt-2">
|
|
Use the rich text editor to add formatted content, lists, and more.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Action Buttons */}
|
|
<div className="flex gap-3 pt-4 border-t border-gray-700">
|
|
<Link
|
|
to={`/boards/${boardId}/wikis`}
|
|
className="px-6 py-2 rounded-lg border border-gray-600 text-gray-300 hover:text-white hover:border-gray-500 transition-colors"
|
|
>
|
|
Cancel
|
|
</Link>
|
|
<button
|
|
type="submit"
|
|
disabled={!name.trim()}
|
|
className="flex-1 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-600 disabled:cursor-not-allowed text-white px-6 py-2 rounded-lg flex items-center justify-center gap-2 transition-colors"
|
|
>
|
|
<span className="w-5 h-5">
|
|
<CheckSquareIcon />
|
|
</span>
|
|
Create Wiki
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</WidePageLayout>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default CreateWiki;
|