diff --git a/apps/db/migrations/40_servizio_interr.up.sql b/apps/db/migrations/40_servizio_interr.up.sql
new file mode 100644
index 0000000..3dd0fd5
--- /dev/null
+++ b/apps/db/migrations/40_servizio_interr.up.sql
@@ -0,0 +1,7 @@
+ALTER TABLE IF EXISTS public.servizio
+ADD COLUMN IF NOT EXISTS "interruzioneDays" integer NOT NULL DEFAULT 14;
+
+ALTER TABLE IF EXISTS public.servizio
+ADD COLUMN IF NOT EXISTS "acceptedInterr" boolean NOT NULL DEFAULT FALSE;
+
+ALTER TABLE IF EXISTS public.servizio DROP COLUMN IF EXISTS "isSent";
\ No newline at end of file
diff --git a/apps/infoalloggi/src/components/annunci_map.tsx b/apps/infoalloggi/src/components/annunci_map.tsx
index 0484340..f65250f 100644
--- a/apps/infoalloggi/src/components/annunci_map.tsx
+++ b/apps/infoalloggi/src/components/annunci_map.tsx
@@ -120,6 +120,7 @@ const SelectedComp = memo(
href={`/annuncio/${selected.codice}`}
initial={{ opacity: 0, scale: 0 }}
key={selected.id}
+ rel="noopener noreferrer"
target="_blank"
transition={{
duration: 0.1,
diff --git a/apps/infoalloggi/src/components/servizio/interruzione.tsx b/apps/infoalloggi/src/components/servizio/interruzione.tsx
new file mode 100644
index 0000000..2253a21
--- /dev/null
+++ b/apps/infoalloggi/src/components/servizio/interruzione.tsx
@@ -0,0 +1,249 @@
+import { add, differenceInDays, isBefore } from "date-fns";
+import { ArrowRight, Clock, ClockAlert, XCircle } from "lucide-react";
+import toast from "react-hot-toast";
+import { Confirm } from "~/components/confirm";
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "~/components/ui/alert-dialog";
+import { Button } from "~/components/ui/button";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "~/components/ui/card";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "~/components/ui/tooltip";
+import { useTranslation } from "~/providers/I18nProvider";
+import { useServizio } from "~/providers/ServizioProvider";
+import { api } from "~/utils/api";
+
+export const DisclaimerInterruzioneServizio = () => {
+ const { servizio, servizioId } = useServizio();
+ const { t } = useTranslation();
+ const utils = api.useUtils();
+ const { mutate: interrompiServizio } =
+ api.servizio.interruzioneServizio.useMutation({
+ onError: (error) => {
+ console.error(error);
+ toast.error("Errore durante la richiesta di interruzione");
+ },
+ onSuccess: async () => {
+ await utils.servizio.invalidate();
+ toast.success("Interruzione richiesta");
+ },
+ });
+ const { mutate: updateServizio } = api.servizio.updateServizio.useMutation({
+ onError: (error) => {
+ console.error(error);
+ toast.error("Errore");
+ },
+ onSuccess: async () => {
+ await utils.servizio.invalidate();
+ },
+ });
+
+ if (!servizio.decorrenza) return null;
+
+ return (
+
+
+
+
+
+
+ Sono passati {differenceInDays(new Date(), servizio.decorrenza)}{" "}
+ giorni dall'inizio della tua ricerca
+
+
+ Hai trovato qualche immobile interessante? Ricordati che{" "}
+ se non intendi confermare nessun immobile, puoi interrompere la
+ ricerca entro 14 giorni dalla decorrenza, evitando così di
+ dover pagare il saldo del servizio acquistato.
+
+
+
+
+
+
+
+
+
+ Continua
+
+ Continua a cercare casa
+
+
+
+
+
+ Avrai sempre modo di interrompere il servizio usando il pulsante
+ relativo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Interrompi
+
+
+ Termina la tua ricerca ora
+
+
+
+ Hai fino al{" "}
+ {add(servizio.decorrenza, {
+ days: servizio.interruzioneDays,
+ }).toLocaleDateString("it-IT")}{" "}
+ per interrompere il servizio senza costi aggiuntivi.
+
+ Se hai bisogno di assistenza, contattaci.
+
- );
-};
-
-const NewServizioModal = ({ userId }: { userId: UsersId }) => {
- const [open, setOpen] = useState(false);
- const utils = api.useUtils();
-
- const { mutate: add } = api.servizio.addServizio.useMutation({
- onError: (error) => {
- toast.error(error.message);
- },
- onSuccess: async () => {
- toast.success("Servizio creato con successo");
- await utils.servizio.invalidate();
-
- setOpen(false);
- },
- });
-
- function onSubmit(fields: FormValues) {
- add({ data: { ...fields, user_id: userId } });
- }
- return (
-
- );
-};
diff --git a/apps/infoalloggi/src/components/servizio/servizio.tsx b/apps/infoalloggi/src/components/servizio/servizio.tsx
index dba2bb5..dfdb69c 100644
--- a/apps/infoalloggi/src/components/servizio/servizio.tsx
+++ b/apps/infoalloggi/src/components/servizio/servizio.tsx
@@ -1,4 +1,4 @@
-import { add } from "date-fns";
+import { add, isAfter, isBefore } from "date-fns";
import {
ArrowRight,
BadgeCheck,
@@ -16,6 +16,7 @@ import {
} from "lucide-react";
import Link from "next/link";
import toast from "react-hot-toast";
+import { DisclaimerInterruzioneServizio } from "~/components/servizio/interruzione";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import {
@@ -28,6 +29,7 @@ import type { Rinnovi } from "~/schemas/public/Rinnovi";
import type { UsersId } from "~/schemas/public/Users";
import type { ServizioData } from "~/server/controllers/servizio.controller";
import { api } from "~/utils/api";
+import { DEFAULT_SERVIZIO_DURATION_DAYS } from "~/utils/config";
import { Confirm } from "../confirm";
import { AlarmClockSVG } from "../svgs";
import {
@@ -165,7 +167,10 @@ const ServizioLinkCard = ({
} else if (servizio.decorrenza) {
const now = new Date();
const decorrenza = new Date(servizio.decorrenza);
- if (now > add(decorrenza, { days: 60 }) && !servizio.isOkSaldo) {
+ if (
+ now > add(decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }) &&
+ !servizio.isOkSaldo
+ ) {
status = "scaduto";
StatusIcon = CircleMinus;
}
@@ -285,9 +290,9 @@ const Content = () => {
? new Date(servizio.decorrenza).toLocaleDateString("it-IT")
: "";
const end_txt = servizio.decorrenza
- ? new Date(add(servizio.decorrenza, { days: 60 })).toLocaleDateString(
- "it-IT",
- )
+ ? new Date(
+ add(servizio.decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }),
+ ).toLocaleDateString("it-IT")
: "";
return (
@@ -341,6 +346,7 @@ const Main = () => {
},
});
+ // se interrotto, mostra avvisos
if (servizio.isInterrotto) {
return (
<>
@@ -349,6 +355,7 @@ const Main = () => {
>
);
}
+ // mostra onboarding
if (!servizio.onboardOk) {
return (
@@ -376,6 +383,7 @@ const Main = () => {
);
}
+ // se non ok acconto, mostra invito a completare pagamento acconto o ad attivare se acconto già inserito
if (!servizio.isOkAcconto || servizio.decorrenza === null) {
const acconti = servizio.ordini.filter(
(o) => o.type === OrderTypeEnum.Acconto,
@@ -468,13 +476,15 @@ const Main = () => {
);
}
+ //servizio scaduto se decorrenza + 60 giorni è passato e non è ok saldo
if (
new Date() >
add(servizio.decorrenza, {
- days: 60,
+ days: DEFAULT_SERVIZIO_DURATION_DAYS,
}) &&
!servizio.isOkSaldo
) {
+ //todo capire come fare con saldo quando scade
return (
<>
{t.servizio.scaduto}
@@ -482,10 +492,12 @@ const Main = () => {
>
);
}
+
const annuncioConfermato = servizio.annunci.filter(
(a) => a.accettato_conferma_at !== null,
);
+ // in conferma, mostra solo annunci confermati
if (servizio.isOkSaldo && annuncioConfermato.length > 0) {
return (
<>
@@ -503,6 +515,23 @@ const Main = () => {
>
);
}
+
+ // se superato periodo interruzione, ma non interrotto, non scaduto e non in conferma, mostra avviso
+ if (
+ !servizio.acceptedInterr &&
+ isBefore(
+ new Date(),
+ add(servizio.decorrenza, { days: servizio.interruzioneDays }),
+ ) &&
+ isAfter(
+ new Date(),
+ add(servizio.decorrenza, { days: servizio.interruzioneDays - 5 }),
+ )
+ ) {
+ return ;
+ }
+
+ // normal case
return (
<>
{annuncioConfermato.length > 0 && (
@@ -511,31 +540,29 @@ const Main = () => {
{t.servizio.saldi_in_attesa}
- {servizio.annunci
- .filter((a) => a.accettato_conferma_at !== null)
- .map((a) => (
-