From 58ea25418051d6d4323e279f6f0d1773222fb10a Mon Sep 17 00:00:00 2001 From: Marco Pedone Date: Tue, 17 Mar 2026 18:47:30 +0100 Subject: [PATCH] feat: refactor Annuncio context and related data fetching for improved structure and clarity --- apps/infoalloggi/src/pages/annuncio/[cod].tsx | 207 ++++++++---------- .../src/providers/AnnuncioProvider.tsx | 7 +- .../src/server/api/routers/annunci.ts | 7 +- .../server/controllers/annunci.controller.ts | 51 ++++- 4 files changed, 133 insertions(+), 139 deletions(-) diff --git a/apps/infoalloggi/src/pages/annuncio/[cod].tsx b/apps/infoalloggi/src/pages/annuncio/[cod].tsx index cd6d74b..92f24ef 100644 --- a/apps/infoalloggi/src/pages/annuncio/[cod].tsx +++ b/apps/infoalloggi/src/pages/annuncio/[cod].tsx @@ -25,7 +25,7 @@ import { TouchProvider } from "~/components/custom_ui/HybridTooltip"; import Input from "~/components/custom_ui/input"; import { ComeFunziona } from "~/components/expand_guida"; import FailedAnnuncioLoading from "~/components/failed-loading"; -import { IconMatrix, type IconType } from "~/components/IconComponents"; +import { IconMatrix } from "~/components/IconComponents"; import InformationBubble from "~/components/InformationBubble"; import { LoadingPage } from "~/components/loading"; import { MappaDialogFullscreen } from "~/components/MapDialog"; @@ -54,10 +54,7 @@ import { import { Label } from "~/components/ui/label"; import { VideoPlayer } from "~/components/videoPlayer"; import { env } from "~/env"; -import { - type CaratteristicheFiltered, - filteredCaratteristiche, -} from "~/hooks/schedaAnnuncioUtils"; +import { filteredCaratteristiche } from "~/hooks/schedaAnnuncioUtils"; import { useStaleImageReload } from "~/hooks/staleImage"; import { useMediaQuery } from "~/hooks/use-media-query"; import { handleConsegna } from "~/lib/annuncio_details"; @@ -68,9 +65,7 @@ import { AnnuncioContext, useAnnuncio } from "~/providers/AnnuncioProvider"; import { useTranslation } from "~/providers/I18nProvider"; import { buildRicercaUrl } from "~/providers/RicercaProvider"; import { useSession } from "~/providers/SessionProvider"; -import type { Annunci } from "~/schemas/public/Annunci"; import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum"; -import type { VideosRefs } from "~/schemas/public/VideosRefs"; import { generateSSGHelper } from "~/server/utils/ssgHelper"; import { api } from "~/utils/api"; @@ -135,10 +130,9 @@ const AnnuncioDettaglio: NextPage = ({ const AnnuncioView = ({ cod, flag }: Omit) => { const session = useSession(); - const { locale } = useTranslation(); useStaleImageReload(); - const { data, isLoading } = api.annunci.getAnnuncio.useQuery( + const { data, isLoading } = api.annunci.getAnnuncioData.useQuery( { cod: cod, }, @@ -156,13 +150,6 @@ const AnnuncioView = ({ cod, flag }: Omit) => { return ; } - 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 ( @@ -176,7 +163,7 @@ const AnnuncioView = ({ cod, flag }: Omit) => {
- + {session.user?.isAdmin ? ( <> ) => {
- +
- +
@@ -248,7 +224,7 @@ export async function getStaticProps( notFound: true, }; } - await ssg.annunci.getAnnuncio.prefetch({ cod: cod }); + await ssg.annunci.getAnnuncioData.prefetch({ cod: cod }); const meta = await ssg.annunci.getAnnuncioMeta.fetch({ cod: cod }); @@ -388,42 +364,30 @@ const Pricing = ({ isDesktop }: { isDesktop: boolean }) => { ); }; -const TestiAnnuncio = ({ - titolo, - description, - filteredCaratt, -}: { - titolo: string; - description: string; - filteredCaratt: - | { - text: string; - icon: IconType; - value: string | null; - }[] - | null; -}) => { +const TestiAnnuncio = () => { + const { locale } = useTranslation(); + const { titolo_it, titolo_en, desc_it, desc_en } = useAnnuncio(); + return ( <> -

{titolo}

+

+ {locale === "it" ? titolo_it : titolo_en} +

- {filteredCaratt && ( - - )} + + ); }; -const CaratteristicheAccordion = ({ - filteredCaratt, -}: { - filteredCaratt: CaratteristicheFiltered; -}) => { +const CaratteristicheAccordion = () => { + const { caratteristiche } = useAnnuncio(); + if (!caratteristiche) return null; return ( Altre caratteristiche - {Object.entries(filteredCaratt).map(([key, scheda_value]) => { - const { text, icon, value } = scheda_value; - if (value === null) return null; - return ( -
- - {text}: {value} -
- ); - })} + {Object.entries(filteredCaratteristiche(caratteristiche)).map( + ([key, scheda_value]) => { + const { text, icon, value } = scheda_value; + if (value === null) return null; + return ( +
+ + {text}: {value} +
+ ); + }, + )}
); }; -const CardInfos = ({ data }: { data: Annunci }) => { +const CardInfos = () => { const { t } = useTranslation(); - + const { + codice, + prezzo, + tipo, + numero_camere, + numero_bagni, + caratteristiche, + numero_postiauto, + mq, + piano, + stato, + consegna, + lat_secondario, + lon_secondario, + } = useAnnuncio(); return ( - {t.annunci.codice} {data.codice} + {t.annunci.codice} {codice}
- {data.prezzo && (data.prezzo / 1e2).toFixed(2).replace(".", ",")}{" "} + {prezzo && (prezzo / 1e2).toFixed(2).replace(".", ",")}{" "} {t.annunci.euro_mese}
- {data.prezzo && ( + {prezzo && ( { {t.annunci.prezzo_giorno}
- {(data.prezzo / 1e2 / 30).toFixed(2).replace(".", ",")}{" "} + {(prezzo / 1e2 / 30).toFixed(2).replace(".", ",")}{" "} {t.annunci.euro_giorno}
@@ -494,13 +474,13 @@ const CardInfos = ({ data }: { data: Annunci }) => {
- {data.tipo} + {tipo}
- {data.tipo === "Transitorio" && ( + {tipo === "Transitorio" && ( { {(() => { - if (!data.numero_camere) return "N/A"; - if (data.numero_camere > 1) - return `${data.numero_camere} ${t.card.camere2}`; - if (data.numero_camere === 1) - return `${data.numero_camere} ${t.card.camere1}`; + if (!numero_camere) return "N/A"; + if (numero_camere > 1) + return `${numero_camere} ${t.card.camere2}`; + if (numero_camere === 1) + return `${numero_camere} ${t.card.camere1}`; })()}
- {data.numero_bagni || 0} {t.annunci.bagni} + {numero_bagni || 0} {t.annunci.bagni}
- {data.caratteristiche?.Scheda_Arredi || ""} + {caratteristiche?.Scheda_Arredi || ""}
- {data.numero_postiauto || 0} {t.annunci.posti_auto} + {numero_postiauto || 0} {t.annunci.posti_auto}
@@ -550,21 +530,19 @@ const CardInfos = ({ data }: { data: Annunci }) => {
- {data.mq ? Number(data.mq).toLocaleString("it-IT") : "--"} m - 2 + {mq ? Number(mq).toLocaleString("it-IT") : "--"} m2
- {data.piano !== null && data.piano !== "" && ( + {piano !== null && piano !== "" && ( <> {(() => { - if (data.piano === "0") return t.annunci.p_terra; - if (data.piano === "0.5") return t.annunci.p_rialzato; - if (data.piano) - return `${data.piano}° ${t.annunci.piano}`; + if (piano === "0") return t.annunci.p_terra; + if (piano === "0.5") return t.annunci.p_rialzato; + if (piano) return `${piano}° ${t.annunci.piano}`; return "--"; })()} @@ -575,7 +553,7 @@ const CardInfos = ({ data }: { data: Annunci }) => {
- {data.stato === "Trattativa" ? ( + {stato === "Trattativa" ? (
{t.annunci.in_aggiornamento} @@ -587,7 +565,7 @@ const CardInfos = ({ data }: { data: Annunci }) => { {handleConsegna({ aggiornamento: t.card.in_aggiornamento, - consegna: data.consegna, + consegna: consegna, consegna_da: t.card.consegna_da, mesi: t.parametri.mesi, subito: t.card.consegna_subito, @@ -597,10 +575,7 @@ const CardInfos = ({ data }: { data: Annunci }) => { )}
- +
@@ -677,28 +652,16 @@ const ShareComponent = () => { ); }; -const AnnuncioFooter = ({ - tipo, - comune, - consegna, - videos, - external_videos, - updated_at, -}: { - tipo: string; - comune: string | null; - consegna: number | null; - videos: Pick[]; - external_videos: string[]; - updated_at: Date | null; -}) => { +const AnnuncioFooter = () => { + const { tipo, comune, consegna, videos, external_videos, media_updated_at } = + useAnnuncio(); const { t } = useTranslation(); return (

Video: @@ -710,17 +673,23 @@ const AnnuncioFooter = ({ className="h-96 max-w-96" coverImage={getStorageUrl({ storageId: video.thumb, - params: { cacheKey: updated_at?.toISOString(), media: "image" }, + params: { + cacheKey: media_updated_at?.toISOString(), + media: "image", + }, })} key={`videoplayer-${video.video}`} // Cache busting videoSrc={getStorageUrl({ storageId: video.video, - params: { cacheKey: updated_at?.toISOString(), media: "video" }, + params: { + cacheKey: media_updated_at?.toISOString(), + media: "video", + }, })} /> ); })} - {external_videos.map((videoUrl) => { + {external_videos?.map((videoUrl) => { const embedUrl = getYouTubeEmbedUrl(videoUrl); if (!embedUrl) return null; return ( diff --git a/apps/infoalloggi/src/providers/AnnuncioProvider.tsx b/apps/infoalloggi/src/providers/AnnuncioProvider.tsx index e42e181..2ef8404 100644 --- a/apps/infoalloggi/src/providers/AnnuncioProvider.tsx +++ b/apps/infoalloggi/src/providers/AnnuncioProvider.tsx @@ -1,10 +1,7 @@ import { createContext, useContext } from "react"; -import type { Annunci } from "~/schemas/public/Annunci"; +import type { AnnuncioData } from "~/server/controllers/annunci.controller"; -export const AnnuncioContext = createContext | null>(null); +export const AnnuncioContext = createContext(null); export const useAnnuncio = () => { const context = useContext(AnnuncioContext); diff --git a/apps/infoalloggi/src/server/api/routers/annunci.ts b/apps/infoalloggi/src/server/api/routers/annunci.ts index c8fbe20..bfc5efb 100644 --- a/apps/infoalloggi/src/server/api/routers/annunci.ts +++ b/apps/infoalloggi/src/server/api/routers/annunci.ts @@ -11,10 +11,10 @@ import { import { editAnnuncioHandler, get_AnnunciPositionsHandler, - getAnnunciByCod, getAnnunciById_rawImgUrls, getAnnunciListHandler, getAnnunciMetaByCod, + getAnnuncioData, getAnnunciRicerca, getCodici_AnnunciHandler, getOptions_AnnunciHandler, @@ -52,15 +52,14 @@ export const annunciRouter = createTRPCRouter({ getAnnunciOptions: publicProcedure.query(async () => { return await getOptions_AnnunciHandler(); }), - /** TODO da limitare per evitare leak */ - getAnnuncio: publicProcedure + getAnnuncioData: publicProcedure .input( z.object({ cod: z.string(), }), ) .query(async ({ input }) => { - return await getAnnunciByCod({ ...input }); + return await getAnnuncioData({ ...input }); }), getAnnuncioFull: adminProcedure .input( diff --git a/apps/infoalloggi/src/server/controllers/annunci.controller.ts b/apps/infoalloggi/src/server/controllers/annunci.controller.ts index d8511f5..38f9167 100644 --- a/apps/infoalloggi/src/server/controllers/annunci.controller.ts +++ b/apps/infoalloggi/src/server/controllers/annunci.controller.ts @@ -72,26 +72,55 @@ export const getCodici_AnnunciHandler = async (): Promise => { } }; -export const getAnnunciByCod = async ({ - cod, -}: { - cod: string; -}): Promise => { +export type AnnuncioData = Awaited>; +export const getAnnuncioData = async ({ cod }: { cod: string }) => { try { const annuncio = await db .selectFrom("annunci") - .selectAll() + .select([ + "anno", + "accessori", + "caratteristiche", + "categorie", + "desc_en", + "desc_it", + "tipo", + "titolo_it", + "titolo_en", + "stato", + "media_updated_at", + "id", + "codice", + "comune", + "consegna", + "external_videos", + "prezzo", + "numero_camere", + "numero_bagni", + "numero_balconi", + "numero_postiauto", + "numero_box", + "numero_vani", + "numero_terrazzi", + "mq", + "piano", + "piano_palazzo", + "lat_secondario", + "lon_secondario", + "media_updated_at", + ]) .select((_eb) => [withImages(), withVideos()]) .where("annunci.web", "=", true) .where("tipo", "is not", null) .where("codice", "=", cod) - .executeTakeFirst(); - - if (!annuncio || annuncio.tipo === null) { + .executeTakeFirstOrThrow( + () => new Error(`Annuncio non trovato - codice: ${cod}`), + ); + const { tipo, ...rest } = annuncio; + if (tipo === null) { return null; } - - return annuncio as AnnunciWithMedia; + return { tipo, ...rest }; } catch (e) { throw new TRPCError({ cause: (e as Error).cause,