infoalloggi-monorepo/apps/infoalloggi/src/components/tables/servizio-table.tsx

269 lines
9.8 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
import toast from "react-hot-toast";
import type { Servizio } from "~/schemas/public/Servizio";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "~/components/ui/table";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuPortal,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import {
Copy,
EllipsisVertical,
ExternalLink,
Mail,
Trash2,
Wrench,
} from "lucide-react";
import { Button } from "~/components/ui/button";
import { Confirm } from "~/components/confirm";
import Link from "next/link";
import { env } from "~/env.mjs";
export const TabServizio = ({
userId,
setEditData,
setOpen,
}: {
userId: UsersId;
setEditData: (data: Servizio | undefined) => void;
setOpen: (open: boolean) => void;
}) => {
const { data } = api.servizio.getUserServizi.useQuery({ userId });
const utils = api.useUtils();
const { mutate: remove } = api.servizio.deleteServizio.useMutation({
onSuccess: async () => {
toast.success("Servizio rimosso con successo");
await utils.servizio.getUserServizi.invalidate();
},
onError: (error) => {
toast.error(error.message);
},
});
const { mutate: sendEmail } = api.servizio.sendServizioEmail.useMutation({
onSuccess: async () => {
toast.success("Servizio rimosso con successo");
await utils.servizio.getUserServizi.invalidate();
},
onError: (error) => {
toast.error(error.message);
},
});
const { mutate: update } = api.servizio.updateServizio.useMutation({
onSuccess: async () => {
toast.success("Servizio modificato con successo");
await utils.servizio.getUserServizi.invalidate();
},
onError: (error) => {
toast.error(error.message);
},
});
if (!data) return <LoadingPage />;
return (
<Table>
<TableCaption>
{data.length > 0
? "Lista dai servizi dell'utente"
: "Nessun servizio attualmente inserito"}
</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Id</TableHead>
<TableHead>Tipologia</TableHead>
<TableHead>Creato Il</TableHead>
<TableHead>Inviato</TableHead>
<TableHead>Status</TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data.map((servizio, idx) => {
const onboardDone =
servizio.isSent ||
servizio.isInterrotto ||
servizio.isOkAcconto ||
servizio.decorrenza !== null;
return (
<TableRow key={idx}>
<TableCell className="font-medium">
{servizio.servizio_id}
</TableCell>
<TableCell>{servizio.tipologia}</TableCell>
<TableCell>
{new Date(servizio.created_at).toLocaleDateString("it-IT", {
year: "numeric",
month: "2-digit",
day: "2-digit",
})}
</TableCell>
<TableCell>
{servizio.isSent ? (
<span className="text-green-500">Inviato</span>
) : (
<span className="text-neutral-500">Non inviato</span>
)}
</TableCell>
<TableCell>
{servizio.isInterrotto ? (
2025-08-04 17:45:44 +02:00
<span className="text-red-500">Interrotto</span>
) : servizio.isOkAcconto && servizio.decorrenza !== null ? (
<span className="text-green-500">Attivo</span>
2025-08-04 17:45:44 +02:00
) : (
<span className="text-neutral-500">Inattivo</span>
)}
</TableCell>
<TableCell>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" aria-label="Servizio Actions">
<EllipsisVertical />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem asChild>
<Confirm
title="Invia email"
description="Sei sicuro di voler inviare l'email?"
onConfirm={() => {
sendEmail({
servizioId: servizio.servizio_id,
userId: userId,
});
}}
>
<Button
disabled={onboardDone}
aria-label="Invia Email Servizio"
variant="ghost"
className="flex w-full justify-start gap-3 px-2 font-normal"
size="sm"
>
<Mail className="stroke-foreground size-5" />
Invia all&apos;utente
</Button>
</Confirm>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
aria-label="Apri Onboarding Servizio"
href={`/area-riservata/admin/user-view/onboard/${servizio.servizio_id}`}
className="!p-0"
>
<Button
variant="ghost"
size="sm"
className="flex w-full justify-start gap-3 px-2 font-normal"
disabled={onboardDone}
>
<ExternalLink className="stroke-foreground size-5" />
Apri Onboarding
</Button>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Button
aria-label="Invia Email Servizio"
variant="ghost"
className="flex w-full justify-start gap-3 px-2 font-normal"
size="sm"
disabled={onboardDone}
onClick={async () => {
await navigator.clipboard.writeText(
`${env.NEXT_PUBLIC_BASE_URL}/servizio/pre-onboard/${servizio.servizio_id}`,
);
toast.success("Copiato negli appunti", {
icon: "📋",
});
}}
>
<Copy className="stroke-foreground size-5" />
Copia Link
</Button>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger className="flex items-center gap-3 hover:cursor-pointer">
<Wrench className="stroke-foreground size-5" />
<span className="text-foreground">Status Servizio</span>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuRadioGroup
value={String(servizio.isOkAcconto)}
onValueChange={(v) => {
console.log(v);
update({
servizioId: servizio.servizio_id,
data: {
isOkAcconto: v === "true",
decorrenza: v === "true" ? new Date() : null,
},
});
}}
>
<DropdownMenuRadioItem value="true">
Attivo
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="false">
Disattiva
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem
aria-label="Modifica Parametri Servizio"
className="flex items-center gap-3 hover:cursor-pointer"
onClick={() => {
setEditData(servizio);
setOpen(true);
}}
>
<Wrench className="stroke-foreground size-5" />
Modifica parametri
</DropdownMenuItem>
<DropdownMenuItem
aria-label="Elimina Servizio"
className="flex items-center gap-3 hover:cursor-pointer"
onClick={() =>
confirm("Sei sicuro di voler eliminare il servizio?") &&
remove({ servizioId: servizio.servizio_id })
}
>
<Trash2 className="stroke-foreground size-5" />
Elimina Servizio
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
);
};