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

196 lines
5.8 KiB
TypeScript
Raw Normal View History

import { ExternalLink, UnfoldVertical } from "lucide-react";
import Link from "next/link";
import { replaceWithBr } from "~/lib/newlineToBr";
import { cn, formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useServizio } from "~/providers/ServizioProvider";
import type { Annunci } from "~/schemas/public/Annunci";
import type { AnnuncioRicerca } from "~/server/controllers/annunci.controller";
import { api } from "~/utils/api";
import { CardAnnuncio, CarouselAnnuncio } from "../annuncio_card";
import { InteressatoButtonServizio } from "../annuncio-interactions/annuncio_interactions";
import { LoadingPage } from "../loading";
import { Badge } from "../ui/badge";
import { Button } from "../ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../ui/dialog";
export const AnnunciCompatibili = () => {
const { servizioId } = useServizio();
const { data, isLoading } = api.servizio.getCompatibileAnnunci.useQuery({
servizioId,
});
return (
<Dialog>
<DialogTrigger asChild>
<Button className="w-full bg-purple-500 sm:w-fit">
Esplora Annunci Compatibili
</Button>
</DialogTrigger>
<DialogContent className="max-w-xl p-2 sm:max-w-5xl sm:p-6 md:max-w-7xl">
<DialogHeader>
<DialogTitle className="pt-6">
Annunci compatibili con le preferenze del servizio
</DialogTitle>
<DialogDescription className="sr-only"></DialogDescription>
</DialogHeader>
<div className="flex max-h-[80vh] flex-col gap-2 overflow-y-auto p-0.5 sm:p-2">
{isLoading ? (
<LoadingPage />
) : (
<>
{!data || data.length === 0 ? (
<div className="flex items-center justify-center gap-1 rounded-md bg-white p-4 sm:flex">
<span>
Nessun annuncio compatibile trovato. Amplia la ricerca per
trovare annunci compatibili.
</span>
</div>
) : (
<div className="relative z-0 mx-auto grid max-w-7xl grid-flow-row grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-6 sm:gap-y-8 lg:grid-cols-3">
{data.map((annuncio) => (
<div
className="flex flex-col justify-center gap-1"
key={annuncio.codice}
>
<CardAnnuncio
{...annuncio}
className="outline outline-neutral-500"
noLink
onlyFirstImage
/>
<div className="flex items-center justify-between gap-2">
<div className="w-full">
<AnnuncioDettaglio data={annuncio} />
</div>
<div className="w-full">
<InteressatoButtonServizio annuncioId={annuncio.id} />
</div>
</div>
</div>
))}
</div>
)}
</>
)}
</div>
<DialogFooter>
<DialogClose asChild></DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
const TipoBadge = ({ tipo }: { tipo: Annunci["tipo"] }) => {
return (
<Badge
className={cn(
"font-semibold text-md",
tipo === "Transitorio" && "bg-transitorio",
tipo === "Stabile" && "bg-stabile",
tipo === "Cessione" && "bg-blue-400",
tipo === "Vendita" && "bg-green-400",
)}
>
Affitto {tipo}
</Badge>
);
};
const AnnuncioDettaglio = ({ data }: { data: AnnuncioRicerca }) => {
const { locale, t } = useTranslation();
return (
<Dialog>
<DialogTrigger asChild>
<Button aria-label="Dettagli Annuncio" variant="outline">
<UnfoldVertical className="size-6" /> Dettagli annuncio
</Button>
</DialogTrigger>
<DialogContent className="max-h-[70vh] max-w-xl overflow-y-auto sm:max-w-6xl">
<DialogHeader className="flex-row items-center gap-4">
<DialogTitle className="text-xl">Annuncio {data.codice}</DialogTitle>
<Link href={`/annuncio/${data.codice}`} target="_blank">
<Button size="sm" variant="info">
<span>Vai alla pagina completa</span>{" "}
<ExternalLink className="size-4" />
</Button>
</Link>
<DialogDescription className="sr-only">
Annuncio {data.codice}
</DialogDescription>
</DialogHeader>
<div className="flex flex-col gap-2 px-2">
<div className="w-full contain-inline-size">
<CarouselAnnuncio
immagini={data.images.map((img) => img.img)}
updated_at={data.media_updated_at}
videos={data.url_video}
/>
</div>
<div>
<div className="flex items-center gap-4">
<TipoBadge tipo={data.tipo} />
{data.stato === "Trattativa" && (
<Badge className="bg-violet-500 font-semibold text-md">
Annuncio in Trattativa
</Badge>
)}
</div>
<div className="mt-1 space-y-2">
<div className="flex flex-row justify-around">
<div className="text-center">
<dt className="sr-only">{t.card.codice}</dt>
<dd className="font-semibold text-lg">Cod: {data.codice}</dd>
</div>
<div className="text-center">
<dt className="sr-only">{t.card.prezzo}</dt>
<dd className="font-semibold text-lg">
{formatCurrency(data.prezzo / 1e2)}
</dd>
</div>
</div>
<div className="mb-3">
<dt className="sr-only">{t.card.titolo}</dt>
<dd className="font-semibold text-base md:text-lg">
{locale === "it" ? data.titolo_it : data.titolo_en}
</dd>
</div>
<div className="mb-3">
<dd
className="text-base"
dangerouslySetInnerHTML={{
__html: replaceWithBr(
(locale === "it" ? data.desc_it : data.desc_en) || "",
),
}}
/>
</div>
</div>
</div>
</div>
<DialogFooter>
<DialogClose asChild></DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
};