initial commit: rocket.new export of broadcastbeat
This commit is contained in:
89
src/app/api/forum/user-profile/route.ts
Normal file
89
src/app/api/forum/user-profile/route.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
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 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user