infoalloggi-monorepo/apps/infoalloggi/src/pages/servizio/conferma-immobile/[...slug].tsx

216 lines
6.6 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
import type { GetServerSideProps } from "next";
import type { NextPageWithLayout } from "~/pages/_app";
import { zAnnuncioId, zServizioId } from "~/server/utils/zod_types";
import { AreaRiservataLayout } from "~/components/Layout";
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
import { Button } from "~/components/ui/button";
import { Checkbox } from "~/components/ui/checkbox";
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import toast from "react-hot-toast";
import { useTranslation } from "~/providers/I18nProvider";
import { useRouter } from "next/router";
import type { ServizioServizioId } from "~/schemas/public/Servizio";
import type { AnnunciId } from "~/schemas/public/Annunci";
import { Status500 } from "~/components/status-page";
import { useState } from "react";
import { DocNotFoundPage } from "~/components/doc_not_found";
import { FileSection } from "~/components/servizio/conferma";
type ConfermaImmobileProps = {
servizioId: ServizioServizioId;
annuncioId: AnnunciId;
};
const ConfermaImmobile: NextPageWithLayout<ConfermaImmobileProps> = ({
servizioId,
annuncioId,
}: ConfermaImmobileProps) => {
const { data, isLoading } = api.servizio.getServizioAnnuncio.useQuery({
servizioId,
annuncioId,
});
if (isLoading) return <LoadingPage />;
if (!data) return <Status500 />;
if (!data.doc_conferma_ref) return <DocNotFoundPage />;
return (
<div className="mx-2 flex flex-1 overflow-auto">
<div className="mx-auto flex grow sm:grow-0">
<div className="flex flex-col items-center space-y-4 py-4">
<h1 className="text-xl font-bold">Conferma Immobile</h1>
<p className="text-center">
Il documento sottostante riassume le condizioni della locazione tra
te e il proprietario
</p>
<FileSection storageId={data.doc_conferma_ref} />
<div className="flex max-w-3xl flex-col gap-2 rounded-md bg-green-400 p-4 text-left">
<p className="text-xl font-semibold">
Per confermare l&apos;immobile procedi al bonifico di caparra!
</p>
<p>Coordinate bancarie:</p>
<p>Intestazione: {data.caparra_intestazione || ""}</p>
<p>IBAN: {data.caparra_iban || ""}</p>
<p>Importo: {data.caparra_importo || ""}</p>
<p>Causale: {data.caparra_causale || ""}</p>
<p className="text-xl font-semibold">
Mandaci la contabile del bonifico una volta effettuato!
</p>
</div>
<ConfirmSection servizioId={servizioId} annuncioId={annuncioId} />
</div>
</div>
</div>
);
};
const ConfirmSection = ({
servizioId,
annuncioId,
}: {
servizioId: ServizioServizioId;
annuncioId: AnnunciId;
}) => {
const { t } = useTranslation();
const router = useRouter();
const [letto, setLetto] = useState(false);
const [accettato, setAccettato] = useState(false);
const utils = api.useUtils();
const { mutate: conferma } = api.servizio.updateServizioAnnunci.useMutation({
onMutate: () => {
const toastId = toast.loading(t.caricamento, {
icon: "🔄",
});
return { toastId };
},
onSuccess: async (_error, _variables, context) => {
await utils.storage.getUserStorage.invalidate();
toast.success("Confermato", {
icon: "👍",
id: context?.toastId,
});
await router.push("/area-riservata/dashboard");
},
});
return (
<>
<div className="flex flex-col items-start space-y-3">
<div className="flex space-x-2">
<Checkbox
id="letto"
checked={letto}
onCheckedChange={(v) => v != "indeterminate" && setLetto(v)}
/>
<div className="grid gap-1.5 leading-none">
<label
htmlFor="letto"
className="text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Dichiaro di aver letto e compreso il documento.
</label>
</div>
</div>
<div className="flex space-x-2">
<Checkbox
id="termini"
checked={accettato}
onCheckedChange={(v) => v != "indeterminate" && setAccettato(v)}
/>
<div className="grid gap-1.5 leading-none">
<label
htmlFor="termini"
className="text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Accetto i termini e condizioni.
</label>
<p className="text-muted-foreground text-sm">
Confermi la tua accettazione dei Termini di servizio e della
Politica sulla privacy di InfoAlloggi.it.
</p>
</div>
</div>
</div>
<Button
disabled={!letto || !accettato}
onClick={() => {
// Handle confirmation logic here
conferma({
servizioId,
annuncioId,
data: {
accettato_conferma_at: new Date(),
},
});
//TODO mandare al saldo o in qualche modo segnare il servizio come completato e da pagare
}}
>
Conferma la presa visione e Procedi al saldo del servizio
</Button>
</>
);
};
ConfermaImmobile.getLayout = function getLayout(page) {
return (
<AreaRiservataLayout noSidebar noFooter>
{page}
</AreaRiservataLayout>
);
};
export default ConfermaImmobile;
export const getServerSideProps = (async (context) => {
const slug = context.params?.slug;
if (!slug || slug.length != 2) {
return {
notFound: true,
};
}
const [servizioId, annuncioId] = slug;
if (!servizioId || !annuncioId) {
return {
notFound: true,
};
}
const parsedServizioId = zServizioId.safeParse(servizioId);
const parsedAnnuncioId = zAnnuncioId.safeParse(parseInt(annuncioId));
if (!parsedServizioId.success || !parsedAnnuncioId.success) {
return {
notFound: true,
};
}
const access_token = context.req.cookies.access_token;
const helper = await TrpcAuthedFetchingIstance({ access_token });
if (helper) {
await helper.trpc.servizio.getServizioAnnuncio.prefetch({
servizioId: parsedServizioId.data,
annuncioId: parsedAnnuncioId.data,
});
return {
props: {
servizioId: parsedServizioId.data,
annuncioId: parsedAnnuncioId.data,
trpcState: helper.trpc.dehydrate(),
},
};
}
return {
redirect: {
destination: "/500",
permanent: false,
},
};
}) satisfies GetServerSideProps<ConfermaImmobileProps>;