Simplify admin stats
This commit is contained in:
parent
5f80ec4570
commit
a2bc6b6857
1 changed files with 12 additions and 111 deletions
|
|
@ -2,127 +2,28 @@ import { NextResponse } from "next/server";
|
|||
import { requireAdmin } from "@/lib/admin-auth";
|
||||
import { sql } from "@/db";
|
||||
|
||||
// Get stats from database
|
||||
export async function GET(request: Request) {
|
||||
const auth = await requireAdmin(request);
|
||||
if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });
|
||||
|
||||
try {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const period = searchParams.get("period") || "30"; // days
|
||||
|
||||
// Get total counts
|
||||
const familyCount = await sql`SELECT COUNT(*) as count FROM families`;
|
||||
const userCount = await sql`SELECT COUNT(*) as count FROM users`;
|
||||
const childCount = await sql`SELECT COUNT(*) as count FROM children`;
|
||||
|
||||
// Get tier breakdown
|
||||
const tierStats = await sql`
|
||||
SELECT tier, COUNT(*) as count
|
||||
FROM families
|
||||
GROUP BY tier
|
||||
`;
|
||||
const familyCount = await sql`SELECT COUNT(*)::int as count FROM families`;
|
||||
const userCount = await sql`SELECT COUNT(*)::int as count FROM users`;
|
||||
const childCount = await sql`SELECT COUNT(*)::int as count FROM children`;
|
||||
const tierStats = await sql`SELECT tier, COUNT(*)::int as count FROM families GROUP BY tier`;
|
||||
|
||||
const proFamilies = tierStats.find((t: any) => t.tier === "pro")?.count || 0;
|
||||
const freeFamilies = tierStats.find((t: any) => t.tier === "free")?.count || 0;
|
||||
const mrr = proFamilies * 9.99;
|
||||
|
||||
// Get MRR (assuming $9.99/month for pro)
|
||||
const PRO_PRICE = 9.99;
|
||||
const mrr = proFamilies * PRO_PRICE;
|
||||
|
||||
// Get new families by day (last N days)
|
||||
const newFamilies = await sql`
|
||||
SELECT DATE(created_at) as date, COUNT(*) as count
|
||||
FROM families
|
||||
WHERE created_at > NOW() - INTERVAL '${sql(period)} days'
|
||||
GROUP BY DATE(created_at)
|
||||
ORDER BY date
|
||||
`;
|
||||
|
||||
// Get new users by day
|
||||
const newUsers = await sql`
|
||||
SELECT DATE(created_at) as date, COUNT(*) as count
|
||||
FROM users
|
||||
WHERE created_at > NOW() - INTERVAL '${sql(period)} days'
|
||||
GROUP BY DATE(created_at)
|
||||
ORDER BY date
|
||||
`;
|
||||
|
||||
// Get children by age group
|
||||
const childrenByAge = await sql`
|
||||
SELECT
|
||||
CASE
|
||||
WHEN AGE(birth_date) < INTERVAL '1 year' THEN '0-1'
|
||||
WHEN AGE(birth_date) < INTERVAL '2 years' THEN '1-2'
|
||||
WHEN AGE(birth_date) < INTERVAL '3 years' THEN '2-3'
|
||||
WHEN AGE(birth_date) < INTERVAL '4 years' THEN '3-4'
|
||||
WHEN AGE(birth_date) < INTERVAL '5 years' THEN '4-5'
|
||||
ELSE '5+'
|
||||
END as age_group,
|
||||
COUNT(*) as count
|
||||
FROM children
|
||||
GROUP BY age_group
|
||||
ORDER BY age_group
|
||||
`;
|
||||
|
||||
// For now, return mock data structure if tables are empty
|
||||
const stats = {
|
||||
overview: {
|
||||
totalFamilies: familyCount[0]?.count || 0,
|
||||
totalUsers: userCount[0]?.count || 0,
|
||||
totalChildren: childCount[0]?.count || 0,
|
||||
proFamilies,
|
||||
freeFamilies,
|
||||
mrr: Number(mrr.toFixed(2)),
|
||||
avgRevenuePerUser: proFamilies > 0 ? Number((mrr / (proFamilies + freeFamilies)).toFixed(2)) : 0,
|
||||
},
|
||||
conversions: {
|
||||
freeToPro: 0, // Track upgrades
|
||||
conversionRate: freeFamilies > 0 ? Number(((proFamilies / (proFamilies + freeFamilies)) * 100).toFixed(1)) : 0,
|
||||
},
|
||||
growth: {
|
||||
familiesByDay: newFamilies.length > 0 ? newFamilies.map((r: any) => ({
|
||||
date: r.date,
|
||||
count: Number(r.count),
|
||||
})) : [
|
||||
{ date: new Date().toISOString().split("T")[0], count: 0 },
|
||||
],
|
||||
usersByDay: newUsers.length > 0 ? newUsers.map((r: any) => ({
|
||||
date: r.date,
|
||||
count: Number(r.count),
|
||||
})) : [
|
||||
{ date: new Date().toISOString().split("T")[0], count: 0 },
|
||||
],
|
||||
},
|
||||
childrenByAge: childrenByAge.length > 0 ? childrenByAge.map((r: any) => ({
|
||||
ageGroup: r.age_group,
|
||||
count: Number(r.count),
|
||||
})) : [],
|
||||
};
|
||||
|
||||
return NextResponse.json(stats);
|
||||
return NextResponse.json({
|
||||
overview: { totalFamilies: familyCount[0]?.count || 0, totalUsers: userCount[0]?.count || 0, totalChildren: childCount[0]?.count || 0, proFamilies, freeFamilies, mrr, avgRevenuePerUser: 0 },
|
||||
conversions: { freeToPro: 0, conversionRate: 0 },
|
||||
growth: { familiesByDay: [], usersByDay: [] },
|
||||
childrenByAge: []
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Admin stats error:", error);
|
||||
// Return empty stats on error
|
||||
return NextResponse.json({
|
||||
overview: {
|
||||
totalFamilies: 0,
|
||||
totalUsers: 0,
|
||||
totalChildren: 0,
|
||||
proFamilies: 0,
|
||||
freeFamilies: 0,
|
||||
mrr: 0,
|
||||
avgRevenuePerUser: 0,
|
||||
},
|
||||
conversions: {
|
||||
freeToPro: 0,
|
||||
conversionRate: 0,
|
||||
},
|
||||
growth: {
|
||||
familiesByDay: [],
|
||||
usersByDay: [],
|
||||
},
|
||||
childrenByAge: [],
|
||||
});
|
||||
return NextResponse.json({ error: String(error) }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue