2026-01-12 16:00:53 +01:00
|
|
|
import { ArrowRight, BadgePlus } from "lucide-react";
|
2025-08-04 17:45:44 +02:00
|
|
|
import Link from "next/link";
|
2025-08-28 18:27:07 +02:00
|
|
|
import toast from "react-hot-toast";
|
|
|
|
|
import { ContattoAnnuncio } from "~/components/annuncio-interactions/contatto_modal";
|
|
|
|
|
import LoadingButton from "~/components/custom_ui/loading-button";
|
2025-12-11 15:41:57 +01:00
|
|
|
import { Button } from "~/components/ui/button";
|
2025-08-04 17:45:44 +02:00
|
|
|
import { useAnnuncio } from "~/providers/AnnuncioProvider";
|
2026-02-25 15:30:53 +01:00
|
|
|
import { useTranslation } from "~/providers/I18nProvider";
|
2025-11-04 19:18:13 +01:00
|
|
|
import { useServizio } from "~/providers/ServizioProvider";
|
2025-08-04 17:45:44 +02:00
|
|
|
import type { SessionContextType } from "~/providers/SessionProvider";
|
|
|
|
|
import type { AnnunciId } from "~/schemas/public/Annunci";
|
2025-08-28 18:27:07 +02:00
|
|
|
import type { UsersId } from "~/schemas/public/Users";
|
|
|
|
|
import { api } from "~/utils/api";
|
2025-08-04 17:45:44 +02:00
|
|
|
|
|
|
|
|
export const AnnuncioInteractions = ({
|
2025-08-28 18:27:07 +02:00
|
|
|
session,
|
|
|
|
|
disabled,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
session: SessionContextType;
|
|
|
|
|
disabled?: boolean;
|
2025-08-04 17:45:44 +02:00
|
|
|
}) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
const { id, tipo } = useAnnuncio();
|
2026-02-25 15:30:53 +01:00
|
|
|
const { locale } = useTranslation();
|
2025-08-28 18:27:07 +02:00
|
|
|
if (disabled) {
|
|
|
|
|
return (
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="w-full rounded-md bg-red-500 p-2 text-center font-semibold text-base text-white">
|
2026-02-25 15:30:53 +01:00
|
|
|
{locale === "it"
|
|
|
|
|
? "Richieste Temporaneamente disattivate"
|
|
|
|
|
: "Requests Temporarily Disabled"}
|
2025-08-28 18:27:07 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex w-full flex-col justify-around gap-3 md:gap-5">
|
|
|
|
|
{session.user ? (
|
|
|
|
|
tipo ? (
|
|
|
|
|
<ServizioInteraction
|
|
|
|
|
annuncioId={id}
|
2025-08-29 16:18:32 +02:00
|
|
|
tipologia={tipo}
|
|
|
|
|
userId={session.user.id}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
) : (
|
2026-02-25 15:30:53 +01:00
|
|
|
<span>{locale === "it" ? "Errore" : "Error"}</span>
|
2025-08-28 18:27:07 +02:00
|
|
|
)
|
|
|
|
|
) : (
|
|
|
|
|
<div className="flex w-full flex-col gap-2">
|
2025-10-20 11:41:54 +02:00
|
|
|
<ContattoAnnuncio />
|
2026-01-12 16:00:53 +01:00
|
|
|
{/* <span className="w-full text-center text-sm">oppure</span>
|
2025-08-28 18:27:07 +02:00
|
|
|
<Link
|
|
|
|
|
aria-label="Login"
|
|
|
|
|
href={{
|
|
|
|
|
pathname: "/login",
|
|
|
|
|
query: { redirect: router.asPath },
|
|
|
|
|
}}
|
|
|
|
|
>
|
2025-12-11 15:41:57 +01:00
|
|
|
<Button className="w-full">
|
2026-01-16 15:47:38 +01:00
|
|
|
<LogIn />
|
2025-12-11 15:41:57 +01:00
|
|
|
<span>Accedi se hai un account</span>
|
|
|
|
|
</Button>
|
2026-01-12 16:00:53 +01:00
|
|
|
</Link> */}
|
2025-08-28 18:27:07 +02:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const ServizioInteraction = ({
|
2025-08-28 18:27:07 +02:00
|
|
|
userId,
|
|
|
|
|
tipologia,
|
|
|
|
|
annuncioId,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
userId: UsersId;
|
|
|
|
|
tipologia: string;
|
|
|
|
|
annuncioId: AnnunciId;
|
2025-08-04 17:45:44 +02:00
|
|
|
}) => {
|
2026-02-25 15:30:53 +01:00
|
|
|
const { locale } = useTranslation();
|
2025-08-28 18:27:07 +02:00
|
|
|
const { data: servizio, isLoading } =
|
|
|
|
|
api.servizio.AnnuncioServizioTipologiaMatch.useQuery({
|
|
|
|
|
annuncioId,
|
2025-08-29 16:18:32 +02:00
|
|
|
tipologia,
|
|
|
|
|
userId,
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-29 16:18:32 +02:00
|
|
|
if (isLoading) return <LoadingButton className="w-full" loading />;
|
2025-08-28 18:27:07 +02:00
|
|
|
if (
|
|
|
|
|
servizio === undefined ||
|
|
|
|
|
servizio.status === "invalid" ||
|
|
|
|
|
servizio.status === "not_found"
|
|
|
|
|
) {
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
2026-02-25 15:30:53 +01:00
|
|
|
<p>
|
|
|
|
|
{locale === "it"
|
|
|
|
|
? "Non hai un servizio attivo"
|
|
|
|
|
: "You do not have an active service"}
|
|
|
|
|
</p>
|
2025-08-28 18:27:07 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
if (servizio.status === "already_saved") {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex w-full flex-col gap-2">
|
|
|
|
|
<div className="w-full text-center font-semibold text-green-500">
|
2026-02-25 15:30:53 +01:00
|
|
|
{locale === "it" ? "Annuncio già salvato!" : "Listing already saved!"}
|
2025-08-28 18:27:07 +02:00
|
|
|
</div>
|
|
|
|
|
<Link
|
2026-02-25 15:30:53 +01:00
|
|
|
aria-label={
|
|
|
|
|
locale === "it"
|
|
|
|
|
? "Vai alla tua area riservata"
|
|
|
|
|
: "Go to your reserved area"
|
|
|
|
|
}
|
2025-08-29 16:18:32 +02:00
|
|
|
href={`/area-riservata/dashboard`}
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
2025-11-03 10:59:45 +01:00
|
|
|
<Button className="w-full" variant="success">
|
2026-02-25 15:30:53 +01:00
|
|
|
{locale === "it"
|
|
|
|
|
? "Vai alla tua area riservata"
|
|
|
|
|
: "Go to your reserved area"}{" "}
|
|
|
|
|
<ArrowRight />
|
2025-08-28 18:27:07 +02:00
|
|
|
</Button>
|
|
|
|
|
</Link>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-11-04 19:18:13 +01:00
|
|
|
return <InteressatoButtonUserOnly annuncioId={annuncioId} />;
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
2025-11-04 19:18:13 +01:00
|
|
|
const InteressatoButtonUserOnly = ({
|
|
|
|
|
annuncioId,
|
|
|
|
|
}: {
|
|
|
|
|
annuncioId: AnnunciId;
|
|
|
|
|
}) => {
|
2026-02-25 15:30:53 +01:00
|
|
|
const { locale } = useTranslation();
|
2025-08-28 18:27:07 +02:00
|
|
|
const { data: hasInterest, isLoading } =
|
|
|
|
|
api.intrests.hasUserInterest.useQuery({
|
|
|
|
|
annuncioId,
|
|
|
|
|
});
|
|
|
|
|
const utils = api.useUtils();
|
|
|
|
|
const { mutate: add } = api.intrests.addIntrest.useMutation({
|
|
|
|
|
onSuccess: async () => {
|
|
|
|
|
await utils.intrests.hasUserInterest.invalidate({
|
|
|
|
|
annuncioId,
|
|
|
|
|
});
|
2026-02-25 15:30:53 +01:00
|
|
|
toast.success(
|
|
|
|
|
locale === "it"
|
|
|
|
|
? "Richiesta di interesse inviata con successo!"
|
|
|
|
|
: "Interest request sent successfully!",
|
|
|
|
|
);
|
2025-08-28 18:27:07 +02:00
|
|
|
},
|
|
|
|
|
});
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
if (isLoading || hasInterest === undefined) {
|
|
|
|
|
return (
|
2025-11-03 10:59:45 +01:00
|
|
|
<Button className="w-full" disabled>
|
2025-08-28 18:27:07 +02:00
|
|
|
<BadgePlus className="size-6" />
|
2026-02-25 15:30:53 +01:00
|
|
|
{locale === "it" ? "Caricamento..." : "Loading..."}
|
2025-08-28 18:27:07 +02:00
|
|
|
</Button>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if (hasInterest) {
|
|
|
|
|
return (
|
2025-10-10 16:18:43 +02:00
|
|
|
<span className="flex w-full items-center justify-center gap-2 rounded-md bg-green-500 p-2 font-semibold text-sm text-white">
|
2025-08-28 18:27:07 +02:00
|
|
|
<BadgePlus className="inline size-5" />
|
2026-02-25 15:30:53 +01:00
|
|
|
{locale === "it"
|
|
|
|
|
? "Hai già mandato una richiesta"
|
|
|
|
|
: "You have already sent a request"}
|
2025-08-28 18:27:07 +02:00
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return (
|
|
|
|
|
<Button
|
2026-02-25 15:30:53 +01:00
|
|
|
aria-label={locale === "it" ? "Sono interessato" : "I'm interested"}
|
2026-01-20 19:18:23 +01:00
|
|
|
className="w-full text-lg md:text-base lg:text-lg"
|
2025-08-28 18:27:07 +02:00
|
|
|
onClick={() => {
|
|
|
|
|
add({
|
|
|
|
|
annuncioId,
|
|
|
|
|
});
|
|
|
|
|
}}
|
2026-01-20 19:18:23 +01:00
|
|
|
size="xl"
|
|
|
|
|
variant="success"
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
|
|
|
|
<BadgePlus className="size-6" />
|
2026-02-25 15:30:53 +01:00
|
|
|
{locale === "it" ? "Sono interessato" : "I'm interested"}
|
2025-08-28 18:27:07 +02:00
|
|
|
</Button>
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
2025-11-04 19:18:13 +01:00
|
|
|
export const InteressatoButtonServizio = ({
|
2025-08-28 18:27:07 +02:00
|
|
|
annuncioId,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
annuncioId: AnnunciId;
|
2025-08-04 17:45:44 +02:00
|
|
|
}) => {
|
2025-11-04 19:18:13 +01:00
|
|
|
const { isAdmin, servizioId, userId } = useServizio();
|
2026-02-25 15:30:53 +01:00
|
|
|
const { locale } = useTranslation();
|
2025-08-28 18:27:07 +02:00
|
|
|
const utils = api.useUtils();
|
2025-11-04 19:18:13 +01:00
|
|
|
|
2025-12-04 17:16:49 +01:00
|
|
|
const invalidateAll = async () => {
|
|
|
|
|
await utils.intrests.getUserInterests.invalidate();
|
|
|
|
|
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
|
|
|
|
|
await utils.servizio.getAnnunciAvailableToAdd.invalidate({
|
|
|
|
|
servizioId,
|
|
|
|
|
});
|
|
|
|
|
await utils.servizio.AnnuncioServizioTipologiaMatch.invalidate({
|
|
|
|
|
userId,
|
|
|
|
|
});
|
|
|
|
|
await utils.servizio.getCompatibileAnnunci.invalidate({
|
|
|
|
|
servizioId,
|
|
|
|
|
});
|
|
|
|
|
};
|
2025-11-04 19:18:13 +01:00
|
|
|
const { mutate: adminAdd, isPending: isAdminPending } =
|
|
|
|
|
api.servizio.addServizioAnnunci.useMutation({
|
|
|
|
|
onError: (error) => {
|
|
|
|
|
console.error(error);
|
|
|
|
|
toast.error("Errore durante l'aggiunta dell'annuncio");
|
|
|
|
|
},
|
|
|
|
|
onSuccess: async () => {
|
2025-12-04 17:16:49 +01:00
|
|
|
await invalidateAll();
|
2025-11-04 19:18:13 +01:00
|
|
|
|
|
|
|
|
toast.success("Annuncio aggiunto alla ricerca");
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const { mutate: add, isPending } = api.intrests.addIntrest.useMutation({
|
2025-08-28 18:27:07 +02:00
|
|
|
onSuccess: async () => {
|
2025-12-04 17:16:49 +01:00
|
|
|
await invalidateAll();
|
2025-08-28 18:27:07 +02:00
|
|
|
toast.success("Richiesta di interesse inviata con successo!");
|
|
|
|
|
},
|
|
|
|
|
});
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return (
|
2025-11-04 19:18:13 +01:00
|
|
|
<LoadingButton
|
2025-08-29 16:18:32 +02:00
|
|
|
aria-label="Sono interessato"
|
2025-11-03 10:59:45 +01:00
|
|
|
className="w-full"
|
2025-11-04 19:18:13 +01:00
|
|
|
loading={isPending || isAdminPending}
|
2025-08-28 18:27:07 +02:00
|
|
|
onClick={() => {
|
2025-11-04 19:18:13 +01:00
|
|
|
if (isAdmin && servizioId) {
|
|
|
|
|
adminAdd({
|
|
|
|
|
servizioId,
|
|
|
|
|
annunci: [annuncioId],
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
add({
|
|
|
|
|
annuncioId,
|
|
|
|
|
});
|
|
|
|
|
}}
|
2025-08-29 16:18:32 +02:00
|
|
|
variant="info"
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
|
|
|
|
<BadgePlus className="size-6" />
|
2026-02-25 15:30:53 +01:00
|
|
|
{isAdmin
|
|
|
|
|
? "Aggiungi"
|
|
|
|
|
: locale === "it"
|
|
|
|
|
? "Sono interessato"
|
|
|
|
|
: "I'm interested"}
|
2025-11-04 19:18:13 +01:00
|
|
|
</LoadingButton>
|
2025-08-28 18:27:07 +02:00
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|