mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-26 14:56:39 +00:00
show required tier in paid features alert
This commit is contained in:
@@ -1963,6 +1963,12 @@
|
|||||||
"orgAuthNoAccount": "Don't have an account?",
|
"orgAuthNoAccount": "Don't have an account?",
|
||||||
"subscriptionRequiredToUse": "A subscription is required to use this feature.",
|
"subscriptionRequiredToUse": "A subscription is required to use this feature.",
|
||||||
"mustUpgradeToUse": "You must upgrade your subscription to use this feature.",
|
"mustUpgradeToUse": "You must upgrade your subscription to use this feature.",
|
||||||
|
"subscriptionRequiredTierToUse": "This feature requires <tierLink>{tier}</tierLink> or higher.",
|
||||||
|
"upgradeToTierToUse": "Upgrade to <tierLink>{tier}</tierLink> or higher to use this feature.",
|
||||||
|
"subscriptionTierTier1": "Home",
|
||||||
|
"subscriptionTierTier2": "Team",
|
||||||
|
"subscriptionTierTier3": "Business",
|
||||||
|
"subscriptionTierEnterprise": "Enterprise",
|
||||||
"idpDisabled": "Identity providers are disabled.",
|
"idpDisabled": "Identity providers are disabled.",
|
||||||
"orgAuthPageDisabled": "Organization auth page is disabled.",
|
"orgAuthPageDisabled": "Organization auth page is disabled.",
|
||||||
"domainRestartedDescription": "Domain verification restarted successfully",
|
"domainRestartedDescription": "Domain verification restarted successfully",
|
||||||
|
|||||||
@@ -3,18 +3,55 @@
|
|||||||
import { Card, CardContent } from "@app/components/ui/card";
|
import { Card, CardContent } from "@app/components/ui/card";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { usePaidStatus } from "@app/hooks/usePaidStatus";
|
import { usePaidStatus } from "@app/hooks/usePaidStatus";
|
||||||
import { ExternalLink, KeyRound, Sparkles } from "lucide-react";
|
import { ExternalLink, KeyRound } from "lucide-react";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import { Tier } from "@server/types/Tiers";
|
import { Tier } from "@server/types/Tiers";
|
||||||
|
|
||||||
|
const TIER_ORDER: Tier[] = ["tier1", "tier2", "tier3", "enterprise"];
|
||||||
|
|
||||||
|
const TIER_TRANSLATION_KEYS: Record<Tier, "subscriptionTierTier1" | "subscriptionTierTier2" | "subscriptionTierTier3" | "subscriptionTierEnterprise"> = {
|
||||||
|
tier1: "subscriptionTierTier1",
|
||||||
|
tier2: "subscriptionTierTier2",
|
||||||
|
tier3: "subscriptionTierTier3",
|
||||||
|
enterprise: "subscriptionTierEnterprise"
|
||||||
|
};
|
||||||
|
|
||||||
|
function getRequiredTier(tiers: Tier[]): Tier | null {
|
||||||
|
if (tiers.length === 0) return null;
|
||||||
|
let min: Tier | null = null;
|
||||||
|
for (const tier of tiers) {
|
||||||
|
const idx = TIER_ORDER.indexOf(tier);
|
||||||
|
if (idx === -1) continue;
|
||||||
|
if (min === null || TIER_ORDER.indexOf(min) > idx) {
|
||||||
|
min = tier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
const bannerClassName =
|
const bannerClassName =
|
||||||
"mb-6 border-purple-500/30 bg-linear-to-br from-purple-500/10 via-background to-background overflow-hidden";
|
"mb-6 border-purple-500/30 bg-linear-to-br from-purple-500/10 via-background to-background overflow-hidden";
|
||||||
const bannerContentClassName = "py-3 px-4";
|
const bannerContentClassName = "py-3 px-4";
|
||||||
const bannerRowClassName =
|
const bannerRowClassName =
|
||||||
"flex items-center gap-2.5 text-sm text-muted-foreground";
|
"flex items-center gap-2.5 text-sm text-muted-foreground";
|
||||||
const bannerIconClassName = "size-4 shrink-0 text-purple-500";
|
const bannerIconClassName = "size-4 shrink-0 text-purple-500";
|
||||||
|
const PRICING_URL = "https://pangolin.net/pricing";
|
||||||
|
|
||||||
|
function tierLinkRenderer(chunks: React.ReactNode) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
href={PRICING_URL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-1 font-medium text-purple-600 underline"
|
||||||
|
>
|
||||||
|
{chunks}
|
||||||
|
<ExternalLink className="size-3.5 shrink-0" />
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
tiers: Tier[];
|
tiers: Tier[];
|
||||||
@@ -22,8 +59,10 @@ type Props = {
|
|||||||
|
|
||||||
export function PaidFeaturesAlert({ tiers }: Props) {
|
export function PaidFeaturesAlert({ tiers }: Props) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { hasSaasSubscription, hasEnterpriseLicense, isActive } = usePaidStatus();
|
const { hasSaasSubscription, hasEnterpriseLicense, isActive, subscriptionTier } = usePaidStatus();
|
||||||
const { env } = useEnvContext();
|
const { env } = useEnvContext();
|
||||||
|
const requiredTier = getRequiredTier(tiers);
|
||||||
|
const requiredTierName = requiredTier ? t(TIER_TRANSLATION_KEYS[requiredTier]) : null;
|
||||||
|
|
||||||
if (env.flags.disableEnterpriseFeatures) {
|
if (env.flags.disableEnterpriseFeatures) {
|
||||||
return null;
|
return null;
|
||||||
@@ -36,7 +75,21 @@ export function PaidFeaturesAlert({ tiers }: Props) {
|
|||||||
<CardContent className={bannerContentClassName}>
|
<CardContent className={bannerContentClassName}>
|
||||||
<div className={bannerRowClassName}>
|
<div className={bannerRowClassName}>
|
||||||
<KeyRound className={bannerIconClassName} />
|
<KeyRound className={bannerIconClassName} />
|
||||||
<span>{isActive ? t("mustUpgradeToUse") : t("subscriptionRequiredToUse")}</span>
|
<span>
|
||||||
|
{requiredTierName
|
||||||
|
? isActive
|
||||||
|
? t.rich("upgradeToTierToUse", {
|
||||||
|
tier: requiredTierName,
|
||||||
|
tierLink: tierLinkRenderer
|
||||||
|
})
|
||||||
|
: t.rich("subscriptionRequiredTierToUse", {
|
||||||
|
tier: requiredTierName,
|
||||||
|
tierLink: tierLinkRenderer
|
||||||
|
})
|
||||||
|
: isActive
|
||||||
|
? t("mustUpgradeToUse")
|
||||||
|
: t("subscriptionRequiredToUse")}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user