From 9c18ca37ab24feea728ed3573b5ceeb882759f09 Mon Sep 17 00:00:00 2001 From: Marco Pedone Date: Thu, 20 Nov 2025 12:38:42 +0100 Subject: [PATCH] Refactor API structure and update flag handling - Replaced references to `api.settings` with `api.etichette`, `api.flags`, and `api.strings` in various admin pages to align with new API structure. - Removed the deprecated `settingsRouter` and introduced `flagsRouter`, `etichetteRouter`, and `stringsRouter` to handle respective functionalities. - Updated the `Flags` schema to change the `value` field from string to boolean. - Modified flag handling logic in the `SendMessage` and `NewMail` functions to check for boolean flags instead of string values. - Added migration script to convert the `value` column in the `flags` table from string to boolean. - Implemented new routers for banners, etichette, flags, revalidation, and strings to encapsulate related functionalities. --- apps/db/migrations/27_flags_bool.up.sql | 25 ++ apps/infoalloggi/src/components/Layout.tsx | 4 +- apps/infoalloggi/src/components/etichette.tsx | 2 +- .../src/components/tables/flags-table.tsx | 9 +- .../src/forms/FormEditAnnuncio.tsx | 4 +- apps/infoalloggi/src/forms/FormFlags.tsx | 21 +- apps/infoalloggi/src/forms/FormPrezzo.tsx | 2 +- apps/infoalloggi/src/pages/annuncio/[cod].tsx | 2 +- .../pages/area-riservata/admin/annunci.tsx | 24 +- .../pages/area-riservata/admin/banners.tsx | 22 +- .../pages/area-riservata/admin/etichette.tsx | 16 +- .../src/pages/area-riservata/admin/flags.tsx | 25 +- .../area-riservata/admin/testi-stringhe.tsx | 16 +- apps/infoalloggi/src/pages/privacy-policy.tsx | 4 +- .../pages/servizio/condizioni/[stringaId].tsx | 4 +- .../src/pages/termini-condizioni.tsx | 4 +- apps/infoalloggi/src/schemas/public/Flags.ts | 2 +- apps/infoalloggi/src/server/api/root.ts | 12 +- .../src/server/api/routers/banners.ts | 81 ++++ .../src/server/api/routers/etichette.ts | 54 +++ .../src/server/api/routers/flags.ts | 58 +++ .../src/server/api/routers/revalidation.ts | 133 ++++++ .../src/server/api/routers/settings.ts | 379 ------------------ .../src/server/api/routers/strings.ts | 78 ++++ .../server/controllers/flags.controller.ts | 12 +- .../server/controllers/skebby.controller.ts | 53 +-- .../infoalloggi/src/server/services/mailer.ts | 4 +- 27 files changed, 555 insertions(+), 495 deletions(-) create mode 100644 apps/db/migrations/27_flags_bool.up.sql create mode 100644 apps/infoalloggi/src/server/api/routers/banners.ts create mode 100644 apps/infoalloggi/src/server/api/routers/etichette.ts create mode 100644 apps/infoalloggi/src/server/api/routers/flags.ts create mode 100644 apps/infoalloggi/src/server/api/routers/revalidation.ts delete mode 100644 apps/infoalloggi/src/server/api/routers/settings.ts create mode 100644 apps/infoalloggi/src/server/api/routers/strings.ts diff --git a/apps/db/migrations/27_flags_bool.up.sql b/apps/db/migrations/27_flags_bool.up.sql new file mode 100644 index 0000000..b347b42 --- /dev/null +++ b/apps/db/migrations/27_flags_bool.up.sql @@ -0,0 +1,25 @@ +-- Converts the 'value' column from a string to a boolean. +-- If 'value' is 'true' (case insensitive), it will be set to TRUE, otherwise FALSE. + +DO $$ +BEGIN + -- Check if the column is not already boolean + IF EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = 'public' + AND table_name = 'flags' + AND column_name = 'value' + AND data_type != 'boolean' + ) THEN + -- Convert the column type + ALTER TABLE public.flags + ALTER COLUMN value TYPE BOOLEAN USING (LOWER(value) = 'true'); + END IF; +END $$; + +-- Ensure that the 'value' column is not NULL (idempotent) +ALTER TABLE public.flags ALTER COLUMN VALUE SET NOT NULL; + +-- Set a default value for the 'value' column (idempotent) +ALTER TABLE public.flags ALTER COLUMN VALUE SET DEFAULT FALSE; \ No newline at end of file diff --git a/apps/infoalloggi/src/components/Layout.tsx b/apps/infoalloggi/src/components/Layout.tsx index 126ebee..a16821e 100644 --- a/apps/infoalloggi/src/components/Layout.tsx +++ b/apps/infoalloggi/src/components/Layout.tsx @@ -51,7 +51,7 @@ export const Layout = ({ containerClassName, footerClassName, }: Props) => { - const { data: bannerData } = api.settings.getBannerData.useQuery({ + const { data: bannerData } = api.banners.getBannerData.useQuery({ area_riservata: false, }); @@ -87,7 +87,7 @@ export const AreaRiservataLayout = ({ containerClassName, footerClassName, }: AreaRiservataLayoutProps) => { - const { data: bannerData } = api.settings.getBannerData.useQuery({ + const { data: bannerData } = api.banners.getBannerData.useQuery({ area_riservata: true, }); const session = useSession(); diff --git a/apps/infoalloggi/src/components/etichette.tsx b/apps/infoalloggi/src/components/etichette.tsx index 6be7bcd..e94b7c1 100644 --- a/apps/infoalloggi/src/components/etichette.tsx +++ b/apps/infoalloggi/src/components/etichette.tsx @@ -77,7 +77,7 @@ export const EtichetteModal = ({ const [selected, setSelected] = useState(null); const utils = api.useUtils(); const { data } = api.chat.getChatEtichette.useQuery({ chatId }); - const { data: etichette } = api.settings.getAllEtichette.useQuery(); + const { data: etichette } = api.etichette.getAllEtichette.useQuery(); const { mutate: remove } = api.chat.removeEtichettaFromChat.useMutation({ onSuccess: async () => { diff --git a/apps/infoalloggi/src/components/tables/flags-table.tsx b/apps/infoalloggi/src/components/tables/flags-table.tsx index 8373050..c7a4aa5 100644 --- a/apps/infoalloggi/src/components/tables/flags-table.tsx +++ b/apps/infoalloggi/src/components/tables/flags-table.tsx @@ -4,12 +4,11 @@ import { DataTable } from "~/components/custom_ui/data-table"; import { DataTableColumnHeader } from "~/components/custom_ui/dataTable-header"; import type { SearchFiltro } from "~/components/custom_ui/dataTable-toolbar"; import { Button } from "~/components/ui/button"; -import type { initialValues } from "~/forms/FormFlags"; import type { Flags } from "~/schemas/public/Flags"; export const FlagsTable = (props: { data: Flags[]; setOpenEdit: (status: boolean) => void; - setEditData: (data: initialValues | null) => void; + setEditData: (data: Flags | null) => void; }) => { const { data, setOpenEdit, setEditData } = props; @@ -40,7 +39,11 @@ export const FlagsTable = (props: { accessorKey: "value", cell: ({ row }) => { const data = row.original; - return data.value === null ? "null" : data.value; + return data.value ? ( + Attivo + ) : ( + Inattivo + ); }, enableHiding: false, header: ({ column }) => ( diff --git a/apps/infoalloggi/src/forms/FormEditAnnuncio.tsx b/apps/infoalloggi/src/forms/FormEditAnnuncio.tsx index 16f6d4a..13ce2ad 100644 --- a/apps/infoalloggi/src/forms/FormEditAnnuncio.tsx +++ b/apps/infoalloggi/src/forms/FormEditAnnuncio.tsx @@ -134,7 +134,7 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => { }); const { mutateAsync: revalidate } = - api.settings.revalidateAnnuncio.useMutation({ + api.revalidation.revalidateAnnuncio.useMutation({ onSettled: async () => { await utils.annunci.getAnnuncio.invalidate({ cod: data.codice }); await utils.annunci.getAnnuncioById_rawImgUrls.invalidate({ @@ -144,7 +144,7 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => { }, }); - const { mutateAsync: update } = api.settings.updateAnnuncio.useMutation({ + const { mutateAsync: update } = api.revalidation.updateAnnuncio.useMutation({ onSettled: async () => { await utils.annunci.getAnnuncio.invalidate({ cod: data.codice }); await utils.annunci.getAnnuncioById_rawImgUrls.invalidate({ diff --git a/apps/infoalloggi/src/forms/FormFlags.tsx b/apps/infoalloggi/src/forms/FormFlags.tsx index 357401f..32533f5 100644 --- a/apps/infoalloggi/src/forms/FormFlags.tsx +++ b/apps/infoalloggi/src/forms/FormFlags.tsx @@ -9,16 +9,17 @@ import { } from "~/components/custom_ui/form"; import Input from "~/components/custom_ui/input"; import { Button } from "~/components/ui/button"; +import { Switch } from "~/components/ui/switch"; import { useZodForm } from "~/lib/zodForm"; -import type { FlagsId } from "~/schemas/public/Flags"; +import type { Flags, FlagsId } from "~/schemas/public/Flags"; export type initialValues = { id: FlagsId; value: string; }; //TODO salvare flags come boolean type FormProps = { - initialValues: initialValues | null; - submitMutation: (values: initialValues) => void; + initialValues: Flags | null; + submitMutation: (values: Flags) => void; handleRemove: (id: FlagsId) => void; }; export const FormFlags = ({ @@ -28,7 +29,7 @@ export const FormFlags = ({ }: FormProps) => { const Schema = z.object({ id: z.string(), - value: z.string(), + value: z.boolean(), }); type FormValues = z.infer; @@ -37,7 +38,7 @@ export const FormFlags = ({ if (!initialValues) { defaultValues = { id: "", - value: "", + value: false, }; } else { defaultValues = { @@ -88,15 +89,15 @@ export const FormFlags = ({ render={({ field }) => (
- Valore testuale + Attivo/Inattivo
-
diff --git a/apps/infoalloggi/src/forms/FormPrezzo.tsx b/apps/infoalloggi/src/forms/FormPrezzo.tsx index 46a486c..6a3528f 100644 --- a/apps/infoalloggi/src/forms/FormPrezzo.tsx +++ b/apps/infoalloggi/src/forms/FormPrezzo.tsx @@ -37,7 +37,7 @@ export const FormPrezzo = ({ submitMutation, }: FormPrezzoProps) => { const { data: stringhe_condizioni } = - api.settings.getStringheCondizioni.useQuery(); + api.strings.getStringheCondizioni.useQuery(); const stringhe_condizioni_options = [ "", diff --git a/apps/infoalloggi/src/pages/annuncio/[cod].tsx b/apps/infoalloggi/src/pages/annuncio/[cod].tsx index 5d49dcd..9d4cee4 100644 --- a/apps/infoalloggi/src/pages/annuncio/[cod].tsx +++ b/apps/infoalloggi/src/pages/annuncio/[cod].tsx @@ -226,7 +226,7 @@ export async function getStaticProps( const meta = await ssg.annunci.getAnnuncioMeta.fetch({ cod: cod }); - const flag = await ssg.settings.GetFlagValue.fetch({ + const flag = await ssg.flags.GetFlagValue.fetch({ id: "ANNUNCIO_INTERACTIONS_DISABLED", }); return { diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/annunci.tsx b/apps/infoalloggi/src/pages/area-riservata/admin/annunci.tsx index 214c4ba..b2a3ed4 100644 --- a/apps/infoalloggi/src/pages/area-riservata/admin/annunci.tsx +++ b/apps/infoalloggi/src/pages/area-riservata/admin/annunci.tsx @@ -18,19 +18,21 @@ import { api } from "~/utils/api"; const Admin_Annunci: NextPageWithLayout = () => { const { data, isLoading, refetch } = api.annunci.getAnnunciList.useQuery(); const utils = api.useUtils(); - const { mutateAsync: update } = api.settings.updateAllAnnunci.useMutation({ - onSettled: async () => { - await utils.annunci.getAnnunciList.invalidate(); - toast.success( - "La revalidazione dell'annuncio è stata richiesta con successo,\n potrebbero volerci alcuni minuti prima che le modifiche siano visibili.", - { - duration: 5000, - }, - ); + const { mutateAsync: update } = api.revalidation.updateAllAnnunci.useMutation( + { + onSettled: async () => { + await utils.annunci.getAnnunciList.invalidate(); + toast.success( + "La revalidazione dell'annuncio è stata richiesta con successo,\n potrebbero volerci alcuni minuti prima che le modifiche siano visibili.", + { + duration: 5000, + }, + ); + }, }, - }); + ); const { mutateAsync: revalidate } = - api.settings.revalidateAllAnnunci.useMutation({ + api.revalidation.revalidateAllAnnunci.useMutation({ onSettled: async () => { await utils.annunci.getAnnunciList.invalidate(); toast.success("Revalidazione completata"); diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/banners.tsx b/apps/infoalloggi/src/pages/area-riservata/admin/banners.tsx index 21e5340..aba527c 100644 --- a/apps/infoalloggi/src/pages/area-riservata/admin/banners.tsx +++ b/apps/infoalloggi/src/pages/area-riservata/admin/banners.tsx @@ -21,7 +21,7 @@ import { generateSSGHelper } from "~/server/utils/ssgHelper"; import { api } from "~/utils/api"; const AdminBanners: NextPageWithLayout = () => { - const { data, isLoading, refetch } = api.settings.getBannerAllData.useQuery(); + const { data, isLoading, refetch } = api.banners.getBannerAllData.useQuery(); const [openEdit, setOpenEdit] = useState(false); const [editData, setEditData] = useState(null); @@ -87,7 +87,7 @@ export default AdminBanners; export async function getServerSideProps() { const helpers = generateSSGHelper(); - await helpers.settings.getBannerAllData.prefetch(); + await helpers.banners.getBannerAllData.prefetch(); return { props: { @@ -110,36 +110,36 @@ const EditModal = ({ setOpen: (status: boolean) => void; }) => { const utils = api.useUtils(); - const { mutate: edit } = api.settings.updateBanner.useMutation({ + const { mutate: edit } = api.banners.updateBanner.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getBannerAllData.invalidate(); - await utils.settings.getBannerData.invalidate(); + await utils.banners.getBannerAllData.invalidate(); + await utils.banners.getBannerData.invalidate(); setOpen(false); }, }); - const { mutate: add } = api.settings.addBanner.useMutation({ + const { mutate: add } = api.banners.addBanner.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getBannerAllData.invalidate(); - await utils.settings.getBannerData.invalidate(); + await utils.banners.getBannerAllData.invalidate(); + await utils.banners.getBannerData.invalidate(); setOpen(false); }, }); - const { mutate: del } = api.settings.deleteBanner.useMutation({ + const { mutate: del } = api.banners.deleteBanner.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getBannerAllData.invalidate(); - await utils.settings.getBannerData.invalidate(); + await utils.banners.getBannerAllData.invalidate(); + await utils.banners.getBannerData.invalidate(); setOpen(false); }, }); diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/etichette.tsx b/apps/infoalloggi/src/pages/area-riservata/admin/etichette.tsx index 6aa3681..9ae9adb 100644 --- a/apps/infoalloggi/src/pages/area-riservata/admin/etichette.tsx +++ b/apps/infoalloggi/src/pages/area-riservata/admin/etichette.tsx @@ -22,7 +22,7 @@ import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper"; import { api } from "~/utils/api"; const AdminEtichette: NextPageWithLayout = () => { - const { data, isLoading, refetch } = api.settings.getAllEtichette.useQuery(); + const { data, isLoading, refetch } = api.etichette.getAllEtichette.useQuery(); const [openEdit, setOpenEdit] = useState(false); const [editData, setEditData] = useState(null); @@ -91,7 +91,7 @@ export const getServerSideProps = (async (context) => { const helpers = await TrpcAuthedFetchingIstance({ access_token }); if (helpers) { - await helpers.trpc.settings.getAllEtichette.prefetch(); + await helpers.trpc.etichette.getAllEtichette.prefetch(); return { props: { trpcState: helpers.trpc.dehydrate(), @@ -117,37 +117,37 @@ const EditModal = ({ setOpen: (status: boolean) => void; }) => { const utils = api.useUtils(); - const { mutate: edit } = api.settings.updateEtichetta.useMutation({ + const { mutate: edit } = api.etichette.updateEtichetta.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getAllEtichette.invalidate(); + await utils.etichette.getAllEtichette.invalidate(); await utils.chat.getChatEtichette.invalidate(); await utils.chat.getActiveChats.invalidate(); setOpen(false); }, }); - const { mutate: add } = api.settings.addEtichetta.useMutation({ + const { mutate: add } = api.etichette.addEtichetta.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getAllEtichette.invalidate(); + await utils.etichette.getAllEtichette.invalidate(); await utils.chat.getChatEtichette.invalidate(); await utils.chat.getActiveChats.invalidate(); setOpen(false); }, }); - const { mutate: del } = api.settings.removeEtichetta.useMutation({ + const { mutate: del } = api.etichette.removeEtichetta.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getAllEtichette.invalidate(); + await utils.etichette.getAllEtichette.invalidate(); await utils.chat.getChatEtichette.invalidate(); await utils.chat.getActiveChats.invalidate(); setOpen(false); diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/flags.tsx b/apps/infoalloggi/src/pages/area-riservata/admin/flags.tsx index d856d92..46ef585 100644 --- a/apps/infoalloggi/src/pages/area-riservata/admin/flags.tsx +++ b/apps/infoalloggi/src/pages/area-riservata/admin/flags.tsx @@ -14,21 +14,22 @@ import { DialogHeader, DialogTitle, } from "~/components/ui/dialog"; -import { FormFlags, type initialValues } from "~/forms/FormFlags"; +import { FormFlags } from "~/forms/FormFlags"; import type { NextPageWithLayout } from "~/pages/_app"; +import type { Flags } from "~/schemas/public/Flags"; import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper"; import { api } from "~/utils/api"; const AdminFlags: NextPageWithLayout = () => { - const { data, isLoading, refetch } = api.settings.GetFlags.useQuery(); + const { data, isLoading, refetch } = api.flags.GetFlags.useQuery(); const [openEdit, setOpenEdit] = useState(false); - const [editData, setEditData] = useState(null); + const [editData, setEditData] = useState(null); const handleOpen = (status: boolean) => { setOpenEdit(status); }; - const handleEdit = (data: initialValues | null) => { + const handleEdit = (data: Flags | null) => { setEditData(data); }; @@ -89,7 +90,7 @@ export const getServerSideProps = (async (context) => { const helpers = await TrpcAuthedFetchingIstance({ access_token }); if (helpers) { - await helpers.trpc.settings.GetFlags.prefetch(); + await helpers.trpc.flags.GetFlags.prefetch(); return { props: { trpcState: helpers.trpc.dehydrate(), @@ -110,38 +111,38 @@ const EditModal = ({ open, setOpen, }: { - initial: initialValues | null; + initial: Flags | null; open: boolean; setOpen: (status: boolean) => void; }) => { const utils = api.useUtils(); - const { mutate: edit } = api.settings.EditFlag.useMutation({ + const { mutate: edit } = api.flags.EditFlag.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.GetFlags.invalidate(); + await utils.flags.GetFlags.invalidate(); setOpen(false); }, }); - const { mutate: add } = api.settings.AddFlag.useMutation({ + const { mutate: add } = api.flags.AddFlag.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.GetFlags.invalidate(); + await utils.flags.GetFlags.invalidate(); setOpen(false); }, }); - const { mutate: remove } = api.settings.RemoveFlag.useMutation({ + const { mutate: remove } = api.flags.RemoveFlag.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.GetFlags.invalidate(); + await utils.flags.GetFlags.invalidate(); setOpen(false); }, }); diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/testi-stringhe.tsx b/apps/infoalloggi/src/pages/area-riservata/admin/testi-stringhe.tsx index 1c01daa..7fe76a3 100644 --- a/apps/infoalloggi/src/pages/area-riservata/admin/testi-stringhe.tsx +++ b/apps/infoalloggi/src/pages/area-riservata/admin/testi-stringhe.tsx @@ -22,7 +22,7 @@ import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper"; import { api } from "~/utils/api"; const AdminTestiStringhe: NextPageWithLayout = () => { - const { data, isLoading, refetch } = api.settings.getStringhe.useQuery(); + const { data, isLoading, refetch } = api.strings.getStringhe.useQuery(); const [openEdit, setOpenEdit] = useState(false); const [editData, setEditData] = useState(null); @@ -90,7 +90,7 @@ export const getServerSideProps = (async (context) => { const helpers = await TrpcAuthedFetchingIstance({ access_token }); if (helpers) { - await helpers.trpc.settings.getStringhe.prefetch(); + await helpers.trpc.strings.getStringhe.prefetch(); return { props: { trpcState: helpers.trpc.dehydrate(), @@ -117,33 +117,33 @@ const EditModal = ({ setOpen: (status: boolean) => void; }) => { const utils = api.useUtils(); - const { mutate: edit } = api.settings.updateStringa.useMutation({ + const { mutate: edit } = api.strings.updateStringa.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getStringhe.invalidate(); + await utils.strings.getStringhe.invalidate(); setOpen(false); }, }); - const { mutate: add } = api.settings.newStringa.useMutation({ + const { mutate: add } = api.strings.newStringa.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getStringhe.invalidate(); + await utils.strings.getStringhe.invalidate(); setOpen(false); }, }); - const { mutate: del } = api.settings.deleteStringa.useMutation({ + const { mutate: del } = api.strings.deleteStringa.useMutation({ onError: (error) => { toast.error(error.message); }, onSuccess: async () => { toast.success("Successo"); - await utils.settings.getStringhe.invalidate(); + await utils.strings.getStringhe.invalidate(); setOpen(false); }, }); diff --git a/apps/infoalloggi/src/pages/privacy-policy.tsx b/apps/infoalloggi/src/pages/privacy-policy.tsx index c21a221..74d56aa 100644 --- a/apps/infoalloggi/src/pages/privacy-policy.tsx +++ b/apps/infoalloggi/src/pages/privacy-policy.tsx @@ -10,7 +10,7 @@ const PrivacyPolicy: NextPage = () => { const key = ( locale === "en" ? "PRIVACY_POLICY_ENG" : "PRIVACY_POLICY" ) as TestiEStringheStingaId; - const { data } = api.settings.getStringa.useQuery({ + const { data } = api.strings.getStringa.useQuery({ stringaId: key, }); return ( @@ -37,7 +37,7 @@ export const getServerSideProps = (async (context) => { const key = locale === "en" ? "PRIVACY_POLICY_ENG" : "PRIVACY_POLICY"; const helpers = generateSSGHelper(); - await helpers.settings.getStringa.prefetch({ + await helpers.strings.getStringa.prefetch({ stringaId: key as TestiEStringheStingaId, }); return { diff --git a/apps/infoalloggi/src/pages/servizio/condizioni/[stringaId].tsx b/apps/infoalloggi/src/pages/servizio/condizioni/[stringaId].tsx index c998192..99d54f8 100644 --- a/apps/infoalloggi/src/pages/servizio/condizioni/[stringaId].tsx +++ b/apps/infoalloggi/src/pages/servizio/condizioni/[stringaId].tsx @@ -15,7 +15,7 @@ type CondizioniProps = { const CondizioniPage: NextPageWithLayout = ({ stringaId, }: CondizioniProps) => { - const { data, isLoading } = api.settings.getStringa.useQuery({ + const { data, isLoading } = api.strings.getStringa.useQuery({ stringaId, }); @@ -75,7 +75,7 @@ export const getServerSideProps = (async (context) => { const helper = await TrpcAuthedFetchingIstance({ access_token }); if (helper) { - await helper.trpc.settings.getStringa.prefetch({ + await helper.trpc.strings.getStringa.prefetch({ stringaId: parsed.data, }); diff --git a/apps/infoalloggi/src/pages/termini-condizioni.tsx b/apps/infoalloggi/src/pages/termini-condizioni.tsx index ef6c6b0..557b59f 100644 --- a/apps/infoalloggi/src/pages/termini-condizioni.tsx +++ b/apps/infoalloggi/src/pages/termini-condizioni.tsx @@ -10,7 +10,7 @@ const Termini_Condizioni: NextPage = () => { const key = ( locale === "en" ? "TERMINI_CONDIZIONI_ENG" : "TERMINI_CONDIZIONI" ) as TestiEStringheStingaId; - const { data } = api.settings.getStringa.useQuery({ + const { data } = api.strings.getStringa.useQuery({ stringaId: key, }); return ( @@ -36,7 +36,7 @@ export const getServerSideProps = (async (context) => { const key = locale === "en" ? "TERMINI_CONDIZIONI_ENG" : "TERMINI_CONDIZIONI"; const helpers = generateSSGHelper(); - await helpers.settings.getStringa.prefetch({ + await helpers.strings.getStringa.prefetch({ stringaId: key as TestiEStringheStingaId, }); return { diff --git a/apps/infoalloggi/src/schemas/public/Flags.ts b/apps/infoalloggi/src/schemas/public/Flags.ts index cb7c285..b9338c5 100644 --- a/apps/infoalloggi/src/schemas/public/Flags.ts +++ b/apps/infoalloggi/src/schemas/public/Flags.ts @@ -10,7 +10,7 @@ export type FlagsId = string & { __brand: 'public.flags' }; export default interface FlagsTable { id: ColumnType; - value: ColumnType; + value: ColumnType; } export type Flags = Selectable; diff --git a/apps/infoalloggi/src/server/api/root.ts b/apps/infoalloggi/src/server/api/root.ts index c4119da..3631598 100644 --- a/apps/infoalloggi/src/server/api/root.ts +++ b/apps/infoalloggi/src/server/api/root.ts @@ -12,14 +12,18 @@ import { messagesSSERouter } from "~/server/api/routers/messages_sse"; import { pagamentiRouter } from "~/server/api/routers/pagamenti"; import { prezziarioRouter } from "~/server/api/routers/prezziario"; import { servizioRouter } from "~/server/api/routers/servizio"; -import { settingsRouter } from "~/server/api/routers/settings"; import { statsRouter } from "~/server/api/routers/stats"; import { storageRouter } from "~/server/api/routers/storage"; import { stripeRouter } from "~/server/api/routers/stripe"; import { testRouter } from "~/server/api/routers/test"; import { usersRouter } from "~/server/api/routers/users"; import { createTRPCRouter } from "~/server/api/trpc"; +import { bannersRouter } from "./routers/banners"; import { catastoRouter } from "./routers/catasto"; +import { etichetteRouter } from "./routers/etichette"; +import { flagsRouter } from "./routers/flags"; +import { revalidationRouter } from "./routers/revalidation"; +import { stringsRouter } from "./routers/strings"; import { syncRouter } from "./routers/sync"; //import { lazy } from '@trpc/server'; @@ -39,7 +43,6 @@ export const appRouter = createTRPCRouter({ pagamenti: pagamentiRouter, prezziario: prezziarioRouter, servizio: servizioRouter, - settings: settingsRouter, stats: statsRouter, storage: storageRouter, stripe: stripeRouter, @@ -47,5 +50,10 @@ export const appRouter = createTRPCRouter({ users: usersRouter, sync: syncRouter, catasto: catastoRouter, + banners: bannersRouter, + flags: flagsRouter, + etichette: etichetteRouter, + strings: stringsRouter, + revalidation: revalidationRouter, }); export type AppRouter = typeof appRouter; diff --git a/apps/infoalloggi/src/server/api/routers/banners.ts b/apps/infoalloggi/src/server/api/routers/banners.ts new file mode 100644 index 0000000..01a77d5 --- /dev/null +++ b/apps/infoalloggi/src/server/api/routers/banners.ts @@ -0,0 +1,81 @@ +import { z } from "zod/v4"; +import type { BannersIdbanner } from "~/schemas/public/Banners"; +import { + adminProcedure, + createTRPCRouter, + publicProcedure, +} from "~/server/api/trpc"; +import { db } from "~/server/db"; +import { + addBanner, + deleteBanner, + getAllBanners, + getBanner, + updateBanner, +} from "~/server/services/banners.service"; + +export const bannersRouter = createTRPCRouter({ + addBanner: adminProcedure + .input( + z.object({ + 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(), + is_active: z.boolean(), + is_unskippable: z.boolean(), + show_private: z.boolean(), + show_public: z.boolean(), + testo: z.string().nullable(), + titolo: z.string().nullable(), + }), + ) + .mutation(async ({ input }) => { + return await addBanner({ db, input }); + }), + getBannerAllData: publicProcedure.query(async () => { + return await getAllBanners({ db }); + }), + deleteBanner: adminProcedure + .input(z.object({ idbanner: z.custom() })) + .mutation(async ({ input }) => { + return await deleteBanner({ db, input }); + }), + updateBanner: adminProcedure + .input( + z.object({ + 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(), + is_active: z.boolean(), + is_unskippable: z.boolean(), + show_private: z.boolean(), + show_public: z.boolean(), + testo: z.string().nullable(), + titolo: z.string().nullable(), + }), + ) + .mutation(async ({ input }) => { + return await updateBanner({ db, input }); + }), + + getBannerData: publicProcedure + .input( + z.object({ + area_riservata: z.boolean(), + }), + ) + .query(async ({ input }) => { + return await getBanner({ + area_riservata: input.area_riservata, + db, + }); + }), +}); diff --git a/apps/infoalloggi/src/server/api/routers/etichette.ts b/apps/infoalloggi/src/server/api/routers/etichette.ts new file mode 100644 index 0000000..28f16d5 --- /dev/null +++ b/apps/infoalloggi/src/server/api/routers/etichette.ts @@ -0,0 +1,54 @@ +import { z } from "zod/v4"; +import { adminProcedure, createTRPCRouter } from "~/server/api/trpc"; +import { + addEtichetta, + getAllEtichette, + removeEtichetta, + updateEtichetta, +} from "~/server/controllers/etichette.controller"; +import { db } from "~/server/db"; +import { zEtichettaId } from "~/server/utils/zod_types"; + +export const etichetteRouter = createTRPCRouter({ + 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, + }); + }), + getAllEtichette: adminProcedure.query(async () => { + return await getAllEtichette({ db }); + }), + removeEtichetta: adminProcedure + .input(z.object({ id_etichetta: zEtichettaId })) + .mutation(async ({ input }) => { + return await removeEtichetta({ + db, + etichettaid: input.id_etichetta, + }); + }), + updateEtichetta: adminProcedure + .input( + z.object({ + color_hex: z.string().max(7), + id_etichetta: zEtichettaId, + title: z.string(), + }), + ) + .mutation(async ({ input }) => { + return await updateEtichetta({ + color_hex: input.color_hex, + db, + etichettaid: input.id_etichetta, + title: input.title, + }); + }), +}); diff --git a/apps/infoalloggi/src/server/api/routers/flags.ts b/apps/infoalloggi/src/server/api/routers/flags.ts new file mode 100644 index 0000000..066f1cc --- /dev/null +++ b/apps/infoalloggi/src/server/api/routers/flags.ts @@ -0,0 +1,58 @@ +import { z } from "zod/v4"; +import { + adminProcedure, + createTRPCRouter, + publicProcedure, +} from "~/server/api/trpc"; +import { + AddFlagHandler, + EditFlagHandler, + GetFlagHandler, + GetFlagValueHandler, + RemoveFlagHandler, +} from "~/server/controllers/flags.controller"; +import { db } from "~/server/db"; +import { zFlagsId } from "~/server/utils/zod_types"; + +export const flagsRouter = createTRPCRouter({ + AddFlag: adminProcedure + .input( + z.object({ + id: zFlagsId, + value: z.boolean(), + }), + ) + .mutation(async ({ input }) => { + return await AddFlagHandler({ db, input }); + }), + EditFlag: adminProcedure + .input( + z.object({ + id: zFlagsId, + value: z.boolean(), + }), + ) + .mutation(async ({ input }) => { + return await EditFlagHandler({ db, input }); + }), + + GetFlags: adminProcedure.query(async () => { + return await GetFlagHandler({ db }); + }), + + GetFlagValue: publicProcedure + .input(z.object({ id: z.string() })) + .query(async ({ input }) => { + return await GetFlagValueHandler({ db, id: input.id }); + }), + RemoveFlag: adminProcedure + + .input( + z.object({ + id: zFlagsId, + }), + ) + .mutation(async ({ input }) => { + return await RemoveFlagHandler({ db, id: input.id }); + }), +}); diff --git a/apps/infoalloggi/src/server/api/routers/revalidation.ts b/apps/infoalloggi/src/server/api/routers/revalidation.ts new file mode 100644 index 0000000..1031e0a --- /dev/null +++ b/apps/infoalloggi/src/server/api/routers/revalidation.ts @@ -0,0 +1,133 @@ +import { TRPCError } from "@trpc/server"; +import { z } from "zod/v4"; +import { env } from "~/env"; +import { adminProcedure, createTRPCRouter } from "~/server/api/trpc"; +import { getCodici_AnnunciHandler } from "~/server/controllers/annunci.controller"; +import { + revalidate, + revalidateMultiple, +} from "~/server/utils/revalidationHelper"; + +export const revalidationRouter = createTRPCRouter({ + revalidateAllAnnunci: adminProcedure.mutation(async () => { + try { + const annunciOnline = await getCodici_AnnunciHandler(); + const { success, failed } = await revalidateMultiple( + annunciOnline.map((cod) => `/annuncio/${cod}`), + ); + //console.log(`Successfully revalidated pages: ${success.join(", ")}`); + if (success.length === 0) { + console.log("No annunci were revalidated."); + } + 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 () => { + try { + const response = await fetch(`${env.BACKENDSERVER_URL}/update`); + + if (!response.ok) { + const errorData = await response.text().catch(() => "Unknown error"); + throw new Error( + `Update failed with status ${response.status}: ${errorData}`, + ); + } + + const data = await response.json().catch(() => ({})); + const annunciOnline = await getCodici_AnnunciHandler(); + const { success, failed } = await revalidateMultiple( + annunciOnline.map((cod) => `/annuncio/${cod}`), + ); + if (success.length === 0) { + console.log("No annunci were revalidated."); + } + //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", + details: data, + }; + } catch (err) { + console.error("Update error:", err); + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: err instanceof Error ? err.message : "Update failed", + cause: err, + }); + } + }), + updateAnnuncio: adminProcedure + .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( + `Update failed with status ${response.status}: ${errorData}`, + ); + } + + const data = await response.json().catch(() => ({})); + await revalidate(`/annuncio/${input.cod}`); + return { + status: "success", + details: data, + }; + } catch (err) { + console.error("Update error:", err); + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: err instanceof Error ? err.message : "Update failed", + cause: err, + }); + } + }), +}); diff --git a/apps/infoalloggi/src/server/api/routers/settings.ts b/apps/infoalloggi/src/server/api/routers/settings.ts deleted file mode 100644 index d689369..0000000 --- a/apps/infoalloggi/src/server/api/routers/settings.ts +++ /dev/null @@ -1,379 +0,0 @@ -import { TRPCError } from "@trpc/server"; -import { z } from "zod/v4"; -import { env } from "~/env"; -import type { BannersIdbanner } from "~/schemas/public/Banners"; -import { - adminProcedure, - createTRPCRouter, - publicProcedure, -} from "~/server/api/trpc"; -import { getCodici_AnnunciHandler } from "~/server/controllers/annunci.controller"; -import { - addEtichetta, - getAllEtichette, - removeEtichetta, - updateEtichetta, -} from "~/server/controllers/etichette.controller"; -import { - AddFlagHandler, - EditFlagHandler, - GetFlagHandler, - GetFlagValueHandler, - RemoveFlagHandler, -} from "~/server/controllers/flags.controller"; -import { db } from "~/server/db"; -import { - addBanner, - deleteBanner, - getAllBanners, - getBanner, - updateBanner, -} from "~/server/services/banners.service"; -import { - deleteStringa, - getStringa, - getStringhe, - getStringheFiltered, - newStringa, - updateStringhe, -} from "~/server/services/testi_stringhe.service"; -import { - revalidate, - revalidateMultiple, -} from "~/server/utils/revalidationHelper"; -import { - zEtichettaId, - zFlagsId, - zTestiEStringheStingaId, -} from "~/server/utils/zod_types"; - -export const settingsRouter = createTRPCRouter({ - AddFlag: adminProcedure - .input( - z.object({ - id: zFlagsId, - value: z.string(), - }), - ) - .mutation(async ({ input }) => { - return await AddFlagHandler({ db, input }); - }), - addBanner: adminProcedure - .input( - z.object({ - 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(), - is_active: z.boolean(), - is_unskippable: z.boolean(), - show_private: z.boolean(), - show_public: z.boolean(), - testo: z.string().nullable(), - titolo: z.string().nullable(), - }), - ) - .mutation(async ({ input }) => { - 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() })) - .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, - }); - }), - - EditFlag: adminProcedure - .input( - z.object({ - id: zFlagsId, - value: z.string(), - }), - ) - .mutation(async ({ input }) => { - return await EditFlagHandler({ db, input }); - }), - // Flags routes - GetFlags: adminProcedure.query(async () => { - return await GetFlagHandler({ db }); - }), - - GetFlagValue: publicProcedure - .input(z.object({ id: z.string() })) - .query(async ({ input }) => { - return await GetFlagValueHandler({ db, id: input.id }); - }), - - // Etichette routes - getAllEtichette: adminProcedure.query(async () => { - return await getAllEtichette({ db }); - }), - getBannerAllData: publicProcedure.query(async () => { - return await getAllBanners({ db }); - }), - // Banner routes - getBannerData: publicProcedure - .input( - z.object({ - area_riservata: z.boolean(), - }), - ) - .query(async ({ input }) => { - return await getBanner({ - area_riservata: input.area_riservata, - db, - }); - }), - getStringa: publicProcedure - .input( - z.object({ - stringaId: zTestiEStringheStingaId, - }), - ) - .query(async ({ input }) => { - return await getStringa({ - db, - stringaId: input.stringaId, - }); - }), - - // Testi e stringhe routes - getStringhe: adminProcedure.query(async () => { - return await getStringhe({ db }); - }), - getStringheCondizioni: adminProcedure.query(async () => { - return await getStringheFiltered({ contains: "CONDIZIONI", db }); - }), - newStringa: adminProcedure - .input( - z.object({ - stringaId: zTestiEStringheStingaId, - stringaValue: z.string().nullable(), - }), - ) - .mutation(async ({ input }) => { - return await newStringa({ - db, - stringaId: input.stringaId, - stringaValue: input.stringaValue, - }); - }), - RemoveFlag: adminProcedure - - .input( - z.object({ - id: zFlagsId, - }), - ) - .mutation(async ({ input }) => { - return await RemoveFlagHandler({ db, id: input.id }); - }), - removeEtichetta: adminProcedure - .input(z.object({ id_etichetta: zEtichettaId })) - .mutation(async ({ input }) => { - return await removeEtichetta({ - db, - etichettaid: input.id_etichetta, - }); - }), - updateBanner: adminProcedure - .input( - z.object({ - 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(), - is_active: z.boolean(), - is_unskippable: z.boolean(), - show_private: z.boolean(), - show_public: z.boolean(), - testo: z.string().nullable(), - titolo: z.string().nullable(), - }), - ) - .mutation(async ({ input }) => { - return await updateBanner({ db, input }); - }), - updateEtichetta: adminProcedure - .input( - z.object({ - color_hex: z.string().max(7), - id_etichetta: zEtichettaId, - title: z.string(), - }), - ) - .mutation(async ({ input }) => { - return await updateEtichetta({ - color_hex: input.color_hex, - db, - etichettaid: input.id_etichetta, - title: input.title, - }); - }), - updateStringa: adminProcedure - .input( - z.object({ - stringaId: zTestiEStringheStingaId, - stringaValue: z.string().nullable(), - }), - ) - .mutation(async ({ input }) => { - return await updateStringhe({ - db, - stringaId: input.stringaId, - stringaValue: input.stringaValue, - }); - }), - revalidateAllAnnunci: adminProcedure.mutation(async () => { - try { - const annunciOnline = await getCodici_AnnunciHandler(); - const { success, failed } = await revalidateMultiple( - annunciOnline.map((cod) => `/annuncio/${cod}`), - ); - //console.log(`Successfully revalidated pages: ${success.join(", ")}`); - if (success.length === 0) { - console.log("No annunci were revalidated."); - } - 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 () => { - try { - const response = await fetch(`${env.BACKENDSERVER_URL}/update`); - - if (!response.ok) { - const errorData = await response.text().catch(() => "Unknown error"); - throw new Error( - `Update failed with status ${response.status}: ${errorData}`, - ); - } - - const data = await response.json().catch(() => ({})); - const annunciOnline = await getCodici_AnnunciHandler(); - const { success, failed } = await revalidateMultiple( - annunciOnline.map((cod) => `/annuncio/${cod}`), - ); - if (success.length === 0) { - console.log("No annunci were revalidated."); - } - //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", - details: data, - }; - } catch (err) { - console.error("Update error:", err); - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: err instanceof Error ? err.message : "Update failed", - cause: err, - }); - } - }), - updateAnnuncio: adminProcedure - .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( - `Update failed with status ${response.status}: ${errorData}`, - ); - } - - const data = await response.json().catch(() => ({})); - await revalidate(`/annuncio/${input.cod}`); - return { - status: "success", - details: data, - }; - } catch (err) { - console.error("Update error:", err); - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: err instanceof Error ? err.message : "Update failed", - cause: err, - }); - } - }), -}); diff --git a/apps/infoalloggi/src/server/api/routers/strings.ts b/apps/infoalloggi/src/server/api/routers/strings.ts new file mode 100644 index 0000000..e06ae95 --- /dev/null +++ b/apps/infoalloggi/src/server/api/routers/strings.ts @@ -0,0 +1,78 @@ +import { z } from "zod/v4"; +import { + adminProcedure, + createTRPCRouter, + publicProcedure, +} from "~/server/api/trpc"; +import { db } from "~/server/db"; +import { + deleteStringa, + getStringa, + getStringhe, + getStringheFiltered, + newStringa, + updateStringhe, +} from "~/server/services/testi_stringhe.service"; +import { zTestiEStringheStingaId } from "~/server/utils/zod_types"; + +export const stringsRouter = createTRPCRouter({ + getStringa: publicProcedure + .input( + z.object({ + stringaId: zTestiEStringheStingaId, + }), + ) + .query(async ({ input }) => { + return await getStringa({ + db, + stringaId: input.stringaId, + }); + }), + getStringhe: adminProcedure.query(async () => { + return await getStringhe({ db }); + }), + getStringheCondizioni: adminProcedure.query(async () => { + return await getStringheFiltered({ contains: "CONDIZIONI", db }); + }), + deleteStringa: adminProcedure + .input( + z.object({ + stringaId: zTestiEStringheStingaId, + }), + ) + .mutation(async ({ input }) => { + return await deleteStringa({ + db, + stringaId: input.stringaId, + }); + }), + newStringa: adminProcedure + .input( + z.object({ + stringaId: zTestiEStringheStingaId, + stringaValue: z.string().nullable(), + }), + ) + .mutation(async ({ input }) => { + return await newStringa({ + db, + stringaId: input.stringaId, + stringaValue: input.stringaValue, + }); + }), + + updateStringa: adminProcedure + .input( + z.object({ + stringaId: zTestiEStringheStingaId, + stringaValue: z.string().nullable(), + }), + ) + .mutation(async ({ input }) => { + return await updateStringhe({ + db, + stringaId: input.stringaId, + stringaValue: input.stringaValue, + }); + }), +}); diff --git a/apps/infoalloggi/src/server/controllers/flags.controller.ts b/apps/infoalloggi/src/server/controllers/flags.controller.ts index 543e26e..ce6bdbc 100644 --- a/apps/infoalloggi/src/server/controllers/flags.controller.ts +++ b/apps/infoalloggi/src/server/controllers/flags.controller.ts @@ -1,5 +1,5 @@ import { TRPCError } from "@trpc/server"; -import type { FlagsId } from "~/schemas/public/Flags"; +import type { Flags, FlagsId } from "~/schemas/public/Flags"; import type { Querier } from "~/server/db"; export const EditFlagHandler = async ({ @@ -7,10 +7,7 @@ export const EditFlagHandler = async ({ input, }: { db: Querier; - input: { - id: FlagsId; - value: string; - }; + input: Flags; }) => { try { return await db @@ -83,10 +80,7 @@ export const AddFlagHandler = async ({ input, }: { db: Querier; - input: { - id: FlagsId; - value: string; - }; + input: Flags; }) => { try { await db diff --git a/apps/infoalloggi/src/server/controllers/skebby.controller.ts b/apps/infoalloggi/src/server/controllers/skebby.controller.ts index 38d342a..f3736e7 100644 --- a/apps/infoalloggi/src/server/controllers/skebby.controller.ts +++ b/apps/infoalloggi/src/server/controllers/skebby.controller.ts @@ -133,9 +133,34 @@ async function sendSMS(auth: Auth, smsData: SMSData) { export const SendMessage = async (data: MinimalSMSData) => { const smsFlag = await GetFlagValueHandler({ db: db, - id: "SMS_OFF", + id: "SMS_ENABLED", }); - if (smsFlag === "true") { + if (smsFlag) { + try { + const auth = await login(env.SKEBBY_USER, env.SKEBBY_PASS); + await sendSMS(auth, { + ...data, + message_type: MessageType.HIGH_QUALITY, + sender: "InfoAlloggi", + }); + } catch (error) { + console.error("Error:", error); + + await NewMail({ + template: { + mailType: "generic", + props: { + testo: `Errore durante l'invio dell'SMS: to:${data.recipient.join(", ")} Mgs:${data.message}; ${error instanceof Error ? error.message : String(error)}`, + title: "Errore invio SMS", + }, + }, + mail: { + subject: "Errore invio SMS", + to: "web@infoalloggi.it", + }, + }); + } + } else { console.warn( `SMS sending is disabled to:${data.recipient.join(", ")} Mgs:${data.message}`, ); @@ -144,28 +169,4 @@ export const SendMessage = async (data: MinimalSMSData) => { success: true, }; } - try { - const auth = await login(env.SKEBBY_USER, env.SKEBBY_PASS); - await sendSMS(auth, { - ...data, - message_type: MessageType.HIGH_QUALITY, - sender: "InfoAlloggi", - }); - } catch (error) { - console.error("Error:", error); - - await NewMail({ - template: { - mailType: "generic", - props: { - testo: `Errore durante l'invio dell'SMS: to:${data.recipient.join(", ")} Mgs:${data.message}; ${error instanceof Error ? error.message : String(error)}`, - title: "Errore invio SMS", - }, - }, - mail: { - subject: "Errore invio SMS", - to: "web@infoalloggi.it", - }, - }); - } }; diff --git a/apps/infoalloggi/src/server/services/mailer.ts b/apps/infoalloggi/src/server/services/mailer.ts index 0ea2da8..f982305 100644 --- a/apps/infoalloggi/src/server/services/mailer.ts +++ b/apps/infoalloggi/src/server/services/mailer.ts @@ -189,9 +189,9 @@ export const genMail = async ({ ...mail }: MailsTemplates) => { export const NewMail = async ({ template, userId, mail }: NewMailProps) => { const emailFlag = await GetFlagValueHandler({ db: db, - id: "EMAIL_OFF", + id: "EMAIL_ENABLED", }); - if (emailFlag === "false") { + if (emailFlag) { try { if (template) { const { html } = await genMail({ ...template });