import { useId } from 'react'; import { getCatalogEntry, requiredPlanLabelForFeature } from '../lib/licensing'; import { __, sprintf } from '../lib/i18n'; import { sikshyaPricingUrl } from '../lib/upgradeUrl'; import type { SikshyaReactConfig } from '../types'; import { PREMIUM_HERO_GRADIENT_CLASS, PREMIUM_LOCK_CARD_CLASS, PremiumGatedSurface, } from './PremiumGatedSurface'; type Props = { config: SikshyaReactConfig; featureId: string; /** Used when the catalog row is missing */ featureTitle: string; description: string; }; type ValueRow = { title: string; detail: string; }; /** * Build a 4-row value grid from the catalog description. If the description has * multiple sentences we use them; otherwise we fall back to category-generic * Pro benefits so the grid always feels populated. */ function buildValueRows(fullDescription: string): ValueRow[] { const sentences = fullDescription .trim() .split(/(?<=[.!?])\s+/) .map((s) => s.trim()) .filter((s) => s.length > 8); const generic: ValueRow[] = [ { title: __('Full feature access', 'sikshya'), detail: __('Use this module without any limits.', 'sikshya'), }, { title: __('Priority support', 'sikshya'), detail: __('Direct email support from our team.', 'sikshya'), }, { title: __('Regular updates', 'sikshya'), detail: __('New features and improvements as they ship.', 'sikshya'), }, { title: __('Self-hosted, no SaaS', 'sikshya'), detail: __('Runs on your WordPress — your data stays with you.', 'sikshya'), }, ]; const rows: ValueRow[] = []; for (let i = 0; i < Math.min(2, sentences.length); i++) { const s = sentences[i]; const words = s.split(/\s+/); const titleWords = words.slice(0, Math.min(6, Math.max(3, Math.floor(words.length / 3)))); const titleText = titleWords.join(' ').replace(/[.,;:]$/, ''); const detailText = words.slice(titleWords.length).join(' ').replace(/^[,;:]\s*/, '') || s; rows.push({ title: titleText, detail: detailText }); } for (const g of generic) { if (rows.length >= 4) break; if (!rows.some((r) => r.title.toLowerCase() === g.title.toLowerCase())) { rows.push(g); } } return rows.slice(0, 4); } /** * Plan-gate upgrade screen — feels like a real upgrade pitch. Brand-gradient * hero header (purple-led, since "Upgrade" surfaces use the logo accent purple * across the product), value-grid of 4 highlights, and a strong purple CTA. */ export function PlanUpgradeOverlay(props: Props) { const { config, featureId, featureTitle, description } = props; const brandName = config.branding?.pluginName?.trim() || 'Sikshya'; const entry = getCatalogEntry(config, featureId); const title = entry?.label || featureTitle; const body = (entry?.description && entry.description.trim()) || description; const plan = requiredPlanLabelForFeature(config, featureId); // Both upgrade CTAs route to the canonical Sikshya LMS pricing page with // UTM tags so the campaign analytics on mantrabrain.com can distinguish // primary "Upgrade to {Plan}" clicks from secondary "See pricing" clicks // and attribute them back to the specific feature that triggered the gate. const upgradeHref = sikshyaPricingUrl('upgrade-cta', featureId); const seePlansHref = sikshyaPricingUrl('see-plans', featureId); const titleId = useId(); const descId = useId(); const valueRows = buildValueRows(body); return (
{/* Hero — purple-led gradient (logo accent → darker accent → navy edge) */}
{/* Subtle decorative radials */}
{/* Lock + Pro badge */}
{sprintf(__('%1$s Pro · %2$s', 'sikshya'), brandName, plan)}
{/* Title — smaller, like the earlier version */}

{sprintf(__('Unlock %s', 'sikshya'), title)}

{body}

{/* Value grid */}

{__('What you unlock', 'sikshya')}

{valueRows.map((row, i) => (
{row.title}
{row.detail}
))}
{/* Action band — purple "Upgrade to {plan}" CTA */}

{__('14-day refund · Cancel anytime · Existing data stays exactly as it is', 'sikshya')}

); }