2025-10-15 15:45:24 +02:00
|
|
|
import { TRPCError } from "@trpc/server";
|
2025-08-07 14:50:40 +02:00
|
|
|
import { z } from "zod/v4";
|
2025-10-20 16:22:20 +02:00
|
|
|
import { env } from "~/env";
|
2025-08-04 17:45:44 +02:00
|
|
|
import type { BannersIdbanner } from "~/schemas/public/Banners";
|
|
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
adminProcedure,
|
|
|
|
|
createTRPCRouter,
|
|
|
|
|
publicProcedure,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/server/api/trpc";
|
2025-10-17 19:14:27 +02:00
|
|
|
import { getCodici_AnnunciHandler } from "~/server/controllers/annunci.controller";
|
2025-08-04 17:45:44 +02:00
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
addEtichetta,
|
|
|
|
|
getAllEtichette,
|
|
|
|
|
removeEtichetta,
|
|
|
|
|
updateEtichetta,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/server/controllers/etichette.controller";
|
|
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
AddFlagHandler,
|
|
|
|
|
EditFlagHandler,
|
|
|
|
|
GetFlagHandler,
|
|
|
|
|
GetFlagValueHandler,
|
|
|
|
|
RemoveFlagHandler,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/server/controllers/flags.controller";
|
|
|
|
|
import { db } from "~/server/db";
|
|
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
addBanner,
|
|
|
|
|
deleteBanner,
|
|
|
|
|
getAllBanners,
|
|
|
|
|
getBanner,
|
|
|
|
|
updateBanner,
|
|
|
|
|
} from "~/server/services/banners.service";
|
|
|
|
|
import {
|
|
|
|
|
deleteStringa,
|
|
|
|
|
getStringa,
|
|
|
|
|
getStringhe,
|
|
|
|
|
getStringheFiltered,
|
|
|
|
|
newStringa,
|
|
|
|
|
updateStringhe,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/server/services/testi_stringhe.service";
|
2025-10-17 19:14:27 +02:00
|
|
|
import {
|
|
|
|
|
revalidate,
|
|
|
|
|
revalidateMultiple,
|
|
|
|
|
} from "~/server/utils/revalidationHelper";
|
2025-08-04 17:45:44 +02:00
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
zEtichettaId,
|
|
|
|
|
zFlagsId,
|
|
|
|
|
zTestiEStringheStingaId,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/server/utils/zod_types";
|
|
|
|
|
|
|
|
|
|
export const settingsRouter = createTRPCRouter({
|
2025-08-28 18:27:07 +02:00
|
|
|
AddFlag: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
id: zFlagsId,
|
|
|
|
|
value: z.string(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await AddFlagHandler({ db, input });
|
|
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
addBanner: adminProcedure
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
2025-08-29 16:18:32 +02:00
|
|
|
color: z.string().nullable(),
|
|
|
|
|
cta_href: z.string().nullable(),
|
|
|
|
|
cta_icon: z.string().nullable(),
|
|
|
|
|
cta_text: z.string().nullable(),
|
|
|
|
|
has_cta: z.boolean(),
|
|
|
|
|
hide_duration: z.number().nullable(),
|
|
|
|
|
idbanner: z.custom<BannersIdbanner>(),
|
|
|
|
|
is_active: z.boolean(),
|
|
|
|
|
is_unskippable: z.boolean(),
|
|
|
|
|
show_private: z.boolean(),
|
|
|
|
|
show_public: z.boolean(),
|
|
|
|
|
testo: z.string().nullable(),
|
|
|
|
|
titolo: z.string().nullable(),
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
2025-08-29 16:18:32 +02:00
|
|
|
return await addBanner({ db, input });
|
|
|
|
|
}),
|
|
|
|
|
addEtichetta: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
color_hex: z.string().max(7),
|
|
|
|
|
title: z.string(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await addEtichetta({
|
|
|
|
|
color_hex: input.color_hex,
|
|
|
|
|
db,
|
|
|
|
|
title: input.title,
|
|
|
|
|
});
|
|
|
|
|
}),
|
|
|
|
|
deleteBanner: adminProcedure
|
|
|
|
|
.input(z.object({ idbanner: z.custom<BannersIdbanner>() }))
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await deleteBanner({ db, input });
|
|
|
|
|
}),
|
|
|
|
|
deleteStringa: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
stringaId: zTestiEStringheStingaId,
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await deleteStringa({
|
|
|
|
|
db,
|
|
|
|
|
stringaId: input.stringaId,
|
|
|
|
|
});
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
EditFlag: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
id: zFlagsId,
|
|
|
|
|
value: z.string(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await EditFlagHandler({ db, input });
|
|
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
// Flags routes
|
|
|
|
|
GetFlags: adminProcedure.query(async () => {
|
|
|
|
|
return await GetFlagHandler({ db });
|
|
|
|
|
}),
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
GetFlagValue: publicProcedure
|
|
|
|
|
.input(z.object({ id: z.string() }))
|
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await GetFlagValueHandler({ db, id: input.id });
|
|
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
|
|
|
|
|
// Etichette routes
|
|
|
|
|
getAllEtichette: adminProcedure.query(async () => {
|
|
|
|
|
return await getAllEtichette({ db });
|
|
|
|
|
}),
|
|
|
|
|
getBannerAllData: publicProcedure.query(async () => {
|
|
|
|
|
return await getAllBanners({ db });
|
|
|
|
|
}),
|
2025-08-28 18:27:07 +02:00
|
|
|
// Banner routes
|
|
|
|
|
getBannerData: publicProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
area_riservata: z.boolean(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await getBanner({
|
|
|
|
|
area_riservata: input.area_riservata,
|
2025-08-29 16:18:32 +02:00
|
|
|
db,
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
|
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
getStringa: publicProcedure
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
2025-08-29 16:18:32 +02:00
|
|
|
stringaId: zTestiEStringheStingaId,
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
)
|
2025-08-29 16:18:32 +02:00
|
|
|
.query(async ({ input }) => {
|
|
|
|
|
return await getStringa({
|
|
|
|
|
db,
|
|
|
|
|
stringaId: input.stringaId,
|
|
|
|
|
});
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-29 16:18:32 +02:00
|
|
|
// Testi e stringhe routes
|
|
|
|
|
getStringhe: adminProcedure.query(async () => {
|
|
|
|
|
return await getStringhe({ db });
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
getStringheCondizioni: adminProcedure.query(async () => {
|
|
|
|
|
return await getStringheFiltered({ contains: "CONDIZIONI", db });
|
|
|
|
|
}),
|
|
|
|
|
newStringa: adminProcedure
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
2025-08-29 16:18:32 +02:00
|
|
|
stringaId: zTestiEStringheStingaId,
|
|
|
|
|
stringaValue: z.string().nullable(),
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
2025-08-29 16:18:32 +02:00
|
|
|
return await newStringa({
|
2025-08-28 18:27:07 +02:00
|
|
|
db,
|
2025-08-29 16:18:32 +02:00
|
|
|
stringaId: input.stringaId,
|
|
|
|
|
stringaValue: input.stringaValue,
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
|
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
RemoveFlag: adminProcedure
|
|
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
2025-08-29 16:18:32 +02:00
|
|
|
id: zFlagsId,
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
2025-08-29 16:18:32 +02:00
|
|
|
return await RemoveFlagHandler({ db, id: input.id });
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
removeEtichetta: adminProcedure
|
|
|
|
|
.input(z.object({ id_etichetta: zEtichettaId }))
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await removeEtichetta({
|
|
|
|
|
db,
|
|
|
|
|
etichettaid: input.id_etichetta,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
updateBanner: adminProcedure
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
2025-08-29 16:18:32 +02:00
|
|
|
color: z.string().nullable(),
|
|
|
|
|
cta_href: z.string().nullable(),
|
|
|
|
|
cta_icon: z.string().nullable(),
|
|
|
|
|
cta_text: z.string().nullable(),
|
|
|
|
|
has_cta: z.boolean(),
|
|
|
|
|
hide_duration: z.number().nullable(),
|
|
|
|
|
idbanner: z.custom<BannersIdbanner>(),
|
|
|
|
|
is_active: z.boolean(),
|
|
|
|
|
is_unskippable: z.boolean(),
|
|
|
|
|
show_private: z.boolean(),
|
|
|
|
|
show_public: z.boolean(),
|
|
|
|
|
testo: z.string().nullable(),
|
|
|
|
|
titolo: z.string().nullable(),
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
)
|
2025-08-29 16:18:32 +02:00
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await updateBanner({ db, input });
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
2025-08-29 16:18:32 +02:00
|
|
|
updateEtichetta: adminProcedure
|
2025-08-28 18:27:07 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
2025-08-29 16:18:32 +02:00
|
|
|
color_hex: z.string().max(7),
|
|
|
|
|
id_etichetta: zEtichettaId,
|
|
|
|
|
title: z.string(),
|
2025-08-28 18:27:07 +02:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
2025-08-29 16:18:32 +02:00
|
|
|
return await updateEtichetta({
|
|
|
|
|
color_hex: input.color_hex,
|
2025-08-28 18:27:07 +02:00
|
|
|
db,
|
2025-08-29 16:18:32 +02:00
|
|
|
etichettaid: input.id_etichetta,
|
|
|
|
|
title: input.title,
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
|
|
|
|
}),
|
|
|
|
|
updateStringa: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
stringaId: zTestiEStringheStingaId,
|
|
|
|
|
stringaValue: z.string().nullable(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
return await updateStringhe({
|
|
|
|
|
db,
|
|
|
|
|
stringaId: input.stringaId,
|
|
|
|
|
stringaValue: input.stringaValue,
|
|
|
|
|
});
|
|
|
|
|
}),
|
2025-10-15 15:45:24 +02:00
|
|
|
revalidateAllAnnunci: adminProcedure.mutation(async () => {
|
2025-10-17 19:14:27 +02:00
|
|
|
try {
|
|
|
|
|
const annunciOnline = await getCodici_AnnunciHandler();
|
|
|
|
|
const { success, failed } = await revalidateMultiple(
|
|
|
|
|
annunciOnline.map((cod) => `/annuncio/${cod}`),
|
|
|
|
|
);
|
|
|
|
|
console.log(`Successfully revalidated pages: ${success.join(", ")}`);
|
|
|
|
|
if (failed.length > 0) {
|
|
|
|
|
failed.forEach(({ path, error }) => {
|
|
|
|
|
console.error(`Failed to revalidate ${path}: ${error}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
status: "success",
|
|
|
|
|
};
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error("Revalidation error:", err);
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: err instanceof Error ? err.message : "Revalidation failed",
|
|
|
|
|
cause: err,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
revalidateAnnuncio: adminProcedure
|
|
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
cod: z.string(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
try {
|
|
|
|
|
await revalidate(`/annuncio/${input.cod}`);
|
|
|
|
|
return {
|
|
|
|
|
status: "success",
|
|
|
|
|
};
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error("Revalidation error:", err);
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: err instanceof Error ? err.message : "Revalidation failed",
|
|
|
|
|
cause: err,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
updateAllAnnunci: adminProcedure.mutation(async () => {
|
2025-10-15 15:45:24 +02:00
|
|
|
try {
|
|
|
|
|
const response = await fetch(`${env.BACKENDSERVER_URL}/update`);
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
const errorData = await response.text().catch(() => "Unknown error");
|
|
|
|
|
throw new Error(
|
2025-10-17 19:14:27 +02:00
|
|
|
`Update failed with status ${response.status}: ${errorData}`,
|
2025-10-15 15:45:24 +02:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const data = await response.json().catch(() => ({}));
|
2025-10-17 19:14:27 +02:00
|
|
|
const annunciOnline = await getCodici_AnnunciHandler();
|
|
|
|
|
const { success, failed } = await revalidateMultiple(
|
|
|
|
|
annunciOnline.map((cod) => `/annuncio/${cod}`),
|
|
|
|
|
);
|
|
|
|
|
console.log(`Successfully revalidated pages: ${success.join(", ")}`);
|
|
|
|
|
if (failed.length > 0) {
|
|
|
|
|
failed.forEach(({ path, error }) => {
|
|
|
|
|
console.error(`Failed to revalidate ${path}: ${error}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-10-15 15:45:24 +02:00
|
|
|
return {
|
|
|
|
|
status: "success",
|
|
|
|
|
details: data,
|
|
|
|
|
};
|
|
|
|
|
} catch (err) {
|
2025-10-17 19:14:27 +02:00
|
|
|
console.error("Update error:", err);
|
2025-10-15 15:45:24 +02:00
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
2025-10-17 19:14:27 +02:00
|
|
|
message: err instanceof Error ? err.message : "Update failed",
|
2025-10-15 15:45:24 +02:00
|
|
|
cause: err,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}),
|
2025-10-17 19:14:27 +02:00
|
|
|
updateAnnuncio: adminProcedure
|
2025-10-15 15:45:24 +02:00
|
|
|
.input(
|
|
|
|
|
z.object({
|
|
|
|
|
cod: z.string(),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.mutation(async ({ input }) => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch(
|
|
|
|
|
`${env.BACKENDSERVER_URL}/update-cod/${input.cod}`,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
const errorData = await response.text().catch(() => "Unknown error");
|
|
|
|
|
throw new Error(
|
2025-10-17 19:14:27 +02:00
|
|
|
`Update failed with status ${response.status}: ${errorData}`,
|
2025-10-15 15:45:24 +02:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const data = await response.json().catch(() => ({}));
|
2025-10-17 19:14:27 +02:00
|
|
|
await revalidate(`/annuncio/${input.cod}`);
|
2025-10-15 15:45:24 +02:00
|
|
|
return {
|
|
|
|
|
status: "success",
|
|
|
|
|
details: data,
|
|
|
|
|
};
|
|
|
|
|
} catch (err) {
|
2025-10-17 19:14:27 +02:00
|
|
|
console.error("Update error:", err);
|
2025-10-15 15:45:24 +02:00
|
|
|
throw new TRPCError({
|
|
|
|
|
code: "INTERNAL_SERVER_ERROR",
|
2025-10-17 19:14:27 +02:00
|
|
|
message: err instanceof Error ? err.message : "Update failed",
|
2025-10-15 15:45:24 +02:00
|
|
|
cause: err,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}),
|
2025-08-04 17:45:44 +02:00
|
|
|
});
|