158 lines
5.7 KiB
TypeScript
158 lines
5.7 KiB
TypeScript
import { useParams, Link, useNavigate } from 'react-router-dom';
|
|
import { WidePageLayout } from '../components/WidePageLayout';
|
|
import RichTextContent from '../components/RichTextContent';
|
|
import useWikis from '../hooks/useWikis';
|
|
import type { Wiki } from '../types/epic';
|
|
import PlusIcon from '../components/icons/PlusIcon';
|
|
import Edit2Icon from '../components/icons/Edit2Icon';
|
|
import Trash2Icon from '../components/icons/Trash2Icon';
|
|
|
|
export function BoardWikis() {
|
|
const { id } = useParams<{ id: string }>();
|
|
const navigate = useNavigate();
|
|
const { wikis, deleteWiki } = useWikis(id || '0');
|
|
|
|
const handleDeleteWiki = async (wikiId: number, wikiName: string) => {
|
|
if (confirm(`Are you sure you want to delete wiki "${wikiName}"?`)) {
|
|
try {
|
|
await deleteWiki(wikiId);
|
|
} catch {
|
|
// Error is handled by the hook
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<WidePageLayout>
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<Link
|
|
to={`/boards/${id}`}
|
|
className="text-gray-400 hover:text-white transition-colors text-sm"
|
|
>
|
|
← Back to Board
|
|
</Link>
|
|
<h1 className="text-3xl font-bold text-white mt-2">Wikis</h1>
|
|
<p className="text-gray-400 mt-1">
|
|
Manage and view wikis for this board ({wikis.length} wikis)
|
|
</p>
|
|
</div>
|
|
<Link
|
|
to={`/boards/${id}/wikis/new`}
|
|
className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center gap-2 transition-colors"
|
|
>
|
|
<PlusIcon className="w-4 h-4" />
|
|
Create Wiki
|
|
</Link>
|
|
</div>
|
|
</WidePageLayout>
|
|
|
|
<WidePageLayout>
|
|
{wikis.length === 0 ? (
|
|
<div className="bg-gray-800 rounded-lg p-8 border border-gray-700">
|
|
<div className="text-center py-12">
|
|
<div className="text-6xl mb-4">📚</div>
|
|
<h2 className="text-xl font-bold text-white mb-2">No Wikis Yet</h2>
|
|
<p className="text-gray-400 mb-6">
|
|
Create your first wiki to start documenting your knowledge.
|
|
</p>
|
|
<Link
|
|
to={`/boards/${id}/wikis/new`}
|
|
className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg inline-flex items-center gap-2 transition-colors"
|
|
>
|
|
<PlusIcon className="w-4 h-4" />
|
|
Create First Wiki
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
{wikis.map((wiki) => (
|
|
<WikiCard
|
|
key={wiki.id}
|
|
wiki={wiki}
|
|
onClick={() => navigate(`/boards/${id}/wikis/${wiki.id}`)}
|
|
onDelete={() => handleDeleteWiki(wiki.id, wiki.name)}
|
|
onEdit={() => navigate(`/boards/${id}/wikis/${wiki.id}/edit`)}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
</WidePageLayout>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface WikiCardProps {
|
|
wiki: Wiki;
|
|
onClick: () => void;
|
|
onDelete: () => void;
|
|
onEdit: () => void;
|
|
}
|
|
|
|
function WikiCard({ wiki, onClick, onDelete, onEdit }: WikiCardProps) {
|
|
return (
|
|
<div
|
|
className="bg-gray-800 rounded-lg border border-gray-700 hover:border-gray-600 transition-all cursor-pointer overflow-hidden group"
|
|
onClick={onClick}
|
|
>
|
|
<div className="p-4">
|
|
{/* Header with actions */}
|
|
<div className="flex items-start justify-between mb-2">
|
|
<h3 className="text-lg font-semibold text-white flex-1">{wiki.name}</h3>
|
|
<div className="flex gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onEdit();
|
|
}}
|
|
className="text-gray-400 hover:text-white transition-colors p-1"
|
|
title="Edit wiki"
|
|
>
|
|
<Edit2Icon className="w-4 h-4" />
|
|
</button>
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onDelete();
|
|
}}
|
|
className="text-gray-400 hover:text-red-400 transition-colors p-1"
|
|
title="Delete wiki"
|
|
>
|
|
<Trash2Icon className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Summary */}
|
|
{wiki.summary && <p className="text-gray-400 text-sm mb-3 line-clamp-2">{wiki.summary}</p>}
|
|
|
|
{/* Rich text content preview */}
|
|
{wiki.content && Array.isArray(wiki.content) && wiki.content.length > 0 && (
|
|
<div className="mb-3 max-h-[120px] overflow-hidden relative">
|
|
<RichTextContent
|
|
content={wiki.content}
|
|
className="text-sm text-gray-400 line-clamp-3"
|
|
/>
|
|
{/* Fade overlay at bottom */}
|
|
<div className="absolute bottom-0 left-0 right-0 h-8 bg-gradient-to-t from-gray-800 to-transparent pointer-events-none" />
|
|
</div>
|
|
)}
|
|
|
|
{/* Footer with metadata */}
|
|
<div className="flex items-center justify-between text-xs text-gray-500 mt-3 pt-3 border-t border-gray-700">
|
|
<div className="flex items-center gap-4">
|
|
{wiki.category && (
|
|
<span className="px-2 py-1 bg-gray-700 text-gray-400 rounded">{wiki.category}</span>
|
|
)}
|
|
{wiki.tags && wiki.tags.length > 0 && <span>{wiki.tags.length} tag(s)</span>}
|
|
</div>
|
|
{wiki.updated_at && <span>{new Date(wiki.updated_at).toLocaleDateString()}</span>}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default BoardWikis;
|