lovart3/components/billing/manage-subscription-button.tsx
Your Name 353c3d04ff
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
feat: add billing center and stripe portal management
2026-02-12 12:49:03 +08:00

64 lines
1.5 KiB
TypeScript

"use client";
import { Loader2 } from "lucide-react";
import { useState } from "react";
import { cn } from "@/lib/utils";
export function ManageSubscriptionButton({
className,
}: {
className?: string;
}) {
const [isPending, setIsPending] = useState(false);
async function handleOpenPortal() {
if (isPending) {
return;
}
setIsPending(true);
try {
const response = await fetch("/api/billing/portal", {
method: "POST",
});
const data = (await response.json()) as { error?: string; url?: string };
if (!response.ok || !data.url) {
window.alert(data.error || "打开订阅管理失败,请稍后重试。");
return;
}
window.location.assign(data.url);
} catch (error) {
console.error("[ManageSubscriptionButton] portal error", error);
window.alert("打开订阅管理失败,请稍后重试。");
} finally {
setIsPending(false);
}
}
return (
<button
className={cn(
"inline-flex items-center justify-center gap-2 rounded-xl border border-white/20 px-4 py-2 text-sm text-zinc-100 hover:border-white/40",
isPending && "cursor-not-allowed opacity-70",
className
)}
disabled={isPending}
onClick={handleOpenPortal}
type="button"
>
{isPending ? (
<>
<Loader2 className="h-4 w-4 animate-spin" />
正在跳转...
</>
) : (
"管理订阅"
)}
</button>
);
}