Files
GibSend/apps/web/src/server/api/routers/email.ts
2025-05-11 23:34:21 +10:00

101 lines
2.7 KiB
TypeScript

import { Email, EmailStatus, Prisma } from "@prisma/client";
import { format, subDays } from "date-fns";
import { z } from "zod";
import { DEFAULT_QUERY_LIMIT } from "~/lib/constants";
import {
createTRPCRouter,
emailProcedure,
teamProcedure,
} from "~/server/api/trpc";
import { db } from "~/server/db";
import { cancelEmail, updateEmail } from "~/server/service/email-service";
const statuses = Object.values(EmailStatus) as [EmailStatus];
export const emailRouter = createTRPCRouter({
emails: teamProcedure
.input(
z.object({
page: z.number().optional(),
status: z.enum(statuses).optional().nullable(),
domain: z.number().optional(),
search: z.string().optional().nullable(),
apiId: z.number().optional(),
})
)
.query(async ({ ctx, input }) => {
const page = input.page || 1;
const limit = DEFAULT_QUERY_LIMIT;
const offset = (page - 1) * limit;
const emails = await db.$queryRaw<Array<Email>>`
SELECT
id,
"createdAt",
"latestStatus",
subject,
"to",
"scheduledAt"
FROM "Email"
WHERE "teamId" = ${ctx.team.id}
${input.status ? Prisma.sql`AND "latestStatus"::text = ${input.status}` : Prisma.sql``}
${input.domain ? Prisma.sql`AND "domainId" = ${input.domain}` : Prisma.sql``}
${input.apiId ? Prisma.sql`AND "apiId" = ${input.apiId}` : Prisma.sql``}
${
input.search
? Prisma.sql`AND (
"subject" ILIKE ${`%${input.search}%`}
OR EXISTS (
SELECT 1 FROM unnest("to") AS email
WHERE email ILIKE ${`%${input.search}%`}
)
)`
: Prisma.sql``
}
ORDER BY "createdAt" DESC
LIMIT ${DEFAULT_QUERY_LIMIT}
OFFSET ${offset}
`;
return { emails };
}),
getEmail: emailProcedure.query(async ({ input }) => {
const email = await db.email.findUnique({
where: {
id: input.id,
},
select: {
emailEvents: {
orderBy: {
status: "desc",
},
},
id: true,
createdAt: true,
latestStatus: true,
subject: true,
to: true,
from: true,
domainId: true,
text: true,
html: true,
scheduledAt: true,
},
});
return email;
}),
cancelEmail: emailProcedure.mutation(async ({ input }) => {
await cancelEmail(input.id);
}),
updateEmailScheduledAt: emailProcedure
.input(z.object({ scheduledAt: z.string().datetime() }))
.mutation(async ({ input }) => {
await updateEmail(input.id, { scheduledAt: input.scheduledAt });
}),
});