mirror of
https://github.com/oiov/wr.do.git
synced 2026-05-15 18:19:44 +08:00
301 lines
8.1 KiB
TypeScript
301 lines
8.1 KiB
TypeScript
import { prisma } from "@/lib/db";
|
|
import { checkUserStatus } from "@/lib/dto/user";
|
|
import { TIME_RANGES } from "@/lib/enums";
|
|
import { getCurrentUser } from "@/lib/session";
|
|
import { getStartDate } from "@/lib/utils";
|
|
|
|
export const revalidate = 60;
|
|
|
|
export async function GET(req: Request) {
|
|
try {
|
|
const user = checkUserStatus(await getCurrentUser());
|
|
if (user instanceof Response) return user;
|
|
if (user.role !== "ADMIN") {
|
|
return Response.json("Unauthorized", {
|
|
status: 401,
|
|
statusText: "Unauthorized",
|
|
});
|
|
}
|
|
|
|
const url = new URL(req.url);
|
|
const range = url.searchParams.get("range") || "7d";
|
|
|
|
const startDate = getStartDate(range);
|
|
if (!startDate) {
|
|
return Response.json({ statusText: "Invalid range" }, { status: 400 });
|
|
}
|
|
|
|
// Calculate previous period start and end dates
|
|
const rangeDuration = TIME_RANGES[range];
|
|
const prevStartDate = new Date(startDate.getTime() - rangeDuration);
|
|
const prevEndDate = startDate;
|
|
|
|
const users = await prisma.user.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: startDate,
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
const records = await prisma.userRecord.findMany({
|
|
where: {
|
|
created_on: {
|
|
gte: startDate,
|
|
},
|
|
},
|
|
orderBy: {
|
|
created_on: "desc",
|
|
},
|
|
select: {
|
|
created_on: true,
|
|
},
|
|
});
|
|
const urls = await prisma.userUrl.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: startDate,
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
const emails = await prisma.userEmail.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: startDate,
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
const inbox = await prisma.forwardEmail.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: startDate,
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
const sends = await prisma.userSendEmail.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: startDate,
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
|
|
// Fetch previous period data
|
|
const prevUsers = await prisma.user.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: prevStartDate,
|
|
lt: prevEndDate,
|
|
},
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
const prevRecords = await prisma.userRecord.findMany({
|
|
where: {
|
|
created_on: {
|
|
gte: prevStartDate,
|
|
lt: prevEndDate,
|
|
},
|
|
},
|
|
select: {
|
|
created_on: true,
|
|
},
|
|
});
|
|
const prevUrls = await prisma.userUrl.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: prevStartDate,
|
|
lt: prevEndDate,
|
|
},
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
const prevEmails = await prisma.userEmail.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: prevStartDate,
|
|
lt: prevEndDate,
|
|
},
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
const prevInbox = await prisma.forwardEmail.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: prevStartDate,
|
|
lt: prevEndDate,
|
|
},
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
const prevSends = await prisma.userSendEmail.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: prevStartDate,
|
|
lt: prevEndDate,
|
|
},
|
|
},
|
|
select: {
|
|
createdAt: true,
|
|
},
|
|
});
|
|
|
|
// Process current period data
|
|
const userCountByDate: { [date: string]: number } = {};
|
|
const recordCountByDate: { [date: string]: number } = {};
|
|
const urlCountByDate: { [date: string]: number } = {};
|
|
const emailCountByDate: { [date: string]: number } = {};
|
|
const inboxCountByDate: { [date: string]: number } = {};
|
|
const sendCountByDate: { [date: string]: number } = {};
|
|
|
|
users.forEach((user) => {
|
|
const date = user.createdAt!.toISOString().split("T")[0];
|
|
userCountByDate[date] = (userCountByDate[date] || 0) + 1;
|
|
});
|
|
records.forEach((record) => {
|
|
const date = record.created_on!.toISOString().split("T")[0];
|
|
recordCountByDate[date] = (recordCountByDate[date] || 0) + 1;
|
|
});
|
|
urls.forEach((url) => {
|
|
const date = url.createdAt.toISOString().split("T")[0];
|
|
urlCountByDate[date] = (urlCountByDate[date] || 0) + 1;
|
|
});
|
|
emails.forEach((email) => {
|
|
const date = email.createdAt.toISOString().split("T")[0];
|
|
emailCountByDate[date] = (emailCountByDate[date] || 0) + 1;
|
|
});
|
|
inbox.forEach((email) => {
|
|
const date = email.createdAt.toISOString().split("T")[0];
|
|
inboxCountByDate[date] = (inboxCountByDate[date] || 0) + 1;
|
|
});
|
|
sends.forEach((send) => {
|
|
const date = send.createdAt.toISOString().split("T")[0];
|
|
sendCountByDate[date] = (sendCountByDate[date] || 0) + 1;
|
|
});
|
|
|
|
const allDates = Array.from(
|
|
new Set([
|
|
...Object.keys(userCountByDate),
|
|
...Object.keys(recordCountByDate),
|
|
...Object.keys(urlCountByDate),
|
|
...Object.keys(emailCountByDate),
|
|
...Object.keys(inboxCountByDate),
|
|
...Object.keys(sendCountByDate),
|
|
]),
|
|
);
|
|
const combinedData = allDates.map((date) => ({
|
|
date,
|
|
records: recordCountByDate[date] || 0,
|
|
urls: urlCountByDate[date] || 0,
|
|
users: userCountByDate[date] || 0,
|
|
emails: emailCountByDate[date] || 0,
|
|
inbox: inboxCountByDate[date] || 0,
|
|
sends: sendCountByDate[date] || 0,
|
|
}));
|
|
|
|
const total = {
|
|
records: combinedData.reduce((acc, curr) => acc + curr.records, 0),
|
|
urls: combinedData.reduce((acc, curr) => acc + curr.urls, 0),
|
|
users: combinedData.reduce((acc, curr) => acc + curr.users, 0),
|
|
emails: combinedData.reduce((acc, curr) => acc + curr.emails, 0),
|
|
inbox: combinedData.reduce((acc, curr) => acc + curr.inbox, 0),
|
|
sends: combinedData.reduce((acc, curr) => acc + curr.sends, 0),
|
|
};
|
|
|
|
// Calculate totals for previous period
|
|
const prevTotal = {
|
|
records: prevRecords.length,
|
|
urls: prevUrls.length,
|
|
users: prevUsers.length,
|
|
emails: prevEmails.length,
|
|
inbox: prevInbox.length,
|
|
sends: prevSends.length,
|
|
};
|
|
|
|
// Calculate growth rates
|
|
const growthRates = {
|
|
records:
|
|
prevTotal.records === 0
|
|
? total.records > 0
|
|
? 100
|
|
: 0
|
|
: ((total.records - prevTotal.records) / prevTotal.records) * 100,
|
|
urls:
|
|
prevTotal.urls === 0
|
|
? total.urls > 0
|
|
? 100
|
|
: 0
|
|
: ((total.urls - prevTotal.urls) / prevTotal.urls) * 100,
|
|
users:
|
|
prevTotal.users === 0
|
|
? total.users > 0
|
|
? 100
|
|
: 0
|
|
: ((total.users - prevTotal.users) / prevTotal.users) * 100,
|
|
emails:
|
|
prevTotal.emails === 0
|
|
? total.emails > 0
|
|
? 100
|
|
: 0
|
|
: ((total.emails - prevTotal.emails) / prevTotal.emails) * 100,
|
|
inbox:
|
|
prevTotal.inbox === 0
|
|
? total.inbox > 0
|
|
? 100
|
|
: 0
|
|
: ((total.inbox - prevTotal.inbox) / prevTotal.inbox) * 100,
|
|
sends:
|
|
prevTotal.sends === 0
|
|
? total.sends > 0
|
|
? 100
|
|
: 0
|
|
: ((total.sends - prevTotal.sends) / prevTotal.sends) * 100,
|
|
};
|
|
|
|
return Response.json({
|
|
list: combinedData.reverse(),
|
|
total,
|
|
growthRates,
|
|
});
|
|
} catch (error) {
|
|
return Response.json({ statusText: "Server error" }, { status: 500 });
|
|
}
|
|
}
|