2025-08-28 18:27:07 +02:00
|
|
|
import { TRPCError } from "@trpc/server";
|
2025-10-20 16:22:20 +02:00
|
|
|
import { env } from "~/env";
|
2025-11-28 15:11:14 +01:00
|
|
|
import { getStorageUrl } from "~/lib/storage_utils";
|
2025-08-28 12:37:32 +02:00
|
|
|
import type {
|
2025-08-28 18:27:07 +02:00
|
|
|
Annunci,
|
|
|
|
|
AnnunciId,
|
|
|
|
|
AnnunciUpdate,
|
2025-08-28 12:37:32 +02:00
|
|
|
} from "~/schemas/public/Annunci";
|
2025-10-27 17:58:42 +01:00
|
|
|
import type { ImagesRefs } from "~/schemas/public/ImagesRefs";
|
2025-08-04 17:45:44 +02:00
|
|
|
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
2025-11-18 15:20:14 +01:00
|
|
|
import type { VideosRefs } from "~/schemas/public/VideosRefs";
|
2025-08-28 18:27:07 +02:00
|
|
|
import { db } from "~/server/db";
|
2025-11-18 15:20:14 +01:00
|
|
|
import { withImages, withVideos } from "~/utils/kysely-helper";
|
2025-10-17 19:14:27 +02:00
|
|
|
import { revalidate } from "../utils/revalidationHelper";
|
2025-08-04 17:45:44 +02:00
|
|
|
|
|
|
|
|
// const ratelimit = new RateLimiterHandler({
|
|
|
|
|
// windowSize: 10,
|
|
|
|
|
// maxRequests: 10,
|
|
|
|
|
// analytics: true,
|
|
|
|
|
// });
|
2025-11-18 15:20:14 +01:00
|
|
|
export type AnnunciWithMedia = Annunci & {
|
2026-01-20 18:38:17 +01:00
|
|
|
tipo: string;
|
2025-10-27 17:58:42 +01:00
|
|
|
images: Pick<ImagesRefs, "img" | "thumb">[];
|
2025-11-18 15:20:14 +01:00
|
|
|
videos: Pick<VideosRefs, "video" | "thumb">[];
|
2025-10-27 17:58:42 +01:00
|
|
|
};
|
2025-08-04 17:45:44 +02:00
|
|
|
|
|
|
|
|
export const getAnnunciListHandler = async (): Promise<
|
2025-08-28 18:27:07 +02:00
|
|
|
Pick<
|
|
|
|
|
Annunci,
|
|
|
|
|
"id" | "codice" | "titolo_it" | "comune" | "tipo" | "locatore" | "stato"
|
|
|
|
|
>[]
|
2025-08-04 17:45:44 +02:00
|
|
|
> => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
return await db
|
|
|
|
|
.selectFrom("annunci")
|
|
|
|
|
.select([
|
|
|
|
|
"id",
|
|
|
|
|
"codice",
|
|
|
|
|
"titolo_it",
|
|
|
|
|
"comune",
|
|
|
|
|
"tipo",
|
|
|
|
|
"locatore",
|
|
|
|
|
"stato",
|
|
|
|
|
])
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore query getAllRaw: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getCodici_AnnunciHandler = async (): Promise<string[]> => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
const codici = await db
|
|
|
|
|
.selectFrom("annunci")
|
|
|
|
|
.select("codice")
|
|
|
|
|
.where("annunci.web", "=", true)
|
|
|
|
|
.where("stato", "!=", "Sospeso")
|
|
|
|
|
.execute();
|
|
|
|
|
if (!codici) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return codici.map((c) => c.codice);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore query getCodici: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
2026-03-17 18:47:30 +01:00
|
|
|
export type AnnuncioData = Awaited<ReturnType<typeof getAnnuncioData>>;
|
|
|
|
|
export const getAnnuncioData = async ({ cod }: { cod: string }) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
const annuncio = await db
|
|
|
|
|
.selectFrom("annunci")
|
2026-03-17 18:47:30 +01:00
|
|
|
.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",
|
|
|
|
|
])
|
2025-11-18 15:20:14 +01:00
|
|
|
.select((_eb) => [withImages(), withVideos()])
|
2025-08-28 18:27:07 +02:00
|
|
|
.where("annunci.web", "=", true)
|
2026-01-20 18:38:17 +01:00
|
|
|
.where("tipo", "is not", null)
|
2025-08-28 18:27:07 +02:00
|
|
|
.where("codice", "=", cod)
|
2026-03-17 18:47:30 +01:00
|
|
|
.executeTakeFirstOrThrow(
|
|
|
|
|
() => new Error(`Annuncio non trovato - codice: ${cod}`),
|
|
|
|
|
);
|
|
|
|
|
const { tipo, ...rest } = annuncio;
|
|
|
|
|
if (tipo === null) {
|
2025-08-28 18:27:07 +02:00
|
|
|
return null;
|
|
|
|
|
}
|
2026-03-17 18:47:30 +01:00
|
|
|
return { tipo, ...rest };
|
2025-08-28 18:27:07 +02:00
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
2025-08-29 16:18:32 +02:00
|
|
|
cause: (e as Error).cause,
|
2025-08-28 18:27:07 +02:00
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore query getAnnunciByCod: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-08 13:30:21 +02:00
|
|
|
};
|
|
|
|
|
export const getAnnunciMetaByCod = async ({ cod }: { cod: string }) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
const annuncio = await db
|
|
|
|
|
.selectFrom("annunci")
|
2025-11-24 18:03:13 +01:00
|
|
|
.select((_eb) => [
|
|
|
|
|
"titolo_it",
|
|
|
|
|
"desc_it",
|
|
|
|
|
withImages(),
|
|
|
|
|
"media_updated_at",
|
|
|
|
|
])
|
2025-08-28 18:27:07 +02:00
|
|
|
.where("annunci.web", "=", true)
|
|
|
|
|
.where("codice", "=", cod)
|
|
|
|
|
.executeTakeFirst();
|
|
|
|
|
if (!annuncio) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2025-10-07 18:07:57 +02:00
|
|
|
const ogImage =
|
2025-10-27 17:58:42 +01:00
|
|
|
annuncio.images && annuncio.images.length > 0 && annuncio.images[0]
|
2025-11-28 15:11:14 +01:00
|
|
|
? getStorageUrl({
|
|
|
|
|
storageId: annuncio.images[0].img,
|
|
|
|
|
params: {
|
|
|
|
|
cacheKey: annuncio.media_updated_at?.toISOString(),
|
|
|
|
|
media: "image",
|
|
|
|
|
},
|
|
|
|
|
host: env.BASE_URL,
|
|
|
|
|
})
|
2025-10-27 17:58:42 +01:00
|
|
|
: `${env.BASE_URL}/og.jpg`;
|
2025-08-08 13:30:21 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return {
|
|
|
|
|
description: annuncio.desc_it || "",
|
2025-10-07 18:07:57 +02:00
|
|
|
ogImage,
|
2025-10-20 16:39:59 +02:00
|
|
|
ogUrl: `${env.BASE_URL}/annuncio/${cod}`,
|
2025-08-29 16:18:32 +02:00
|
|
|
title: annuncio.titolo_it || "",
|
2025-08-28 18:27:07 +02:00
|
|
|
};
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore query getAnnunciMetaByCod: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
2025-08-29 18:18:37 +02:00
|
|
|
export const getAnnunciById_rawImgUrls = async ({
|
2025-08-28 18:27:07 +02:00
|
|
|
id,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
id: AnnunciId;
|
2025-11-18 15:20:14 +01:00
|
|
|
}): Promise<AnnunciWithMedia | null> => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
const annuncio = await db
|
|
|
|
|
.selectFrom("annunci")
|
|
|
|
|
.selectAll()
|
2025-11-18 15:20:14 +01:00
|
|
|
.select((_eb) => [withImages(), withVideos()])
|
2025-08-28 18:27:07 +02:00
|
|
|
.where("id", "=", id)
|
2026-01-20 18:38:17 +01:00
|
|
|
.where("tipo", "is not", null)
|
2025-08-28 18:27:07 +02:00
|
|
|
.executeTakeFirst();
|
2026-01-20 18:38:17 +01:00
|
|
|
if (!annuncio || annuncio.tipo === null) {
|
2025-08-28 18:27:07 +02:00
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "NOT_FOUND",
|
|
|
|
|
message: "Annuncio non trovato",
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2026-01-20 18:38:17 +01:00
|
|
|
return annuncio as AnnunciWithMedia;
|
2025-08-28 18:27:07 +02:00
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore query getAnnuncioById : ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export type AnnuncioRicercaWPosition = AnnuncioRicerca & {
|
2025-08-28 18:27:07 +02:00
|
|
|
lat_secondario: string | null;
|
|
|
|
|
lon_secondario: string | null;
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const get_AnnunciPositionsHandler = async ({
|
2025-08-28 18:27:07 +02:00
|
|
|
tipologia,
|
|
|
|
|
comune,
|
|
|
|
|
consegna,
|
2025-12-29 19:10:46 +01:00
|
|
|
minBudget,
|
|
|
|
|
maxBudget,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
tipologia?: string;
|
|
|
|
|
comune?: string;
|
2025-12-29 18:33:00 +01:00
|
|
|
consegna?: number[];
|
2025-12-29 19:10:46 +01:00
|
|
|
minBudget?: number;
|
|
|
|
|
maxBudget?: number;
|
2025-08-04 17:45:44 +02:00
|
|
|
}): Promise<AnnuncioRicercaWPosition[]> => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
let query = db
|
|
|
|
|
.selectFrom("annunci")
|
2025-11-18 15:20:14 +01:00
|
|
|
.select((_eb) => [
|
2025-08-28 18:27:07 +02:00
|
|
|
"id",
|
|
|
|
|
"codice",
|
|
|
|
|
"comune",
|
|
|
|
|
"provincia",
|
|
|
|
|
"prezzo",
|
|
|
|
|
"consegna",
|
|
|
|
|
"numero_camere",
|
|
|
|
|
"mq",
|
|
|
|
|
"tipo",
|
|
|
|
|
"titolo_it",
|
|
|
|
|
"titolo_en",
|
2025-11-07 17:03:08 +01:00
|
|
|
"desc_en",
|
|
|
|
|
"desc_it",
|
|
|
|
|
"web",
|
2025-08-28 18:27:07 +02:00
|
|
|
"modificato_il",
|
|
|
|
|
"stato",
|
2025-11-18 15:20:14 +01:00
|
|
|
"external_videos",
|
2025-08-28 18:27:07 +02:00
|
|
|
"lon_secondario",
|
|
|
|
|
"lat_secondario",
|
2025-11-06 13:17:20 +01:00
|
|
|
"media_updated_at",
|
2025-11-03 18:49:27 +01:00
|
|
|
"homepage",
|
2025-11-18 15:20:14 +01:00
|
|
|
withImages(),
|
|
|
|
|
withVideos(),
|
2025-08-28 18:27:07 +02:00
|
|
|
])
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
.where("web", "=", true)
|
|
|
|
|
.where("stato", "!=", "Sospeso")
|
|
|
|
|
.orderBy("id", "asc");
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
if (tipologia && tipologia !== "") {
|
|
|
|
|
query = query.where("tipo", "=", tipologia);
|
|
|
|
|
}
|
|
|
|
|
if (comune && comune !== "") {
|
|
|
|
|
query = query.where("comune", "like", comune);
|
|
|
|
|
}
|
|
|
|
|
if (consegna) {
|
2025-12-29 18:33:00 +01:00
|
|
|
query = query.where("consegna", "in", consegna);
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-12-29 19:10:46 +01:00
|
|
|
if (minBudget) {
|
|
|
|
|
query = query.where("prezzo", ">=", minBudget);
|
|
|
|
|
}
|
|
|
|
|
if (maxBudget) {
|
|
|
|
|
query = query.where("prezzo", "<=", maxBudget);
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
const annunci = await query.execute();
|
|
|
|
|
if (!annunci) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return annunci;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore query getAnnunciPositions: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export type AnnuncioRicerca = Pick<
|
2025-08-28 18:27:07 +02:00
|
|
|
Annunci,
|
|
|
|
|
| "id"
|
|
|
|
|
| "codice"
|
|
|
|
|
| "comune"
|
|
|
|
|
| "provincia"
|
|
|
|
|
| "prezzo"
|
|
|
|
|
| "consegna"
|
|
|
|
|
| "numero_camere"
|
|
|
|
|
| "mq"
|
|
|
|
|
| "tipo"
|
|
|
|
|
| "titolo_it"
|
|
|
|
|
| "titolo_en"
|
2025-11-07 17:03:08 +01:00
|
|
|
| "desc_en"
|
|
|
|
|
| "desc_it"
|
2025-08-28 18:27:07 +02:00
|
|
|
| "modificato_il"
|
|
|
|
|
| "stato"
|
2025-11-18 15:20:14 +01:00
|
|
|
| "external_videos"
|
2025-11-06 13:17:20 +01:00
|
|
|
| "media_updated_at"
|
2025-11-03 18:49:27 +01:00
|
|
|
| "homepage"
|
2025-11-07 17:03:08 +01:00
|
|
|
| "web"
|
2025-10-27 17:58:42 +01:00
|
|
|
> & {
|
|
|
|
|
images: Pick<ImagesRefs, "img" | "thumb">[];
|
2025-11-18 15:20:14 +01:00
|
|
|
videos: Pick<VideosRefs, "video" | "thumb">[];
|
2025-10-27 17:58:42 +01:00
|
|
|
};
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-11-27 13:37:37 +01:00
|
|
|
export const getAnnunciRicerca = async ({
|
2025-08-28 18:27:07 +02:00
|
|
|
tipologia,
|
|
|
|
|
comune,
|
|
|
|
|
consegna,
|
|
|
|
|
sort,
|
2025-12-29 19:10:46 +01:00
|
|
|
minBudget,
|
|
|
|
|
maxBudget,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
tipologia?: string;
|
|
|
|
|
comune?: string;
|
2025-12-29 18:33:00 +01:00
|
|
|
consegna?: number[];
|
2025-08-28 18:27:07 +02:00
|
|
|
sort?: "Recenti" | "Prezzo" | "Consegna" | "Mq";
|
2025-12-29 19:10:46 +01:00
|
|
|
minBudget?: number;
|
|
|
|
|
maxBudget?: number;
|
2025-11-27 13:37:37 +01:00
|
|
|
}): Promise<AnnuncioRicerca[]> => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
let query = db
|
|
|
|
|
.selectFrom("annunci")
|
2025-11-18 15:20:14 +01:00
|
|
|
.select((_eb) => [
|
2025-08-28 18:27:07 +02:00
|
|
|
"id",
|
|
|
|
|
"codice",
|
|
|
|
|
"comune",
|
|
|
|
|
"provincia",
|
|
|
|
|
"prezzo",
|
|
|
|
|
"consegna",
|
|
|
|
|
"numero_camere",
|
|
|
|
|
"mq",
|
|
|
|
|
"tipo",
|
|
|
|
|
"titolo_it",
|
|
|
|
|
"titolo_en",
|
2025-11-07 17:03:08 +01:00
|
|
|
"desc_en",
|
|
|
|
|
"desc_it",
|
|
|
|
|
"web",
|
2025-08-28 18:27:07 +02:00
|
|
|
"modificato_il",
|
|
|
|
|
"stato",
|
2025-11-18 15:20:14 +01:00
|
|
|
"external_videos",
|
2025-11-06 13:17:20 +01:00
|
|
|
"media_updated_at",
|
2025-11-03 18:49:27 +01:00
|
|
|
"homepage",
|
2025-11-18 15:20:14 +01:00
|
|
|
withImages(),
|
|
|
|
|
withVideos(),
|
2025-08-28 18:27:07 +02:00
|
|
|
])
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
.where("web", "=", true)
|
|
|
|
|
.where("stato", "!=", "Sospeso");
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
if (tipologia && tipologia !== "") {
|
|
|
|
|
query = query.where("tipo", "=", tipologia);
|
|
|
|
|
}
|
|
|
|
|
if (comune && comune !== "") {
|
|
|
|
|
query = query.where("comune", "like", comune);
|
|
|
|
|
}
|
|
|
|
|
if (consegna) {
|
2025-12-29 18:33:00 +01:00
|
|
|
query = query.where("consegna", "in", consegna);
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-12-29 19:10:46 +01:00
|
|
|
if (minBudget) {
|
|
|
|
|
query = query.where("prezzo", ">=", minBudget);
|
|
|
|
|
}
|
|
|
|
|
if (maxBudget) {
|
|
|
|
|
query = query.where("prezzo", "<=", maxBudget);
|
|
|
|
|
}
|
2025-09-01 16:48:03 +02:00
|
|
|
|
|
|
|
|
switch (sort) {
|
|
|
|
|
case "Recenti":
|
|
|
|
|
query = query.orderBy("modificato_il", "desc");
|
|
|
|
|
break;
|
|
|
|
|
case "Prezzo":
|
|
|
|
|
query = query.orderBy("prezzo", "asc");
|
|
|
|
|
break;
|
|
|
|
|
case "Consegna":
|
|
|
|
|
query = query.orderBy("consegna", "asc");
|
|
|
|
|
break;
|
|
|
|
|
case "Mq":
|
|
|
|
|
query = query.orderBy("mq", "asc");
|
|
|
|
|
break;
|
|
|
|
|
case undefined:
|
|
|
|
|
break;
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-09-01 16:48:03 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
query = query.orderBy("id", "asc");
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-11-27 13:37:37 +01:00
|
|
|
return await query.execute();
|
2025-08-28 18:27:07 +02:00
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
2025-11-27 13:37:37 +01:00
|
|
|
message: `Errore query ricercaAnnunci: ${(e as Error).message}`,
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getOptions_AnnunciHandler = async () => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
const comuni = await db
|
|
|
|
|
.selectFrom("annunci")
|
2025-12-29 19:10:46 +01:00
|
|
|
.select(["comune", "tipo", "consegna", "prezzo"])
|
2025-08-28 18:27:07 +02:00
|
|
|
.where("web", "=", true)
|
|
|
|
|
.where("stato", "!=", "Sospeso")
|
|
|
|
|
.distinct()
|
|
|
|
|
.execute();
|
2025-12-29 19:10:46 +01:00
|
|
|
const results: {
|
|
|
|
|
comune: string;
|
|
|
|
|
tipo: string;
|
|
|
|
|
consegna: number;
|
|
|
|
|
prezzo: number;
|
|
|
|
|
}[] = [];
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
for (const comune of comuni) {
|
2025-12-29 19:10:46 +01:00
|
|
|
if (comune.comune && comune.tipo && comune.consegna && comune.prezzo) {
|
2025-08-28 18:27:07 +02:00
|
|
|
results.push({
|
|
|
|
|
comune: comune.comune,
|
|
|
|
|
consegna: comune.consegna,
|
2025-08-29 16:18:32 +02:00
|
|
|
tipo: comune.tipo,
|
2025-12-29 19:10:46 +01:00
|
|
|
prezzo: comune.prezzo,
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return results;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore query getComuni: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const editAnnuncioHandler = async ({
|
2025-08-28 18:27:07 +02:00
|
|
|
annuncioId,
|
|
|
|
|
data,
|
2025-08-28 12:37:32 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
annuncioId: AnnunciId;
|
|
|
|
|
data: AnnunciUpdate;
|
2025-08-28 12:37:32 +02:00
|
|
|
}) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
2025-10-17 19:14:27 +02:00
|
|
|
const annuncio = await db
|
2025-08-28 18:27:07 +02:00
|
|
|
.updateTable("annunci")
|
|
|
|
|
.set({
|
|
|
|
|
...data,
|
2025-11-06 13:17:20 +01:00
|
|
|
modificato_il: new Date(),
|
2025-08-28 18:27:07 +02:00
|
|
|
})
|
|
|
|
|
.where("id", "=", annuncioId)
|
2025-10-17 19:14:27 +02:00
|
|
|
.returning("codice")
|
2026-03-05 10:29:08 +01:00
|
|
|
.executeTakeFirstOrThrow(() => {
|
|
|
|
|
throw new Error(`Annuncio not found - annuncioId: ${annuncioId}`);
|
|
|
|
|
});
|
2025-10-17 19:14:27 +02:00
|
|
|
await revalidate(`/annuncio/${annuncio.codice}`);
|
2025-08-28 18:27:07 +02:00
|
|
|
return true;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore interno: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getProprietarioDataHandler = async ({
|
2025-08-28 18:27:07 +02:00
|
|
|
annuncioId,
|
|
|
|
|
servizioId,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
annuncioId: AnnunciId;
|
|
|
|
|
servizioId: ServizioServizioId;
|
2025-08-04 17:45:44 +02:00
|
|
|
}) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
try {
|
|
|
|
|
const opened_at = await db
|
|
|
|
|
.selectFrom("servizio_annunci")
|
|
|
|
|
.select("open_contatti_at")
|
|
|
|
|
.where("servizio_id", "=", servizioId)
|
|
|
|
|
.where("annunci_id", "=", annuncioId)
|
|
|
|
|
.executeTakeFirst();
|
|
|
|
|
if (!opened_at || !opened_at.open_contatti_at) {
|
2025-08-29 16:18:32 +02:00
|
|
|
return { opened_at: null, propData: null };
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
const propData = await db
|
|
|
|
|
.selectFrom("annunci")
|
|
|
|
|
.select([
|
|
|
|
|
"codice",
|
|
|
|
|
"comune",
|
|
|
|
|
"indirizzo",
|
|
|
|
|
"civico",
|
|
|
|
|
"provincia",
|
|
|
|
|
"regione",
|
|
|
|
|
"cap",
|
|
|
|
|
"lat",
|
|
|
|
|
"lon",
|
|
|
|
|
"numero",
|
|
|
|
|
"locatore",
|
|
|
|
|
])
|
|
|
|
|
.where("id", "=", annuncioId)
|
2026-03-05 10:29:08 +01:00
|
|
|
.executeTakeFirstOrThrow(() => {
|
|
|
|
|
throw new Error(`Annuncio not found - annuncioId: ${annuncioId}`);
|
|
|
|
|
});
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-29 16:18:32 +02:00
|
|
|
return { opened_at: opened_at.open_contatti_at, propData };
|
2025-08-28 18:27:07 +02:00
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore recupero dati proprietario: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
2026-03-02 15:35:23 +01:00
|
|
|
|
|
|
|
|
export type ImgToRemove = {
|
|
|
|
|
type: "img";
|
|
|
|
|
id: ImagesRefs["img"];
|
|
|
|
|
};
|
|
|
|
|
export type VideoToRemove = {
|
|
|
|
|
type: "video";
|
|
|
|
|
id: VideosRefs["video"];
|
|
|
|
|
};
|
|
|
|
|
export const removeAnnuncioMedia = async ({
|
|
|
|
|
id,
|
|
|
|
|
type,
|
|
|
|
|
}: ImgToRemove | VideoToRemove) => {
|
|
|
|
|
try {
|
|
|
|
|
if (type === "img") {
|
|
|
|
|
await db.deleteFrom("images_refs").where("img", "=", id).execute();
|
|
|
|
|
}
|
|
|
|
|
if (type === "video") {
|
|
|
|
|
await db.deleteFrom("videos_refs").where("video", "=", id).execute();
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: `Errore rimozione media: ${(e as Error).message}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|