dvijaykrishnan's picture
feat: Implement admin management for product requests and affiliate proposals, including new database migrations and expanded dashboard statistics.
7bb5991
Raw
History Blame Contribute Delete
2.47 kB
"use server";
import { db } from "@/lib/db";
import {
users,
youtubeVideos,
detectedObjects,
interestPledges,
productRequests,
affiliateProposals,
} from "@/lib/db/schema";
import { count, eq, sql } from "drizzle-orm";
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
/**
* Ensures the user is an authorized admin.
* Uses ADMIN_EMAILS from environment variables.
*/
async function ensureAdmin() {
const session = await auth.api.getSession({
headers: await headers()
});
const adminEmails = process.env.ADMIN_EMAILS?.split(",") || [];
if (!session?.user?.email || !adminEmails.includes(session.user.email)) {
throw new Error("Unauthorized");
}
}
export async function getAdminStats() {
await ensureAdmin();
const [userCount] = await db.select({ count: count() }).from(users);
const [pendingAnalysis] = await db.select({ count: count() }).from(youtubeVideos).where(eq(youtubeVideos.scanStatus, 'pending_analysis'));
const [awaitingApproval] = await db.select({ count: count() }).from(youtubeVideos).where(eq(youtubeVideos.scanStatus, 'awaiting_approval'));
const [totalProducts] = await db.select({ count: count() }).from(detectedObjects);
// Interest Items: Detections with 1+ "I want this" requests
const interestCount = await db
.select({ count: sql<number>`count(distinct ${detectedObjects.id})` })
.from(detectedObjects)
.innerJoin(interestPledges, eq(detectedObjects.id, interestPledges.detectedObjectId))
.groupBy(detectedObjects.id)
.having(sql`count(${interestPledges.id}) >= 1`);
// Pending Community Requests
const [pendingRequests] = await db.select({ count: count() })
.from(productRequests)
.where(eq(productRequests.status, 'PENDING'));
// Pending Affiliate Proposals
const [pendingProposals] = await db.select({ count: count() })
.from(affiliateProposals)
.where(eq(affiliateProposals.status, 'PENDING'));
return {
totalUsers: Number(userCount.count),
pendingAnalysis: Number(pendingAnalysis.count),
awaitingApproval: Number(awaitingApproval.count),
totalProducts: Number(totalProducts.count),
highInterestItems: interestCount.length,
pendingRequests: Number(pendingRequests.count),
pendingProposals: Number(pendingProposals.count),
};
}