refactor: update email service functions and add delete all user emails functionality

This commit is contained in:
Marco Pedone 2025-12-29 16:00:57 +01:00
parent c1a383bd2d
commit a0d5faf972
5 changed files with 87 additions and 31 deletions

View file

@ -38,7 +38,7 @@ export const EmailAccordion = ({
const iframeHeight = mobile ? 600 : 500;
return (
<div className="mx-auto py-4">
<div className="mx-auto w-full py-4">
<Accordion
className="space-y-4"
collapsible

View file

@ -1,11 +1,21 @@
import { MoreVertical, Trash2 } from "lucide-react";
import type { GetServerSideProps } from "next";
import toast from "react-hot-toast";
import { EmailAccordion } from "~/components/area-riservata/comunicazioni";
import { Confirm } from "~/components/confirm";
import { AreaRiservataLayoutUserView } from "~/components/Layout";
import { Button } from "~/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import type { NextPageWithLayout } from "~/pages/_app";
import { useEnforcedSession } from "~/providers/SessionProvider";
import type { UsersId } from "~/schemas/public/Users";
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
import { zUserId } from "~/server/utils/zod_types";
import { api } from "~/utils/api";
type ComunicazioniUserProps = {
userId: UsersId;
@ -15,17 +25,54 @@ const ComunicazioniUser: NextPageWithLayout<ComunicazioniUserProps> = ({
userId,
}: ComunicazioniUserProps) => {
const { user } = useEnforcedSession();
return (
<main className="flex flex-1 flex-col items-start gap-4 md:gap-8">
<div className="grid w-full auto-rows-max items-start gap-2 md:gap-4">
<div className="overflow-auto border-none">
<h3 className="font-bold text-2xl">Comunicazioni</h3>
const utils = api.useUtils();
const { mutate } = api.comunicazioni.deleteAllUserEmails.useMutation({
onError: (error) => {
console.error(error);
toast.error("Errore durante l'eliminazione delle comunicazioni");
},
onSuccess: async () => {
toast.success("Comunicazioni eliminate");
await utils.comunicazioni.getEmails.invalidate({ userId });
},
});
return (
<main className="flex flex-1 flex-col items-start gap-4">
<div className="flex w-full items-center justify-between">
<h3 className="font-bold text-2xl">Comunicazioni</h3>
<Popover>
<PopoverTrigger asChild>
<Button size="sm">
<MoreVertical />
</Button>
</PopoverTrigger>
<PopoverContent
align="end"
className="flex w-fit flex-col items-center gap-4"
>
<Confirm
description="Sei sicuro di voler eliminare tutte le comunicazioni?"
onConfirm={() => {
mutate({ userId });
}}
title="Elimina tutte le comunicazioni"
>
<Button
aria-label="Delete Comunicazioni"
className="w-full"
size="sm"
variant="destructive"
>
<Trash2 />
<span>Elimina tutto</span>
</Button>
</Confirm>
</PopoverContent>
</Popover>
</div>
<div className="w-full py-4">
<EmailAccordion isAdmin={user.isAdmin} userId={userId} />
</div>
</div>
</div>
</main>
);
};

View file

@ -5,7 +5,11 @@ import {
createTRPCRouter,
protectedProcedure,
} from "~/server/api/trpc";
import { DeleteEmail, GetEmails } from "~/server/services/email.service";
import {
deleteAllUserEmails,
deleteEmail,
getEmails,
} from "~/server/services/email.service";
import { NewMail } from "~/server/services/mailer";
import { zUserId } from "~/server/utils/zod_types";
@ -24,7 +28,7 @@ export const comunicazioniRouter = createTRPCRouter({
getEmails: protectedProcedure
.input(z.object({ userId: zUserId }))
.query(async ({ input }) => {
return await GetEmails({
return await getEmails({
userId: input.userId,
});
}),
@ -35,23 +39,17 @@ export const comunicazioniRouter = createTRPCRouter({
}),
)
.mutation(async ({ input }) => {
return await DeleteEmail({
return await deleteEmail({
id_email: input.id_email,
});
}),
// storeEmail: publicProcedure
// .input(
// z.object({
// data: z.custom<MailsTemplates>(),
// userId: zUserId,
// }),
// )
// .mutation(async ({ input }) => {
// return await StoreEmail({
// data: input.data,
// userId: input.userId,
// });
// }),
deleteAllUserEmails: adminProcedure
.input(z.object({ userId: zUserId }))
.mutation(async ({ input }) => {
return await deleteAllUserEmails({
userId: input.userId,
});
}),
sendSchedaAnnuncioEmail: adminProcedure
.input(
z.object({

View file

@ -4,7 +4,7 @@ import type { UsersId } from "~/schemas/public/Users";
import { db } from "~/server/db";
import { genMail, type MailsTemplates } from "~/server/services/mailer";
export const StoreEmail = async ({
export const storeEmail = async ({
userId,
data,
}: {
@ -28,7 +28,7 @@ export const StoreEmail = async ({
}
};
export const GetEmails = async ({ userId }: { userId: UsersId }) => {
export const getEmails = async ({ userId }: { userId: UsersId }) => {
try {
const mails = await db
.selectFrom("emails")
@ -56,7 +56,7 @@ export const GetEmails = async ({ userId }: { userId: UsersId }) => {
}
};
export const DeleteEmail = async ({
export const deleteEmail = async ({
id_email,
}: {
id_email: EmailsIdEmail;
@ -70,3 +70,14 @@ export const DeleteEmail = async ({
});
}
};
export const deleteAllUserEmails = async ({ userId }: { userId: UsersId }) => {
try {
await db.deleteFrom("emails").where("user_id", "=", userId).execute();
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Errore durante l'eliminazione delle email dell'utente: ${(e as Error).message}`,
});
}
};

View file

@ -41,7 +41,7 @@ import { env } from "~/env";
import type { UsersId } from "~/schemas/public/Users";
import { GetFlagValueHandler } from "~/server/controllers/flags.controller";
import { db } from "~/server/db";
import { StoreEmail } from "~/server/services/email.service";
import { storeEmail } from "~/server/services/email.service";
const mailer = async (options: Options) => {
const smtpTransport = createTransport({
@ -230,6 +230,6 @@ export const NewMail = async ({ template, userId, mail }: NewMailProps) => {
if (userId && template) {
// Store the email in the database if userId is provided
await StoreEmail({ data: template, userId });
await storeEmail({ data: template, userId });
}
};