diff --git a/apps/infoalloggi/package.json b/apps/infoalloggi/package.json
index dac9f43..c2863ba 100644
--- a/apps/infoalloggi/package.json
+++ b/apps/infoalloggi/package.json
@@ -5,7 +5,7 @@
"build": "next build",
"d": "npm run-p dev stripe-dev -cl",
"dev": "next dev --turbopack",
- "dev-https": "cross-env NEXT_PUBLIC_BASE_URL='https://localhost:3000' INTERNAL_BASE_URL='https://localhost:3000' next dev --experimental-https --turbopack",
+ "dev-https": "cross-env NEXT_PUBLIC_BASE_URL='https://localhost:3000' INTERNAL_BASE_URL='https://localhost:3000' BASE_URL='https://localhost:3000' next dev --experimental-https --turbopack",
"email": "cross-env NEXT_PUBLIC_BASE_URL='https://localhost:3000' email dev --port 3500",
"idev": "cross-env NODE_OPTIONS='--inspect' next dev --turbopack",
"knip": "knip --no-exit-code --no-config-hints",
diff --git a/apps/infoalloggi/src/components/Layout.tsx b/apps/infoalloggi/src/components/Layout.tsx
index 1d700ec..0d6211b 100644
--- a/apps/infoalloggi/src/components/Layout.tsx
+++ b/apps/infoalloggi/src/components/Layout.tsx
@@ -164,33 +164,41 @@ export const AreaRiservataLayoutUserView = ({
children: ReactNode & { props: { userId: UsersId } };
}) => {
const { t } = useTranslation();
-
+ const session = useSession();
const props = children.props as { userId: UsersId };
-
+ if (session.status === "pending") {
+ return ;
+ }
+ if (session.status === "error" || !session.user) {
+ window.location.reload();
+ return ;
+ }
return (
-
- {t.heads.area_riservata_titolo}
-
-
-
-
+
+
+ {t.heads.area_riservata_titolo}
+
+
+
+
-
-
+
+
- {children}
+ {children}
+
-
+
diff --git a/apps/infoalloggi/src/components/area-riservata/comunicazioni.tsx b/apps/infoalloggi/src/components/area-riservata/comunicazioni.tsx
index 41f5e10..91145a0 100644
--- a/apps/infoalloggi/src/components/area-riservata/comunicazioni.tsx
+++ b/apps/infoalloggi/src/components/area-riservata/comunicazioni.tsx
@@ -1,4 +1,5 @@
-import { useState } from "react";
+import { type IframeHTMLAttributes, useState } from "react";
+import toast from "react-hot-toast";
import {
Accordion,
AccordionContent,
@@ -8,56 +9,126 @@ import {
import { useMediaQuery } from "~/hooks/use-media-query";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
-
-export const EmailAccordion = ({ userId }: { userId: UsersId }) => {
+import { Button } from "../ui/button";
+export const EmailAccordion = ({
+ userId,
+ isAdmin,
+}: {
+ userId: UsersId;
+ isAdmin: boolean;
+}) => {
const { data } = api.comunicazioni.getEmails.useQuery({
userId,
});
+ const utils = api.useUtils();
+ const { mutate: deleteEmail } = api.comunicazioni.deleteEmail.useMutation({
+ onSuccess: async () => {
+ toast.success("Email eliminata con successo");
+ setOpenEmail("unset");
+ await utils.comunicazioni.getEmails.invalidate({ userId });
+ },
+ });
- // Track which accordion item is open
- const [openIndex, setOpenIndex] = useState
(undefined);
+ const [openEmail, setOpenEmail] = useState("unset");
const mobile = useMediaQuery("(max-width: 768px)");
if (!data || data.length === 0) {
return Nessuna comunicazione trovata
;
}
+ const iframeHeight = mobile ? 600 : 500;
return (
- {data.map((email, index) => (
-
-
- Email “{email.title}” del{" "}
- {new Date(email.created_at).toLocaleDateString("it-IT", {
- day: "2-digit",
- month: "2-digit",
- year: "numeric",
- })}
-
-
- {openIndex === String(index) && (
-
- )}
-
-
- ))}
+ {data.map((email) => {
+ const isOpen = openEmail === email.id_email.toString();
+ return (
+
+
+ “{email.title}” -{" "}
+ {new Date(email.created_at).toLocaleDateString("it-IT", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
+ hour: "2-digit",
+ minute: "2-digit",
+ })}
+
+
+ {isAdmin && (
+
+
+
+ )}
+
+ {isOpen && (
+
+ )}
+
+
+ );
+ })}
);
};
+
+const LoadingEmailIframe = (props: IframeHTMLAttributes) => {
+ const [loaded, setLoaded] = useState(false);
+
+ return (
+
+
+
+
+
+ Caricamento email...
+
+
+
+
+ {/** biome-ignore lint/a11y/noNoninteractiveElementInteractions:
*/}
+
+ );
+};
diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/user-view/comunicazioni/[userId].tsx b/apps/infoalloggi/src/pages/area-riservata/admin/user-view/comunicazioni/[userId].tsx
index 95b4ea9..24a6fa7 100644
--- a/apps/infoalloggi/src/pages/area-riservata/admin/user-view/comunicazioni/[userId].tsx
+++ b/apps/infoalloggi/src/pages/area-riservata/admin/user-view/comunicazioni/[userId].tsx
@@ -2,6 +2,7 @@ import type { GetServerSideProps } from "next";
import { EmailAccordion } from "~/components/area-riservata/comunicazioni";
import { AreaRiservataLayoutUserView } from "~/components/Layout";
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";
@@ -13,6 +14,7 @@ type ComunicazioniUserProps = {
const ComunicazioniUser: NextPageWithLayout = ({
userId,
}: ComunicazioniUserProps) => {
+ const { user } = useEnforcedSession();
return (
@@ -20,7 +22,7 @@ const ComunicazioniUser: NextPageWithLayout
= ({
Comunicazioni
-
+
diff --git a/apps/infoalloggi/src/pages/area-riservata/comunicazioni.tsx b/apps/infoalloggi/src/pages/area-riservata/comunicazioni.tsx
index df40a21..f1fff1f 100644
--- a/apps/infoalloggi/src/pages/area-riservata/comunicazioni.tsx
+++ b/apps/infoalloggi/src/pages/area-riservata/comunicazioni.tsx
@@ -21,7 +21,10 @@ const Comunicazioni: NextPageWithLayout = () => {
Comunicazioni
-
+
>
);
diff --git a/apps/infoalloggi/src/server/api/routers/comunicazioni.ts b/apps/infoalloggi/src/server/api/routers/comunicazioni.ts
index 6303107..c57a1dc 100644
--- a/apps/infoalloggi/src/server/api/routers/comunicazioni.ts
+++ b/apps/infoalloggi/src/server/api/routers/comunicazioni.ts
@@ -1,10 +1,11 @@
import { z } from "zod/v4";
+import type { EmailsIdEmail } from "~/schemas/public/Emails";
import {
adminProcedure,
createTRPCRouter,
protectedProcedure,
} from "~/server/api/trpc";
-import { GetEmails } from "~/server/services/email.service";
+import { DeleteEmail, GetEmails } from "~/server/services/email.service";
import { NewMail } from "~/server/services/mailer";
import { zUserId } from "~/server/utils/zod_types";
@@ -27,6 +28,17 @@ export const comunicazioniRouter = createTRPCRouter({
userId: input.userId,
});
}),
+ deleteEmail: adminProcedure
+ .input(
+ z.object({
+ id_email: z.custom(),
+ }),
+ )
+ .mutation(async ({ input }) => {
+ return await DeleteEmail({
+ id_email: input.id_email,
+ });
+ }),
// storeEmail: publicProcedure
// .input(
// z.object({
diff --git a/apps/infoalloggi/src/server/services/email.service.ts b/apps/infoalloggi/src/server/services/email.service.ts
index e9a90d9..3245600 100644
--- a/apps/infoalloggi/src/server/services/email.service.ts
+++ b/apps/infoalloggi/src/server/services/email.service.ts
@@ -1,4 +1,5 @@
import { TRPCError } from "@trpc/server";
+import type { EmailsIdEmail } from "~/schemas/public/Emails";
import type { UsersId } from "~/schemas/public/Users";
import { db } from "~/server/db";
import { genMail, type MailsTemplates } from "~/server/services/mailer";
@@ -41,6 +42,7 @@ export const GetEmails = async ({ userId }: { userId: UsersId }) => {
return {
...(await genMail(mail.data as MailsTemplates)),
created_at: mail.created_at,
+ id_email: mail.id_email,
};
}),
);
@@ -53,3 +55,18 @@ export const GetEmails = async ({ userId }: { userId: UsersId }) => {
});
}
};
+
+export const DeleteEmail = async ({
+ id_email,
+}: {
+ id_email: EmailsIdEmail;
+}) => {
+ try {
+ await db.deleteFrom("emails").where("id_email", "=", id_email).execute();
+ } catch (e) {
+ throw new TRPCError({
+ code: "INTERNAL_SERVER_ERROR",
+ message: `Errore durante l'eliminazione dell'email: ${(e as Error).message}`,
+ });
+ }
+};