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 <copilot@github.com>
This commit is contained in:
parent
984b1d7ae5
commit
b3c70bfa1a
23 changed files with 582 additions and 591 deletions
|
|
@ -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,
|
||||
|
|
|
|||
33
apps/db/migrations/49_potenziali_to_appunti.up.sql
Normal file
33
apps/db/migrations/49_potenziali_to_appunti.up.sql
Normal file
|
|
@ -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 $$;
|
||||
|
|
@ -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())");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <Target {...rest} />;
|
||||
case "thumbs-up":
|
||||
return <ThumbsUp {...rest} />;
|
||||
case "note":
|
||||
return <NotebookPen {...rest} />;
|
||||
default:
|
||||
throw new Error(`Invalid icon type: ${type satisfies never}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<ScrollArea className="w-screen pr-2 sm:w-full">
|
||||
<KanbanProvider
|
||||
|
|
@ -85,8 +85,8 @@ export const Potenziali = () => {
|
|||
</div>
|
||||
</KanbanHeader>
|
||||
<KanbanCards className="mx-auto w-68" id={column.id}>
|
||||
{(data: PotenzialeData) => (
|
||||
<PotenzialeCardItem
|
||||
{(data: AppuntiData) => (
|
||||
<AppuntiCardItem
|
||||
columnId={column.id}
|
||||
data={data}
|
||||
key={data.id}
|
||||
|
|
@ -101,11 +101,11 @@ export const Potenziali = () => {
|
|||
);
|
||||
};
|
||||
// 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 (
|
||||
<Credenza onOpenChange={setOpen} open={open}>
|
||||
|
|
@ -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<UsersId | null>(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<PotenzialeData>(data);
|
||||
const [state, setState] = useState<AppuntiData>(data);
|
||||
const [hasChanges, setHasChanges] = useState(false);
|
||||
const { data: admins, isLoading } = api.users.getAdmins.useQuery();
|
||||
useEffect(() => {
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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: () => <LoadingPage />,
|
||||
|
|
@ -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 (
|
||||
<PotenzialiProvider>
|
||||
<AppuntiProvider>
|
||||
<Head>
|
||||
<title>Potenziali - Infoalloggi.it</title>
|
||||
<title>Appunti - Infoalloggi.it</title>
|
||||
</Head>
|
||||
<div className="mx-1 w-full flex-1">
|
||||
<div className="mx-auto w-full pt-4">
|
||||
<div className="mx-3 flex flex-wrap items-start justify-between pb-5">
|
||||
<div className="flex max-w-lg items-center gap-3">
|
||||
<h3 className="font-bold text-accent-foreground text-xl sm:text-2xl">
|
||||
Potenziali
|
||||
Appunti
|
||||
</h3>
|
||||
</div>
|
||||
<NewColumn />
|
||||
</div>
|
||||
|
||||
<PotenzialiBoard />
|
||||
<AppuntiBoard />
|
||||
</div>
|
||||
</div>
|
||||
</PotenzialiProvider>
|
||||
</AppuntiProvider>
|
||||
);
|
||||
};
|
||||
export default AdminPotenziali;
|
||||
export default AdminAppunti;
|
||||
|
||||
AdminPotenziali.getLayout = function getLayout(page) {
|
||||
AdminAppunti.getLayout = function getLayout(page) {
|
||||
return <AreaRiservataLayout>{page}</AreaRiservataLayout>;
|
||||
};
|
||||
|
|
@ -265,11 +265,7 @@ const SezioneComuni = () => {
|
|||
<DialogDescription className="sr-only">desc</DialogDescription>
|
||||
</DialogHeader>
|
||||
<FormComuni
|
||||
handleRemove={() =>
|
||||
deleteComune({
|
||||
id: selectedComune.id,
|
||||
})
|
||||
}
|
||||
handleRemove={() => deleteComune(selectedComune.id)}
|
||||
initialValues={selectedComune}
|
||||
submitMutation={(values) => {
|
||||
editComune({
|
||||
|
|
@ -580,11 +576,7 @@ const SezioneProvincie = () => {
|
|||
<DialogDescription className="sr-only">desc</DialogDescription>
|
||||
</DialogHeader>
|
||||
<FormProvincie
|
||||
handleRemove={() =>
|
||||
deleteProvincia({
|
||||
id: selectedProvincia.id,
|
||||
})
|
||||
}
|
||||
handleRemove={() => deleteProvincia(selectedProvincia.id)}
|
||||
initialValues={selectedProvincia}
|
||||
submitMutation={(values) => {
|
||||
editProvincia({
|
||||
|
|
@ -865,11 +857,7 @@ const SezioneNazioni = () => {
|
|||
<DialogDescription className="sr-only">desc</DialogDescription>
|
||||
</DialogHeader>
|
||||
<FormNazioni
|
||||
handleRemove={() =>
|
||||
deleteNazione({
|
||||
id: selectedNazione.id,
|
||||
})
|
||||
}
|
||||
handleRemove={() => deleteNazione(selectedNazione.id)}
|
||||
initialValues={selectedNazione}
|
||||
submitMutation={(values) => {
|
||||
editNazione({
|
||||
|
|
|
|||
151
apps/infoalloggi/src/providers/AppuntiProvider.tsx
Normal file
151
apps/infoalloggi/src/providers/AppuntiProvider.tsx
Normal file
|
|
@ -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<AppuntiContextType | null>(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 (
|
||||
<AppuntiContext.Provider
|
||||
value={{
|
||||
data: data || [],
|
||||
columns: columns || [],
|
||||
setData,
|
||||
updateCall,
|
||||
addItem,
|
||||
removeItem,
|
||||
addColumn,
|
||||
updateItem,
|
||||
removeColumn,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AppuntiContext.Provider>
|
||||
);
|
||||
};
|
||||
export const useAppunti = () => {
|
||||
const context = useContext(AppuntiContext);
|
||||
if (!context) {
|
||||
throw new Error("useAppunti must be used within a AppuntiProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
|
@ -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<PotenzialiContextType | null>(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 (
|
||||
<PotenzialiContext.Provider
|
||||
value={{
|
||||
data: data || [],
|
||||
columns: columns || [],
|
||||
setData,
|
||||
updateCall,
|
||||
addItem,
|
||||
removeItem,
|
||||
addColumn,
|
||||
updateItem,
|
||||
removeColumn,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</PotenzialiContext.Provider>
|
||||
);
|
||||
};
|
||||
export const usePotenziali = () => {
|
||||
const context = useContext(PotenzialiContext);
|
||||
if (!context) {
|
||||
throw new Error("usePotenziali must be used within a PotenzialiProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
57
apps/infoalloggi/src/schemas/public/Appunti.ts
Normal file
57
apps/infoalloggi/src/schemas/public/Appunti.ts
Normal file
|
|
@ -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<AppuntiId, AppuntiId | undefined, AppuntiId>;
|
||||
|
||||
name: ColumnType<string, string, string>;
|
||||
|
||||
descrizione: ColumnType<string | null, string | null, string | null>;
|
||||
|
||||
created_at: ColumnType<Date, Date | string | undefined, Date | string>;
|
||||
|
||||
userid: ColumnType<UsersId | null, UsersId | null, UsersId | null>;
|
||||
|
||||
appunti_group_id: ColumnType<AppuntiGroupsId, AppuntiGroupsId, AppuntiGroupsId>;
|
||||
}
|
||||
|
||||
export type Appunti = Selectable<AppuntiTable>;
|
||||
|
||||
export type NewAppunti = Insertable<AppuntiTable>;
|
||||
|
||||
export type AppuntiUpdate = Updateable<AppuntiTable>;
|
||||
|
||||
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(),
|
||||
});
|
||||
40
apps/infoalloggi/src/schemas/public/AppuntiGroups.ts
Normal file
40
apps/infoalloggi/src/schemas/public/AppuntiGroups.ts
Normal file
|
|
@ -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<AppuntiGroupsId, AppuntiGroupsId | undefined, AppuntiGroupsId>;
|
||||
|
||||
name: ColumnType<string, string, string>;
|
||||
|
||||
color: ColumnType<string, string | undefined, string>;
|
||||
}
|
||||
|
||||
export type AppuntiGroups = Selectable<AppuntiGroupsTable>;
|
||||
|
||||
export type NewAppuntiGroups = Insertable<AppuntiGroupsTable>;
|
||||
|
||||
export type AppuntiGroupsUpdate = Updateable<AppuntiGroupsTable>;
|
||||
|
||||
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(),
|
||||
});
|
||||
|
|
@ -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<PotenzialiId, PotenzialiId | undefined, PotenzialiId>;
|
||||
|
||||
name: ColumnType<string, string, string>;
|
||||
|
||||
descrizione: ColumnType<string | null, string | null, string | null>;
|
||||
|
||||
created_at: ColumnType<Date, Date | string | undefined, Date | string>;
|
||||
|
||||
userid: ColumnType<UsersId | null, UsersId | null, UsersId | null>;
|
||||
|
||||
potenziali_group_id: ColumnType<PotenzialiGroupsId, PotenzialiGroupsId, PotenzialiGroupsId>;
|
||||
}
|
||||
|
||||
export type Potenziali = Selectable<PotenzialiTable>;
|
||||
|
||||
export type NewPotenziali = Insertable<PotenzialiTable>;
|
||||
|
||||
export type PotenzialiUpdate = Updateable<PotenzialiTable>;
|
||||
|
||||
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(),
|
||||
});
|
||||
|
|
@ -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<PotenzialiGroupsId, PotenzialiGroupsId | undefined, PotenzialiGroupsId>;
|
||||
|
||||
name: ColumnType<string, string, string>;
|
||||
|
||||
color: ColumnType<string, string | undefined, string>;
|
||||
}
|
||||
|
||||
export type PotenzialiGroups = Selectable<PotenzialiGroupsTable>;
|
||||
|
||||
export type NewPotenzialiGroups = Insertable<PotenzialiGroupsTable>;
|
||||
|
||||
export type PotenzialiGroupsUpdate = Updateable<PotenzialiGroupsTable>;
|
||||
|
||||
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(),
|
||||
});
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
76
apps/infoalloggi/src/server/api/routers/appunti.ts
Normal file
76
apps/infoalloggi/src/server/api/routers/appunti.ts
Normal file
|
|
@ -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<AppuntiData[]>(),
|
||||
}),
|
||||
)
|
||||
.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);
|
||||
}),
|
||||
});
|
||||
|
|
@ -54,14 +54,8 @@ 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 () => {
|
||||
|
|
@ -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);
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<PotenzialeData[]>(),
|
||||
}),
|
||||
)
|
||||
.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);
|
||||
}),
|
||||
});
|
||||
162
apps/infoalloggi/src/server/services/appunti.service.ts
Normal file
162
apps/infoalloggi/src/server/services/appunti.service.ts
Normal file
|
|
@ -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<Appunti, "appunti_group_id"> & {
|
||||
column: string;
|
||||
} & Nullable<Pick<Users, "username">>;
|
||||
|
||||
export const getAppunti = async (): Promise<AppuntiData[]> => {
|
||||
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<AppuntiGroups[]> => {
|
||||
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}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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<Potenziali, "potenziali_group_id"> & {
|
||||
column: string;
|
||||
} & Nullable<Pick<Users, "username">>;
|
||||
|
||||
export const getPotenziali = async (): Promise<PotenzialeData[]> => {
|
||||
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<PotenzialiGroups[]> => {
|
||||
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}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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
|
||||
]);
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue