"use client"; import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import type { SubscriptionGateState } from "@/lib/polar/current-subscription"; import { PlansModal } from "@/components/billing/plans-modal"; import { getPlanById, getPlanByProductId, type PolarPlan } from "@/lib/polar/plans"; import { useSubscriptionQuery } from "@/lib/hooks/queries/use-subscription-query"; import { useProductsQuery } from "@/lib/hooks/queries/use-products-query"; import { Skeleton } from "@/components/ui/skeleton"; import { usePermissions } from "@/lib/hooks/use-permissions"; import { PERMISSIONS } from "@/lib/auth/permissions"; interface SubscriptionPaywallProps { // No props required - component fetches its own data } export function SubscriptionPaywall({}: SubscriptionPaywallProps = {}) { const router = useRouter(); const { hasPermission, isInitialized: permissionsReady, } = usePermissions(); const hasSubscriptionPermission = hasPermission(PERMISSIONS.ORG_MANAGE); const shouldLoadSubscription = permissionsReady && hasSubscriptionPermission; const [isPlansOpen, setPlansOpen] = useState(false); const { data: state, isLoading, error: subscriptionError, } = useSubscriptionQuery({ enabled: shouldLoadSubscription, }); const { data: products, error: productsError } = useProductsQuery({ enabled: shouldLoadSubscription, }); // Redirect to dashboard if subscription becomes active useEffect(() => { if (state?.isActive) { router.replace("/dashboard"); } }, [state?.isActive, router]); if (permissionsReady && !hasSubscriptionPermission) { return (

Subscription access restricted

You don't have permission to manage subscription or billing settings. Contact your workspace administrator if you believe this is an error.

); } const loadError = subscriptionError ?? productsError; if (shouldLoadSubscription && loadError) { return (

We couldn't load your subscription

{loadError.message || "Please refresh the page or reach out to support."}

); } if (!shouldLoadSubscription || isLoading || !state) { return (
); } // If subscription is active but haven't redirected yet, show loading if (state.isActive) { return (

Redirecting to dashboard...

); } const usage = state.usage; const included = usage?.included ?? 1000; // Default fallback const used = usage?.used ?? 0; const remaining = usage?.remaining ?? included; const plan = resolvePlanFromState(state, products ?? []); const planPrice = plan?.price ?? null; const formattedPrice = planPrice != null ? formatUsd(planPrice) : null; const interval = plan?.interval === "month" ? "per month" : "per billing period"; const contactHref = process.env.NEXT_PUBLIC_CONTACT_EMAIL || process.env.NOTIFICATION_EMAIL || "mailto:info@yourdomain.com"; console.info("[Polar] Rendering SubscriptionPaywall", { isActive: state.isActive, reason: state.reason, status: state.status, included, used, remaining, plan: plan?.id ?? "unknown", planPrice, }); const featureList = buildFeatureList({ includedInvoices: included, plan, }); return (
{plan?.name ?? "Pro Plan"}

Unlock the full AP automation experience

Process invoices faster, eliminate duplicates, and stay ahead of the month-end crunch. Subscribe now to regain access to the dashboard.

{featureList.map((feature) => ( ))}
Talk to sales
); } interface FeatureProps { title: string; description: string; } function Feature({ title, description }: FeatureProps) { return (

{title}

{description}

); } interface UsageItemProps { label: string; value: number; total: number; } function UsageItem({ label, value, total }: UsageItemProps) { const percentage = Math.min(Math.round((value / Math.max(total, 1)) * 100), 100); return (
{label}
{value.toLocaleString()} of {total.toLocaleString()}
); } function resolvePlanFromState(state: SubscriptionGateState, products: PolarPlan[]): PolarPlan | null { if (state.planId) { const byId = getPlanById(products, state.planId); if (byId) { return byId; } } if (state.subscription?.productId) { const bySubscriptionProduct = getPlanByProductId(products, state.subscription.productId); if (bySubscriptionProduct) { return bySubscriptionProduct; } } if (state.productId) { const byProduct = getPlanByProductId(products, state.productId); if (byProduct) { return byProduct; } } return null; } function buildFeatureList({ includedInvoices, plan, }: { includedInvoices: number; plan: PolarPlan | null; }) { const features: Array<{ title: string; description: string }> = [ { title: `${includedInvoices.toLocaleString()} invoices / month included`, description: "Metered usage with overage protection. Track consumption in real time.", }, ]; if (plan?.price != null) { features.push({ title: `${formatUsd(plan.price)} flat subscription`, description: "Predictable billing aligned with your finance team’s needs.", }); } if (plan?.benefits?.length) { for (const benefit of plan.benefits) { features.push({ title: benefit, description: "Included with your current plan.", }); } } else { features.push( { title: "Approvals & anomaly detection", description: "Keep approvers accountable and surface risk before it hits ERP.", }, { title: "Export-ready payments", description: "Generate payment files that drop straight into NetSuite and SAP.", } ); } return features; } function formatUsd(amount: number) { return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: amount % 1 === 0 ? 0 : 2, }).format(amount); }