2025-08-07 14:50:40 +02:00
|
|
|
import { z } from "zod/v4";
|
2026-04-28 20:32:19 +02:00
|
|
|
import { AnnunciUpdateSchema, annunciId } from "~/schemas/public/Annunci";
|
|
|
|
|
import { servizioServizioId } from "~/schemas/public/Servizio";
|
2025-08-04 17:45:44 +02:00
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
adminProcedure,
|
2026-01-12 10:05:42 +01:00
|
|
|
apiProcedure,
|
2025-08-28 18:27:07 +02:00
|
|
|
createTRPCRouter,
|
|
|
|
|
protectedProcedure,
|
|
|
|
|
publicProcedure,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/server/api/trpc";
|
|
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
editAnnuncioHandler,
|
|
|
|
|
get_AnnunciPositionsHandler,
|
2025-08-29 18:18:37 +02:00
|
|
|
getAnnunciById_rawImgUrls,
|
2025-08-28 18:27:07 +02:00
|
|
|
getAnnunciListHandler,
|
2026-03-17 18:47:30 +01:00
|
|
|
getAnnuncioData,
|
2025-11-27 13:37:37 +01:00
|
|
|
getAnnunciRicerca,
|
2026-04-03 18:57:39 +02:00
|
|
|
getAnnunciSchedaData,
|
2025-08-28 18:27:07 +02:00
|
|
|
getCodici_AnnunciHandler,
|
|
|
|
|
getOptions_AnnunciHandler,
|
|
|
|
|
getProprietarioDataHandler,
|
2026-03-02 15:35:23 +01:00
|
|
|
type ImgToRemove,
|
|
|
|
|
removeAnnuncioMedia,
|
|
|
|
|
type VideoToRemove,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/server/controllers/annunci.controller";
|
2026-04-16 16:31:25 +02:00
|
|
|
import { getIncrociAnnuncio } from "~/server/controllers/servizio.controller";
|
2026-01-12 10:05:42 +01:00
|
|
|
import { db } from "~/server/db";
|
2026-04-03 18:57:39 +02:00
|
|
|
import { NewMail } from "~/server/services/mailer";
|
|
|
|
|
import { TypstGenerate } from "~/server/services/typst.service";
|
2025-08-04 17:45:44 +02:00
|
|
|
|
|
|
|
|
export const annunciRouter = createTRPCRouter({
|
2025-08-29 16:18:32 +02:00
|
|
|
editAnnuncio: adminProcedure
|
2026-04-28 20:32:19 +02:00
|
|
|
.input(z.object({ annuncioId: annunciId, data: AnnunciUpdateSchema }))
|
2025-08-29 16:18:32 +02:00
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await editAnnuncioHandler({
|
|
|
|
|
...input,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2025-08-28 18:27:07 +02:00
|
|
|
getAnnunciList: publicProcedure.query(async () => {
|
|
|
|
|
return await getAnnunciListHandler();
|
|
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
getAnnunciOptions: publicProcedure.query(async () => {
|
|
|
|
|
return await getOptions_AnnunciHandler();
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
2026-03-17 18:47:30 +01:00
|
|
|
getAnnuncioData: publicProcedure
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
cod: z.string(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
2026-03-19 10:20:41 +01:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
.query(async ({ input }) => {
|
2026-03-17 18:47:30 +01:00
|
|
|
return await getAnnuncioData({ ...input });
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
2026-03-12 16:55:06 +01:00
|
|
|
getAnnuncioFull: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-04-28 20:32:19 +02:00
|
|
|
id: annunciId,
|
2026-03-12 16:55:06 +01:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await db
|
|
|
|
|
.selectFrom("annunci")
|
|
|
|
|
.selectAll()
|
|
|
|
|
.where("id", "=", input.id)
|
|
|
|
|
.executeTakeFirst();
|
|
|
|
|
}),
|
2025-08-29 18:18:37 +02:00
|
|
|
getAnnuncioById_rawImgUrls: publicProcedure
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-04-28 20:32:19 +02:00
|
|
|
id: annunciId,
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ input }) => {
|
2025-08-29 18:18:37 +02:00
|
|
|
return await getAnnunciById_rawImgUrls({ ...input });
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
2026-04-03 18:57:39 +02:00
|
|
|
getSchedaAnnuncioData: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-04-28 20:32:19 +02:00
|
|
|
id: annunciId,
|
2026-04-03 18:57:39 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await getAnnunciSchedaData(input.id);
|
|
|
|
|
}),
|
|
|
|
|
getSchedaAnnuncioPdf: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-04-28 20:32:19 +02:00
|
|
|
id: annunciId,
|
2026-04-03 18:57:39 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
const data = await getAnnunciSchedaData(input.id);
|
|
|
|
|
const pdfBuffer = await TypstGenerate({
|
|
|
|
|
templateId: "annuncio.typ",
|
|
|
|
|
data,
|
|
|
|
|
});
|
|
|
|
|
return {
|
|
|
|
|
pdf: pdfBuffer.toString("base64"),
|
|
|
|
|
title: `scheda-annuncio-${data.codice}.pdf`,
|
|
|
|
|
};
|
|
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
getCodici: publicProcedure.query(async () => {
|
|
|
|
|
return await getCodici_AnnunciHandler();
|
|
|
|
|
}),
|
2025-08-28 18:27:07 +02:00
|
|
|
getMapping: publicProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
comune: z.string().optional(),
|
2025-12-29 18:33:00 +01:00
|
|
|
consegna: z.number().array().optional(),
|
2025-08-29 16:18:32 +02:00
|
|
|
tipologia: z.string().optional(),
|
2025-12-29 19:10:46 +01:00
|
|
|
minBudget: z.number().optional(),
|
|
|
|
|
maxBudget: z.number().optional(),
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await get_AnnunciPositionsHandler({
|
|
|
|
|
...input,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
getProprietarioData: protectedProcedure
|
2026-04-28 20:32:19 +02:00
|
|
|
.input(z.object({ annuncioId: annunciId, servizioId: servizioServizioId }))
|
2025-08-28 18:27:07 +02:00
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await getProprietarioDataHandler({
|
|
|
|
|
annuncioId: input.annuncioId,
|
|
|
|
|
servizioId: input.servizioId,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2025-11-27 13:37:37 +01:00
|
|
|
|
|
|
|
|
annunciRicerca: publicProcedure
|
2025-08-29 16:18:32 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
comune: z.string().optional(),
|
2025-12-29 18:33:00 +01:00
|
|
|
consegna: z.number().array().optional(),
|
2025-08-29 16:18:32 +02:00
|
|
|
sort: z.enum(["Recenti", "Prezzo", "Consegna", "Mq"]).optional(),
|
|
|
|
|
tipologia: z.string().optional(),
|
2025-12-29 19:10:46 +01:00
|
|
|
minBudget: z.number().optional(),
|
|
|
|
|
maxBudget: z.number().optional(),
|
2025-08-29 16:18:32 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ input }) => {
|
2025-11-27 13:37:37 +01:00
|
|
|
return await getAnnunciRicerca({
|
2025-08-29 16:18:32 +02:00
|
|
|
...input,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2026-03-05 12:32:03 +01:00
|
|
|
/**Used for cron job */
|
2026-01-12 10:05:42 +01:00
|
|
|
checkAnnunci: apiProcedure.query(async () => {
|
|
|
|
|
const hasAnnunci = await db
|
|
|
|
|
.selectFrom("annunci")
|
|
|
|
|
.select("id")
|
|
|
|
|
.where("stato", "=", "Attivo")
|
|
|
|
|
.where("web", "is", true)
|
|
|
|
|
.execute();
|
|
|
|
|
if (hasAnnunci.length === 0) {
|
|
|
|
|
await NewMail({
|
|
|
|
|
template: {
|
|
|
|
|
mailType: "generic",
|
|
|
|
|
props: {
|
|
|
|
|
title: "Attenzione: Nessun annuncio attivo!",
|
|
|
|
|
testo:
|
|
|
|
|
"Nel sistema non è presente nessun annuncio con stato Attivo e visibile sul web.",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
mail: {
|
|
|
|
|
subject: "Attenzione: Nessun annuncio attivo!",
|
|
|
|
|
to: "m.pedone98@gmail.com",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return { status: "no_annunci", timestamp: Date.now() };
|
|
|
|
|
}
|
|
|
|
|
return { status: "ok", timestamp: Date.now() };
|
|
|
|
|
}),
|
2026-03-02 15:35:23 +01:00
|
|
|
removeAnnuncioMedia: adminProcedure
|
|
|
|
|
.input(z.custom<ImgToRemove | VideoToRemove>())
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await removeAnnuncioMedia({
|
|
|
|
|
...input,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2026-04-16 16:31:25 +02:00
|
|
|
getIncrociAnnuncio: protectedProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
2026-04-28 20:32:19 +02:00
|
|
|
annuncioId: annunciId,
|
2026-04-16 16:31:25 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await getIncrociAnnuncio(input.annuncioId);
|
|
|
|
|
}),
|
2025-08-04 17:45:44 +02:00
|
|
|
});
|