134 lines
3.7 KiB
TypeScript
134 lines
3.7 KiB
TypeScript
import { type IframeHTMLAttributes, useState } from "react";
|
|
import toast from "react-hot-toast";
|
|
import {
|
|
Accordion,
|
|
AccordionContent,
|
|
AccordionItem,
|
|
AccordionTrigger,
|
|
} from "~/components/ui/accordion";
|
|
import { useMediaQuery } from "~/hooks/use-media-query";
|
|
import type { UsersId } from "~/schemas/public/Users";
|
|
import { api } from "~/utils/api";
|
|
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 });
|
|
},
|
|
});
|
|
|
|
const [openEmail, setOpenEmail] = useState<string | "unset">("unset");
|
|
|
|
const mobile = useMediaQuery("(max-width: 768px)");
|
|
if (!data || data.length === 0) {
|
|
return <div className="text-center">Nessuna comunicazione trovata</div>;
|
|
}
|
|
const iframeHeight = mobile ? 600 : 500;
|
|
|
|
return (
|
|
<div className="mx-auto w-full py-4">
|
|
<Accordion
|
|
className="space-y-4"
|
|
collapsible
|
|
onValueChange={setOpenEmail}
|
|
type="single"
|
|
value={openEmail}
|
|
>
|
|
{data.map((email) => {
|
|
const isOpen = openEmail === email.id_email.toString();
|
|
return (
|
|
<AccordionItem
|
|
className="space-y-2 border-none"
|
|
key={email.id_email}
|
|
value={email.id_email.toString()}
|
|
>
|
|
<AccordionTrigger className="rounded-md bg-muted px-4 py-2">
|
|
“{email.title}” -{" "}
|
|
{new Date(email.created_at).toLocaleDateString("it-IT", {
|
|
day: "2-digit",
|
|
month: "2-digit",
|
|
year: "numeric",
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
})}
|
|
</AccordionTrigger>
|
|
<AccordionContent className="overflow-clip rounded-md border">
|
|
{isAdmin && (
|
|
<div className="flex h-7 w-full items-center justify-end bg-secondary px-4">
|
|
<Button
|
|
className="h-5"
|
|
onClick={() =>
|
|
confirm(
|
|
"Sei sicuro di voler eliminare questa email?",
|
|
) &&
|
|
deleteEmail({
|
|
id_email: email.id_email,
|
|
})
|
|
}
|
|
variant="destructive"
|
|
>
|
|
Rimuovi
|
|
</Button>
|
|
</div>
|
|
)}
|
|
|
|
{isOpen && (
|
|
<LoadingEmailIframe
|
|
height={iframeHeight}
|
|
srcDoc={email.html}
|
|
title="Email Content"
|
|
width="100%"
|
|
/>
|
|
)}
|
|
</AccordionContent>
|
|
</AccordionItem>
|
|
);
|
|
})}
|
|
</Accordion>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const LoadingEmailIframe = (props: IframeHTMLAttributes<HTMLIFrameElement>) => {
|
|
const [loaded, setLoaded] = useState(false);
|
|
|
|
return (
|
|
<div
|
|
className="relative overflow-hidden"
|
|
style={{ height: props.height, width: props.width }}
|
|
>
|
|
<div
|
|
className={`absolute inset-0 flex items-center justify-center bg-muted transition-opacity duration-1000 ${loaded ? "pointer-events-none opacity-0" : "opacity-100"}
|
|
`}
|
|
>
|
|
<div className="flex flex-col items-center gap-3">
|
|
<div className="size-8 animate-spin rounded-full border-4 border-muted-foreground/20 border-t-primary" />
|
|
<p className="animate-pulse text-muted-foreground text-sm">
|
|
Caricamento email...
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/** biome-ignore lint/a11y/noNoninteractiveElementInteractions: <fine here> */}
|
|
<iframe
|
|
{...props}
|
|
className={`absolute inset-0 transition-opacity duration-1000 ${loaded ? "opacity-100" : "opacity-0"}
|
|
`}
|
|
onLoad={() => setLoaded(true)}
|
|
title={props.title ?? "Email preview"}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|