import { useState, useMemo, useCallback } from 'react'; import { formatDateTime } from '../../utils/format'; import type { ForumThread, ForumReply } from '../../types'; export default function IntranetModeration() { const [threads, setThreads] = useState([]); const [replies, setReplies] = useState([]); const [selectedThreadId, setSelectedThreadId] = useState(null); const [search, setSearch] = useState(''); const [activeTab, setActiveTab] = useState<'threads' | 'replies'>('threads'); const filteredThreads = useMemo(() => { if (!search.trim()) return threads; const q = search.toLowerCase(); return threads.filter((t) => t.title.toLowerCase().includes(q) || t.authorName.toLowerCase().includes(q)); }, [threads, search]); const selectedThreadReplies = useMemo(() => { if (!selectedThreadId) return []; return replies.filter((r) => r.threadId === selectedThreadId); }, [replies, selectedThreadId]); const deleteThread = useCallback((id: string) => { setThreads((prev) => prev.filter((t) => t.id !== id)); setReplies((prev) => prev.filter((r) => r.threadId !== id)); if (selectedThreadId === id) setSelectedThreadId(null); }, [selectedThreadId]); const togglePin = useCallback((id: string) => { setThreads((prev) => prev.map((t) => t.id === id ? { ...t, isPinned: !t.isPinned } : t)); }, []); const toggleLock = useCallback((id: string) => { setThreads((prev) => prev.map((t) => t.id === id ? { ...t, isLocked: !t.isLocked } : t)); }, []); const deleteReply = useCallback((id: string) => { setReplies((prev) => prev.filter((r) => r.id !== id)); }, []); const recentReplies = useMemo(() => { return [...replies].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()).slice(0, 20); }, [replies]); return (
INTRANET / MODERATION

FORUM MODERATION

{threads.length} threads — {replies.length} replies

{/* Tabs */}
{(['threads', 'replies'] as const).map((tab) => ( ))}
{activeTab === 'threads' && (
{/* Thread list */}
setSearch(e.target.value)} style={{ marginBottom: '1rem', maxWidth: '300px' }} />
{filteredThreads.map((thread) => (
{thread.isPinned && Pinned} {thread.isLocked && Locked}
{thread.title}
by {thread.authorName} — {thread.categoryName} — {thread.replyCount} replies
))} {filteredThreads.length === 0 && (
No threads found.
)}
{/* Thread replies panel */} {selectedThreadId && (
REPLIES ({selectedThreadReplies.length})
{selectedThreadReplies.length === 0 ? (
No replies.
) : (
{selectedThreadReplies.map((reply) => (
{reply.authorName}
{reply.content.slice(0, 150)}{reply.content.length > 150 ? '...' : ''}
))}
)}
)}
)} {activeTab === 'replies' && (
{recentReplies.map((reply) => { const thread = threads.find((t) => t.id === reply.threadId); return (
by {reply.authorName} {thread && <> in {thread.title}} {' '}— {formatDateTime(reply.createdAt)}
{reply.content}
); })} {recentReplies.length === 0 && (
No replies found.
)}
)}
); }