forum: render threads on /forum default view (not just search mode)
Bug: the index page only fetched threads when user was actively searching, filtering by category, or sorting non-default. Default load → setThreads([]) → forum looked empty even though 50+ threads existed in the DB. Fix: always fetch on mount + filter changes (drop the isSearchMode gate on the effect), and add a Recent Threads section in the default view above the Browse Categories list, showing the 12 most recent threads with author + reply count. API + DB unchanged.
This commit is contained in:
@@ -232,27 +232,25 @@ export default function ForumIndexPage() {
|
|||||||
.catch(() => setFollowingLoading(false));
|
.catch(() => setFollowingLoading(false));
|
||||||
}, [feedMode, currentUserId]);
|
}, [feedMode, currentUserId]);
|
||||||
|
|
||||||
// Load threads when search/category/sort changes
|
// Always load threads on mount + whenever search/category/sort changes.
|
||||||
|
// (Prior version only loaded in "search mode" which left the forum
|
||||||
|
// index blank by default, hiding all threads in the DB.)
|
||||||
const isSearchMode = debouncedSearch.trim() !== '' || selectedCategory !== '' || sort !== 'newest';
|
const isSearchMode = debouncedSearch.trim() !== '' || selectedCategory !== '' || sort !== 'newest';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isSearchMode) {
|
|
||||||
setThreads([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setThreadsLoading(true);
|
setThreadsLoading(true);
|
||||||
const params = new URLSearchParams({ limit: '30', sort });
|
const params = new URLSearchParams({ limit: '30', sort });
|
||||||
if (debouncedSearch.trim()) params.set('search', debouncedSearch.trim());
|
if (debouncedSearch.trim()) params.set('search', debouncedSearch.trim());
|
||||||
if (selectedCategory) params.set('category_id', selectedCategory);
|
if (selectedCategory) params.set('category_id', selectedCategory);
|
||||||
|
|
||||||
fetch(`/api/forum/threads?${params.toString()}`)
|
fetch(`/api/forum/threads?${params.toString()}`)
|
||||||
.then(r => r.json())
|
.then((r) => r.json())
|
||||||
.then(d => {
|
.then((d) => {
|
||||||
setThreads(d.threads || []);
|
setThreads(d.threads || []);
|
||||||
setThreadsLoading(false);
|
setThreadsLoading(false);
|
||||||
})
|
})
|
||||||
.catch(() => setThreadsLoading(false));
|
.catch(() => setThreadsLoading(false));
|
||||||
}, [debouncedSearch, selectedCategory, sort, isSearchMode]);
|
}, [debouncedSearch, selectedCategory, sort]);
|
||||||
|
|
||||||
const sortOptions: { value: SortOption; label: string }[] = [
|
const sortOptions: { value: SortOption; label: string }[] = [
|
||||||
{ value: 'newest', label: 'Newest' },
|
{ value: 'newest', label: 'Newest' },
|
||||||
@@ -527,6 +525,39 @@ export default function ForumIndexPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Recent Threads — newest first across all categories */}
|
||||||
|
{!loading && !error && threads.length > 0 && (
|
||||||
|
<div className="mb-8">
|
||||||
|
<h2 className="text-white font-heading font-bold text-base mb-3">Recent Threads</h2>
|
||||||
|
<div className="space-y-1">
|
||||||
|
{threads.slice(0, 12).map((thread) => (
|
||||||
|
<Link
|
||||||
|
key={thread.id}
|
||||||
|
href={`/forum/thread/${thread.id}`}
|
||||||
|
className="flex items-center gap-4 bg-[#1a1a1a] hover:bg-[#1e2a3a] border border-[#252525] hover:border-[#3b82f6] rounded-lg px-4 py-3 transition-all group"
|
||||||
|
>
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<h3 className="text-white font-body font-semibold text-sm group-hover:text-[#3b82f6] transition-colors truncate">
|
||||||
|
{thread.title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-[#666] font-body text-xs mt-0.5">
|
||||||
|
by <Link href={`/forum/user/${encodeURIComponent(thread.author_name)}`} className="text-[#888] hover:text-[#3b82f6] hover:underline" onClick={(e) => e.stopPropagation()}>{thread.author_name}</Link>
|
||||||
|
{thread.forum_categories && (
|
||||||
|
<> · <span className="text-[#3b82f6]">{thread.forum_categories.name}</span></>
|
||||||
|
)}
|
||||||
|
{' · '}{timeAgo(thread.last_reply_at || thread.created_at)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex-shrink-0 text-right hidden sm:block">
|
||||||
|
<div className="text-[#aaa] font-body text-sm font-semibold">{thread.reply_count}</div>
|
||||||
|
<div className="text-[#555] font-body text-xs">replies</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{!loading && !error && (
|
{!loading && !error && (
|
||||||
<>
|
<>
|
||||||
<h2 className="text-white font-heading font-bold text-base mb-3">Browse Categories</h2>
|
<h2 className="text-white font-heading font-bold text-base mb-3">Browse Categories</h2>
|
||||||
|
|||||||
Reference in New Issue
Block a user