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 { requireAdmin } from "@/lib/admin-auth";
|
||||||
import { sql } from "@/db";
|
import { sql } from "@/db";
|
||||||
|
|
||||||
// Get stats from database
|
|
||||||
export async function GET(request: Request) {
|
export async function GET(request: Request) {
|
||||||
const auth = await requireAdmin(request);
|
const auth = await requireAdmin(request);
|
||||||
if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });
|
if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { searchParams } = new URL(request.url);
|
const familyCount = await sql`SELECT COUNT(*)::int as count FROM families`;
|
||||||
const period = searchParams.get("period") || "30"; // days
|
const userCount = await sql`SELECT COUNT(*)::int as count FROM users`;
|
||||||
|
const childCount = await sql`SELECT COUNT(*)::int as count FROM children`;
|
||||||
// Get total counts
|
const tierStats = await sql`SELECT tier, COUNT(*)::int as count FROM families GROUP BY tier`;
|
||||||
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 proFamilies = tierStats.find((t: any) => t.tier === "pro")?.count || 0;
|
const proFamilies = tierStats.find((t: any) => t.tier === "pro")?.count || 0;
|
||||||
const freeFamilies = tierStats.find((t: any) => t.tier === "free")?.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)
|
return NextResponse.json({
|
||||||
const PRO_PRICE = 9.99;
|
overview: { totalFamilies: familyCount[0]?.count || 0, totalUsers: userCount[0]?.count || 0, totalChildren: childCount[0]?.count || 0, proFamilies, freeFamilies, mrr, avgRevenuePerUser: 0 },
|
||||||
const mrr = proFamilies * PRO_PRICE;
|
conversions: { freeToPro: 0, conversionRate: 0 },
|
||||||
|
growth: { familiesByDay: [], usersByDay: [] },
|
||||||
// Get new families by day (last N days)
|
childrenByAge: []
|
||||||
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);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Admin stats error:", error);
|
console.error("Admin stats error:", error);
|
||||||
// Return empty stats on error
|
return NextResponse.json({ error: String(error) }, { status: 500 });
|
||||||
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: [],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue