feat: add GET /api/projects using NextAuth + Postgres
This commit is contained in:
58
app/api/projects/route.ts
Normal file
58
app/api/projects/route.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { getServerSession } from 'next-auth';
|
||||||
|
import { authOptions } from '@/lib/auth/authOptions';
|
||||||
|
import { query } from '@/lib/db-postgres';
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const session = await getServerSession(authOptions);
|
||||||
|
if (!session?.user?.email) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const email = session.user.email;
|
||||||
|
|
||||||
|
// Fetch projects joined on user email
|
||||||
|
const projects = await query<any>(`
|
||||||
|
SELECT p.id, p.data, p.workspace, p.slug
|
||||||
|
FROM fs_projects p
|
||||||
|
JOIN fs_users u ON u.id = p.user_id
|
||||||
|
WHERE u.data->>'email' = $1
|
||||||
|
ORDER BY (p.data->>'updatedAt') DESC NULLS LAST
|
||||||
|
`, [email]);
|
||||||
|
|
||||||
|
// Fetch session stats per project
|
||||||
|
const sessionStats = await query<any>(`
|
||||||
|
SELECT
|
||||||
|
s.data->>'projectId' AS project_id,
|
||||||
|
COUNT(*)::int AS session_count,
|
||||||
|
COALESCE(SUM((s.data->>'cost')::float), 0) AS total_cost
|
||||||
|
FROM fs_sessions s
|
||||||
|
JOIN fs_users u ON u.id = s.user_id
|
||||||
|
WHERE u.data->>'email' = $1
|
||||||
|
GROUP BY s.data->>'projectId'
|
||||||
|
`, [email]);
|
||||||
|
|
||||||
|
const statsByProject = new Map(sessionStats.map((s: any) => [s.project_id, s]));
|
||||||
|
|
||||||
|
const result = projects.map((p: any) => {
|
||||||
|
const stats = statsByProject.get(p.id) || { session_count: 0, total_cost: 0 };
|
||||||
|
return {
|
||||||
|
id: p.id,
|
||||||
|
...p.data,
|
||||||
|
stats: {
|
||||||
|
sessions: stats.session_count || 0,
|
||||||
|
costs: parseFloat(stats.total_cost) || 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json({ projects: result });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[GET /api/projects] Error:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Failed to fetch projects', details: error instanceof Error ? error.message : String(error) },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user