kanban-app/frontend/src/pages/CreateWiki.tsx

185 lines
6.7 KiB
TypeScript
Raw Normal View History

2026-03-22 11:52:33 +00:00
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;