Files
avbeat-com/src/app/api/forum/user-profile/route.ts
2026-05-07 16:39:17 +00:00

90 lines
3.0 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase/server';
export async function GET(req: NextRequest) {
try {
const supabase = await createClient();
const { searchParams } = new URL(req.url);
const userId = searchParams.get('user_id');
if (!userId) {
return NextResponse.json({ error: 'user_id is required' }, { status: 400 });
}
// Fetch user profile
const { data: profile, error: profileError } = await supabase
.from('user_profiles')
.select('id, full_name, avatar_url, bio, website, location, reputation, created_at')
.eq('id', userId)
.single();
if (profileError || !profile) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
// Fetch user's threads (post history)
const { data: threads } = await supabase
.from('forum_threads')
.select('id, title, body, vote_score, upvotes, reply_count, view_count, created_at, forum_categories(id, name, slug)')
.eq('author_id', userId)
.order('created_at', { ascending: false })
.limit(50);
// Fetch user's replies
const { data: replies } = await supabase
.from('forum_replies')
.select('id, body, vote_score, upvotes, created_at, thread_id, forum_threads(id, title)')
.eq('author_id', userId)
.order('created_at', { ascending: false })
.limit(50);
// Top threads by vote score
const topThreads = [...(threads || [])]
.sort((a, b) => (b.vote_score || 0) - (a.vote_score || 0))
.slice(0, 5);
// Contributions by category
const categoryMap: Record<string, { name: string; slug: string; count: number }> = {};
(threads || []).forEach((t: any) => {
const cat = t.forum_categories;
if (cat) {
if (!categoryMap[cat.id]) {
categoryMap[cat.id] = { name: cat.name, slug: cat.slug, count: 0 };
}
categoryMap[cat.id].count++;
}
});
const contributionsByCategory = Object.values(categoryMap).sort((a, b) => b.count - a.count);
// Stats
const totalThreads = (threads || []).length;
const totalReplies = (replies || []).length;
const totalUpvotesReceived = (threads || []).reduce((sum: number, t: any) => sum + (t.upvotes || 0), 0)
+ (replies || []).reduce((sum: number, r: any) => sum + (r.upvotes || 0), 0);
// Fetch earned badges
const { data: badges } = await supabase
.from('user_badges')
.select('badge_type, awarded_at, awarded_reason')
.eq('user_id', userId)
.order('awarded_at', { ascending: true });
return NextResponse.json({
profile,
threads: threads || [],
replies: replies || [],
topThreads,
contributionsByCategory,
badges: badges || [],
stats: {
totalThreads,
totalReplies,
totalPosts: totalThreads + totalReplies,
totalUpvotesReceived,
},
});
} catch (err: any) {
return NextResponse.json({ error: err.message }, { status: 500 });
}
}