109 lines
2.8 KiB
TypeScript
109 lines
2.8 KiB
TypeScript
import MainButton from "@/components/MainButton";
|
|
import Title from "@/components/Title";
|
|
import routes from "@/routes";
|
|
import { actions } from "@/store";
|
|
import {
|
|
PaymentElement,
|
|
useElements,
|
|
useStripe,
|
|
} from "@stripe/react-stripe-js";
|
|
import { useState } from "react";
|
|
import { useDispatch } from "react-redux";
|
|
import { useNavigate } from "react-router-dom";
|
|
import styles from "./styles.module.css";
|
|
|
|
export type TConfirmType = "payment" | "setup";
|
|
|
|
interface ICheckoutFormProps {
|
|
children?: JSX.Element | null;
|
|
subscriptionReceiptId?: string;
|
|
returnUrl?: string;
|
|
confirmType?: TConfirmType;
|
|
isHide?: boolean;
|
|
}
|
|
|
|
export default function CheckoutForm({
|
|
children,
|
|
subscriptionReceiptId,
|
|
returnUrl,
|
|
confirmType = "payment",
|
|
isHide = false,
|
|
}: ICheckoutFormProps) {
|
|
const stripe = useStripe();
|
|
const elements = useElements();
|
|
const dispatch = useDispatch();
|
|
const navigate = useNavigate();
|
|
|
|
const [message, setMessage] = useState("");
|
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
const [formReady, setFormReady] = useState(false);
|
|
|
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
e.preventDefault();
|
|
|
|
if (!stripe || !elements) {
|
|
return;
|
|
}
|
|
|
|
setIsProcessing(true);
|
|
|
|
try {
|
|
const { error } = await stripe[
|
|
confirmType === "payment" ? "confirmPayment" : "confirmSetup"
|
|
]({
|
|
elements,
|
|
confirmParams: {
|
|
return_url: returnUrl
|
|
? returnUrl
|
|
: `https://${window.location.host}/payment/result/${subscriptionReceiptId}/`,
|
|
},
|
|
});
|
|
if (error) {
|
|
setMessage(error?.message || "Oops! Something went wrong.");
|
|
} else {
|
|
dispatch(actions.status.update("subscribed"));
|
|
navigate(routes.client.paymentSuccess());
|
|
}
|
|
} catch (error) {
|
|
console.log("error -> ", error);
|
|
setMessage("Oops! Something went wrong.");
|
|
} finally {
|
|
setIsProcessing(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<form
|
|
className={`payment-form-stripe ${isHide ? styles.hide : ""}`}
|
|
id="payment-form"
|
|
onSubmit={handleSubmit}
|
|
>
|
|
{children ? children : null}
|
|
<PaymentElement
|
|
options={{
|
|
terms: { card: "never" },
|
|
wallets: {
|
|
googlePay: "never",
|
|
applePay: "never",
|
|
},
|
|
}}
|
|
onReady={() => setFormReady(true)}
|
|
/>
|
|
<MainButton
|
|
color="blue"
|
|
disabled={isProcessing || !formReady}
|
|
id="submit"
|
|
className={styles.button}
|
|
>
|
|
<img src="/lock.svg" alt="Secure" />
|
|
<span id="button-text">{isProcessing ? "Processing..." : "Start"}</span>
|
|
</MainButton>
|
|
{!!message.length && (
|
|
<Title variant="h5" style={{ color: "red" }}>
|
|
{message}
|
|
</Title>
|
|
)}
|
|
</form>
|
|
);
|
|
}
|