diff --git a/src/app/api/forum/categories/route.ts b/src/app/api/forum/categories/route.ts index 0ad7cd4..b73adfc 100644 --- a/src/app/api/forum/categories/route.ts +++ b/src/app/api/forum/categories/route.ts @@ -4,13 +4,42 @@ import { createClient } from '@/lib/supabase/server'; export async function GET() { try { const supabase = await createClient(); - const { data, error } = await supabase + const { data: cats, error } = await supabase .from('forum_categories') .select('*') .order('display_order', { ascending: true }); if (error) throw error; - return NextResponse.json({ categories: data }); + + // Latest thread per category — joined client-side so we keep one + // round-trip per category instead of N+1. Each cat ends up with + // last_thread_title + last_activity_at attached. + const catIds = (cats || []).map((c: any) => c.id); + let lastByCat: Record = {}; + if (catIds.length) { + const { data: latest } = await supabase + .from('forum_threads') + .select('id, category_id, title, last_reply_at, created_at') + .in('category_id', catIds) + .order('last_reply_at', { ascending: false, nullsFirst: false }) + .limit(2000); + for (const t of latest || []) { + const k = t.category_id as string; + if (!lastByCat[k]) { + lastByCat[k] = { + title: t.title, + at: t.last_reply_at || t.created_at, + }; + } + } + } + const enriched = (cats || []).map((c: any) => ({ + ...c, + last_thread_title: lastByCat[c.id]?.title || null, + last_activity_at: lastByCat[c.id]?.at || null, + })); + + return NextResponse.json({ categories: enriched }); } catch (err: any) { return NextResponse.json({ error: err.message }, { status: 500 }); } diff --git a/src/app/forum/page.tsx b/src/app/forum/page.tsx index 6b2ea0e..ebb4fde 100644 --- a/src/app/forum/page.tsx +++ b/src/app/forum/page.tsx @@ -17,6 +17,8 @@ interface ForumCategory { thread_count: number; post_count: number; display_order: number; + last_thread_title?: string | null; + last_activity_at?: string | null; } interface ForumThread { @@ -549,38 +551,10 @@ export default function ForumIndexPage() { )} - {/* Recent Threads — newest first across all categories */} - {!loading && !error && threads.length > 0 && ( -
-

Recent Threads

-
- {threads.slice(0, 12).map((thread) => ( - -
-

- {thread.title} -

-

- by e.stopPropagation()}>{thread.author_name} - {thread.forum_categories && ( - <> · {thread.forum_categories.name} - )} - {' · '}{timeAgo(thread.last_reply_at || thread.created_at)} -

-
-
-
{thread.reply_count}
-
replies
-
- - ))} -
-
- )} + {/* "Recent Threads" widget removed per Ryan — users can drill + into a category to see latest-first ordering. Each category + card now surfaces the last-post title + timestamp inline so + the homepage glance still shows activity. */} {!loading && !error && ( <> @@ -598,6 +572,15 @@ export default function ForumIndexPage() { {cat.name}

{cat.description}

+ {cat.last_thread_title && ( +

+ Last post:{' '} + {cat.last_thread_title} + {cat.last_activity_at && ( + · {timeAgo(cat.last_activity_at)} + )} +

+ )}
{cat.thread_count}