import { Armchair, Bath, BedDouble, Building2, Car, Copy, Edit, ExternalLink, Ruler, Share2, } from "lucide-react"; import type { GetStaticPaths, GetStaticPropsContext, NextPage } from "next"; import Head from "next/head"; import Link from "next/link"; import { IconMatrix, type IconType } from "~/components/IconComponents"; import FailedAnnuncioLoading, { LoadingPage } from "~/components/loading"; import { Button, buttonVariants } from "~/components/ui/button"; import { type CaratteristicheFiltered, filteredCaratteristiche, } from "~/hooks/schedaAnnuncioUtils"; import { cn } from "~/lib/utils"; import { generateSSGHelper } from "~/server/utils/ssgHelper"; import { api } from "~/utils/api"; import { useTranslation } from "~/providers/I18nProvider"; import { useSession } from "~/providers/SessionProvider"; import { AnnuncioInteractions } from "~/components/annuncio-interactions/annuncio_interactions"; import { CarouselAnnuncio } from "~/components/annuncio_card"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "~/components/ui/accordion"; import { AnnuncioContext } from "~/providers/AnnuncioProvider"; import { MappaDialogFullscreen } from "~/components/MapDialog"; import { handleConsegna } from "~/lib/annuncio_details"; import { PricingComponent } from "~/components/prezzi"; import type { AnnunciWithCoverImage } from "~/server/controllers/annunci.controller"; import { useMediaQuery } from "~/hooks/use-media-query"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "~/components/ui/dialog"; import { Label } from "~/components/ui/label"; import Input from "~/components/custom_ui/input"; import toast from "react-hot-toast"; import { VideoPlayer } from "~/components/videoPlayer"; import { TouchProvider } from "~/components/custom_ui/HybridTooltip"; import InformationBubble from "~/components/InformationBubble"; import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum"; import { useEffect, useState } from "react"; import { env } from "~/env.mjs"; type AnnuncioProps = { cod: string; flag: string; }; const AnnuncioDettaglio: NextPage = ({ cod, flag, }: AnnuncioProps) => { const session = useSession(); const { locale } = useTranslation(); const [url, setUrl] = useState(""); useEffect(() => { if (typeof window !== "undefined") { setUrl(window.location.href); } }, []); const { data, isLoading } = api.annunci.getAnnuncio.useQuery( { cod: cod, }, { refetchOnMount: false }, ); const isDesktop = useMediaQuery("(min-width: 768px)"); if (isLoading || session.status === "pending") return ; if ( (!isLoading && !data) || session.status === "error" || (data && data.stato === "Sospeso") ) { return ; } if (!isLoading && data) { const titolo = (locale === "it" ? data.titolo_it : data.titolo_en) || ""; const description = (locale === "it" ? data.desc_it : data.desc_en) || ""; const filteredCaratt = data.caratteristiche ? filteredCaratteristiche(data.caratteristiche) : null; return (
{`${cod} | ${titolo}`} {data.titolo_it && ( )} {data.coverImage && ( )} {typeof window !== "undefined" && ( )}
{session.user?.isAdmin ? ( Modifica annuncio ) : ( )} {data.tipo && (data.tipo == "Transitorio" || data.tipo == "Stabile") && ( <> )}
); } return
Errore
; }; export async function getStaticProps( context: GetStaticPropsContext<{ cod: string }>, ) { const ssg = generateSSGHelper(); const cod = context.params?.cod; if (typeof cod !== "string") throw new Error("no cod"); await ssg.annunci.getAnnuncio.prefetch({ cod: cod }); const flag = await ssg.settings.GetFlagValue.fetch({ id: "ANNUNCIO_INTERACTIONS_DISABLED", }); return { props: { trpcState: ssg.dehydrate(), cod, flag, }, revalidate: 1, }; } export const getStaticPaths: GetStaticPaths = async () => { return { paths: [], fallback: "blocking", }; }; export default AnnuncioDettaglio; const Pricing = ({ isDesktop, tipologia, }: { isDesktop: boolean; tipologia: TipologiaPosizioneEnum; }) => { const { t } = useTranslation(); const { data: prezziario, isLoading } = api.prezziario.getPrezziPerTipologia.useQuery({ tipologia, }); if (isLoading) return ; if (!prezziario) return null; const cta = tipologia == TipologiaPosizioneEnum.Transitorio ? t.pricing_cmp.cta_breve : t.pricing_cmp.cta_stabile; const opzioni = tipologia == TipologiaPosizioneEnum.Transitorio ? [ t.pricing_cmp.breve_option1, t.pricing_cmp.breve_option2, t.pricing_cmp.breve_option3, t.pricing_cmp.breve_option4, t.pricing_cmp.breve_option5, ] : [t.pricing_cmp.stabile_option1, t.pricing_cmp.stabile_option2]; const style = tipologia == TipologiaPosizioneEnum.Transitorio ? "border-rose-400 bg-rose-400" : "border-indigo-400 bg-indigo-400"; const pricing = prezziario.saldi.map((s) => ({ downPayment: prezziario.acconto.prezzo_cent / 100, secondPayment: s.prezzo_cent / 100, })); if (isDesktop) { return ( ); } else { return ( {t.pricing_cmp.cta_costo} ); } }; const TestiAnnuncio = ({ titolo, description, filteredCaratt, }: { titolo: string; description: string; filteredCaratt: | { text: string; icon: IconType; value: string | null; }[] | null; }) => { function replaceWithBr(text: string) { return text.replace(/\n/g, "
"); } return ( <>

{titolo}

{filteredCaratt && ( )} ); }; const CaratteristicheAccordion = ({ filteredCaratt, }: { filteredCaratt: CaratteristicheFiltered; }) => { return ( Altre caratteristiche {Object.entries(filteredCaratt).map(([key, scheda_value]) => { const { text, icon, value } = scheda_value; if (value === null) return null; return (
{text}: {value}
); })}
); }; const CardInfos = ({ data }: { data: AnnunciWithCoverImage }) => { const { t } = useTranslation(); return ( Codice {data.codice}
{data.prezzo && (data.prezzo / 1e2).toFixed(2).replace(".", ",")}{" "} €/mese
{data.prezzo && (
Prezzo al giorno
{(data.prezzo / 1e2 / 30).toFixed(2).replace(".", ",")} €/gg
)}
Affitto {data.tipo}{" "}
{data.tipo == "Transitorio" && ( )}

Fornitura:

{data.numero_camere && data.numero_camere ? data.numero_camere > 1 ? `${data.numero_camere} ${t.card.camere2}` : `${data.numero_camere} ${t.card.camere1}` : "N/A"}
{data.numero_bagni} bagni
{data.caratteristiche?.Scheda_Arredi || ""}
{data.numero_postiauto} posti auto

Dati immobile:

{data.mq} m2
{data.piano && data.piano === "0" ? "piano terra" : `${data.piano}° piano`}
{data.stato === "Trattativa" ? ( "Annuncio in aggiornamento" ) : ( <> Disponibilità:{" "} {handleConsegna({ consegna: data.consegna, consegna_da: t.card.consegna_da, mesi: t.preferenze.mesi, subito: t.card.consegna_subito, aggiornamento: t.card.in_aggiornamento, })} )}
); }; const ShareComponent = () => { const { t } = useTranslation(); const [link, setLink] = useState(""); useEffect(() => { if (typeof window !== "undefined") { setLink(window.location.href); } }, []); const handleCopyLink = async () => { if (navigator.clipboard && navigator.clipboard.writeText) { try { await navigator.clipboard.writeText(link); toast(t.share.copiato, { icon: "📋" }); } catch (err) { console.error("Failed to copy: ", err); } } else { // Fallback for browsers that do not support navigator.clipboard.writeText const textArea = document.createElement("textarea"); textArea.value = link; document.body.appendChild(textArea); textArea.select(); try { document.execCommand("copy"); toast(t.share.copiato, { icon: "📋" }); } catch (err) { console.error("Failed to copy: ", err); } document.body.removeChild(textArea); } }; return ( {t.share.condividi} {t.share.descrizione}
); }; const AnnuncioFooter = ({ tipo, comune, consegna, url_video, first_image, }: { tipo: string | null; comune: string | null; consegna: number | null; url_video: string[]; first_image: string; }) => { return (

Video:

{url_video.map((video) => { if (!video) return null; if (video.includes("youtu")) { return null; /*return (