Add admin portal

This commit is contained in:
Jose Selesan
2026-06-10 09:39:20 -03:00
parent c278c78e3d
commit c1c2f18471
50 changed files with 2713 additions and 69 deletions

View File

@@ -0,0 +1,80 @@
import { db } from '@/lib/prisma';
type ComplexStats = {
id: string;
complexName: string;
complexSlug: string;
city: string | null;
planCode: string | null;
planName: string | null;
userCount: number;
courtCount: number;
totalBookings: number;
avgBookingsPerDay: number;
bookingsByStatus: {
confirmed: number;
cancelled: number;
completed: number;
noshow: number;
};
paymentStatus: 'active' | 'no_plan' | 'expired';
};
export async function getComplexStatsList(): Promise<ComplexStats[]> {
const complexes = await db.complex.findMany({
include: {
plan: true,
users: true,
courts: {
include: {
bookings: true,
},
},
},
});
return complexes.map((complex) => {
const courtCount = complex.courts.length;
const allBookings = complex.courts.flatMap((c) => c.bookings);
const bookingsByStatus = {
confirmed: allBookings.filter((b) => b.status === 'CONFIRMED').length,
cancelled: allBookings.filter((b) => b.status === 'CANCELLED').length,
completed: allBookings.filter((b) => b.status === 'COMPLETED').length,
noshow: allBookings.filter((b) => b.status === 'NOSHOW').length,
};
const totalBookings = allBookings.length;
let avgBookingsPerDay = 0;
if (allBookings.length > 0) {
const dates = allBookings.map((b) => b.bookingDate);
const minDate = new Date(Math.min(...dates.map((d) => d.getTime())));
const daysDiff = Math.max(
1,
Math.ceil((Date.now() - minDate.getTime()) / (1000 * 60 * 60 * 24))
);
avgBookingsPerDay = Math.round((totalBookings / daysDiff) * 100) / 100;
}
let paymentStatus: 'active' | 'no_plan' | 'expired' = 'no_plan';
if (complex.plan) {
paymentStatus = 'active';
}
return {
id: complex.id,
complexName: complex.complexName,
complexSlug: complex.complexSlug,
city: complex.city,
planCode: complex.planCode,
planName: complex.plan?.name ?? null,
userCount: complex.users.length,
courtCount,
totalBookings,
avgBookingsPerDay,
bookingsByStatus,
paymentStatus,
};
});
}