import { add, format, isAfter, isBefore } from "date-fns"; import { ArrowRight, BadgeCheck, CalendarClock, CircleCheck, CircleCheckBig, CircleHelp, CircleMinus, ClockFading, ExternalLink, type LucideIcon, MousePointerClick, PackageCheck, SearchX, Timer, Trash2, } 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 { ServizioAnnuncioProvider, ServizioProvider, useServizio, } from "~/providers/ServizioProvider"; import { orderTypeEnum } from "~/schemas/public/OrderTypeEnum"; 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 { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "../ui/alert-dialog"; import { Button } from "../ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "../ui/card"; import { SaldoButton } from "./annuncio_actions"; import { AnnuncioCard, AnnuncioDisplay } from "./annuncio_card"; import { AnnunciCompatibili } from "./compatibili_dialog"; import { AdminServizioActions, ServizioInfos } from "./servizio_actions"; export const ServizioList = ({ data, isAdmin, userId, }: { data: ( | { d: Date; type: "servizio"; data: ServizioData } | { d: Date; type: "rinnovo"; data: Rinnovi } )[]; isAdmin: boolean; userId: UsersId; }) => { const { t } = useTranslation(); if (data.length === 0) { return (
{t.servizio.nessun_servizio}
); } return (
{data.map(({ d: _d, type, data: s }) => { if (type === "rinnovo") { return ( ); } return ( ); })}
); }; const RinnovoLinkCard = ({ data, isAdmin, userId, }: { data: Rinnovi; isAdmin: boolean; userId: UsersId; }) => { return ( Rinnovo {data.codice} Data rinnovo: {data.decorrenza.toLocaleDateString("it-IT")}
Vai al rinnovo
); }; const ServizioLinkCard = ({ servizio, isAdmin, userId, }: { servizio: ServizioData; isAdmin: boolean; userId: UsersId; }) => { const { t } = useTranslation(); let status: keyof typeof t.servizio.status = "attivo"; let StatusIcon: LucideIcon = CircleCheck; if (servizio.isInterrotto) { status = "interrotto"; StatusIcon = SearchX; } else if (!servizio.isOkAcconto) { status = "in_attesa"; StatusIcon = ClockFading; } else if (servizio.decorrenza) { const now = new Date(); const decorrenza = new Date(servizio.decorrenza); if ( now > add(decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }) && !servizio.isOkSaldo ) { status = "scaduto"; StatusIcon = CircleMinus; } if (servizio.isOkSaldo) { status = "completato"; StatusIcon = CircleCheckBig; } } return ( {status === "in_attesa" ? ( {t.servizio.servizio_titolo} {servizio.tipologia} {t.servizio.servizio_creato_il}{" "} {servizio.created_at.toLocaleDateString("it-IT")}
{t.servizio.status[status]}
{t.servizio.vai_al_servizio}
) : ( {t.servizio.servizio_titolo} {servizio.tipologia} {t.servizio.servizio_creato_il}{" "} {servizio.created_at.toLocaleDateString("it-IT")}
{t.servizio.status[status]}
{t.servizio.vai_al_servizio}
)} ); }; export const Servizio = ({ servizio, userId, isAdmin, }: { servizio: ServizioData; userId: UsersId; isAdmin: boolean; }) => { return ( ); }; const Content = () => { const { servizio } = useServizio(); const { t } = useTranslation(); const dec_txt = servizio.decorrenza ? new Date(servizio.decorrenza).toLocaleDateString("it-IT") : ""; const end_txt = servizio.decorrenza ? new Date( add(servizio.decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }), ).toLocaleDateString("it-IT") : ""; return (

{t.servizio.servizio_titolo} {servizio.tipologia}

{t.servizio.durata_servizio}
{servizio.decorrenza !== null ? `${dec_txt} - ${end_txt}` : "In attesa di attivazione"}
{servizio.decorrenza && (
{t.servizio.interruzione.scadenza}{" "} {format( add(servizio.decorrenza, { days: servizio.interruzioneDays }), "dd/MM/yyyy", )} {t.servizio.interruzione.info_title} {t.servizio.interruzione.info_desc} Capito
)}
); }; const Main = () => { const { servizio, isAdmin, userId } = useServizio(); const { t } = useTranslation(); const utils = api.useUtils(); const { mutate: attivazioneSenzaPagamento } = api.servizio.attivazioneSenzaPagamento.useMutation({ onError: () => { toast.error("Errore durante l'attivazione del servizio"); }, onSuccess: async () => { toast.success("Servizio modificato con successo"); await utils.servizio.invalidate(); }, }); // se interrotto, mostra avvisos if (servizio.isInterrotto) { if (isAdmin) { return ( <>
{t.servizio.servizio_interrotto}
{servizio.annunci.map((data) => { return ( ); })} {servizio.annunci.length > 1 && servizio.annunci.length % 2 === 1 && (
)}
); } return (

{t.servizio.servizio_interrotto}

{t.servizio.servizio_interrotto_desc}

); } // mostra onboarding if (!servizio.onboardOk) { return (

{t.servizio.non_attivo}

{isAdmin && }
); } // 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.enum.Acconto, ); const activeAcconto = acconti.find((a) => a.isActive); return (

Parametri di ricerca salvati

{activeAcconto ? (
Attivazione del Servizio Procedendo all'attivazione del servizio, confermi che i parametri di ricerca salvati sono corretti e accetti di essere contattato per eventuali verifiche. {activeAcconto?.testo_condizioni && (

Riceverai copia delle condizioni anche via email

)}
{t.annulla} { attivazioneSenzaPagamento({ ordineId: activeAcconto.ordine_id, }); }} > Attiva il servizio
) : ( )}
{isAdmin && }
); } //servizio scaduto se decorrenza + 60 giorni è passato e non è ok saldo if ( isBefore( add(servizio.decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }), new Date(), ) && !servizio.isOkSaldo ) { //todo capire come fare con saldo quando scade return ( <>

{t.servizio.scaduto}

{t.servizio.scaduto_desc}

); } const InConferma = servizio.annunci.filter((a) => a.status_conferma !== null); // in conferma, mostra solo annunci confermati if (servizio.isOkSaldo && InConferma.length > 0) { return ( <> {InConferma.map((data) => { return ( ); })} {isAdmin && (

Altri annunci:

{servizio.annunci .filter((a) => a.status_conferma === null) .map((data) => { return ( ); })} {servizio.annunci.length > 1 && servizio.annunci.length % 2 === 1 && (
)}
)} ); } // se superato periodo interruzione, ma non interrotto, non scaduto e non in conferma, mostra avviso if ( !isAdmin && !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 ( <> {InConferma.length > 0 && (
{t.servizio.saldi_in_attesa}
{InConferma.map((a) => (

{a.codice}

))}
)}
{servizio.annunci.map((data) => { return ( ); })} {servizio.annunci.length > 1 && servizio.annunci.length % 2 === 1 && (
)}
{servizio.annunci.length === 0 && (

Cerca un annuncio ora!

)}
); }; const AnnunciAnteprima = () => { const { servizio, isAdmin } = useServizio(); const { t } = useTranslation(); const utils = api.useUtils(); const { mutate: removeAnnuncioServizio } = api.servizio.removeAnnuncioServizio.useMutation({ onError: () => { toast.error("Errore durante la rimozione dell'annuncio dal servizio"); }, onSuccess: async () => { await utils.servizio.invalidate(); toast.success("Annuncio rimosso"); }, }); if (servizio.annunci.length > 0) { return (

{t.servizio.per_te_1} {servizio.annunci.length} {t.servizio.per_te_2}

{servizio.annunci.map((data) => (
{isAdmin && ( { removeAnnuncioServizio({ annuncioId: data.annunci_id, servizioId: servizio.servizio_id, }); }} title="Rimuovi Annuncio" > )}
))} {servizio.annunci.length % 2 === 1 && (
)}
); } return null; };