demo login, super admin view, password reset
- Landing page: 'Try the Demo' button links to /login?demo=1 - Login page: 'Try the Demo — no signup needed' button auto-logs in as demo@pnpl.app - /login?demo=1: auto-triggers demo login on page load - Super Admin page (/dashboard/admin): platform stats, org list, user list, recent pledges - /api/admin: returns cross-org data, gated by super_admin role check - Sidebar shows 'Super Admin' link only for super_admin users - Password reset: omair@quikcue.com = Omair2026!, demo@pnpl.app = demo1234 - omair@quikcue.com confirmed as super_admin role
This commit is contained in:
99
pledge-now-pay-later/src/app/api/admin/route.ts
Normal file
99
pledge-now-pay-later/src/app/api/admin/route.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { NextResponse } from "next/server"
|
||||
import prisma from "@/lib/prisma"
|
||||
import { getUser } from "@/lib/session"
|
||||
|
||||
/**
|
||||
* GET /api/admin — Super admin overview
|
||||
* Returns all orgs, users, pledges across the entire platform.
|
||||
*/
|
||||
export async function GET() {
|
||||
const user = await getUser()
|
||||
if (!user || user.role !== "super_admin") {
|
||||
return NextResponse.json({ error: "Forbidden" }, { status: 403 })
|
||||
}
|
||||
|
||||
if (!prisma) return NextResponse.json({ error: "No DB" }, { status: 503 })
|
||||
|
||||
const [orgs, users, pledgeStats, recentPledges, eventCount] = await Promise.all([
|
||||
prisma.organization.findMany({
|
||||
select: {
|
||||
id: true, name: true, slug: true, country: true, createdAt: true,
|
||||
bankSortCode: true, bankAccountNo: true,
|
||||
_count: { select: { users: true, events: true, pledges: true } },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
}),
|
||||
prisma.user.findMany({
|
||||
select: {
|
||||
id: true, email: true, name: true, role: true, createdAt: true,
|
||||
organization: { select: { name: true } },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
}),
|
||||
prisma.pledge.groupBy({
|
||||
by: ["status"],
|
||||
_count: true,
|
||||
_sum: { amountPence: true },
|
||||
}),
|
||||
prisma.pledge.findMany({
|
||||
select: {
|
||||
id: true, reference: true, amountPence: true, status: true,
|
||||
donorName: true, createdAt: true, dueDate: true,
|
||||
event: { select: { name: true } },
|
||||
organization: { select: { name: true } },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: 20,
|
||||
}),
|
||||
prisma.event.count(),
|
||||
])
|
||||
|
||||
const totalPledgedPence = pledgeStats.reduce((s, p) => s + (p._sum.amountPence || 0), 0)
|
||||
const totalCollectedPence = pledgeStats
|
||||
.filter(p => p.status === "paid")
|
||||
.reduce((s, p) => s + (p._sum.amountPence || 0), 0)
|
||||
const totalPledgeCount = pledgeStats.reduce((s, p) => s + p._count, 0)
|
||||
|
||||
return NextResponse.json({
|
||||
platform: {
|
||||
orgs: orgs.length,
|
||||
users: users.length,
|
||||
events: eventCount,
|
||||
pledges: totalPledgeCount,
|
||||
totalPledgedPence,
|
||||
totalCollectedPence,
|
||||
collectionRate: totalPledgedPence > 0 ? Math.round((totalCollectedPence / totalPledgedPence) * 100) : 0,
|
||||
},
|
||||
orgs: orgs.map(o => ({
|
||||
id: o.id,
|
||||
name: o.name,
|
||||
slug: o.slug,
|
||||
country: o.country,
|
||||
hasBank: !!(o.bankSortCode && o.bankAccountNo),
|
||||
users: o._count.users,
|
||||
events: o._count.events,
|
||||
pledges: o._count.pledges,
|
||||
createdAt: o.createdAt,
|
||||
})),
|
||||
users: users.map(u => ({
|
||||
id: u.id,
|
||||
email: u.email,
|
||||
name: u.name,
|
||||
role: u.role,
|
||||
orgName: u.organization.name,
|
||||
createdAt: u.createdAt,
|
||||
})),
|
||||
byStatus: Object.fromEntries(pledgeStats.map(p => [p.status, { count: p._count, amount: p._sum.amountPence || 0 }])),
|
||||
recentPledges: recentPledges.map(p => ({
|
||||
id: p.id,
|
||||
reference: p.reference,
|
||||
amountPence: p.amountPence,
|
||||
status: p.status,
|
||||
donorName: p.donorName,
|
||||
eventName: p.event.name,
|
||||
orgName: p.organization.name,
|
||||
dueDate: p.dueDate,
|
||||
createdAt: p.createdAt,
|
||||
})),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user