forked from mrwyndham/fastpocket
129 lines
4.3 KiB
TypeScript
129 lines
4.3 KiB
TypeScript
"use client";
|
|
|
|
import { Price, Product, SourceModal } from "@/types";
|
|
import { createCheckoutSession, isAuthenticated } from "@/app/actions";
|
|
import { toast } from "react-toastify";
|
|
import { useRouter } from "next/navigation";
|
|
import Icon from "@/components/Icons/Icon";
|
|
|
|
export default function PriceCard({
|
|
product,
|
|
isAnnual,
|
|
loading,
|
|
}: {
|
|
product?: Product;
|
|
isAnnual?: boolean;
|
|
loading?: boolean;
|
|
}) {
|
|
const router = useRouter();
|
|
const openSignUpModalOnPriceClick = (price: Price, type: string) => {
|
|
const signUpModal = document.getElementById("sign-up-modal");
|
|
if (!signUpModal) return;
|
|
signUpModal.click();
|
|
};
|
|
const generateCheckoutPage = async (price: Price, type: string) => {
|
|
try {
|
|
const checkoutSessionResponse = await createCheckoutSession(
|
|
price.price_id,
|
|
type
|
|
);
|
|
console.log(checkoutSessionResponse);
|
|
router.push(checkoutSessionResponse.url);
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
toast.error(error.message, {
|
|
position: "bottom-left",
|
|
autoClose: 5000,
|
|
hideProgressBar: false,
|
|
closeOnClick: true,
|
|
pauseOnHover: true,
|
|
draggable: true,
|
|
progress: undefined,
|
|
theme: "colored",
|
|
});
|
|
}
|
|
}
|
|
};
|
|
const submitForm = async (product: Product) => {
|
|
const userIsAuthenticated = await isAuthenticated();
|
|
console.log("userIsAuthenticated", userIsAuthenticated);
|
|
const price = isAnnual ? product.yearlyPrice : product.monthlyPrice;
|
|
console.log("price", price);
|
|
console.log("product.type", product.type);
|
|
localStorage.setItem("price", JSON.stringify(price));
|
|
localStorage.setItem("type", product.type);
|
|
if (userIsAuthenticated) {
|
|
await generateCheckoutPage(price, product.type);
|
|
} else {
|
|
openSignUpModalOnPriceClick(price, product.type);
|
|
}
|
|
};
|
|
return (
|
|
<div
|
|
className={`relative w-64 sm:w-80 bg-base-200 rounded-lg p-6 shadow-lg border border-primary/40 ${
|
|
loading ? "animate-pulse h-[20rem]" : ""
|
|
}`}
|
|
>
|
|
<div className="flex flex-col h-full">
|
|
<div className="mb-12 relative">
|
|
{!loading && (
|
|
<p className="absolute top-[-10px] left-[50%] -translate-x-1/2 font-architects-daughter text-sm text-primary text-center">
|
|
$30 off for the first 5 customers{" "}
|
|
<span className="text-secondary">(4 left)</span>
|
|
</p>
|
|
)}
|
|
|
|
<h1 className="text-center text-3xl font-inter font-bold pt-12 text-base-content ">
|
|
{product?.name}
|
|
</h1>
|
|
<h2 className="text-center pt-4 text-base-content ">
|
|
{product?.description}
|
|
</h2>
|
|
</div>
|
|
<div className="pb-12">
|
|
<ul className="flex flex-col gap-y-3 mx-12">
|
|
{product?.metadata?.benefits?.map((x, i) => (
|
|
<li key={i} className="flex items-center gap-x-4 flex-nowrap">
|
|
<Icon name="CheckmarkCircle24Filled" />
|
|
|
|
<p className="w-40 text-base-content overflow-clip text-ellipsis">
|
|
{x}
|
|
</p>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
<div className="flex flex-col mx-auto mt-auto">
|
|
{!loading && (
|
|
<div className="flex flex-row mx-auto gap-x-2 justify-center items-center mb-2">
|
|
<h1 className="text-base-content text-4xl font-bold">
|
|
$
|
|
{isAnnual
|
|
? (product?.yearlyPrice?.unit_amount ?? 0) / 100
|
|
: (product?.monthlyPrice?.unit_amount ?? 0) / 100}
|
|
</h1>
|
|
{product?.type != "one_time" ? (
|
|
<p className="w-16 leading-5 text-sm text-base-content ">
|
|
per user per {isAnnual ? "year" : "month"}
|
|
</p>
|
|
) : (
|
|
<p className="w-16 leading-5 text-sm text-base-content ">
|
|
One Time
|
|
</p>
|
|
)}
|
|
</div>
|
|
)}
|
|
{product && (
|
|
<button
|
|
onClick={() => submitForm(product)}
|
|
className="btn btn-primary rounded-full bg-gradient-to-r from-primary to-secondary outline-none border-none capitalize"
|
|
>
|
|
Let's go!
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|