Spaces:
Sleeping
Sleeping
File size: 3,074 Bytes
fbf3514 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | "use client";
import { useState } from "react";
import { CreditCard, Loader2 } from "lucide-react";
// Razorpay checkout script loader
function loadRazorpayScript(): Promise<boolean> {
return new Promise((resolve) => {
if (typeof window !== "undefined" && (window as any).Razorpay) {
resolve(true);
return;
}
const script = document.createElement("script");
script.src = "https://checkout.razorpay.com/v1/checkout.js";
script.onload = () => resolve(true);
script.onerror = () => resolve(false);
document.body.appendChild(script);
});
}
interface Props {
plan: "pro" | "team";
label?: string;
className?: string;
userName?: string;
userEmail?: string;
}
export function CheckoutButton({ plan, label, className, userName, userEmail }: Props) {
const [loading, setLoading] = useState(false);
async function handleCheckout() {
setLoading(true);
try {
// Load Razorpay script
const loaded = await loadRazorpayScript();
if (!loaded) throw new Error("Failed to load Razorpay");
// Create subscription server-side
const res = await fetch("/api/subscribe/create", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ plan }),
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.error || "Subscription failed");
}
const { subscription_id } = await res.json();
// Open Razorpay checkout
const rzp = new (window as any).Razorpay({
key: process.env.NEXT_PUBLIC_RAZORPAY_KEY_ID,
subscription_id,
name: "ClauseGuard",
description: plan === "pro" ? "Pro — ₹999/mo" : "Team — ₹3,999/mo",
handler: async (response: any) => {
// Verify payment server-side
const verifyRes = await fetch("/api/subscribe/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(response),
});
if (verifyRes.ok) {
window.location.href = "/dashboard-pages/dashboard?subscribed=true";
}
},
prefill: {
name: userName || "",
email: userEmail || "",
},
theme: { color: "#18181b" },
modal: {
ondismiss: () => setLoading(false),
},
});
rzp.on("payment.failed", () => setLoading(false));
rzp.open();
} catch (error) {
console.error("Checkout error:", error);
setLoading(false);
}
}
return (
<button
onClick={handleCheckout}
disabled={loading}
className={className || "w-full flex items-center justify-center gap-2 bg-zinc-900 text-white py-2.5 rounded-lg text-sm font-medium hover:bg-zinc-800 disabled:opacity-40 transition-colors"}
>
{loading ? (
<><Loader2 className="w-4 h-4 animate-spin" /> Processing...</>
) : (
<><CreditCard className="w-4 h-4" /> {label || `Subscribe to ${plan}`}</>
)}
</button>
);
}
|