feat: enhance user management and document handling; refactor service and schema integrations
This commit is contained in:
parent
fa8dcb7d86
commit
d894f9d6ec
16 changed files with 381 additions and 98 deletions
26
apps/db/migrations/24_servizio_annunci_id.up.sql
Normal file
26
apps/db/migrations/24_servizio_annunci_id.up.sql
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
-- Add column only if it doesn't exist
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'servizio_annunci'
|
||||
AND column_name = 'servizio_annunci_id'
|
||||
) THEN
|
||||
ALTER TABLE public.servizio_annunci
|
||||
ADD COLUMN servizio_annunci_id serial NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Add primary key only if it doesn't exist
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint
|
||||
WHERE conname = 'servizio_annunci_pkey'
|
||||
AND conrelid = 'public.servizio_annunci'::regclass
|
||||
) THEN
|
||||
ALTER TABLE public.servizio_annunci
|
||||
ADD PRIMARY KEY (servizio_annunci_id);
|
||||
END IF;
|
||||
END $$;
|
||||
|
|
@ -5,6 +5,7 @@ services:
|
|||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: m.pedone98@gmail.com
|
||||
PGADMIN_DEFAULT_PASSWORD: rootpost
|
||||
PGADMIN_CONFIG_CONSOLE_LOG_LEVEL: 10
|
||||
ports:
|
||||
- "5050:80"
|
||||
volumes:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
import { ExternalLink, Trash2 } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import toast from "react-hot-toast";
|
||||
import { useSession } from "~/providers/SessionProvider";
|
||||
import type { UsersStorageUserStorageId } from "~/schemas/public/UsersStorage";
|
||||
import type { UserWithAnagrafica } from "~/server/services/user.service";
|
||||
import { api } from "~/utils/api";
|
||||
import { Confirm } from "../confirm";
|
||||
import { ImageFlbk } from "../ImageWithFallback";
|
||||
import { LoadingPage } from "../loading";
|
||||
import { Button } from "../ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../ui/card";
|
||||
import { UploadModal } from "../upload_modal";
|
||||
|
||||
export const DocumentiPersonali = ({
|
||||
userData,
|
||||
}: {
|
||||
userData: UserWithAnagrafica;
|
||||
}) => {
|
||||
const utils = api.useUtils();
|
||||
const { mutate, isPending } = api.users.editUserAnagrafica.useMutation({
|
||||
onSuccess: async () => {
|
||||
await utils.users.getClientProfilo.invalidate({
|
||||
userId: userData.id,
|
||||
});
|
||||
},
|
||||
onError: (err) => {
|
||||
toast.error(`Errore aggiornamento servizio: ${err.message}`);
|
||||
},
|
||||
});
|
||||
const handleUpload = (
|
||||
field: "doc_personale_fronte_ref" | "doc_personale_retro_ref",
|
||||
id: UsersStorageUserStorageId,
|
||||
) => {
|
||||
mutate({
|
||||
userId: userData.id,
|
||||
data: { [field]: id },
|
||||
});
|
||||
};
|
||||
|
||||
const { user } = useSession();
|
||||
if (!user) return null;
|
||||
if (isPending) return <LoadingPage />;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Documenti personali</CardTitle>
|
||||
<CardDescription>
|
||||
<p>I tuoi documenti sono necessari per usufruire del servizio.</p>
|
||||
<p>
|
||||
Nel caso di un unico documento (es: scansione fronte e retro del
|
||||
documento) caricarlo 2 volte.
|
||||
</p>
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>
|
||||
<h4 className="mb-2 font-medium">
|
||||
Documento d'identità - Fronte
|
||||
</h4>
|
||||
|
||||
{userData.doc_personale_fronte?.storageId ? (
|
||||
<div className="flex items-center gap-4">
|
||||
<ImageFlbk
|
||||
alt="documento personale fronte"
|
||||
className="size-24 rounded-md object-cover"
|
||||
height={50}
|
||||
src={`/storage-api/get/${userData.doc_personale_fronte.storageId}`}
|
||||
width={50}
|
||||
/>
|
||||
|
||||
<div className="flex flex-col justify-center gap-2">
|
||||
<Link
|
||||
href={`/area-riservata/allegato-view/${userData.doc_personale_fronte.storageId}`}
|
||||
target="_blank"
|
||||
>
|
||||
<Button size="sm">
|
||||
<span>Visualizza</span>
|
||||
<ExternalLink />
|
||||
</Button>
|
||||
</Link>
|
||||
<Confirm
|
||||
description="Sei sicuro di voler eliminare il documento?"
|
||||
onConfirm={() => {
|
||||
mutate({
|
||||
userId: userData.id,
|
||||
data: { doc_personale_fronte_ref: null },
|
||||
});
|
||||
}}
|
||||
title="Elimina Documento"
|
||||
>
|
||||
<Button
|
||||
aria-label="Elimina Doc"
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
>
|
||||
<span>Elimina Documento</span>
|
||||
<Trash2 />
|
||||
</Button>
|
||||
</Confirm>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<UploadModal
|
||||
cb_onUpload={({ userStorageIds }) =>
|
||||
userStorageIds.length > 0 &&
|
||||
userStorageIds[0] &&
|
||||
handleUpload("doc_personale_fronte_ref", userStorageIds[0])
|
||||
}
|
||||
isAdmin={user.isAdmin}
|
||||
maxFiles={1}
|
||||
userId={userData.id}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>
|
||||
<h4 className="mb-2 font-medium">Documento d'identità - Retro</h4>
|
||||
{userData.doc_personale_retro?.storageId ? (
|
||||
<div className="flex items-center gap-4">
|
||||
<ImageFlbk
|
||||
alt="documento personale retro"
|
||||
className="size-24 rounded-md object-cover"
|
||||
height={50}
|
||||
src={`/storage-api/get/${userData.doc_personale_retro.storageId}`}
|
||||
width={50}
|
||||
/>
|
||||
|
||||
<div className="flex flex-col justify-center gap-2">
|
||||
<Link
|
||||
href={`/area-riservata/allegato-view/${userData.doc_personale_retro.storageId}`}
|
||||
target="_blank"
|
||||
>
|
||||
<Button size="sm">
|
||||
<span>Visualizza</span>
|
||||
<ExternalLink />
|
||||
</Button>
|
||||
</Link>
|
||||
<Confirm
|
||||
description="Sei sicuro di voler eliminare il documento?"
|
||||
onConfirm={() => {
|
||||
mutate({
|
||||
userId: userData.id,
|
||||
data: { doc_personale_retro_ref: null },
|
||||
});
|
||||
}}
|
||||
title="Elimina Documento"
|
||||
>
|
||||
<Button
|
||||
aria-label="Elimina Doc"
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
>
|
||||
<span>Elimina Documento</span>
|
||||
<Trash2 />
|
||||
</Button>
|
||||
</Confirm>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<UploadModal
|
||||
cb_onUpload={({ userStorageIds }) =>
|
||||
userStorageIds.length > 0 &&
|
||||
userStorageIds[0] &&
|
||||
handleUpload("doc_personale_retro_ref", userStorageIds[0])
|
||||
}
|
||||
isAdmin={user.isAdmin}
|
||||
maxFiles={1}
|
||||
userId={userData.id}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
I tuoi dati saranno conservati solamente per la durata del servizio,
|
||||
in conformità con la nostra{" "}
|
||||
<Link className="underline" href="/privacy-policy" target="_blank">
|
||||
Informativa sulla Privacy
|
||||
</Link>
|
||||
</p>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
|
@ -57,7 +57,7 @@ export const AdminLavoraConferma = () => {
|
|||
Conferma
|
||||
</Button>
|
||||
</CredenzaTrigger>
|
||||
<CredenzaContent className="max-h-[90vh] w-full px-3 sm:max-w-4xl">
|
||||
<CredenzaContent className="max-h-[90vh] w-full px-3 sm:max-w-6xl">
|
||||
<CredenzaHeader>
|
||||
<CredenzaTitle>Lavorazione conferma</CredenzaTitle>
|
||||
<CredenzaDescription className="sr-only">
|
||||
|
|
@ -65,7 +65,7 @@ export const AdminLavoraConferma = () => {
|
|||
</CredenzaDescription>
|
||||
</CredenzaHeader>
|
||||
<CredenzaBody className="max-h-[80vh] w-full overflow-y-auto pb-5">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col gap-4">
|
||||
<DocSection />
|
||||
<Caparra />
|
||||
{servizio.tipologia === TipologiaPosizioneEnum.Transitorio && (
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ const DocCheckpoint = () => {
|
|||
const { t } = useTranslation();
|
||||
const { userId, servizio } = useServizio();
|
||||
const utils = api.useUtils();
|
||||
const { mutate, isPending } = api.servizio.updateServizio.useMutation({
|
||||
const { mutate, isPending } = api.users.editUserAnagrafica.useMutation({
|
||||
onSuccess: async () => {
|
||||
await utils.servizio.getAllServizioAnnunci.invalidate({
|
||||
userId,
|
||||
|
|
@ -134,8 +134,10 @@ const DocCheckpoint = () => {
|
|||
id: UsersStorageUserStorageId,
|
||||
) => {
|
||||
mutate({
|
||||
servizioId: servizio.servizio_id,
|
||||
data: { [field]: id },
|
||||
userId,
|
||||
data: {
|
||||
[field]: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -66,7 +66,9 @@ export const ProfileFormAccount = ({
|
|||
toast.success(t.profile.aggiornato);
|
||||
await utils.auth.getSession.invalidate();
|
||||
await utils.users.getUser.invalidate();
|
||||
await utils.users.getClientProfilo.invalidate();
|
||||
await utils.users.getClientProfilo.invalidate({
|
||||
userId: id,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -210,15 +210,16 @@ export const ProfileFormAnagrafica = ({
|
|||
toast.success(t.profile.aggiornato);
|
||||
await utils.auth.getSession.invalidate();
|
||||
await utils.users.getUser.invalidate();
|
||||
await utils.users.getClientProfilo.invalidate();
|
||||
await utils.users.getClientProfilo.invalidate({
|
||||
userId: userData.id,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
function onSubmit(fields: ProfileFormValues) {
|
||||
mutate({
|
||||
...fields,
|
||||
idanagrafica: userData.idanagrafica || undefined,
|
||||
userid: userData.id,
|
||||
userId: userData.id,
|
||||
data: { ...fields },
|
||||
});
|
||||
}
|
||||
const nazioni_options = GetNazioni();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
Fingerprint,
|
||||
IdCard,
|
||||
KeyRound,
|
||||
Landmark,
|
||||
Lock,
|
||||
|
|
@ -10,6 +11,7 @@ import {
|
|||
import type { GetServerSideProps } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import toast from "react-hot-toast";
|
||||
import { DocumentiPersonali } from "~/components/area-riservata/documenti_personali";
|
||||
import { AreaRiservataLayoutUserView } from "~/components/Layout";
|
||||
import { LoadingPage } from "~/components/loading";
|
||||
import { Status500 } from "~/components/status-page";
|
||||
|
|
@ -46,7 +48,7 @@ const EditUser: NextPageWithLayout<EditUserProps> = ({
|
|||
const router = useRouter();
|
||||
const utils = api.useUtils();
|
||||
const { data: userData, isLoading } = api.users.getClientProfilo.useQuery({
|
||||
id: userId,
|
||||
userId,
|
||||
});
|
||||
const { mutate: delete_mutate } = api.users.deleteUser.useMutation({
|
||||
onSuccess: async () => {
|
||||
|
|
@ -60,7 +62,9 @@ const EditUser: NextPageWithLayout<EditUserProps> = ({
|
|||
const { mutate: ban_mutate } = api.users.blockUser.useMutation({
|
||||
onSuccess: async (data) => {
|
||||
await utils.users.getUsers.invalidate();
|
||||
await utils.users.getClientProfilo.invalidate();
|
||||
await utils.users.getClientProfilo.invalidate({
|
||||
userId,
|
||||
});
|
||||
if (data[0]?.isBlocked) {
|
||||
toast("Utente bloccato con successo", { icon: "🔒" });
|
||||
} else {
|
||||
|
|
@ -93,6 +97,13 @@ const EditUser: NextPageWithLayout<EditUserProps> = ({
|
|||
<Fingerprint className="size-5" />
|
||||
Anagrafica
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
className="flex items-center gap-1"
|
||||
value="documenti"
|
||||
>
|
||||
<IdCard className="size-5" />
|
||||
Documenti
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
className="flex items-center gap-1"
|
||||
value="password"
|
||||
|
|
@ -184,6 +195,9 @@ const EditUser: NextPageWithLayout<EditUserProps> = ({
|
|||
<TabsContent className="mt-5 h-full space-y-6" value="anagrafica">
|
||||
<ProfileFormAnagrafica userData={userData} />
|
||||
</TabsContent>
|
||||
<TabsContent className="mt-5 h-full space-y-6" value="documenti">
|
||||
<DocumentiPersonali userData={userData} />
|
||||
</TabsContent>
|
||||
<TabsContent className="mt-5 space-y-6" value="password">
|
||||
<OverridePasswordForm id={userData.id} />
|
||||
</TabsContent>
|
||||
|
|
@ -226,7 +240,7 @@ export const getServerSideProps = (async (context) => {
|
|||
const helpers = await TrpcAuthedFetchingIstance({ access_token });
|
||||
if (helpers) {
|
||||
await helpers.trpc.users.getClientProfilo.prefetch({
|
||||
id: parsed.data,
|
||||
userId: parsed.data,
|
||||
});
|
||||
return {
|
||||
props: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { GetServerSideProps } from "next";
|
||||
import Head from "next/head";
|
||||
import { DocumentiPersonali } from "~/components/area-riservata/documenti_personali";
|
||||
import { AreaRiservataLayout } from "~/components/Layout";
|
||||
import { LoadingPage } from "~/components/loading";
|
||||
import { Status500 } from "~/components/status-page";
|
||||
|
|
@ -18,13 +18,14 @@ import { ProfileFormAnagrafica } from "~/forms/FormProfilo_Anagrafica";
|
|||
import type { NextPageWithLayout } from "~/pages/_app";
|
||||
import { useTranslation } from "~/providers/I18nProvider";
|
||||
import { useEnforcedSession } from "~/providers/SessionProvider";
|
||||
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
||||
import { api } from "~/utils/api";
|
||||
|
||||
const Dashboard: NextPageWithLayout = () => {
|
||||
const { t } = useTranslation();
|
||||
const { user } = useEnforcedSession();
|
||||
|
||||
const { data: userData, isLoading } = api.users.getClientProfilo.useQuery({
|
||||
id: undefined,
|
||||
userId: user.id,
|
||||
});
|
||||
const session = useEnforcedSession();
|
||||
if (isLoading) return <LoadingPage />;
|
||||
|
|
@ -58,6 +59,7 @@ const Dashboard: NextPageWithLayout = () => {
|
|||
<TabsList className="mb-2">
|
||||
<TabsTrigger value="account">Account</TabsTrigger>
|
||||
<TabsTrigger value="anagrafica">Anagrafica</TabsTrigger>
|
||||
<TabsTrigger value="documenti">Documenti</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent className="flex flex-col gap-8" value="account">
|
||||
<Card>
|
||||
|
|
@ -106,6 +108,9 @@ const Dashboard: NextPageWithLayout = () => {
|
|||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
<TabsContent className="h-full space-y-6" value="documenti">
|
||||
<DocumentiPersonali userData={userData} />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -116,23 +121,6 @@ const Dashboard: NextPageWithLayout = () => {
|
|||
};
|
||||
export default Dashboard;
|
||||
|
||||
export const getServerSideProps = (async (context) => {
|
||||
const access_token = context.req.cookies.access_token;
|
||||
|
||||
const helpers = await TrpcAuthedFetchingIstance({ access_token });
|
||||
if (helpers) {
|
||||
await helpers.trpc.users.getClientProfilo.prefetch({ id: undefined });
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.trpc.dehydrate(),
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
}) satisfies GetServerSideProps;
|
||||
|
||||
Dashboard.getLayout = function getLayout(page) {
|
||||
return <AreaRiservataLayout>{page}</AreaRiservataLayout>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -61,10 +61,6 @@ export default interface ServizioTable {
|
|||
|
||||
isOkConsulenza: ColumnType<boolean, boolean | undefined, boolean>;
|
||||
|
||||
doc_personale_fronte_ref: ColumnType<UsersStorageUserStorageId | null, UsersStorageUserStorageId | null, UsersStorageUserStorageId | null>;
|
||||
|
||||
doc_personale_retro_ref: ColumnType<UsersStorageUserStorageId | null, UsersStorageUserStorageId | null, UsersStorageUserStorageId | null>;
|
||||
|
||||
doc_motivazione_ref: ColumnType<UsersStorageUserStorageId | null, UsersStorageUserStorageId | null, UsersStorageUserStorageId | null>;
|
||||
|
||||
scadenza_motivazione_transitoria: ColumnType<Date | null, Date | string | null, Date | string | null>;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,13 @@ import type { ServizioServizioId } from './Servizio';
|
|||
import type { AnnunciId } from './Annunci';
|
||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||
|
||||
/** Identifier type for public.servizio_annunci */
|
||||
export type ServizioAnnunciServizioAnnunciId = number & { __brand: 'public.servizio_annunci' };
|
||||
|
||||
/** Represents the table public.servizio_annunci */
|
||||
export default interface ServizioAnnunciTable {
|
||||
servizio_annunci_id: ColumnType<ServizioAnnunciServizioAnnunciId, ServizioAnnunciServizioAnnunciId | undefined, ServizioAnnunciServizioAnnunciId>;
|
||||
|
||||
servizio_id: ColumnType<ServizioServizioId, ServizioServizioId, ServizioServizioId>;
|
||||
|
||||
annunci_id: ColumnType<AnnunciId, AnnunciId, AnnunciId>;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// This file is automatically generated by Kanel. Do not modify manually.
|
||||
|
||||
import type { UsersId } from './Users';
|
||||
import type { UsersStorageUserStorageId } from './UsersStorage';
|
||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||
|
||||
/** Identifier type for public.users_anagrafica */
|
||||
|
|
@ -48,6 +49,10 @@ export default interface UsersAnagraficaTable {
|
|||
codice_destinatario: ColumnType<string | null, string | null, string | null>;
|
||||
|
||||
legale_rappresentante: ColumnType<string | null, string | null, string | null>;
|
||||
|
||||
doc_personale_fronte_ref: ColumnType<UsersStorageUserStorageId | null, UsersStorageUserStorageId | null, UsersStorageUserStorageId | null>;
|
||||
|
||||
doc_personale_retro_ref: ColumnType<UsersStorageUserStorageId | null, UsersStorageUserStorageId | null, UsersStorageUserStorageId | null>;
|
||||
}
|
||||
|
||||
export type UsersAnagrafica = Selectable<UsersAnagraficaTable>;
|
||||
|
|
|
|||
|
|
@ -52,9 +52,14 @@ export const usersRouter = createTRPCRouter({
|
|||
return await editAccountHandler({ ctx, input });
|
||||
}),
|
||||
editUserAnagrafica: protectedProcedure
|
||||
.input(z.custom<UsersAnagraficaUpdate>())
|
||||
.input(
|
||||
z.object({
|
||||
userId: zUserId,
|
||||
data: z.custom<UsersAnagraficaUpdate>(),
|
||||
}),
|
||||
)
|
||||
.mutation(async ({ input }) => {
|
||||
return await editAnagraficaHandler({ input });
|
||||
return await editAnagraficaHandler({ ...input });
|
||||
}),
|
||||
getActiveUsersWithoutChat: adminProcedure.query(async () => {
|
||||
return await getActiveUserWithoutChatHandler({ db });
|
||||
|
|
@ -62,15 +67,13 @@ export const usersRouter = createTRPCRouter({
|
|||
getClientProfilo: protectedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: zUserId.optional(),
|
||||
userId: zUserId,
|
||||
}),
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const userId = input.id || ctx.session.id;
|
||||
|
||||
.query(async ({ input }) => {
|
||||
return getUserWithAnagraficaHandler({
|
||||
db,
|
||||
userId: userId,
|
||||
userId: input.userId,
|
||||
});
|
||||
}),
|
||||
getUser: protectedProcedure
|
||||
|
|
|
|||
|
|
@ -613,6 +613,11 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
|
|||
return await db
|
||||
.selectFrom("servizio")
|
||||
.where("user_id", "=", userId)
|
||||
.leftJoin(
|
||||
"users_anagrafica",
|
||||
"servizio.user_id",
|
||||
"users_anagrafica.userid",
|
||||
)
|
||||
.select((eb) => [
|
||||
"servizio.servizio_id",
|
||||
"servizio.created_at",
|
||||
|
|
@ -632,12 +637,12 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
|
|||
.selectFrom("users_storage")
|
||||
.select([
|
||||
"users_storage.storageId as storageId",
|
||||
"servizio.doc_personale_fronte_ref as ref",
|
||||
"users_anagrafica.doc_personale_fronte_ref as ref",
|
||||
])
|
||||
.whereRef(
|
||||
"users_storage.user_storage_id",
|
||||
"=",
|
||||
"servizio.doc_personale_fronte_ref",
|
||||
"users_anagrafica.doc_personale_fronte_ref",
|
||||
),
|
||||
).as("doc_personale_fronte"),
|
||||
jsonObjectFrom(
|
||||
|
|
@ -645,12 +650,12 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
|
|||
.selectFrom("users_storage")
|
||||
.select([
|
||||
"users_storage.storageId as storageId",
|
||||
"servizio.doc_personale_retro_ref as ref",
|
||||
"users_anagrafica.doc_personale_retro_ref as ref",
|
||||
])
|
||||
.whereRef(
|
||||
"users_storage.user_storage_id",
|
||||
"=",
|
||||
"servizio.doc_personale_retro_ref",
|
||||
"users_anagrafica.doc_personale_retro_ref",
|
||||
),
|
||||
).as("doc_personale_retro"),
|
||||
jsonObjectFrom(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type { Users, UsersId, UsersUpdate } from "~/schemas/public/Users";
|
|||
import type { UsersAnagraficaUpdate } from "~/schemas/public/UsersAnagrafica";
|
||||
import type { Context } from "~/server/api/trpc";
|
||||
import { db, type Querier } from "~/server/db";
|
||||
import { upsertAnagrafica } from "~/server/services/user.service";
|
||||
import { checkCtxAdmin, checkCtxSession } from "~/server/utils/ctxChecker";
|
||||
|
||||
type EditAccountInput = {
|
||||
|
|
@ -58,14 +57,66 @@ export const editAccountHandler = async ({
|
|||
};
|
||||
|
||||
export const editAnagraficaHandler = async ({
|
||||
input,
|
||||
userId,
|
||||
data,
|
||||
}: {
|
||||
input: UsersAnagraficaUpdate;
|
||||
userId: UsersId;
|
||||
data: UsersAnagraficaUpdate;
|
||||
}) => {
|
||||
return await upsertAnagrafica({
|
||||
data: input,
|
||||
db,
|
||||
});
|
||||
try {
|
||||
// biome-ignore lint/correctness/noUnusedVariables: <ignore>
|
||||
const { idanagrafica, userid, ...rest } = data;
|
||||
if (!userId) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Errore interno, utente non trovato",
|
||||
});
|
||||
}
|
||||
|
||||
// if (anagraficaId) {
|
||||
// return await db
|
||||
// .updateTable("users_anagrafica")
|
||||
// .set({
|
||||
// ...rest,
|
||||
// })
|
||||
// .where("userid", "=", userId)
|
||||
// .returningAll()
|
||||
// .executeTakeFirst();
|
||||
// }
|
||||
// const searched = await db
|
||||
// .selectFrom("users_anagrafica")
|
||||
// .select("idanagrafica")
|
||||
// .where("userid", "=", userId)
|
||||
// .executeTakeFirst();
|
||||
// if (searched) {
|
||||
// return await db
|
||||
// .updateTable("users_anagrafica")
|
||||
// .set({
|
||||
// ...rest,
|
||||
// })
|
||||
// .where("userid", "=", userId)
|
||||
// .returningAll()
|
||||
// .executeTakeFirst();
|
||||
// }
|
||||
return await db
|
||||
.insertInto("users_anagrafica")
|
||||
.values({
|
||||
...rest,
|
||||
userid: userId,
|
||||
})
|
||||
.onConflict((oc) =>
|
||||
oc.column("userid").doUpdateSet({
|
||||
...rest,
|
||||
}),
|
||||
)
|
||||
.returningAll()
|
||||
.executeTakeFirst();
|
||||
} catch (e) {
|
||||
throw new TRPCError({
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
message: `Errore updateAnagrafica: ${(e as Error).message}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteUserHandler = async ({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { TRPCError } from "@trpc/server";
|
||||
import { jsonObjectFrom } from "kysely/helpers/postgres";
|
||||
import type { NewUsers, UsersId } from "~/schemas/public/Users";
|
||||
import type { UsersAnagraficaUpdate } from "~/schemas/public/UsersAnagrafica";
|
||||
import type { Session } from "~/server/api/trpc";
|
||||
import { db, type Querier } from "~/server/db";
|
||||
|
||||
|
|
@ -125,6 +125,34 @@ export const getUserWithAnagraficaHandler = async ({
|
|||
.where("id", "=", userId)
|
||||
.leftJoin("users_anagrafica", "users_anagrafica.userid", "users.id")
|
||||
.selectAll("users_anagrafica")
|
||||
.select((eb) => [
|
||||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("users_storage")
|
||||
.select([
|
||||
"users_storage.storageId as storageId",
|
||||
"users_anagrafica.doc_personale_fronte_ref as ref",
|
||||
])
|
||||
.whereRef(
|
||||
"users_storage.user_storage_id",
|
||||
"=",
|
||||
"users_anagrafica.doc_personale_fronte_ref",
|
||||
),
|
||||
).as("doc_personale_fronte"),
|
||||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("users_storage")
|
||||
.select([
|
||||
"users_storage.storageId as storageId",
|
||||
"users_anagrafica.doc_personale_retro_ref as ref",
|
||||
])
|
||||
.whereRef(
|
||||
"users_storage.user_storage_id",
|
||||
"=",
|
||||
"users_anagrafica.doc_personale_retro_ref",
|
||||
),
|
||||
).as("doc_personale_retro"),
|
||||
])
|
||||
.executeTakeFirstOrThrow();
|
||||
} catch (e) {
|
||||
throw new TRPCError({
|
||||
|
|
@ -133,45 +161,3 @@ export const getUserWithAnagraficaHandler = async ({
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const upsertAnagrafica = async ({
|
||||
db,
|
||||
data,
|
||||
}: {
|
||||
db: Querier;
|
||||
data: UsersAnagraficaUpdate;
|
||||
}) => {
|
||||
try {
|
||||
const { idanagrafica, userid, ...rest } = data;
|
||||
if (!userid) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Errore interno, utente non trovato",
|
||||
});
|
||||
}
|
||||
if (idanagrafica) {
|
||||
return await db
|
||||
.updateTable("users_anagrafica")
|
||||
.set({
|
||||
...rest,
|
||||
})
|
||||
.where("userid", "=", userid)
|
||||
.returningAll()
|
||||
.executeTakeFirst();
|
||||
}
|
||||
return await db
|
||||
.insertInto("users_anagrafica")
|
||||
.values({
|
||||
userid,
|
||||
...rest,
|
||||
})
|
||||
.onConflict((oc) => oc.column("userid").doNothing())
|
||||
.returningAll()
|
||||
.executeTakeFirst();
|
||||
} catch (e) {
|
||||
throw new TRPCError({
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
message: `Errore updateAnagrafica: ${(e as Error).message}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue