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

215 lines
6.6 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
import {
Credenza,
CredenzaContent,
CredenzaHeader,
CredenzaTitle,
CredenzaDescription,
CredenzaBody,
CredenzaFooter,
CredenzaClose,
} from "~/components/custom_ui/credenza";
import { PaymentsTable } from "~/components/tables/payments-table";
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
import { api } from "~/utils/api";
import { Confirm } from "~/components/confirm";
import { Button } from "~/components/ui/button";
import { CircleCheck, CircleSlash, ReceiptText, Trash2 } from "lucide-react";
import toast from "react-hot-toast";
import type { UsersId } from "~/schemas/public/Users";
import { cn } from "~/lib/utils";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
import Link from "next/link";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
export const OrdiniModal = ({
isAdmin,
open,
setModalOpen,
ordineId,
userId,
}: {
isAdmin: boolean;
open: boolean;
setModalOpen: (open: boolean) => void;
ordineId: OrdiniOrdineId;
userId: UsersId | undefined;
}) => {
const utils = api.useUtils();
const { mutate: remove } = api.servizio.removeOrder.useMutation({
onSuccess: async () => {
toast.success("Ordine rimosso con successo!");
await utils.servizio.getOrdini.invalidate({
userId,
});
setModalOpen(false);
},
onError: (error) => {
toast.error(`Errore durante la rimozione ordine: ${error.message}`);
},
});
const { mutate: update } = api.servizio.updateOrder.useMutation({
onSuccess: async (data) => {
if (data.type === OrderTypeEnum.Acconto && data.isActive) {
updateServizio({
servizioId: data.servizio_id,
data: {
isOkAcconto: true,
decorrenza: new Date(),
},
});
}
toast.success("Ordine aggiornato con successo!");
await utils.servizio.getOrdini.invalidate({
userId,
});
await utils.servizio.getOrdineById.invalidate({
ordineId,
});
},
onError: (error) => {
toast.error(`Errore durante la modifica: ${error.message}`);
},
});
const { mutate: updateServizio } = api.servizio.updateServizio.useMutation({
onSuccess: async () => {
toast.success("Servizio modificato con successo");
await utils.servizio.getUserServizi.invalidate();
},
onError: (error) => {
toast.error(error.message);
},
});
const { data } = api.servizio.getOrdineById.useQuery({
ordineId,
});
if (!data) return null;
return (
<Credenza
open={open}
onOpenChange={(b) => {
setModalOpen(b);
}}
>
<CredenzaContent className="max-h-[90vh] max-w-2xl">
<CredenzaHeader>
<CredenzaTitle>Dettagli Ordine</CredenzaTitle>
<CredenzaDescription>
Visualizza i dettagli e i pagamenti associati.
</CredenzaDescription>
</CredenzaHeader>
<CredenzaBody className="max-h-[80vh] space-y-2 overflow-auto pb-5">
<p>Id Ordine: {data.ordine_id}</p>
<p>
Data Ordine:
{new Date(data.created_at).toLocaleDateString("it-IT", {
year: "numeric",
month: "2-digit",
day: "2-digit",
})}
</p>
<p>Tipologia: {data.type.toString()}</p>
<p>Pack ID: {data.packid}</p>
<p className="flex items-center gap-2">
Stato:{" "}
{data.isActive ? (
<span className="inline-flex items-center gap-1 text-green-500">
<CircleCheck className="size-5" />
Attivo
</span>
) : (
<span className="inline-flex items-center gap-1">
<CircleSlash className="size-5" />
Non Attivo
</span>
)}
</p>
{data.isActive &&
data.pagamenti.find(
(p) => p.paymentstatus === PaymentStatusEnum.success,
) && (
<div>
<Link
href={`/area-riservata/payment-recap/${data.ordine_id}`}
target="_blank"
>
<Button variant="outline" className="flex items-center gap-2">
Ricevuta di cortesia <ReceiptText />
</Button>
</Link>
</div>
)}
<PaymentsTable data={data.pagamenti} isAdmin={isAdmin} isUserView />
</CredenzaBody>
<CredenzaFooter
className={cn(
"flex w-full",
isAdmin ? "sm:justify-between" : "sm:justify-end",
)}
>
{isAdmin && (
<div className="flex items-center gap-4">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" aria-label="Modifica Status">
Modifica Status
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>Status</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup
value={data.isActive ? "true" : "false"}
onValueChange={(v) => {
update({
ordineId,
data: { isActive: v === "true" },
});
}}
>
<DropdownMenuRadioItem value="true">
Attivo
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="false">
Non Attivo
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<Confirm
title="Elimina ordine"
description="Sei sicuro di voler eliminare l'ordine?"
onConfirm={() => {
remove({ ordineId });
}}
>
<Button variant="destructive" aria-label="Elimina Ordine">
<Trash2 className="size-6" />
Elimina Ordine
</Button>
</Confirm>
</div>
)}
<CredenzaClose asChild>
<Button variant="ghost">Chiudi</Button>
</CredenzaClose>
</CredenzaFooter>
</CredenzaContent>
</Credenza>
);
};