infoalloggi-monorepo/apps/infoalloggi/src/components/annuncio-interactions/annuncio_interactions.tsx

234 lines
5.4 KiB
TypeScript
Raw Normal View History

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";
import { Button } from "~/components/ui/button";
2025-08-04 17:45:44 +02:00
import { useAnnuncio } from "~/providers/AnnuncioProvider";
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();
2025-08-04 17:45:44 +02:00
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">
2025-08-28 18:27:07 +02:00
Richieste Temporaneamente disattivate
</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
/>
) : (
<span>Errore</span>
)
) : (
<div className="flex w-full flex-col gap-2">
<ContattoAnnuncio />
{/* <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 },
}}
>
<Button className="w-full">
<LogIn className="size-5" />
<span>Accedi se hai un account</span>
</Button>
</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
}) => {
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>
<p>Non hai un servizio attivo</p>
</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">
Annuncio già salvato!
</div>
<Link
aria-label="Vai alla tua area riservata"
2025-08-29 16:18:32 +02:00
href={`/area-riservata/dashboard`}
2025-08-28 18:27:07 +02:00
>
<Button className="w-full" variant="success">
2025-08-28 18:27:07 +02:00
Vai alla tua area riservata <ArrowRight />
</Button>
</Link>
</div>
);
}
2025-08-04 17:45:44 +02:00
return <InteressatoButtonUserOnly annuncioId={annuncioId} />;
2025-08-04 17:45:44 +02:00
};
const InteressatoButtonUserOnly = ({
annuncioId,
}: {
annuncioId: AnnunciId;
}) => {
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,
});
toast.success("Richiesta di interesse inviata con successo!");
},
});
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
if (isLoading || hasInterest === undefined) {
return (
<Button className="w-full" disabled>
2025-08-28 18:27:07 +02:00
<BadgePlus className="size-6" />
Caricamento...
</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" />
Hai già mandato una richiesta
</span>
);
}
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
return (
<Button
2025-08-29 16:18:32 +02:00
aria-label="Sono interessato"
className="w-full"
2025-08-28 18:27:07 +02:00
//size="xl"
onClick={() => {
add({
annuncioId,
});
}}
2025-08-29 16:18:32 +02:00
variant="info"
2025-08-28 18:27:07 +02:00
>
<BadgePlus className="size-6" />
Sono interessato
</Button>
);
2025-08-04 17:45:44 +02: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
}) => {
const { isAdmin, servizioId, userId } = useServizio();
2025-08-28 18:27:07 +02:00
const utils = api.useUtils();
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,
});
};
const { mutate: adminAdd, isPending: isAdminPending } =
api.servizio.addServizioAnnunci.useMutation({
onError: (error) => {
console.error(error);
toast.error("Errore durante l'aggiunta dell'annuncio");
},
onSuccess: async () => {
await invalidateAll();
toast.success("Annuncio aggiunto alla ricerca");
},
});
const { mutate: add, isPending } = api.intrests.addIntrest.useMutation({
2025-08-28 18:27:07 +02:00
onSuccess: async () => {
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 (
<LoadingButton
2025-08-29 16:18:32 +02:00
aria-label="Sono interessato"
className="w-full"
loading={isPending || isAdminPending}
2025-08-28 18:27:07 +02:00
onClick={() => {
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" />
{isAdmin ? "Aggiungi" : "Sono interessato"}
</LoadingButton>
2025-08-28 18:27:07 +02:00
);
2025-08-04 17:45:44 +02:00
};