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.
This commit is contained in:
parent
3ea9354abb
commit
9c18ca37ab
27 changed files with 555 additions and 495 deletions
25
apps/db/migrations/27_flags_bool.up.sql
Normal file
25
apps/db/migrations/27_flags_bool.up.sql
Normal file
|
|
@ -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;
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export const EtichetteModal = ({
|
|||
const [selected, setSelected] = useState<EtichetteIdEtichetta | null>(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 () => {
|
||||
|
|
|
|||
|
|
@ -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 ? (
|
||||
<span className="text-success">Attivo</span>
|
||||
) : (
|
||||
<span>Inattivo</span>
|
||||
);
|
||||
},
|
||||
enableHiding: false,
|
||||
header: ({ column }) => (
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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<typeof Schema>;
|
||||
|
||||
|
|
@ -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 }) => (
|
||||
<FormItem>
|
||||
<div className="flex flex-wrap items-center gap-x-2">
|
||||
<FormLabel htmlFor="value">Valore testuale</FormLabel>
|
||||
<FormLabel htmlFor="value">Attivo/Inattivo</FormLabel>
|
||||
<FormMessage />
|
||||
</div>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder=""
|
||||
{...field}
|
||||
<Switch
|
||||
checked={field.value}
|
||||
className="data-[state=checked]:bg-neutral-700"
|
||||
id="value"
|
||||
value={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
|
|
|
|||
|
|
@ -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 = [
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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<Banners | null>(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);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<Etichette | null>(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);
|
||||
|
|
|
|||
|
|
@ -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<initialValues | null>(null);
|
||||
const [editData, setEditData] = useState<Flags | null>(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);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<TestiEStringhe | null>(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);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ type CondizioniProps = {
|
|||
const CondizioniPage: NextPageWithLayout<CondizioniProps> = ({
|
||||
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,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export type FlagsId = string & { __brand: 'public.flags' };
|
|||
export default interface FlagsTable {
|
||||
id: ColumnType<FlagsId, FlagsId, FlagsId>;
|
||||
|
||||
value: ColumnType<string, string, string>;
|
||||
value: ColumnType<boolean, boolean | undefined, boolean>;
|
||||
}
|
||||
|
||||
export type Flags = Selectable<FlagsTable>;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
81
apps/infoalloggi/src/server/api/routers/banners.ts
Normal file
81
apps/infoalloggi/src/server/api/routers/banners.ts
Normal file
|
|
@ -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<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(),
|
||||
}),
|
||||
)
|
||||
.mutation(async ({ input }) => {
|
||||
return await addBanner({ db, input });
|
||||
}),
|
||||
getBannerAllData: publicProcedure.query(async () => {
|
||||
return await getAllBanners({ db });
|
||||
}),
|
||||
deleteBanner: adminProcedure
|
||||
.input(z.object({ idbanner: z.custom<BannersIdbanner>() }))
|
||||
.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<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(),
|
||||
}),
|
||||
)
|
||||
.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,
|
||||
});
|
||||
}),
|
||||
});
|
||||
54
apps/infoalloggi/src/server/api/routers/etichette.ts
Normal file
54
apps/infoalloggi/src/server/api/routers/etichette.ts
Normal file
|
|
@ -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,
|
||||
});
|
||||
}),
|
||||
});
|
||||
58
apps/infoalloggi/src/server/api/routers/flags.ts
Normal file
58
apps/infoalloggi/src/server/api/routers/flags.ts
Normal file
|
|
@ -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 });
|
||||
}),
|
||||
});
|
||||
133
apps/infoalloggi/src/server/api/routers/revalidation.ts
Normal file
133
apps/infoalloggi/src/server/api/routers/revalidation.ts
Normal file
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
|
@ -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<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(),
|
||||
}),
|
||||
)
|
||||
.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<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,
|
||||
});
|
||||
}),
|
||||
|
||||
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<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(),
|
||||
}),
|
||||
)
|
||||
.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,
|
||||
});
|
||||
}
|
||||
}),
|
||||
});
|
||||
78
apps/infoalloggi/src/server/api/routers/strings.ts
Normal file
78
apps/infoalloggi/src/server/api/routers/strings.ts
Normal file
|
|
@ -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,
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue