← back to Hub
app/api/grant/detail/route.ts
63 lines
import { NextRequest, NextResponse } from 'next/server';
import { verifyAuth } from '@/lib/auth';
import { query } from '@/lib/db';
export const dynamic = 'force-dynamic';
export async function GET(request: NextRequest) {
const user = verifyAuth(request);
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
try {
const [
totalGrants,
grantsByStatus,
proposalCount,
newsCount,
totalCollabs,
collabsByType,
totalFunding,
upcomingDeadlines,
] = await Promise.all([
query('grant', 'SELECT COUNT(*) as count FROM grants'),
query('grant', 'SELECT status, COUNT(*) as count FROM grants GROUP BY status ORDER BY count DESC'),
query('grant', 'SELECT COUNT(*) as count FROM grant_proposals'),
query('grant', 'SELECT COUNT(*) as count FROM news_items'),
query('grant', 'SELECT COUNT(*) as count FROM collaborations'),
query('grant', 'SELECT collab_type, COUNT(*) as count FROM collaborations GROUP BY collab_type ORDER BY count DESC'),
query('grant', 'SELECT COALESCE(SUM(amount_awarded), 0) as total FROM grants WHERE amount_awarded IS NOT NULL'),
query('grant', `SELECT id, title, funder, deadline, status FROM grants WHERE deadline IS NOT NULL AND deadline > NOW() ORDER BY deadline ASC LIMIT 5`),
]);
const byStatus: Record<string, number> = {};
for (const row of grantsByStatus.rows) {
byStatus[row.status] = parseInt(row.count);
}
const byType: Record<string, number> = {};
for (const row of collabsByType.rows) {
byType[row.collab_type] = parseInt(row.count);
}
return NextResponse.json({
grants: {
total: parseInt(totalGrants.rows[0].count),
byStatus,
},
proposals: parseInt(proposalCount.rows[0].count),
news: parseInt(newsCount.rows[0].count),
collaborations: {
total: parseInt(totalCollabs.rows[0].count),
byType,
},
total_funding: parseFloat(totalFunding.rows[0].total) || 0,
upcomingDeadlines: upcomingDeadlines.rows,
});
} catch (err) {
console.error('[grant/detail] Error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to fetch Grant data' }, { status: 500 });
}
}