97 lines
3.1 KiB
TypeScript
97 lines
3.1 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useRef } from "react";
|
||
import Link from "next/link";
|
||
import { Button } from "@/components/ui";
|
||
|
||
export function UpgradePrompt({
|
||
open,
|
||
title = "ارتقا لازم است",
|
||
message,
|
||
requiredPlan,
|
||
requiredCapability,
|
||
requiredBundle,
|
||
onClose,
|
||
billingHref = "/billing",
|
||
}: {
|
||
open: boolean;
|
||
title?: string;
|
||
message?: string;
|
||
requiredPlan?: string | null;
|
||
requiredCapability?: string | null;
|
||
requiredBundle?: string | null;
|
||
onClose?: () => void;
|
||
billingHref?: string;
|
||
}) {
|
||
const closeRef = useRef<HTMLButtonElement>(null);
|
||
|
||
useEffect(() => {
|
||
if (!open) return;
|
||
closeRef.current?.focus();
|
||
const onKey = (e: KeyboardEvent) => {
|
||
if (e.key === "Escape") onClose?.();
|
||
};
|
||
window.addEventListener("keydown", onKey);
|
||
return () => window.removeEventListener("keydown", onKey);
|
||
}, [open, onClose]);
|
||
|
||
if (!open) return null;
|
||
return (
|
||
<div
|
||
className="fixed inset-0 z-[80] flex items-center justify-center bg-black/40 p-4"
|
||
role="presentation"
|
||
onClick={() => onClose?.()}
|
||
>
|
||
<div
|
||
role="dialog"
|
||
aria-modal="true"
|
||
aria-labelledby="upgrade-prompt-title"
|
||
className="w-full max-w-md rounded-2xl bg-white p-6 shadow-xl dark:bg-gray-950"
|
||
onClick={(e) => e.stopPropagation()}
|
||
>
|
||
<h3 id="upgrade-prompt-title" className="text-lg font-bold text-secondary dark:text-gray-100">
|
||
{title}
|
||
</h3>
|
||
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
||
{message || "این قابلیت در پلن فعلی یا دوره آزمایشی محدود شده است."}
|
||
</p>
|
||
<ul className="mt-3 space-y-1 text-xs text-gray-500">
|
||
{requiredPlan ? (
|
||
<li>
|
||
پلن لازم: <span className="font-mono text-secondary dark:text-gray-200">{requiredPlan}</span>
|
||
</li>
|
||
) : null}
|
||
{requiredCapability ? (
|
||
<li>
|
||
قابلیت لازم:{" "}
|
||
<span className="font-mono text-secondary dark:text-gray-200">{requiredCapability}</span>
|
||
</li>
|
||
) : null}
|
||
{requiredBundle ? (
|
||
<li>
|
||
باندل لازم:{" "}
|
||
<span className="font-mono text-secondary dark:text-gray-200">{requiredBundle}</span>
|
||
</li>
|
||
) : null}
|
||
</ul>
|
||
<p className="mt-3 text-xs text-gray-400">مسیر ارتقا: Billing → انتخاب پلن → فعالسازی</p>
|
||
<div className="mt-6 flex flex-wrap justify-end gap-2">
|
||
{onClose ? (
|
||
<button
|
||
ref={closeRef}
|
||
type="button"
|
||
className="rounded-xl border border-gray-200 px-3 py-2 text-sm dark:border-gray-700"
|
||
onClick={onClose}
|
||
>
|
||
بستن
|
||
</button>
|
||
) : null}
|
||
<Link href={billingHref}>
|
||
<Button size="sm">مشاهده پلنها و ارتقا</Button>
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|