infoalloggi-monorepo/apps/infoalloggi/src/components/annuncio-interactions/annuncio_interactions.tsx
Marco Pedone 6c36bb9b74 feat: add order editing form and payment processing pages
- Implemented FormEditOrder component for editing orders with validation and submission handling.
- Created SchedaAnnuncioPage for displaying printable announcement details.
- Added BonificoManualePage for manual bank transfer payment instructions.
- Developed PagamentoPage for Stripe payment processing with PaymentIntent creation.
- Introduced PreviewPurchasePage for preparing payment with service details.
- Added pagamenti.controller for handling payment preparation and retrieval of payment data.
2026-03-08 01:02:57 +01:00

251 lines
6 KiB
TypeScript

import { ArrowRight, BadgePlus } from "lucide-react";
import Link from "next/link";
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";
import { useAnnuncio } from "~/providers/AnnuncioProvider";
import { useTranslation } from "~/providers/I18nProvider";
import { useServizio } from "~/providers/ServizioProvider";
import type { SessionContextType } from "~/providers/SessionProvider";
import type { AnnunciId } from "~/schemas/public/Annunci";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
export const AnnuncioInteractions = ({
session,
disabled,
}: {
session: SessionContextType;
disabled?: boolean;
}) => {
const { id, tipo } = useAnnuncio();
const { locale } = useTranslation();
if (disabled) {
return (
<div className="w-full rounded-md bg-red-500 p-2 text-center font-semibold text-base text-white">
{locale === "it"
? "Richieste Temporaneamente disattivate"
: "Requests Temporarily Disabled"}
</div>
);
}
return (
<div className="flex w-full flex-col justify-around gap-3 md:gap-5">
{session.user ? (
tipo ? (
<ServizioInteraction
annuncioId={id}
tipologia={tipo}
userId={session.user.id}
/>
) : (
<span>{locale === "it" ? "Errore" : "Error"}</span>
)
) : (
<div className="flex w-full flex-col gap-2">
<ContattoAnnuncio />
{/* <span className="w-full text-center text-sm">oppure</span>
<Link
aria-label="Login"
href={{
pathname: "/login",
query: { redirect: router.asPath },
}}
>
<Button className="w-full">
<LogIn />
<span>Accedi se hai un account</span>
</Button>
</Link> */}
</div>
)}
</div>
);
};
const ServizioInteraction = ({
userId,
tipologia,
annuncioId,
}: {
userId: UsersId;
tipologia: string;
annuncioId: AnnunciId;
}) => {
const { locale } = useTranslation();
const { data: servizio, isLoading } =
api.servizio.AnnuncioServizioTipologiaMatch.useQuery({
annuncioId,
tipologia,
userId,
});
if (isLoading) return <LoadingButton className="w-full" loading />;
if (
servizio === undefined ||
servizio.status === "invalid" ||
servizio.status === "not_found"
) {
return (
<div>
<p>
{locale === "it"
? "Non hai un servizio attivo"
: "You do not have an active service"}
</p>
</div>
);
}
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">
{locale === "it" ? "Annuncio già salvato!" : "Listing already saved!"}
</div>
<Link
aria-label={
locale === "it"
? "Vai alla tua area riservata"
: "Go to your reserved area"
}
href={`/area-riservata/dashboard`}
>
<Button className="w-full" variant="success">
{locale === "it"
? "Vai alla tua area riservata"
: "Go to your reserved area"}{" "}
<ArrowRight />
</Button>
</Link>
</div>
);
}
return <InteressatoButtonUserOnly annuncioId={annuncioId} />;
};
const InteressatoButtonUserOnly = ({
annuncioId,
}: {
annuncioId: AnnunciId;
}) => {
const { locale } = useTranslation();
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(
locale === "it"
? "Richiesta di interesse inviata con successo!"
: "Interest request sent successfully!",
);
},
});
if (isLoading || hasInterest === undefined) {
return (
<Button className="w-full" disabled>
<BadgePlus className="size-6" />
{locale === "it" ? "Caricamento..." : "Loading..."}
</Button>
);
}
if (hasInterest) {
return (
<span className="flex w-full items-center justify-center gap-2 rounded-md bg-green-500 p-2 font-semibold text-sm text-white">
<BadgePlus className="inline size-5" />
{locale === "it"
? "Hai già mandato una richiesta"
: "You have already sent a request"}
</span>
);
}
return (
<Button
aria-label={locale === "it" ? "Sono interessato" : "I'm interested"}
className="w-full text-lg md:text-base lg:text-lg"
onClick={() => {
add({
annuncioId,
});
}}
size="xl"
variant="success"
>
<BadgePlus className="size-6" />
{locale === "it" ? "Sono interessato" : "I'm interested"}
</Button>
);
};
export const InteressatoButtonServizio = ({
annuncioId,
}: {
annuncioId: AnnunciId;
}) => {
const { isAdmin, servizioId } = useServizio();
const { locale } = useTranslation();
const utils = api.useUtils();
const invalidateAll = async () => {
await utils.intrests.getUserInterests.invalidate();
await utils.servizio.invalidate();
};
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({
onSuccess: async () => {
await invalidateAll();
toast.success("Richiesta di interesse inviata con successo!");
},
});
return (
<LoadingButton
aria-label="Sono interessato"
className="w-full"
loading={isPending || isAdminPending}
onClick={() => {
if (isAdmin && servizioId) {
adminAdd({
servizioId,
annunci: [annuncioId],
});
return;
}
add({
annuncioId,
});
}}
variant="info"
>
<BadgePlus className="size-6" />
{isAdmin
? "Aggiungi"
: locale === "it"
? "Sono interessato"
: "I'm interested"}
</LoadingButton>
);
};