infoalloggi-monorepo/apps/infoalloggi/src/components/servizio/annuncio_actions.tsx

493 lines
13 KiB
TypeScript

import {
Circle,
CircleCheck,
FileBadge,
FileText,
FolderKanban,
Info,
PackageCheck,
Printer,
Trash2,
Workflow,
Wrench,
} from "lucide-react";
import Link from "next/link";
import toast from "react-hot-toast";
import { IncrociDialog } from "~/components/servizio/incroci";
import {
AlertDialog,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "~/components/ui/alert-dialog";
import { Button, type ButtonConfigs } from "~/components/ui/button";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "~/components/ui/popover";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
import type { AnnunciId } from "~/schemas/public/Annunci";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { ServizioServizioId } from "~/schemas/public/Servizio";
import StatusConfermaEnum from "~/schemas/public/StatusConfermaEnum";
import type { ServizioAnnuncioData } from "~/server/controllers/servizio.controller";
import { api } from "~/utils/api";
import { Confirm } from "../confirm";
import { AdminContratto } from "./admin_contratto";
import { ContattiProprietarioModal } from "./modale_contatti";
export const AdminActions = () => {
const { servizioId, isAdmin } = useServizio();
const { data, annuncioId } = useServizioAnnuncio();
const utils = api.useUtils();
const { mutate } = api.servizio.removeAnnuncioServizio.useMutation({
onError: (error) => {
console.error(error);
toast.error("Errore durante la rimozione dell'annuncio");
},
onSuccess: async () => {
await utils.servizio.invalidate();
toast.success("Annuncio rimosso");
},
});
if (!isAdmin) return null;
return (
<>
<h3 className="ml-1 font-semibold">Azioni Admin:</h3>
<div className="flex w-full max-w-fit flex-wrap justify-start gap-3">
<AnnuncioContatti data={data} />
<IncrociDialog
annuncioId={data.id}
props={{ className: "w-fit", size: "sm" }}
/>
<AnnuncioConfermaPopover
annuncioId={annuncioId}
servizioId={servizioId}
status_conferma={data.status_conferma}
/>
{data.status_conferma != null && (
<>
<AdminContratto />
{data.gestionale_id && (
<Link
aria-label="Open Gestionale"
href={`https://win-jk822fggr6b:480/id/${data.gestionale_id}`}
target="_blank"
>
<Button size="sm">
<FolderKanban /> Gestionale
</Button>
</Link>
)}
</>
)}
{/* <Link href={`/annuncio/${data.codice}`} target="_blank">
<Button size="sm" type="button" variant="outline">
<Eye /> pubblica
</Button>
</Link> */}
<Link
href={`/area-riservata/admin/edit-annuncio/${annuncioId}`}
target="_blank"
>
<Button
aria-label="Edit Annuncio"
className="w-fit"
size="sm"
variant="secondary"
>
<Wrench />
<span>Modifica Annuncio</span>
</Button>
</Link>
<Link
href={`/area-riservata/scheda-annuncio-stampa/${data.id}`}
target="_blank"
>
<Button size="sm" type="button" variant="outline">
<Printer /> Scheda
</Button>
</Link>
<Confirm
description="Sei sicuro di voler eliminare l'annuncio?"
onConfirm={() => {
mutate({
annuncioId,
servizioId,
});
}}
title="Elimina annuncio"
>
<Button
aria-label="Delete Annuncio"
className="w-fit"
size="sm"
variant="destructive"
>
<Trash2 />
<span>Elimina</span>
</Button>
</Confirm>
</div>
</>
);
};
export const UserActions = () => {
const { data } = useServizioAnnuncio();
return (
<>
<div className="flex w-full flex-col flex-wrap gap-2 sm:flex-row">
<ContattiProprietarioModal />
</div>
{data.status_conferma != null && <PostConfermaSection />}
</>
);
};
export const AnnuncioConfermaPopover = ({
servizioId,
annuncioId,
status_conferma,
}: {
servizioId: ServizioServizioId;
annuncioId: AnnunciId;
status_conferma: StatusConfermaEnum | null;
}) => {
const utils = api.useUtils();
const { mutate } = api.servizio.updateServizioAnnunci.useMutation({
onSuccess: async () => {
await utils.servizio.invalidate();
},
onError: (error) => {
console.error(error);
toast.error("Errore durante l'aggiornamento dell'annuncio");
},
});
const handleStatusChange = (status: StatusConfermaEnum | null) => {
mutate({
annuncioId,
servizioId,
data: { status_conferma: status },
});
};
return (
<Popover>
<PopoverTrigger asChild>
<Button
size="sm"
variant={status_conferma === null ? "outline" : "orange"}
>
<Workflow /> {status_conferma || "Non in conferma"}
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverHeader>
<PopoverTitle>Status Conferma:</PopoverTitle>
<PopoverDescription className="sr-only">
Description
</PopoverDescription>
</PopoverHeader>
<div className="flex flex-col divide-y rounded-md border border-border">
<Button
className="justify-start rounded-b-none"
onClick={() => handleStatusChange(null)}
variant={status_conferma === null ? "default" : "outline"}
>
{status_conferma === null ? <CircleCheck /> : <Circle />}
Non in conferma
</Button>
{Object.values(StatusConfermaEnum).map((status) => (
<Button
className="justify-start rounded-none last:rounded-b-md"
key={status}
onClick={() => handleStatusChange(status)}
variant={status_conferma === status ? "default" : "outline"}
>
{status_conferma === status ? <CircleCheck /> : <Circle />}
{status}
</Button>
))}
</div>
</PopoverContent>
</Popover>
);
};
export const AnnuncioContatti = ({ data }: { data: ServizioAnnuncioData }) => {
const { data: annuncio, isLoading } = api.annunci.getAnnuncioFull.useQuery({
id: data.id,
});
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button size="sm" variant="outline">
<Info />
<span>Dati Contatto</span>
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Contatti Annuncio {data.codice}</AlertDialogTitle>
<AlertDialogDescription className="sr-only">
desc
</AlertDialogDescription>
</AlertDialogHeader>
<div className="flex w-full flex-col gap-4">
<div>
<span className="font-semibold">Contatti Aperti il: </span>
{data.open_contatti_at
? new Date(data.open_contatti_at).toLocaleString("it-IT")
: "Non ancora aperti"}
</div>
{isLoading ? (
<div className="flex h-24 w-full items-center justify-center">
Loading...
</div>
) : (
<>
<div>
<span className="font-semibold">Locatore/Incaricato: </span>
{annuncio?.locatore || "N/A"}{" "}
{annuncio?.tipo_locatore ? `(${annuncio.tipo_locatore})` : ""}
</div>
<div>
<span className="font-semibold">Email: </span>
{annuncio?.email || "N/A"}
</div>
<div>
<span className="font-semibold">Telefono: </span>
{annuncio?.numero || "N/A"}
</div>
</>
)}
</div>
<AlertDialogFooter>
<AlertDialogCancel>Chiudi</AlertDialogCancel>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};
const PostConfermaSection = () => {
const { servizio, servizioId } = useServizio();
const { data, annuncioId } = useServizioAnnuncio();
const { locale } = useTranslation();
const saldoPaid = servizio.isOkSaldo;
const consulenzaPaid = servizio.isOkConsulenza;
const doc_non_disponibile =
locale === "it"
? "Il documento non è più disponibile"
: "The document is no longer available";
const contatta_supporto =
locale === "it"
? "Se hai bisogno di una copia, contattaci via email o chat."
: "If you need a copy, contact us via email or chat.";
if (!saldoPaid) {
return (
<div className="flex flex-col gap-1">
<h3 className="font-semibold">
{locale === "it"
? "Questo annuncio è stato confermato, procedi al saldo:"
: "This listing has been confirmed, proceed to payment:"}
</h3>
<SaldoButton annuncioId={annuncioId} />
</div>
);
}
if (!data.doc_contratto_added) {
return (
<div className="flex flex-col gap-1 rounded-md border border-card bg-card p-4">
<h3 className="font-semibold text-green-500">
{locale === "it"
? "Ci siamo quasi! Stiamo preparando il contratto per te."
: "Almost there! We are preparing the contract for you."}
</h3>
<h3 className="font-semibold">
{locale === "it"
? "Una volta pronto, riceverai una notifica via email."
: "Once ready, you will receive a notification via email."}
</h3>
</div>
);
}
return (
<div className="flex flex-col gap-2">
<h3 className="font-semibold">
{consulenzaPaid
? locale === "it"
? "Il contratto è pronto, puoi visualizzarlo:"
: "The contract is ready, you can view it:"
: locale === "it"
? "Il contratto è pronto, puoi visualizzarlo e procedere al saldo:"
: "The contract is ready, you can view it and proceed to payment:"}
</h3>
<div className="flex w-full flex-wrap gap-2">
{data.doc_contratto_ref ? (
<Link
aria-label={
locale === "it" ? "Visualizza contratto" : "View contract"
}
className="w-full sm:w-fit"
href={`/servizio/contratto/${servizioId}/${annuncioId}`}
target="_blank"
>
<Button className="w-full">
<FileText />
{locale === "it"
? "Visualizza il contratto"
: "View the contract"}
</Button>
</Link>
) : (
<TooltipProvider delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>
<Button className="w-fit cursor-not-allowed opacity-50">
<FileText />
{locale === "it"
? "Visualizza il contratto"
: "View the contract"}
</Button>
</TooltipTrigger>
<TooltipContent>
<p>{doc_non_disponibile}</p>
<p>{contatta_supporto}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
{!consulenzaPaid &&
servizio.ordini.some(
(o) => o.type === OrderTypeEnum.Consulenza && !o.isActive,
) &&
data.contratto_tipo && <SaldoConsulenzaButton />}
{data.doc_registrazione_added &&
(data.doc_registrazione_ref ? (
<Link
aria-label={
locale === "it" ? "Visualizza registrazione" : "View recording"
}
className="w-full sm:w-fit"
href={`/servizio/contratto-registrazione/${servizioId}/${annuncioId}`}
target="_blank"
>
<Button className="w-full">
<FileBadge />
{locale === "it"
? "Visualizza la registrazione"
: "View the recording"}
</Button>
</Link>
) : (
<TooltipProvider delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>
<Button className="w-fit cursor-not-allowed opacity-50">
<FileBadge />
{locale === "it"
? "Visualizza la registrazione"
: "View the recording"}
</Button>
</TooltipTrigger>
<TooltipContent>
<p>{doc_non_disponibile}</p>
<p>{contatta_supporto}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
))}
</div>
</div>
);
};
export const SaldoButton = ({
variant = "info",
className,
}: {
annuncioId: AnnunciId;
variant?: ButtonConfigs["variant"];
className?: string;
}) => {
const { locale } = useTranslation();
const { servizioId } = useServizio();
return (
<Link
className="w-full sm:w-fit"
href={`/servizio/pagamento?servizioId=${servizioId}&type=${OrderTypeEnum.Saldo}`}
>
<Button
aria-label={locale === "it" ? "Procedi al saldo" : "Proceed to payment"}
className={cn("w-full", className)}
variant={variant}
>
<PackageCheck />
{locale === "it" ? "Procedi al saldo" : "Proceed to payment"}
</Button>
</Link>
);
};
const SaldoConsulenzaButton = ({
variant = "info",
className,
}: {
variant?: ButtonConfigs["variant"];
className?: string;
}) => {
const { locale } = useTranslation();
const { servizioId } = useServizio();
return (
<Link
className="w-full sm:w-fit"
href={`/servizio/pagamento?servizioId=${servizioId}&type=${OrderTypeEnum.Consulenza}`}
>
<Button
aria-label={
locale === "it"
? "Procedi al saldo consulenza"
: "Proceed to payment for the consultation"
}
className={cn("w-full", className)}
variant={variant}
>
<PackageCheck />
{locale === "it"
? "Procedi al saldo della consulenza"
: "Proceed to payment for the consultation"}
</Button>
</Link>
);
};