infoalloggi-monorepo/apps/infoalloggi/src/components/area-riservata/comunicazioni.tsx

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">
&ldquo;{email.title}&rdquo; -{" "}
{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>
);
};