From b3c70bfa1a8ab11c1142278060f1617b26f573b9 Mon Sep 17 00:00:00 2001 From: Marco Pedone Date: Wed, 29 Apr 2026 15:12:52 +0200 Subject: [PATCH] feat: add admin appunti management page and related functionality - Introduced a new page for managing appunti in the admin area. - Created AppuntiProvider to manage appunti state and API interactions. - Added schemas for appunti and appunti groups. - Implemented CRUD operations for appunti and appunti groups in the API. - Removed potenziali related files and services as part of the refactor. - Updated the public schema to include appunti and appunti groups. - Improved error handling in the appunti service. Co-authored-by: Copilot --- apps/db/migrations/47_messages.up.sql | 2 +- .../49_potenziali_to_appunti.up.sql | 33 ++++ apps/infoalloggi/kanel.config.js | 1 - .../src/components/IconComponents.tsx | 4 + .../{potenziali.tsx => appunti.tsx} | 32 ++-- apps/infoalloggi/src/i18n/en.ts | 8 +- apps/infoalloggi/src/i18n/it.ts | 8 +- .../admin/{potenziali.tsx => appunti.tsx} | 28 ++- .../pages/area-riservata/admin/catasto.tsx | 18 +- .../src/providers/AppuntiProvider.tsx | 151 ++++++++++++++++ .../src/providers/PotenzialiProvider.tsx | 155 ---------------- .../infoalloggi/src/schemas/public/Appunti.ts | 57 ++++++ .../src/schemas/public/AppuntiGroups.ts | 40 +++++ .../src/schemas/public/Potenziali.ts | 57 ------ .../src/schemas/public/PotenzialiGroups.ts | 40 ----- .../src/schemas/public/PublicSchema.ts | 12 +- apps/infoalloggi/src/server/api/root.ts | 4 +- .../src/server/api/routers/appunti.ts | 76 ++++++++ .../src/server/api/routers/catasto.ts | 32 +--- .../src/server/api/routers/potenziali.ts | 86 --------- .../src/server/services/appunti.service.ts | 162 +++++++++++++++++ .../src/server/services/potenziali.service.ts | 165 ------------------ .../infoalloggi/src/server/utils/zod_utils.ts | 2 + 23 files changed, 582 insertions(+), 591 deletions(-) create mode 100644 apps/db/migrations/49_potenziali_to_appunti.up.sql rename apps/infoalloggi/src/components/area-riservata/{potenziali.tsx => appunti.tsx} (94%) rename apps/infoalloggi/src/pages/area-riservata/admin/{potenziali.tsx => appunti.tsx} (55%) create mode 100644 apps/infoalloggi/src/providers/AppuntiProvider.tsx delete mode 100644 apps/infoalloggi/src/providers/PotenzialiProvider.tsx create mode 100644 apps/infoalloggi/src/schemas/public/Appunti.ts create mode 100644 apps/infoalloggi/src/schemas/public/AppuntiGroups.ts delete mode 100644 apps/infoalloggi/src/schemas/public/Potenziali.ts delete mode 100644 apps/infoalloggi/src/schemas/public/PotenzialiGroups.ts create mode 100644 apps/infoalloggi/src/server/api/routers/appunti.ts delete mode 100644 apps/infoalloggi/src/server/api/routers/potenziali.ts create mode 100644 apps/infoalloggi/src/server/services/appunti.service.ts delete mode 100644 apps/infoalloggi/src/server/services/potenziali.service.ts diff --git a/apps/db/migrations/47_messages.up.sql b/apps/db/migrations/47_messages.up.sql index b5e2277..c8475af 100644 --- a/apps/db/migrations/47_messages.up.sql +++ b/apps/db/migrations/47_messages.up.sql @@ -5,7 +5,7 @@ SET message = '' WHERE message IS NULL; ALTER TABLE IF EXISTS public.messages - ALTER COLUMN IF EXISTS message SET NOT NULL; + ALTER COLUMN message SET NOT NULL; ALTER TABLE IF EXISTS public.messages ADD COLUMN IF NOT EXISTS reply_to_id UUID REFERENCES messages(messageid) ON DELETE SET NULL, diff --git a/apps/db/migrations/49_potenziali_to_appunti.up.sql b/apps/db/migrations/49_potenziali_to_appunti.up.sql new file mode 100644 index 0000000..eb0a852 --- /dev/null +++ b/apps/db/migrations/49_potenziali_to_appunti.up.sql @@ -0,0 +1,33 @@ +DO $$ +BEGIN + -- 1. Rename Tables + IF EXISTS (SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = 'potenziali') THEN + ALTER TABLE public.potenziali RENAME TO appunti; + END IF; + + IF EXISTS (SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = 'potenziali_groups') THEN + ALTER TABLE public.potenziali_groups RENAME TO appunti_groups; + END IF; + + -- 2. Rename Column (IF EXISTS is supported here in PG 10+) + IF EXISTS (SELECT FROM information_schema.columns WHERE table_name='appunti' AND column_name='potenziali_group_id') THEN + ALTER TABLE public.appunti RENAME COLUMN potenziali_group_id TO appunti_group_id; + END IF; + + -- 3. Rename Constraints (Requires manual check because RENAME CONSTRAINT IF EXISTS doesn't exist) + IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'potenziali_pkey') THEN + ALTER TABLE public.appunti RENAME CONSTRAINT potenziali_pkey TO appunti_pkey; + END IF; + + IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'potenziali_assigned_user') THEN + ALTER TABLE public.appunti RENAME CONSTRAINT potenziali_assigned_user TO appunti_assigned_user; + END IF; + + IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'potenziali_group_fk') THEN + ALTER TABLE public.appunti RENAME CONSTRAINT potenziali_group_fk TO appunti_group_fk; + END IF; + + IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'potenziali_groups_pkey') THEN + ALTER TABLE public.appunti_groups RENAME CONSTRAINT potenziali_groups_pkey TO appunti_groups_pkey; + END IF; +END $$; \ No newline at end of file diff --git a/apps/infoalloggi/kanel.config.js b/apps/infoalloggi/kanel.config.js index 1030bd9..a9988af 100644 --- a/apps/infoalloggi/kanel.config.js +++ b/apps/infoalloggi/kanel.config.js @@ -132,7 +132,6 @@ function zodUpdateInsertionDatesFix(path, lines) { insideUpdateOrInsert = true; } if (insideUpdateOrInsert && line.includes("z.date()")) { - console.log(`Fixing line in ${path}: ${line}`); return line.replace("z.date()", "z.union([z.date(), z.string()]).pipe(z.coerce.date())"); } diff --git a/apps/infoalloggi/src/components/IconComponents.tsx b/apps/infoalloggi/src/components/IconComponents.tsx index a4ea66b..b01f0ce 100644 --- a/apps/infoalloggi/src/components/IconComponents.tsx +++ b/apps/infoalloggi/src/components/IconComponents.tsx @@ -28,6 +28,7 @@ import { MessageSquareText, MessagesSquare, Milestone, + NotebookPen, Paperclip, Pointer, Search, @@ -102,6 +103,7 @@ const iconOptions = [ "bell", "target", "thumbs-up", + "note" ] as const; export type IconType = (typeof iconOptions)[number]; @@ -202,6 +204,8 @@ export const IconMatrix = ({ type, ...rest }: IconMatrixProps) => { return ; case "thumbs-up": return ; + case "note": + return ; default: throw new Error(`Invalid icon type: ${type satisfies never}`); } diff --git a/apps/infoalloggi/src/components/area-riservata/potenziali.tsx b/apps/infoalloggi/src/components/area-riservata/appunti.tsx similarity index 94% rename from apps/infoalloggi/src/components/area-riservata/potenziali.tsx rename to apps/infoalloggi/src/components/area-riservata/appunti.tsx index 495c49a..4b58474 100644 --- a/apps/infoalloggi/src/components/area-riservata/potenziali.tsx +++ b/apps/infoalloggi/src/components/area-riservata/appunti.tsx @@ -11,10 +11,10 @@ import { KanbanProvider, } from "~/components/ui/kanban"; import { ScrollArea, ScrollBar } from "~/components/ui/scroll-area"; -import { usePotenziali } from "~/providers/PotenzialiProvider"; -import type { PotenzialiGroupsId } from "~/schemas/public/PotenzialiGroups"; +import { useAppunti } from "~/providers/AppuntiProvider"; +import type { AppuntiGroupsId } from "~/schemas/public/AppuntiGroups"; import type { UsersId } from "~/schemas/public/Users"; -import type { PotenzialeData } from "~/server/services/potenziali.service"; +import type { AppuntiData } from "~/server/services/appunti.service"; import { api } from "~/utils/api"; import { Confirm } from "../confirm"; import { @@ -43,8 +43,8 @@ import { import { Textarea } from "../ui/textarea"; import { UserAvatar } from "../user_avatar"; -export const Potenziali = () => { - const { data, columns, setData, updateCall, removeColumn } = usePotenziali(); +export const Appunti = () => { + const { data, columns, setData, updateCall, removeColumn } = useAppunti(); return ( { - {(data: PotenzialeData) => ( - ( + { ); }; // 1. Extract the card logic into a separate component -const PotenzialeCardItem = ({ +const AppuntiCardItem = ({ data, columnId, }: { - data: PotenzialeData; + data: AppuntiData; columnId: string; }) => { const [isEditingOpen, setIsEditingOpen] = useState(false); @@ -155,7 +155,7 @@ const PotenzialeCardItem = ({ export const NewColumn = () => { const [newColumnName, setNewColumnName] = useState(""); - const { addColumn } = usePotenziali(); + const { addColumn } = useAppunti(); const [open, setOpen] = useState(false); return ( @@ -194,11 +194,11 @@ export const NewColumn = () => { ); }; -const NewCard = ({ columnId }: { columnId: PotenzialiGroupsId }) => { +const NewCard = ({ columnId }: { columnId: AppuntiGroupsId }) => { const [newItemName, setNewItemName] = useState(""); const [newItemDescrizione, setNewItemDescrizione] = useState(""); const [newItemUserid, setNewItemUserid] = useState(null); - const { addItem } = usePotenziali(); + const { addItem } = useAppunti(); const [open, setOpen] = useState(false); const resetState = () => { @@ -210,7 +210,7 @@ const NewCard = ({ columnId }: { columnId: PotenzialiGroupsId }) => { addItem({ name: newItemName, descrizione: newItemDescrizione, - potenziali_group_id: columnId, + appunti_group_id: columnId, userid: newItemUserid, }); resetState(); @@ -319,11 +319,11 @@ const EditingItem = ({ }: { open: boolean; setOpen: (open: boolean) => void; - data: PotenzialeData; + data: AppuntiData; }) => { - const { updateItem, removeItem } = usePotenziali(); + const { updateItem, removeItem } = useAppunti(); - const [state, setState] = useState(data); + const [state, setState] = useState(data); const [hasChanges, setHasChanges] = useState(false); const { data: admins, isLoading } = api.users.getAdmins.useQuery(); useEffect(() => { diff --git a/apps/infoalloggi/src/i18n/en.ts b/apps/infoalloggi/src/i18n/en.ts index 465a8d2..31753d1 100644 --- a/apps/infoalloggi/src/i18n/en.ts +++ b/apps/infoalloggi/src/i18n/en.ts @@ -656,7 +656,7 @@ export const en: LangDict = { { icon: "cog", items: [ - { href: "/area-riservata/admin/potenziali", title: "Potenziali" }, + { href: "/area-riservata/admin/appunti", title: "Appunti" }, { href: "/area-riservata/admin/utenti", title: "Users" }, { href: "/area-riservata/admin/richieste", title: "Requests" }, { href: "/area-riservata/admin/chats", title: "Chat List" }, @@ -741,9 +741,9 @@ export const en: LangDict = { title: "Dashboard", }, { - href: "/area-riservata/admin/potenziali", - icon: { className: "", icon: "contact" }, - title: "Potenziali", + href: "/area-riservata/admin/appunti", + icon: { className: "", icon: "note" }, + title: "Notes", }, { href: "/area-riservata/admin/utenti", diff --git a/apps/infoalloggi/src/i18n/it.ts b/apps/infoalloggi/src/i18n/it.ts index 1223cca..09c3d92 100644 --- a/apps/infoalloggi/src/i18n/it.ts +++ b/apps/infoalloggi/src/i18n/it.ts @@ -661,7 +661,7 @@ export const it: LangDict = { { icon: "cog", items: [ - { href: "/area-riservata/admin/potenziali", title: "Potenziali" }, + { href: "/area-riservata/admin/appunti", title: "Appunti" }, { href: "/area-riservata/admin/utenti", title: "Utenti" }, { href: "/area-riservata/admin/richieste", title: "Richieste" }, { href: "/area-riservata/admin/chats", title: "Lista Chat" }, @@ -737,9 +737,9 @@ export const it: LangDict = { title: "Dashboard", }, { - href: "/area-riservata/admin/potenziali", - icon: { className: "", icon: "contact" }, - title: "Potenziali", + href: "/area-riservata/admin/Appunti", + icon: { className: "", icon: "note" }, + title: "Appunti", }, { href: "/area-riservata/admin/utenti", diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/potenziali.tsx b/apps/infoalloggi/src/pages/area-riservata/admin/appunti.tsx similarity index 55% rename from apps/infoalloggi/src/pages/area-riservata/admin/potenziali.tsx rename to apps/infoalloggi/src/pages/area-riservata/admin/appunti.tsx index 9c44fff..6a0bf3a 100644 --- a/apps/infoalloggi/src/pages/area-riservata/admin/potenziali.tsx +++ b/apps/infoalloggi/src/pages/area-riservata/admin/appunti.tsx @@ -1,16 +1,14 @@ import dynamic from "next/dynamic"; import Head from "next/head"; -import { NewColumn } from "~/components/area-riservata/potenziali"; +import { NewColumn } from "~/components/area-riservata/appunti"; import { AreaRiservataLayout } from "~/components/Layout"; import { LoadingPage } from "~/components/loading"; import type { NextPageWithLayout } from "~/pages/_app"; -import { PotenzialiProvider } from "~/providers/PotenzialiProvider"; +import { AppuntiProvider } from "~/providers/AppuntiProvider"; -const PotenzialiBoard = dynamic( +const AppuntiBoard = dynamic( () => - import("~/components/area-riservata/potenziali").then( - (mod) => mod.Potenziali, - ), + import("~/components/area-riservata/appunti").then((mod) => mod.Appunti), { ssr: false, loading: () => , @@ -18,33 +16,33 @@ const PotenzialiBoard = dynamic( ); /** - * Pagina di gestione potenziali per admin: /area-riservata/admin/potenziali + * Pagina di gestione appunti per admin: /area-riservata/admin/appunti */ -const AdminPotenziali: NextPageWithLayout = () => { +const AdminAppunti: NextPageWithLayout = () => { return ( - + - Potenziali - Infoalloggi.it + Appunti - Infoalloggi.it

- Potenziali + Appunti

- +
-
+ ); }; -export default AdminPotenziali; +export default AdminAppunti; -AdminPotenziali.getLayout = function getLayout(page) { +AdminAppunti.getLayout = function getLayout(page) { return {page}; }; diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/catasto.tsx b/apps/infoalloggi/src/pages/area-riservata/admin/catasto.tsx index 8b6ed03..51143e1 100644 --- a/apps/infoalloggi/src/pages/area-riservata/admin/catasto.tsx +++ b/apps/infoalloggi/src/pages/area-riservata/admin/catasto.tsx @@ -265,11 +265,7 @@ const SezioneComuni = () => { desc - deleteComune({ - id: selectedComune.id, - }) - } + handleRemove={() => deleteComune(selectedComune.id)} initialValues={selectedComune} submitMutation={(values) => { editComune({ @@ -580,11 +576,7 @@ const SezioneProvincie = () => { desc - deleteProvincia({ - id: selectedProvincia.id, - }) - } + handleRemove={() => deleteProvincia(selectedProvincia.id)} initialValues={selectedProvincia} submitMutation={(values) => { editProvincia({ @@ -865,11 +857,7 @@ const SezioneNazioni = () => { desc - deleteNazione({ - id: selectedNazione.id, - }) - } + handleRemove={() => deleteNazione(selectedNazione.id)} initialValues={selectedNazione} submitMutation={(values) => { editNazione({ diff --git a/apps/infoalloggi/src/providers/AppuntiProvider.tsx b/apps/infoalloggi/src/providers/AppuntiProvider.tsx new file mode 100644 index 0000000..34093f0 --- /dev/null +++ b/apps/infoalloggi/src/providers/AppuntiProvider.tsx @@ -0,0 +1,151 @@ +import { createContext, useContext } from "react"; +import toast from "react-hot-toast"; +import type { AppuntiId, NewAppunti } from "~/schemas/public/Appunti"; +import type { + AppuntiGroups, + AppuntiGroupsId, +} from "~/schemas/public/AppuntiGroups"; + +import type { AppuntiData } from "~/server/services/appunti.service"; +import { api } from "~/utils/api"; + +type AppuntiContextType = { + data: AppuntiData[]; + columns: AppuntiGroups[]; + setData: (data: AppuntiData[]) => void; + updateCall: () => void; + addItem: (item: NewAppunti) => void; + removeItem: (id: AppuntiId) => void; + removeColumn: (id: AppuntiGroupsId) => void; + addColumn: (name: string) => void; + updateItem: (item: AppuntiData) => void; +}; + +const AppuntiContext = createContext(null); + +type AppuntiProviderProps = { + children: React.ReactNode; +}; +export const AppuntiProvider = ({ children }: AppuntiProviderProps) => { + const { data, isError } = api.appunti.getAppunti.useQuery(undefined, { + refetchInterval: 30000, + refetchIntervalInBackground: true, + refetchOnWindowFocus: true, + }); + + if (isError) { + console.error("Errore nel caricamento dei potenziali"); + window.location.reload(); + } + + const { data: columns } = api.appunti.getAppuntiGroups.useQuery(); + + const utils = api.useUtils(); + const { mutate: addItemMutation } = api.appunti.addAppunti.useMutation({ + onSuccess: async () => { + toast.success("Elemento aggiunto con successo"); + await utils.appunti.getAppunti.invalidate(); + await utils.appunti.getAppuntiGroups.invalidate(); + }, + }); + + const addItem = (item: NewAppunti) => { + addItemMutation({ + data: item, + }); + }; + const { mutate: removeItemMutation } = api.appunti.deleteAppunti.useMutation({ + onSuccess: async () => { + toast.success("Elemento rimosso con successo"); + await utils.appunti.getAppunti.invalidate(); + await utils.appunti.getAppuntiGroups.invalidate(); + }, + }); + const removeItem = (id: AppuntiId) => { + removeItemMutation(id); + }; + const setData = (newData: AppuntiData[]) => { + utils.appunti.getAppunti.setData(undefined, newData); + }; + + const { mutate: updateAppuntiMutation } = + api.appunti.updateAppunti.useMutation({ + onSuccess: async () => { + await utils.appunti.getAppunti.invalidate(); + }, + }); + + const updateCall = () => { + updateAppuntiMutation({ + data: utils.appunti.getAppunti.getData() || [], + }); + }; + + const { mutate: addColumnMutation } = api.appunti.addAppuntiGroup.useMutation( + { + onSuccess: async () => { + toast.success("Colonna aggiunta con successo"); + await utils.appunti.getAppunti.invalidate(); + await utils.appunti.getAppuntiGroups.invalidate(); + }, + }, + ); + const addColumn = (name: string) => { + addColumnMutation({ + name, + }); + }; + const { mutate: updateItemMutation } = api.appunti.updateAppunto.useMutation({ + onSuccess: async () => { + toast.success("Elemento aggiornato con successo"); + await utils.appunti.getAppunti.invalidate(); + }, + }); + const updateItem = (item: AppuntiData) => { + const { column, username: _username, ...rest } = item; + updateItemMutation({ + appuntiId: item.id, + data: { + ...rest, + appunti_group_id: column as AppuntiGroupsId, + }, + }); + }; + + const { mutate: removeColumnMutation } = + api.appunti.deleteAppuntiGroup.useMutation({ + onSuccess: async () => { + toast.success("Colonna rimossa con successo"); + await utils.appunti.getAppunti.invalidate(); + await utils.appunti.getAppuntiGroups.invalidate(); + }, + }); + const removeColumn = (id: AppuntiGroupsId) => { + removeColumnMutation(id); + }; + + return ( + + {children} + + ); +}; +export const useAppunti = () => { + const context = useContext(AppuntiContext); + if (!context) { + throw new Error("useAppunti must be used within a AppuntiProvider"); + } + return context; +}; diff --git a/apps/infoalloggi/src/providers/PotenzialiProvider.tsx b/apps/infoalloggi/src/providers/PotenzialiProvider.tsx deleted file mode 100644 index f8d4cc7..0000000 --- a/apps/infoalloggi/src/providers/PotenzialiProvider.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import { createContext, useContext } from "react"; -import toast from "react-hot-toast"; -import type { NewPotenziali, PotenzialiId } from "~/schemas/public/Potenziali"; -import type { - PotenzialiGroups, - PotenzialiGroupsId, -} from "~/schemas/public/PotenzialiGroups"; -import type { PotenzialeData } from "~/server/services/potenziali.service"; -import { api } from "~/utils/api"; - -type PotenzialiContextType = { - data: PotenzialeData[]; - columns: PotenzialiGroups[]; - setData: (data: PotenzialeData[]) => void; - updateCall: () => void; - addItem: (item: NewPotenziali) => void; - removeItem: (id: PotenzialiId) => void; - removeColumn: (id: PotenzialiGroupsId) => void; - addColumn: (name: string) => void; - updateItem: (item: PotenzialeData) => void; -}; - -const PotenzialiContext = createContext(null); - -type PotenzialiProviderProps = { - children: React.ReactNode; -}; -export const PotenzialiProvider = ({ children }: PotenzialiProviderProps) => { - const { data, isError } = api.potenziali.getPotenziali.useQuery(undefined, { - refetchInterval: 30000, - refetchIntervalInBackground: true, - refetchOnWindowFocus: true, - }); - - if (isError) { - console.error("Errore nel caricamento dei potenziali"); - window.location.reload(); - } - - const { data: columns } = api.potenziali.getPotenzialiGroups.useQuery(); - - const utils = api.useUtils(); - const { mutate: addItemMutation } = api.potenziali.addPotenziale.useMutation({ - onSuccess: async () => { - toast.success("Elemento aggiunto con successo"); - await utils.potenziali.getPotenziali.invalidate(); - await utils.potenziali.getPotenzialiGroups.invalidate(); - }, - }); - - const addItem = (item: NewPotenziali) => { - addItemMutation({ - data: item, - }); - }; - const { mutate: removeItemMutation } = - api.potenziali.deletePotenziale.useMutation({ - onSuccess: async () => { - toast.success("Elemento rimosso con successo"); - await utils.potenziali.getPotenziali.invalidate(); - await utils.potenziali.getPotenzialiGroups.invalidate(); - }, - }); - const removeItem = (id: PotenzialiId) => { - removeItemMutation({ - potenzialiId: id, - }); - }; - const setData = (newData: PotenzialeData[]) => { - utils.potenziali.getPotenziali.setData(undefined, newData); - }; - - const { mutate: updatePotenzialiMutation } = - api.potenziali.updatePotenziali.useMutation({ - onSuccess: async () => { - await utils.potenziali.getPotenziali.invalidate(); - }, - }); - - const updateCall = () => { - updatePotenzialiMutation({ - data: utils.potenziali.getPotenziali.getData() || [], - }); - }; - - const { mutate: addColumnMutation } = - api.potenziali.addPotenzialeGroup.useMutation({ - onSuccess: async () => { - toast.success("Colonna aggiunta con successo"); - await utils.potenziali.getPotenziali.invalidate(); - await utils.potenziali.getPotenzialiGroups.invalidate(); - }, - }); - const addColumn = (name: string) => { - addColumnMutation({ - name, - }); - }; - const { mutate: updateItemMutation } = - api.potenziali.updatePotenziale.useMutation({ - onSuccess: async () => { - toast.success("Elemento aggiornato con successo"); - await utils.potenziali.getPotenziali.invalidate(); - }, - }); - const updateItem = (item: PotenzialeData) => { - const { column, username: _username, ...rest } = item; - updateItemMutation({ - potenzialiId: item.id, - data: { - ...rest, - potenziali_group_id: column as PotenzialiGroupsId, - }, - }); - }; - - const { mutate: removeColumnMutation } = - api.potenziali.deletePotenzialeGroup.useMutation({ - onSuccess: async () => { - toast.success("Colonna rimossa con successo"); - await utils.potenziali.getPotenziali.invalidate(); - await utils.potenziali.getPotenzialiGroups.invalidate(); - }, - }); - const removeColumn = (id: PotenzialiGroupsId) => { - removeColumnMutation({ - potenzialiGroupId: id, - }); - }; - - return ( - - {children} - - ); -}; -export const usePotenziali = () => { - const context = useContext(PotenzialiContext); - if (!context) { - throw new Error("usePotenziali must be used within a PotenzialiProvider"); - } - return context; -}; diff --git a/apps/infoalloggi/src/schemas/public/Appunti.ts b/apps/infoalloggi/src/schemas/public/Appunti.ts new file mode 100644 index 0000000..c306f30 --- /dev/null +++ b/apps/infoalloggi/src/schemas/public/Appunti.ts @@ -0,0 +1,57 @@ +import { usersId, type UsersId } from './Users'; +import { appuntiGroupsId, type AppuntiGroupsId } from './AppuntiGroups'; +import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely'; +import { z } from 'zod'; + +/** Identifier type for public.appunti */ +export type AppuntiId = string & { __brand: 'public.appunti' }; + +/** Represents the table public.appunti */ +export default interface AppuntiTable { + id: ColumnType; + + name: ColumnType; + + descrizione: ColumnType; + + created_at: ColumnType; + + userid: ColumnType; + + appunti_group_id: ColumnType; +} + +export type Appunti = Selectable; + +export type NewAppunti = Insertable; + +export type AppuntiUpdate = Updateable; + +export const appuntiId = z.uuid().transform(value => value as AppuntiId); + +export const AppuntiSchema = z.object({ + id: appuntiId, + name: z.string(), + descrizione: z.string().nullable(), + created_at: z.date(), + userid: usersId.nullable(), + appunti_group_id: appuntiGroupsId, +}); + +export const NewAppuntiSchema = z.object({ + id: appuntiId.optional(), + name: z.string(), + descrizione: z.string().optional().nullable(), + created_at: z.union([z.date(), z.string()]).pipe(z.coerce.date()).optional(), + userid: usersId.optional().nullable(), + appunti_group_id: appuntiGroupsId, +}); + +export const AppuntiUpdateSchema = z.object({ + id: appuntiId.optional(), + name: z.string().optional(), + descrizione: z.string().optional().nullable(), + created_at: z.union([z.date(), z.string()]).pipe(z.coerce.date()).optional(), + userid: usersId.optional().nullable(), + appunti_group_id: appuntiGroupsId.optional(), +}); \ No newline at end of file diff --git a/apps/infoalloggi/src/schemas/public/AppuntiGroups.ts b/apps/infoalloggi/src/schemas/public/AppuntiGroups.ts new file mode 100644 index 0000000..1fe426b --- /dev/null +++ b/apps/infoalloggi/src/schemas/public/AppuntiGroups.ts @@ -0,0 +1,40 @@ +import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely'; +import { z } from 'zod'; + +/** Identifier type for public.appunti_groups */ +export type AppuntiGroupsId = string & { __brand: 'public.appunti_groups' }; + +/** Represents the table public.appunti_groups */ +export default interface AppuntiGroupsTable { + id: ColumnType; + + name: ColumnType; + + color: ColumnType; +} + +export type AppuntiGroups = Selectable; + +export type NewAppuntiGroups = Insertable; + +export type AppuntiGroupsUpdate = Updateable; + +export const appuntiGroupsId = z.uuid().transform(value => value as AppuntiGroupsId); + +export const AppuntiGroupsSchema = z.object({ + id: appuntiGroupsId, + name: z.string(), + color: z.string(), +}); + +export const NewAppuntiGroupsSchema = z.object({ + id: appuntiGroupsId.optional(), + name: z.string(), + color: z.string().optional(), +}); + +export const AppuntiGroupsUpdateSchema = z.object({ + id: appuntiGroupsId.optional(), + name: z.string().optional(), + color: z.string().optional(), +}); \ No newline at end of file diff --git a/apps/infoalloggi/src/schemas/public/Potenziali.ts b/apps/infoalloggi/src/schemas/public/Potenziali.ts deleted file mode 100644 index 2f1d320..0000000 --- a/apps/infoalloggi/src/schemas/public/Potenziali.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { usersId, type UsersId } from './Users'; -import { potenzialiGroupsId, type PotenzialiGroupsId } from './PotenzialiGroups'; -import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely'; -import { z } from 'zod'; - -/** Identifier type for public.potenziali */ -export type PotenzialiId = string & { __brand: 'public.potenziali' }; - -/** Represents the table public.potenziali */ -export default interface PotenzialiTable { - id: ColumnType; - - name: ColumnType; - - descrizione: ColumnType; - - created_at: ColumnType; - - userid: ColumnType; - - potenziali_group_id: ColumnType; -} - -export type Potenziali = Selectable; - -export type NewPotenziali = Insertable; - -export type PotenzialiUpdate = Updateable; - -export const potenzialiId = z.uuid().transform(value => value as PotenzialiId); - -export const PotenzialiSchema = z.object({ - id: potenzialiId, - name: z.string(), - descrizione: z.string().nullable(), - created_at: z.date(), - userid: usersId.nullable(), - potenziali_group_id: potenzialiGroupsId, -}); - -export const NewPotenzialiSchema = z.object({ - id: potenzialiId.optional(), - name: z.string(), - descrizione: z.string().optional().nullable(), - created_at: z.union([z.date(), z.string()]).pipe(z.coerce.date()).optional(), - userid: usersId.optional().nullable(), - potenziali_group_id: potenzialiGroupsId, -}); - -export const PotenzialiUpdateSchema = z.object({ - id: potenzialiId.optional(), - name: z.string().optional(), - descrizione: z.string().optional().nullable(), - created_at: z.union([z.date(), z.string()]).pipe(z.coerce.date()).optional(), - userid: usersId.optional().nullable(), - potenziali_group_id: potenzialiGroupsId.optional(), -}); \ No newline at end of file diff --git a/apps/infoalloggi/src/schemas/public/PotenzialiGroups.ts b/apps/infoalloggi/src/schemas/public/PotenzialiGroups.ts deleted file mode 100644 index 52332fc..0000000 --- a/apps/infoalloggi/src/schemas/public/PotenzialiGroups.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely'; -import { z } from 'zod'; - -/** Identifier type for public.potenziali_groups */ -export type PotenzialiGroupsId = string & { __brand: 'public.potenziali_groups' }; - -/** Represents the table public.potenziali_groups */ -export default interface PotenzialiGroupsTable { - id: ColumnType; - - name: ColumnType; - - color: ColumnType; -} - -export type PotenzialiGroups = Selectable; - -export type NewPotenzialiGroups = Insertable; - -export type PotenzialiGroupsUpdate = Updateable; - -export const potenzialiGroupsId = z.uuid().transform(value => value as PotenzialiGroupsId); - -export const PotenzialiGroupsSchema = z.object({ - id: potenzialiGroupsId, - name: z.string(), - color: z.string(), -}); - -export const NewPotenzialiGroupsSchema = z.object({ - id: potenzialiGroupsId.optional(), - name: z.string(), - color: z.string().optional(), -}); - -export const PotenzialiGroupsUpdateSchema = z.object({ - id: potenzialiGroupsId.optional(), - name: z.string().optional(), - color: z.string().optional(), -}); \ No newline at end of file diff --git a/apps/infoalloggi/src/schemas/public/PublicSchema.ts b/apps/infoalloggi/src/schemas/public/PublicSchema.ts index 53b86ff..f9ff662 100644 --- a/apps/infoalloggi/src/schemas/public/PublicSchema.ts +++ b/apps/infoalloggi/src/schemas/public/PublicSchema.ts @@ -5,11 +5,11 @@ import type { default as UsersTable } from './Users'; import type { default as ChatsEtichetteTable } from './ChatsEtichette'; import type { default as TestiEStringheTable } from './TestiEStringhe'; import type { default as UserEtichetteTable } from './UserEtichette'; +import type { default as AppuntiTable } from './Appunti'; import type { default as UsersStorageTable } from './UsersStorage'; import type { default as ServizioAnnunciTable } from './ServizioAnnunci'; import type { default as UserInvitesTable } from './UserInvites'; import type { default as EmailsTable } from './Emails'; -import type { default as PotenzialiGroupsTable } from './PotenzialiGroups'; import type { default as ComuniTable } from './Comuni'; import type { default as RinnoviTable } from './Rinnovi'; import type { default as EventQueueTable } from './EventQueue'; @@ -21,10 +21,10 @@ import type { default as EtichetteTable } from './Etichette'; import type { default as MessagesTable } from './Messages'; import type { default as UsersAnagraficaTable } from './UsersAnagrafica'; import type { default as ProvincieTable } from './Provincie'; -import type { default as PotenzialiTable } from './Potenziali'; import type { default as VideosRefsTable } from './VideosRefs'; import type { default as BanlistTable } from './Banlist'; import type { default as NazioniTable } from './Nazioni'; +import type { default as AppuntiGroupsTable } from './AppuntiGroups'; import type { default as ImagesRefsTable } from './ImagesRefs'; import type { default as BannersTable } from './Banners'; import type { default as ServizioTable } from './Servizio'; @@ -45,6 +45,8 @@ export default interface PublicSchema { user_etichette: UserEtichetteTable; + appunti: AppuntiTable; + users_storage: UsersStorageTable; servizio_annunci: ServizioAnnunciTable; @@ -53,8 +55,6 @@ export default interface PublicSchema { emails: EmailsTable; - potenziali_groups: PotenzialiGroupsTable; - comuni: ComuniTable; rinnovi: RinnoviTable; @@ -77,14 +77,14 @@ export default interface PublicSchema { provincie: ProvincieTable; - potenziali: PotenzialiTable; - videos_refs: VideosRefsTable; banlist: BanlistTable; nazioni: NazioniTable; + appunti_groups: AppuntiGroupsTable; + images_refs: ImagesRefsTable; banners: BannersTable; diff --git a/apps/infoalloggi/src/server/api/root.ts b/apps/infoalloggi/src/server/api/root.ts index 0ed7fc0..0dcc35b 100644 --- a/apps/infoalloggi/src/server/api/root.ts +++ b/apps/infoalloggi/src/server/api/root.ts @@ -17,12 +17,12 @@ import { stripeReportsRouter } from "~/server/api/routers/stripe_reports"; import { testRouter } from "~/server/api/routers/test"; import { usersRouter } from "~/server/api/routers/users"; import { createTRPCRouter } from "~/server/api/trpc"; +import { appuntiRouter } from "./routers/appunti"; import { bannersRouter } from "./routers/banners"; import { catastoRouter } from "./routers/catasto"; import { etichetteRouter } from "./routers/etichette"; import { flagsRouter } from "./routers/flags"; import { inviteRouter } from "./routers/invite"; -import { potenzialiRouter } from "./routers/potenziali"; import { revalidationRouter } from "./routers/revalidation"; import { stringsRouter } from "./routers/strings"; @@ -54,7 +54,7 @@ export const appRouter = createTRPCRouter({ etichette: etichetteRouter, strings: stringsRouter, revalidation: revalidationRouter, - potenziali: potenzialiRouter, + appunti: appuntiRouter, invite: inviteRouter, }); export type AppRouter = typeof appRouter; diff --git a/apps/infoalloggi/src/server/api/routers/appunti.ts b/apps/infoalloggi/src/server/api/routers/appunti.ts new file mode 100644 index 0000000..9fe9696 --- /dev/null +++ b/apps/infoalloggi/src/server/api/routers/appunti.ts @@ -0,0 +1,76 @@ +import z from "zod"; +import { + AppuntiUpdateSchema, + appuntiId, + NewAppuntiSchema, +} from "~/schemas/public/Appunti"; +import { appuntiGroupsId } from "~/schemas/public/AppuntiGroups"; + +import { adminProcedure, createTRPCRouter } from "~/server/api/trpc"; +import { + type AppuntiData, + addAppunti, + addAppuntiGroup, + deleteAppunti, + deleteAppuntiGroup, + getAppunti, + getAppuntiGroups, + updateAppunti, + updateAppunto, +} from "~/server/services/appunti.service"; + +export const appuntiRouter = createTRPCRouter({ + getAppunti: adminProcedure.query(async () => { + return await getAppunti(); + }), + getAppuntiGroups: adminProcedure.query(async () => { + return await getAppuntiGroups(); + }), + addAppunti: adminProcedure + .input( + z.object({ + data: NewAppuntiSchema, + }), + ) + .mutation(async ({ input }) => { + return await addAppunti(input.data); + }), + updateAppunti: adminProcedure + .input( + z.object({ + data: z.custom(), + }), + ) + .mutation(async ({ input }) => { + return await updateAppunti(input.data); + }), + updateAppunto: adminProcedure + .input( + z.object({ + appuntiId: appuntiId, + data: AppuntiUpdateSchema, + }), + ) + .mutation(async ({ input }) => { + return await updateAppunto(input.appuntiId, input.data); + }), + deleteAppunti: adminProcedure.input(appuntiId).mutation(async ({ input }) => { + return await deleteAppunti(input); + }), + + addAppuntiGroup: adminProcedure + .input( + z.object({ + name: z.string().min(1).max(255), + }), + ) + .mutation(async ({ input }) => { + return await addAppuntiGroup({ name: input.name }); + }), + + deleteAppuntiGroup: adminProcedure + .input(appuntiGroupsId) + .mutation(async ({ input }) => { + return await deleteAppuntiGroup(input); + }), +}); diff --git a/apps/infoalloggi/src/server/api/routers/catasto.ts b/apps/infoalloggi/src/server/api/routers/catasto.ts index f5b9ccf..ce14403 100644 --- a/apps/infoalloggi/src/server/api/routers/catasto.ts +++ b/apps/infoalloggi/src/server/api/routers/catasto.ts @@ -54,15 +54,9 @@ export const catastoRouter = createTRPCRouter({ const { id, data } = input; return await editComune({ id, data }); }), - deleteComune: adminProcedure - .input( - z.object({ - id: comuniId, - }), - ) - .mutation(async ({ input }) => { - return await deleteComune(input.id); - }), + deleteComune: adminProcedure.input(comuniId).mutation(async ({ input }) => { + return await deleteComune(input); + }), getProvincie: publicProcedure.query(async () => { return await getProvincie(); @@ -84,13 +78,9 @@ export const catastoRouter = createTRPCRouter({ return await editProvincia({ id, data }); }), deleteProvincia: adminProcedure - .input( - z.object({ - id: provincieId, - }), - ) + .input(provincieId) .mutation(async ({ input }) => { - return await deleteProvincia(input.id); + return await deleteProvincia(input); }), getNazioni: publicProcedure.query(async () => { return await getNazioni(); @@ -111,13 +101,7 @@ export const catastoRouter = createTRPCRouter({ const { id, data } = input; return await editNazione({ id, data }); }), - deleteNazione: adminProcedure - .input( - z.object({ - id: nazioniId, - }), - ) - .mutation(async ({ input }) => { - return await deleteNazione(input.id); - }), + deleteNazione: adminProcedure.input(nazioniId).mutation(async ({ input }) => { + return await deleteNazione(input); + }), }); diff --git a/apps/infoalloggi/src/server/api/routers/potenziali.ts b/apps/infoalloggi/src/server/api/routers/potenziali.ts deleted file mode 100644 index 268390f..0000000 --- a/apps/infoalloggi/src/server/api/routers/potenziali.ts +++ /dev/null @@ -1,86 +0,0 @@ -import z from "zod"; -import { - NewPotenzialiSchema, - PotenzialiUpdateSchema, - potenzialiId, -} from "~/schemas/public/Potenziali"; - -import { potenzialiGroupsId } from "~/schemas/public/PotenzialiGroups"; -import { adminProcedure, createTRPCRouter } from "~/server/api/trpc"; -import { - addPotenziale, - addPotenzialeGroup, - deletePotenziale, - deletePotenzialeGroup, - getPotenziali, - getPotenzialiGroups, - type PotenzialeData, - updatePotenziale, - updatePotenziali, -} from "~/server/services/potenziali.service"; - -export const potenzialiRouter = createTRPCRouter({ - getPotenziali: adminProcedure.query(async () => { - return await getPotenziali(); - }), - getPotenzialiGroups: adminProcedure.query(async () => { - return await getPotenzialiGroups(); - }), - addPotenziale: adminProcedure - .input( - z.object({ - data: NewPotenzialiSchema, - }), - ) - .mutation(async ({ input }) => { - return await addPotenziale(input.data); - }), - updatePotenziali: adminProcedure - .input( - z.object({ - data: z.custom(), - }), - ) - .mutation(async ({ input }) => { - return await updatePotenziali(input.data); - }), - updatePotenziale: adminProcedure - .input( - z.object({ - potenzialiId: potenzialiId, - data: PotenzialiUpdateSchema, - }), - ) - .mutation(async ({ input }) => { - return await updatePotenziale(input.potenzialiId, input.data); - }), - deletePotenziale: adminProcedure - .input( - z.object({ - potenzialiId: potenzialiId, - }), - ) - .mutation(async ({ input }) => { - return await deletePotenziale(input.potenzialiId); - }), - - addPotenzialeGroup: adminProcedure - .input( - z.object({ - name: z.string().min(1).max(255), - }), - ) - .mutation(async ({ input }) => { - return await addPotenzialeGroup({ name: input.name }); - }), - - deletePotenzialeGroup: adminProcedure - .input( - z.object({ - potenzialiGroupId: potenzialiGroupsId, - }), - ) - .mutation(async ({ input }) => { - return await deletePotenzialeGroup(input.potenzialiGroupId); - }), -}); diff --git a/apps/infoalloggi/src/server/services/appunti.service.ts b/apps/infoalloggi/src/server/services/appunti.service.ts new file mode 100644 index 0000000..0b49a96 --- /dev/null +++ b/apps/infoalloggi/src/server/services/appunti.service.ts @@ -0,0 +1,162 @@ +import { TRPCError } from "@trpc/server"; +import type { Nullable } from "kysely"; +import type { + Appunti, + AppuntiId, + AppuntiUpdate, + NewAppunti, +} from "~/schemas/public/Appunti"; +import type { + AppuntiGroups, + AppuntiGroupsId, + NewAppuntiGroups, +} from "~/schemas/public/AppuntiGroups"; +import type { Users } from "~/schemas/public/Users"; +import { db } from "../db"; + +export type AppuntiData = Omit & { + column: string; +} & Nullable>; + +export const getAppunti = async (): Promise => { + try { + const appunti = await db + .selectFrom("appunti") + .select([ + "appunti.id", + "appunti.name", + "appunti.created_at", + "appunti.descrizione", + "appunti.userid", + "appunti.appunti_group_id as column", + ]) + .innerJoin( + "appunti_groups", + "appunti.appunti_group_id", + "appunti_groups.id", + ) + .leftJoin("users", "appunti.userid", "users.id") + .select("users.username") + .orderBy("appunti_groups.name", "asc") + .orderBy("appunti.created_at", "asc") + .execute(); + + return appunti.map((data) => ({ + ...data, + created_at: new Date(data.created_at), + })); + } catch (e) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Failed to fetch Appunti, error: ${(e as Error).message}`, + }); + } +}; + +export const getAppuntiGroups = async (): Promise => { + try { + return await db.selectFrom("appunti_groups").selectAll().execute(); + } catch (e) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Failed to fetch Appunti groups, error: ${(e as Error).message}`, + }); + } +}; + +export const addAppuntiGroup = async (data: NewAppuntiGroups) => { + try { + await db.insertInto("appunti_groups").values(data).execute(); + return { status: "success" }; + } catch (e) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Failed to add Appunti group, error: ${(e as Error).message}`, + }); + } +}; + +export const deleteAppuntiGroup = async (id: AppuntiGroupsId) => { + try { + await db.deleteFrom("appunti_groups").where("id", "=", id).execute(); + return { status: "success" }; + } catch (e) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Failed to delete Appunti group, error: ${(e as Error).message}`, + }); + } +}; + +export const addAppunti = async (data: NewAppunti) => { + try { + await db.insertInto("appunti").values(data).execute(); + return { status: "success" }; + } catch (e) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Failed to add Appunti, error: ${(e as Error).message}`, + }); + } +}; + +export const deleteAppunti = async (id: AppuntiId) => { + try { + await db.deleteFrom("appunti").where("id", "=", id).execute(); + return { status: "success" }; + } catch (e) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Failed to delete Appunti, error: ${(e as Error).message}`, + }); + } +}; + +export const updateAppunto = async (id: AppuntiId, data: AppuntiUpdate) => { + try { + await db.updateTable("appunti").set(data).where("id", "=", id).execute(); + return { status: "success" }; + } catch (e) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Failed to update Appunti, error: ${(e as Error).message}`, + }); + } +}; + +export const updateAppunti = async (data: AppuntiData[]) => { + try { + const db_mappings = await db + .selectFrom("appunti") + .select(["id", "appunti_group_id"]) + .execute(); + + const updates = data + .map((item) => { + const db_item = db_mappings.find((db_item) => db_item.id === item.id); + if (db_item && db_item.appunti_group_id !== item.column) { + const { column, username: _username, ...rest } = item; + return { + ...rest, + appunti_group_id: column as AppuntiGroupsId, + }; + } + return null; + }) + .filter((item) => item !== null); + + for (const item of updates) { + await db + .updateTable("appunti") + .set(item) + .where("id", "=", item.id) + .execute(); + } + return { status: "success" }; + } catch (e) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Failed to update appunti, error: ${(e as Error).message}`, + }); + } +}; diff --git a/apps/infoalloggi/src/server/services/potenziali.service.ts b/apps/infoalloggi/src/server/services/potenziali.service.ts deleted file mode 100644 index 929f2f0..0000000 --- a/apps/infoalloggi/src/server/services/potenziali.service.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { TRPCError } from "@trpc/server"; -import type { Nullable } from "kysely"; -import type { - NewPotenziali, - Potenziali, - PotenzialiId, - PotenzialiUpdate, -} from "~/schemas/public/Potenziali"; -import type { - NewPotenzialiGroups, - PotenzialiGroups, - PotenzialiGroupsId, -} from "~/schemas/public/PotenzialiGroups"; -import type { Users } from "~/schemas/public/Users"; -import { db } from "../db"; - -export type PotenzialeData = Omit & { - column: string; -} & Nullable>; - -export const getPotenziali = async (): Promise => { - try { - const potenziali = await db - .selectFrom("potenziali") - .select([ - "potenziali.id", - "potenziali.name", - "potenziali.created_at", - "potenziali.descrizione", - "potenziali.userid", - "potenziali.potenziali_group_id as column", - ]) - .innerJoin( - "potenziali_groups", - "potenziali.potenziali_group_id", - "potenziali_groups.id", - ) - .leftJoin("users", "potenziali.userid", "users.id") - .select("users.username") - .orderBy("potenziali_groups.name", "asc") - .orderBy("potenziali.created_at", "asc") - .execute(); - - return potenziali.map((data) => ({ - ...data, - created_at: new Date(data.created_at), - })); - } catch (e) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: `Failed to fetch potenziali, error: ${(e as Error).message}`, - }); - } -}; - -export const getPotenzialiGroups = async (): Promise => { - try { - return await db.selectFrom("potenziali_groups").selectAll().execute(); - } catch (e) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: `Failed to fetch potenziali groups, error: ${(e as Error).message}`, - }); - } -}; - -export const addPotenzialeGroup = async (data: NewPotenzialiGroups) => { - try { - await db.insertInto("potenziali_groups").values(data).execute(); - return { status: "success" }; - } catch (e) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: `Failed to add potenziale group, error: ${(e as Error).message}`, - }); - } -}; - -export const deletePotenzialeGroup = async (id: PotenzialiGroupsId) => { - try { - await db.deleteFrom("potenziali_groups").where("id", "=", id).execute(); - return { status: "success" }; - } catch (e) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: `Failed to delete potenziale group, error: ${(e as Error).message}`, - }); - } -}; - -export const addPotenziale = async (data: NewPotenziali) => { - try { - await db.insertInto("potenziali").values(data).execute(); - return { status: "success" }; - } catch (e) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: `Failed to add potenziale, error: ${(e as Error).message}`, - }); - } -}; - -export const deletePotenziale = async (id: PotenzialiId) => { - try { - await db.deleteFrom("potenziali").where("id", "=", id).execute(); - return { status: "success" }; - } catch (e) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: `Failed to delete potenziale, error: ${(e as Error).message}`, - }); - } -}; - -export const updatePotenziale = async ( - id: PotenzialiId, - data: PotenzialiUpdate, -) => { - try { - await db.updateTable("potenziali").set(data).where("id", "=", id).execute(); - return { status: "success" }; - } catch (e) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: `Failed to update potenziale, error: ${(e as Error).message}`, - }); - } -}; - -export const updatePotenziali = async (data: PotenzialeData[]) => { - try { - const db_mappings = await db - .selectFrom("potenziali") - .select(["id", "potenziali_group_id"]) - .execute(); - - const updates = data - .map((item) => { - const db_item = db_mappings.find((db_item) => db_item.id === item.id); - if (db_item && db_item.potenziali_group_id !== item.column) { - const { column, username: _username, ...rest } = item; - return { - ...rest, - potenziali_group_id: column as PotenzialiGroupsId, - }; - } - return null; - }) - .filter((item) => item !== null); - - for (const item of updates) { - await db - .updateTable("potenziali") - .set(item) - .where("id", "=", item.id) - .execute(); - } - return { status: "success" }; - } catch (e) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: `Failed to update potenziali, error: ${(e as Error).message}`, - }); - } -}; diff --git a/apps/infoalloggi/src/server/utils/zod_utils.ts b/apps/infoalloggi/src/server/utils/zod_utils.ts index aa0d88f..348c424 100644 --- a/apps/infoalloggi/src/server/utils/zod_utils.ts +++ b/apps/infoalloggi/src/server/utils/zod_utils.ts @@ -48,3 +48,5 @@ export const MessageUpdateEventSchema = z.discriminatedUnion("eventType", [ }), z.object({ eventType: z.literal("read_receipt"), data: z.null() }), // all unread messages in this chat are now read ]); + +