122 lines
2.8 KiB
TypeScript
122 lines
2.8 KiB
TypeScript
import {
|
|
Elements,
|
|
PaymentElement,
|
|
useElements,
|
|
useStripe,
|
|
} from "@stripe/react-stripe-js";
|
|
import { loadStripe } from "@stripe/stripe-js";
|
|
import { type FormEvent, useState } from "react";
|
|
import { env } from "~/env";
|
|
import { formatCurrency } from "~/lib/utils";
|
|
import { useTranslation } from "~/providers/I18nProvider";
|
|
import LoadingButton from "./custom_ui/loading-button";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "./ui/card";
|
|
|
|
const stripePromise = loadStripe(env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY);
|
|
|
|
export default function CheckoutForm({
|
|
clientSecret,
|
|
titolo,
|
|
prezzo,
|
|
descrizione,
|
|
}: {
|
|
clientSecret: string;
|
|
titolo: string;
|
|
prezzo: number;
|
|
descrizione: string;
|
|
}) {
|
|
return (
|
|
<Elements
|
|
options={{
|
|
appearance: {
|
|
theme: "stripe",
|
|
variables: {
|
|
colorPrimary: "#18181b",
|
|
colorText: "#18181b",
|
|
},
|
|
},
|
|
clientSecret,
|
|
}}
|
|
stripe={stripePromise}
|
|
>
|
|
<PaymentForm descrizione={descrizione} prezzo={prezzo} titolo={titolo} />
|
|
</Elements>
|
|
);
|
|
}
|
|
|
|
const PaymentForm = ({
|
|
titolo,
|
|
prezzo,
|
|
descrizione,
|
|
}: {
|
|
titolo: string;
|
|
prezzo: number;
|
|
descrizione: string;
|
|
}) => {
|
|
const stripe = useStripe();
|
|
const elements = useElements();
|
|
|
|
const [message, setMessage] = useState<string | null>(null);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
|
|
e.preventDefault();
|
|
if (!stripe || !elements) {
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
const { error } = await stripe.confirmPayment({
|
|
confirmParams: {
|
|
return_url: `${env.NEXT_PUBLIC_BASE_URL}/servizio/pagamento-status`,
|
|
},
|
|
elements,
|
|
});
|
|
if (error.type === "card_error" || error.type === "validation_error") {
|
|
setMessage(error.message || "An unexpected error occurred.");
|
|
} else {
|
|
setMessage("An unexpected error occurred.");
|
|
}
|
|
setIsLoading(false);
|
|
};
|
|
|
|
return (
|
|
<Card className="flex w-full flex-col justify-between text-left">
|
|
<CardHeader>
|
|
<CardTitle>
|
|
<p className="text-2xl">{titolo}</p>
|
|
</CardTitle>
|
|
<p>{descrizione}</p>
|
|
<span>
|
|
<span className="font-bold text-3xl">
|
|
{formatCurrency(prezzo / 100)}
|
|
</span>{" "}
|
|
<span className="font-normal text-base sm:text-sm">
|
|
{t.pricing_cmp.risultati_iva}
|
|
</span>
|
|
</span>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<form className="space-y-5" id="payment-form" onSubmit={handleSubmit}>
|
|
<PaymentElement
|
|
id="payment-element"
|
|
options={{ layout: "accordion" }}
|
|
/>
|
|
|
|
<LoadingButton
|
|
aria-label="Procedi al pagamento"
|
|
className="w-full"
|
|
disabled={isLoading || !stripe || !elements}
|
|
loading={isLoading || !stripe || !elements}
|
|
type="submit"
|
|
>
|
|
{t.procedi}
|
|
</LoadingButton>
|
|
{message && <div id="payment-message">{message}</div>}
|
|
</form>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
};
|