@startsimpli/billing 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +194 -0
- package/dist/index.d.ts +194 -0
- package/dist/index.js +961 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +946 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types/index.d.mts +98 -0
- package/dist/types/index.d.ts +98 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/index.mjs +3 -0
- package/dist/types/index.mjs.map +1 -0
- package/package.json +35 -12
- package/src/components/ManageSubscription.test.tsx +0 -1
- package/src/components/PricingDetailPage.integration.test.tsx +0 -1
- package/src/components/PricingDetailPage.test.tsx +0 -1
- package/src/components/PricingPage.test.tsx +0 -1
- package/src/components/PricingSection.test.tsx +0 -1
- package/src/components/SubscriptionManager.test.tsx +33 -1
- package/src/components/SubscriptionManager.tsx +6 -4
- package/src/components/UpgradeModal.test.tsx +0 -1
- package/src/hooks/BillingProvider.test.tsx +12 -63
- package/src/hooks/BillingProvider.tsx +13 -3
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useCheckout.test.tsx +6 -7
- package/src/hooks/usePortal.test.tsx +2 -3
- package/src/hooks/useSubscription.test.tsx +2 -3
- package/src/hooks/useSuccessSync.ts +48 -0
- package/src/index.ts +4 -1
- package/src/server/index.ts +2 -2
- package/src/server/proxy.ts +60 -1
- package/src/types/index.ts +36 -7
- package/src/utils/api.test.ts +13 -14
- package/src/utils/api.ts +28 -13
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/api.ts","../src/hooks/BillingProvider.tsx","../src/hooks/useProduct.ts","../src/hooks/useCheckout.ts","../src/hooks/usePortal.ts","../src/hooks/useSubscription.ts","../src/hooks/useSuccessSync.ts","../src/components/PricingPage.tsx","../src/components/PricingSection.tsx","../src/components/UpgradeModal.tsx","../src/components/PricingDetailPage.tsx","../src/components/ManageSubscription.tsx","../src/components/SubscriptionManager.tsx"],"names":["createContext","useMemo","jsx","useContext","useState","useCallback","useEffect","jsxs","useRef"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * API client for billing endpoints.\n */\n\nimport type {\n BillingConfig,\n BillingProduct,\n CachedSubscriptionState,\n CheckoutResult,\n FreeSubscriptionResult,\n PortalResult,\n SubscriptionInfo,\n} from \"../types\";\n\nexport class BillingApiClient {\n private config: BillingConfig;\n\n constructor(config: BillingConfig) {\n this.config = config;\n }\n\n private get fetcher() {\n return this.config.fetcher ?? fetch.bind(globalThis);\n }\n\n private get headers(): HeadersInit {\n return { \"Content-Type\": \"application/json\" };\n }\n\n /** Fetch a public billing product by slug. */\n async getProduct(slug: string): Promise<BillingProduct> {\n const url = `${this.config.apiBaseUrl}/billing/products/${slug}/`;\n const resp = await this.fetcher(url, {\n headers: this.headers,\n });\n if (!resp.ok) {\n throw new Error(`Failed to fetch product \"${slug}\": ${resp.status}`);\n }\n return resp.json();\n }\n\n /** Create a checkout session for an offer. */\n async createCheckout(params: {\n offerId: string;\n successUrl: string;\n cancelUrl: string;\n quantity?: number;\n }): Promise<CheckoutResult> {\n const url = `${this.config.apiBaseUrl}/billing/offer-checkout/`;\n const resp = await this.fetcher(url, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify({\n offer_id: params.offerId,\n success_url: params.successUrl,\n cancel_url: params.cancelUrl,\n quantity: params.quantity ?? 1,\n }),\n });\n if (!resp.ok) {\n const data = await resp.json().catch(() => ({}));\n throw new Error(\n data.detail ?? `Checkout failed: ${resp.status}`\n );\n }\n return resp.json();\n }\n\n /** Subscribe to a free offer (no billing provider). */\n async subscribeFree(offerId: string): Promise<FreeSubscriptionResult> {\n const url = `${this.config.apiBaseUrl}/billing/subscribe-free/`;\n const resp = await this.fetcher(url, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify({ offer_id: offerId }),\n });\n if (!resp.ok) {\n const data = await resp.json().catch(() => ({}));\n throw new Error(data.detail ?? `Free signup failed: ${resp.status}`);\n }\n return resp.json();\n }\n\n /** Create a customer portal session. */\n async createPortal(returnUrl: string): Promise<PortalResult> {\n const url = `${this.config.apiBaseUrl}/billing/offer-portal/`;\n const resp = await this.fetcher(url, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify({ return_url: returnUrl }),\n });\n if (!resp.ok) {\n const data = await resp.json().catch(() => ({}));\n throw new Error(\n data.detail ?? `Portal session failed: ${resp.status}`\n );\n }\n return resp.json();\n }\n\n /**\n * Eagerly sync subscription state after Stripe checkout redirect.\n * Call this from your success_url page to avoid waiting for the webhook.\n */\n async successSync(): Promise<CachedSubscriptionState | null> {\n const url = `${this.config.apiBaseUrl}/billing/success-sync/`;\n const resp = await this.fetcher(url, {\n method: \"POST\",\n headers: this.headers,\n });\n if (resp.status === 404) {\n return null;\n }\n if (!resp.ok) {\n const data = await resp.json().catch(() => ({}));\n throw new Error(data.detail ?? `Success sync failed: ${resp.status}`);\n }\n return resp.json();\n }\n\n /** Get current user's subscription. */\n async getSubscription(): Promise<SubscriptionInfo | null> {\n const url = `${this.config.apiBaseUrl}/billing/subscription/current/`;\n const resp = await this.fetcher(url, {\n headers: this.headers,\n });\n if (resp.status === 404) {\n return null; // No active subscription\n }\n if (!resp.ok) {\n const data = await resp.json().catch(() => ({}));\n throw new Error(\n data.detail ?? `Failed to fetch subscription: ${resp.status}`\n );\n }\n return resp.json();\n }\n}\n","/**\n * BillingProvider — React context for @simpli/billing.\n *\n * Wrap your app (or a section of it) with <BillingProvider> to configure\n * the API connection. All billing hooks read from this context.\n *\n * Auth is handled server-side by your Next.js Route Handlers — you do NOT\n * pass any tokens here. Set apiBaseUrl to the billing proxy prefix in your app.\n *\n * Usage:\n * <BillingProvider apiBaseUrl=\"/api\">\n * <PricingPage productId=\"crochet-patterns\" />\n * </BillingProvider>\n *\n * Your Next.js app must expose these Route Handlers under apiBaseUrl:\n * GET /api/billing/products/[slug]/ → public (no auth needed)\n * POST /api/billing/offer-checkout/ → calls fetchDjangoServiceToken + proxyBillingRequest\n * POST /api/billing/subscribe-free/ → same\n * POST /api/billing/offer-portal/ → same\n * GET /api/billing/subscription/current/ → same\n */\n\nimport React, { createContext, useContext, useMemo } from \"react\";\nimport type { BillingConfig } from \"../types\";\nimport { BillingApiClient } from \"../utils/api\";\n\ninterface BillingContextValue {\n client: BillingApiClient;\n config: BillingConfig;\n}\n\nconst BillingContext = createContext<BillingContextValue | null>(null);\n\nexport interface BillingProviderProps extends BillingConfig {\n children: React.ReactNode;\n}\n\nexport function BillingProvider({\n children,\n ...config\n}: BillingProviderProps) {\n const value = useMemo(() => {\n const client = new BillingApiClient(config);\n return { client, config };\n }, [config.apiBaseUrl]);\n\n return (\n <BillingContext.Provider value={value}>\n {children}\n </BillingContext.Provider>\n );\n}\n\nexport function useBillingContext(): BillingContextValue {\n const ctx = useContext(BillingContext);\n if (!ctx) {\n throw new Error(\n \"useBillingContext must be used within a <BillingProvider>\"\n );\n }\n return ctx;\n}\n","/**\n * useProduct — Fetch a BillingProduct by slug.\n *\n * Usage:\n * const { product, loading, error } = useProduct(\"raise-simpli\");\n */\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { BillingProduct } from \"../types\";\nimport { useBillingContext } from \"./BillingProvider\";\n\ninterface UseProductResult {\n product: BillingProduct | null;\n loading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\nexport function useProduct(slug: string): UseProductResult {\n const { client } = useBillingContext();\n const [product, setProduct] = useState<BillingProduct | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchProduct = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const data = await client.getProduct(slug);\n setProduct(data);\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n } finally {\n setLoading(false);\n }\n }, [client, slug]);\n\n useEffect(() => {\n fetchProduct();\n }, [fetchProduct]);\n\n return { product, loading, error, refetch: fetchProduct };\n}\n","/**\n * useCheckout — Create a checkout session and redirect, or subscribe to a free offer.\n *\n * Usage:\n * const { checkout, subscribeFree, loading, error } = useCheckout();\n * // For paid offers:\n * await checkout({ offerId, successUrl, cancelUrl });\n * // For free offers:\n * await subscribeFree(offerId);\n */\n\nimport { useCallback, useState } from \"react\";\nimport type { CheckoutResult, FreeSubscriptionResult } from \"../types\";\nimport { useBillingContext } from \"./BillingProvider\";\n\ninterface UseCheckoutResult {\n checkout: (params: {\n offerId: string;\n successUrl: string;\n cancelUrl: string;\n quantity?: number;\n }) => Promise<CheckoutResult>;\n subscribeFree: (offerId: string) => Promise<FreeSubscriptionResult>;\n loading: boolean;\n error: Error | null;\n}\n\nexport function useCheckout(): UseCheckoutResult {\n const { client } = useBillingContext();\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const checkout = useCallback(\n async (params: {\n offerId: string;\n successUrl: string;\n cancelUrl: string;\n quantity?: number;\n }) => {\n setLoading(true);\n setError(null);\n try {\n const result = await client.createCheckout(params);\n return result;\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n setError(err);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [client]\n );\n\n const subscribeFree = useCallback(\n async (offerId: string) => {\n setLoading(true);\n setError(null);\n try {\n const result = await client.subscribeFree(offerId);\n return result;\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n setError(err);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [client]\n );\n\n return { checkout, subscribeFree, loading, error };\n}\n","/**\n * usePortal — Create a customer portal session and redirect.\n *\n * Usage:\n * const { openPortal, loading, error } = usePortal();\n * await openPortal(\"https://app.example.com/settings\");\n */\n\nimport { useCallback, useState } from \"react\";\nimport type { PortalResult } from \"../types\";\nimport { useBillingContext } from \"./BillingProvider\";\n\ninterface UsePortalResult {\n openPortal: (returnUrl: string) => Promise<PortalResult>;\n loading: boolean;\n error: Error | null;\n}\n\nexport function usePortal(): UsePortalResult {\n const { client } = useBillingContext();\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const openPortal = useCallback(\n async (returnUrl: string) => {\n setLoading(true);\n setError(null);\n try {\n const result = await client.createPortal(returnUrl);\n return result;\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n setError(err);\n throw err;\n } finally {\n setLoading(false);\n }\n },\n [client]\n );\n\n return { openPortal, loading, error };\n}\n","/**\n * useSubscription — Fetch current user's active subscription.\n */\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { SubscriptionInfo } from \"../types\";\nimport { useBillingContext } from \"./BillingProvider\";\n\ninterface UseSubscriptionResult {\n subscription: SubscriptionInfo | null;\n loading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\nexport function useSubscription(): UseSubscriptionResult {\n const { client } = useBillingContext();\n const [subscription, setSubscription] = useState<SubscriptionInfo | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchSubscription = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const data = await client.getSubscription();\n setSubscription(data);\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n } finally {\n setLoading(false);\n }\n }, [client]);\n\n useEffect(() => {\n fetchSubscription();\n }, [fetchSubscription]);\n\n return { subscription, loading, error, refetch: fetchSubscription };\n}\n","/**\n * useSuccessSync — Eagerly sync subscription state after Stripe checkout.\n *\n * Call this from your checkout success page. It POSTs to the success-sync\n * endpoint which fetches the latest subscription from Stripe and populates\n * the Redis cache + DB, so the UI can show subscription status immediately\n * instead of waiting for the webhook.\n *\n * Usage:\n * const { sync, data, loading, error } = useSuccessSync();\n * useEffect(() => { sync(); }, [sync]);\n */\n\nimport { useCallback, useState } from \"react\";\nimport type { CachedSubscriptionState } from \"../types\";\nimport { useBillingContext } from \"./BillingProvider\";\n\ninterface UseSuccessSyncResult {\n sync: () => Promise<CachedSubscriptionState | null>;\n data: CachedSubscriptionState | null;\n loading: boolean;\n error: Error | null;\n}\n\nexport function useSuccessSync(): UseSuccessSyncResult {\n const { client } = useBillingContext();\n const [data, setData] = useState<CachedSubscriptionState | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const sync = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await client.successSync();\n setData(result);\n return result;\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n setError(err);\n throw err;\n } finally {\n setLoading(false);\n }\n }, [client]);\n\n return { sync, data, loading, error };\n}\n","/**\n * PricingPage — Drop-in pricing page component.\n *\n * Fetches product data by slug and renders pricing cards for each active offer.\n * Uses standard Tailwind utility classes for styling.\n *\n * Usage:\n * <PricingPage productId=\"raise-simpli\" onSelectOffer={(offer) => checkout(offer)} />\n */\n\nimport React from \"react\";\nimport { useProduct } from \"../hooks/useProduct\";\nimport type { ProductOffer } from \"../types\";\n\nexport interface PricingPageProps {\n /** Product slug (e.g., \"raise-simpli\") */\n productId: string;\n\n /** Called when user clicks an offer's CTA button */\n onSelectOffer?: (offer: ProductOffer) => void;\n}\n\nexport function PricingPage({ productId, onSelectOffer }: PricingPageProps) {\n const { product, loading, error } = useProduct(productId);\n\n if (loading) {\n return (\n <div data-testid=\"pricing-loading\" className=\"text-center py-16 text-gray-500\">\n Loading pricing...\n </div>\n );\n }\n\n if (error || !product) {\n return (\n <div data-testid=\"pricing-error\" className=\"text-center py-16 text-red-600\">\n Unable to load pricing. Please try again.\n </div>\n );\n }\n\n if (product.offers.length === 0) {\n return (\n <div className=\"text-center py-16 text-gray-500\">\n No pricing plans available at this time.\n </div>\n );\n }\n\n return (\n <div data-testid=\"pricing-page\" className=\"max-w-5xl mx-auto px-6 py-12\">\n <div className=\"text-center mb-12\">\n <h1 className=\"text-4xl font-extrabold tracking-tight text-gray-900 mb-3\">\n {product.name}\n </h1>\n <p className=\"text-lg text-gray-500 max-w-xl mx-auto\">\n {product.description}\n </p>\n </div>\n\n <div data-testid=\"pricing-cards\" className=\"flex flex-wrap justify-center gap-6 items-stretch\">\n {product.offers.map((offer) => (\n <PricingCard\n key={offer.id}\n offer={offer}\n onSelect={onSelectOffer}\n />\n ))}\n </div>\n </div>\n );\n}\n\ninterface PricingCardProps {\n offer: ProductOffer;\n onSelect?: (offer: ProductOffer) => void;\n}\n\nfunction PricingCard({ offer, onSelect }: PricingCardProps) {\n const isFeatured = offer.is_featured;\n\n return (\n <div\n data-testid={`pricing-card-${offer.slug}`}\n data-featured={isFeatured || undefined}\n className={`\n flex flex-col relative rounded-2xl p-8 w-full max-w-sm flex-1 min-w-[280px]\n ${isFeatured\n ? \"border-2 border-blue-600 shadow-lg scale-[1.03]\"\n : \"border border-gray-200 bg-white shadow-sm\"\n }\n `}\n >\n {isFeatured && (\n <span className=\"absolute -top-3.5 left-1/2 -translate-x-1/2 bg-blue-600 text-white text-xs font-bold px-4 py-1 rounded-full uppercase tracking-wide whitespace-nowrap\">\n Most Popular\n </span>\n )}\n\n <h2 className=\"text-xl font-bold text-gray-900 mb-4\">{offer.name}</h2>\n\n <div className=\"mb-2\">\n {offer.is_free ? (\n <span className=\"text-4xl font-extrabold text-gray-900\">Free</span>\n ) : (\n <span>\n <span className=\"text-4xl font-extrabold text-gray-900\">\n ${Math.floor(parseFloat(offer.unit_price) || 0)}\n </span>\n <span className=\"text-base text-gray-500 ml-1\"> {offer.interval_display}</span>\n </span>\n )}\n </div>\n\n {offer.trial_days > 0 && (\n <span\n data-testid=\"trial-badge\"\n className=\"inline-block bg-blue-50 text-blue-700 text-sm font-semibold px-3 py-1 rounded-lg mb-5 w-fit\"\n >\n {offer.trial_days}-day free trial\n </span>\n )}\n\n <ul className=\"list-none p-0 m-0 mb-7 flex-1 space-y-0\">\n {offer.features.map((feature) => (\n <li\n key={feature.key}\n className=\"flex items-center gap-2.5 py-2.5 text-sm text-gray-600 border-b border-gray-100 last:border-0\"\n >\n <svg className=\"w-4 h-4 text-green-500 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n <span>{feature.name}</span>\n </li>\n ))}\n </ul>\n\n <button\n onClick={() => onSelect?.(offer)}\n data-testid={`cta-${offer.slug}`}\n className={`\n w-full py-3.5 px-6 text-base font-bold rounded-xl cursor-pointer transition-colors\n ${isFeatured\n ? \"bg-blue-600 text-white hover:bg-blue-700\"\n : \"bg-gray-100 text-gray-800 hover:bg-gray-200\"\n }\n `}\n >\n {offer.cta_text}\n </button>\n </div>\n );\n}\n","/**\n * PricingSection — Compact horizontal pricing section for embedding in landing pages.\n *\n * Renders pricing cards in a horizontal row with limited feature display.\n * Uses standard Tailwind utility classes for styling.\n *\n * Usage:\n * <PricingSection productId=\"raise-simpli\" maxFeatures={3} onSelectOffer={handleSelect} />\n */\n\nimport React from \"react\";\nimport { useProduct } from \"../hooks/useProduct\";\nimport type { ProductOffer } from \"../types\";\n\nexport interface PricingSectionProps {\n /** Product slug (e.g., \"raise-simpli\") */\n productId: string;\n\n /** Called when user clicks an offer's CTA button */\n onSelectOffer?: (offer: ProductOffer) => void;\n\n /** Maximum number of features to display per card (default 4) */\n maxFeatures?: number;\n}\n\nexport function PricingSection({\n productId,\n onSelectOffer,\n maxFeatures = 4,\n}: PricingSectionProps) {\n const { product, loading, error } = useProduct(productId);\n\n if (loading) {\n return (\n <div className=\"text-center py-10 text-gray-500\">\n Loading pricing...\n </div>\n );\n }\n\n if (error || !product) {\n return (\n <div className=\"text-center py-10 text-red-600\">\n Unable to load pricing. Please try again.\n </div>\n );\n }\n\n if (product.offers.length === 0) {\n return (\n <div className=\"text-center py-16 text-gray-500\">\n No pricing plans available at this time.\n </div>\n );\n }\n\n return (\n <div data-testid=\"pricing-section\" className=\"w-full px-4 py-8\">\n <div className=\"flex flex-row flex-wrap justify-center gap-4 items-stretch\">\n {product.offers.map((offer) => (\n <SectionCard\n key={offer.id}\n offer={offer}\n onSelect={onSelectOffer}\n maxFeatures={maxFeatures}\n />\n ))}\n </div>\n </div>\n );\n}\n\ninterface SectionCardProps {\n offer: ProductOffer;\n onSelect?: (offer: ProductOffer) => void;\n maxFeatures: number;\n}\n\nfunction SectionCard({ offer, onSelect, maxFeatures }: SectionCardProps) {\n const isFeatured = offer.is_featured;\n const visibleFeatures = offer.features.slice(0, maxFeatures);\n\n return (\n <div\n data-testid={`section-card-${offer.slug}`}\n data-featured={isFeatured ? \"true\" : undefined}\n className={`\n flex flex-col relative rounded-xl p-6 flex-1 min-w-[220px] max-w-xs\n ${isFeatured\n ? \"border-2 border-blue-600 shadow-md\"\n : \"border border-gray-200 bg-white shadow-sm\"\n }\n `}\n >\n <h3 className=\"text-lg font-bold text-gray-900 mb-2\">{offer.name}</h3>\n\n <div className=\"mb-2\">\n {offer.is_free ? (\n <span className=\"text-2xl font-extrabold text-gray-900\">Free</span>\n ) : (\n <span>\n <span className=\"text-2xl font-extrabold text-gray-900\">\n ${Math.floor(parseFloat(offer.unit_price) || 0)}\n </span>\n <span className=\"text-sm text-gray-500 ml-1\"> {offer.interval_display}</span>\n </span>\n )}\n </div>\n\n {offer.trial_days > 0 && (\n <span\n data-testid=\"trial-badge\"\n className=\"inline-block bg-blue-50 text-blue-700 text-xs font-semibold px-2 py-0.5 rounded-md mb-3 w-fit\"\n >\n {offer.trial_days}-day free trial\n </span>\n )}\n\n <ul className=\"list-none p-0 m-0 mb-4 flex-1 space-y-0\">\n {visibleFeatures.map((feature) => (\n <li\n key={feature.key}\n className=\"flex items-center gap-2 py-1.5 text-sm text-gray-600 border-b border-gray-100 last:border-0\"\n >\n <svg\n className=\"w-3.5 h-3.5 text-green-500 shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n <span>{feature.name}</span>\n </li>\n ))}\n </ul>\n\n <button\n onClick={() => onSelect?.(offer)}\n data-testid={`section-cta-${offer.slug}`}\n className={`\n w-full py-2.5 px-4 text-sm font-bold rounded-lg cursor-pointer transition-colors\n ${isFeatured\n ? \"bg-blue-600 text-white hover:bg-blue-700\"\n : \"bg-gray-100 text-gray-800 hover:bg-gray-200\"\n }\n `}\n >\n {offer.cta_text}\n </button>\n </div>\n );\n}\n","/**\n * UpgradeModal — Modal dialog showing upgrade options with checkout.\n *\n * Usage:\n * <UpgradeModal\n * productId=\"raise-simpli\"\n * open={showModal}\n * onClose={() => setShowModal(false)}\n * />\n */\n\nimport React, { useEffect, useRef, useCallback } from \"react\";\nimport { useProduct } from \"../hooks/useProduct\";\nimport type { ProductOffer } from \"../types\";\n\nexport interface UpgradeModalProps {\n productId: string;\n open: boolean;\n onClose: () => void;\n onSelectOffer?: (offer: ProductOffer) => void;\n}\n\nexport function UpgradeModal({\n productId,\n open,\n onClose,\n onSelectOffer,\n}: UpgradeModalProps) {\n const { product, loading, error } = useProduct(productId);\n const modalRef = useRef<HTMLDivElement>(null);\n const previousFocusRef = useRef<HTMLElement | null>(null);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onClose();\n return;\n }\n\n if (e.key === \"Tab\" && modalRef.current) {\n const focusable = modalRef.current.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])'\n );\n if (focusable.length === 0) return;\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n },\n [onClose]\n );\n\n useEffect(() => {\n if (open) {\n previousFocusRef.current = document.activeElement as HTMLElement | null;\n\n // Focus the first focusable element after render\n const timer = setTimeout(() => {\n if (modalRef.current) {\n const focusable = modalRef.current.querySelector<HTMLElement>(\n 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])'\n );\n focusable?.focus();\n }\n }, 0);\n\n return () => clearTimeout(timer);\n } else {\n previousFocusRef.current?.focus();\n }\n }, [open]);\n\n if (!open) {\n return null;\n }\n\n return (\n <div\n data-testid=\"upgrade-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"upgrade-modal-title\"\n onKeyDown={handleKeyDown}\n ref={modalRef}\n className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-6\"\n >\n <div className=\"bg-white rounded-2xl max-w-3xl w-full max-h-[90vh] overflow-auto p-8 relative\">\n <button\n onClick={onClose}\n aria-label=\"Close\"\n className=\"absolute top-4 right-4 text-gray-400 hover:text-gray-600 text-2xl leading-none p-1 cursor-pointer\"\n >\n ×\n </button>\n\n <h2 id=\"upgrade-modal-title\" className=\"text-2xl font-extrabold text-gray-900 text-center mb-8\">\n Choose a plan\n </h2>\n\n {loading && (\n <div className=\"text-center py-8 text-gray-500\">Loading...</div>\n )}\n\n {error && (\n <div className=\"text-center py-8 text-red-600\">\n Unable to load pricing. Please try again.\n </div>\n )}\n\n {product && (\n <div data-testid=\"upgrade-offers\" className=\"flex flex-wrap justify-center gap-5\">\n {product.offers.map((offer) => {\n const isFeatured = offer.is_featured;\n return (\n <div\n key={offer.id}\n data-testid={`upgrade-offer-${offer.slug}`}\n className={`\n flex flex-col flex-1 min-w-[200px] max-w-[240px] rounded-xl p-6\n ${isFeatured\n ? \"border-2 border-blue-600 shadow-md\"\n : \"border border-gray-200\"\n }\n `}\n >\n <h3 className=\"text-lg font-bold text-gray-900 mb-2\">{offer.name}</h3>\n\n <div className=\"mb-2\">\n {offer.is_free ? (\n <span aria-label=\"Free\">\n <span aria-hidden=\"true\" className=\"text-2xl font-extrabold text-gray-900\">Free</span>\n </span>\n ) : (\n <span aria-label={`${Math.floor(parseFloat(offer.unit_price) || 0)} dollars ${offer.interval_display}`}>\n <span aria-hidden=\"true\" className=\"text-2xl font-extrabold text-gray-900\">\n ${Math.floor(parseFloat(offer.unit_price) || 0)}\n </span>\n <span aria-hidden=\"true\" className=\"text-sm text-gray-500\"> {offer.interval_display}</span>\n </span>\n )}\n </div>\n\n {offer.trial_days > 0 && (\n <span className=\"inline-block bg-blue-50 text-blue-700 text-xs font-semibold px-2.5 py-0.5 rounded-md mb-3 w-fit\">\n {offer.trial_days}-day free trial\n </span>\n )}\n\n {offer.features.length > 0 && (\n <ul className=\"list-none p-0 m-0 mb-4 flex-1 space-y-0\">\n {offer.features.map((f) => (\n <li key={f.key} className=\"flex items-center gap-1.5 py-1 text-sm text-gray-600\">\n <svg className=\"w-3.5 h-3.5 text-green-500 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {f.name}\n </li>\n ))}\n </ul>\n )}\n\n <button\n onClick={() => onSelectOffer?.(offer)}\n data-testid={`upgrade-cta-${offer.slug}`}\n className={`\n w-full py-2.5 px-4 text-sm font-bold rounded-lg cursor-pointer transition-colors\n ${isFeatured\n ? \"bg-blue-600 text-white hover:bg-blue-700\"\n : \"bg-gray-100 text-gray-800 hover:bg-gray-200\"\n }\n `}\n >\n {offer.cta_text}\n </button>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n","/**\n * PricingDetailPage — Full dedicated pricing page with plan comparison and feature table.\n *\n * Renders all offer cards with complete feature lists, plus a comparison table\n * showing features across all plans.\n *\n * Usage:\n * <PricingDetailPage productId=\"raise-simpli\" showComparison={true} />\n */\n\nimport React from \"react\";\nimport { useProduct } from \"../hooks/useProduct\";\nimport type { ProductOffer, OfferFeature } from \"../types\";\n\nexport interface PricingDetailPageProps {\n /** Product slug (e.g., \"raise-simpli\") */\n productId: string;\n\n /** Called when user clicks an offer's CTA button */\n onSelectOffer?: (offer: ProductOffer) => void;\n\n /** Whether to show the feature comparison table (defaults to true) */\n showComparison?: boolean;\n}\n\nexport function PricingDetailPage({\n productId,\n onSelectOffer,\n showComparison = true,\n}: PricingDetailPageProps) {\n const { product, loading, error } = useProduct(productId);\n\n if (loading) {\n return (\n <div className=\"text-center py-16 text-gray-500\">\n Loading pricing...\n </div>\n );\n }\n\n if (error || !product) {\n return (\n <div className=\"text-center py-16 text-red-600\">\n Unable to load pricing. Please try again.\n </div>\n );\n }\n\n if (product.offers.length === 0) {\n return (\n <div className=\"text-center py-16 text-gray-500\">\n No pricing plans available at this time.\n </div>\n );\n }\n\n // Extract all unique feature keys across all offers (preserving order)\n const allFeatureKeys: string[] = [];\n const featureNameMap: Record<string, string> = {};\n for (const offer of product.offers) {\n for (const feature of offer.features) {\n if (!allFeatureKeys.includes(feature.key)) {\n allFeatureKeys.push(feature.key);\n featureNameMap[feature.key] = feature.name;\n }\n }\n }\n\n return (\n <div data-testid=\"pricing-detail\" className=\"max-w-6xl mx-auto px-6 py-12\">\n <div className=\"text-center mb-12\">\n <h1 className=\"text-4xl font-extrabold tracking-tight text-gray-900 mb-3\">\n {product.name}\n </h1>\n <p className=\"text-lg text-gray-500 max-w-xl mx-auto\">\n {product.description}\n </p>\n </div>\n\n <div className=\"flex flex-wrap justify-center gap-6 items-stretch mb-16\">\n {product.offers.map((offer) => (\n <DetailCard\n key={offer.id}\n offer={offer}\n onSelect={onSelectOffer}\n />\n ))}\n </div>\n\n {showComparison && (\n <ComparisonTable\n offers={product.offers}\n featureKeys={allFeatureKeys}\n featureNameMap={featureNameMap}\n />\n )}\n </div>\n );\n}\n\ninterface DetailCardProps {\n offer: ProductOffer;\n onSelect?: (offer: ProductOffer) => void;\n}\n\nfunction DetailCard({ offer, onSelect }: DetailCardProps) {\n const isFeatured = offer.is_featured;\n\n return (\n <div\n data-testid={`detail-card-${offer.slug}`}\n className={`\n flex flex-col relative rounded-2xl p-8 w-full max-w-sm flex-1 min-w-[280px]\n ${isFeatured\n ? \"border-2 border-blue-600 shadow-lg scale-[1.03]\"\n : \"border border-gray-200 bg-white shadow-sm\"\n }\n `}\n >\n {isFeatured && (\n <span className=\"absolute -top-3.5 left-1/2 -translate-x-1/2 bg-blue-600 text-white text-xs font-bold px-4 py-1 rounded-full uppercase tracking-wide whitespace-nowrap\">\n Most Popular\n </span>\n )}\n\n <h2 className=\"text-xl font-bold text-gray-900 mb-4\">{offer.name}</h2>\n\n <div className=\"mb-2\">\n {offer.is_free ? (\n <span aria-label=\"Free\">\n <span aria-hidden=\"true\" className=\"text-4xl font-extrabold text-gray-900\">Free</span>\n </span>\n ) : (\n <span aria-label={`${Math.floor(parseFloat(offer.unit_price) || 0)} dollars ${offer.interval_display}`}>\n <span aria-hidden=\"true\" className=\"text-4xl font-extrabold text-gray-900\">\n ${Math.floor(parseFloat(offer.unit_price) || 0)}\n </span>\n <span aria-hidden=\"true\" className=\"text-base text-gray-500 ml-1\"> {offer.interval_display}</span>\n </span>\n )}\n </div>\n\n {offer.trial_days > 0 && (\n <span className=\"inline-block bg-blue-50 text-blue-700 text-sm font-semibold px-3 py-1 rounded-lg mb-5 w-fit\">\n {offer.trial_days}-day free trial\n </span>\n )}\n\n <ul className=\"list-none p-0 m-0 mb-7 flex-1 space-y-0\">\n {offer.features.map((feature) => (\n <li\n key={feature.key}\n className=\"flex items-center gap-2.5 py-2.5 text-sm text-gray-600 border-b border-gray-100 last:border-0\"\n >\n <FeatureIcon value={feature.value} />\n <span>{feature.name}</span>\n {typeof feature.value !== \"boolean\" && feature.value !== null && feature.value !== undefined && (\n <span className=\"ml-auto text-gray-900 font-medium\">\n {feature.value === -1 ? \"Unlimited\" : String(feature.value)}\n </span>\n )}\n </li>\n ))}\n </ul>\n\n <button\n onClick={() => onSelect?.(offer)}\n data-testid={`detail-cta-${offer.slug}`}\n className={`\n w-full py-3.5 px-6 text-base font-bold rounded-xl cursor-pointer transition-colors\n ${isFeatured\n ? \"bg-blue-600 text-white hover:bg-blue-700\"\n : \"bg-gray-100 text-gray-800 hover:bg-gray-200\"\n }\n `}\n >\n {offer.cta_text}\n </button>\n </div>\n );\n}\n\nfunction FeatureIcon({ value }: { value: unknown }) {\n if (value === false) {\n return (\n <svg role=\"img\" aria-label=\"Not included\" className=\"w-4 h-4 text-gray-300 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n );\n }\n return (\n <svg role=\"img\" aria-label=\"Included\" className=\"w-4 h-4 text-green-500 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n );\n}\n\ninterface ComparisonTableProps {\n offers: ProductOffer[];\n featureKeys: string[];\n featureNameMap: Record<string, string>;\n}\n\nfunction ComparisonTable({ offers, featureKeys, featureNameMap }: ComparisonTableProps) {\n // Build a lookup: offer slug -> feature key -> feature\n const featureLookup: Record<string, Record<string, OfferFeature>> = {};\n for (const offer of offers) {\n featureLookup[offer.slug] = {};\n for (const feature of offer.features) {\n featureLookup[offer.slug][feature.key] = feature;\n }\n }\n\n return (\n <div data-testid=\"comparison-table\" className=\"overflow-x-auto\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"border-b-2 border-gray-200\">\n <th scope=\"col\" className=\"text-left py-4 px-4 text-sm font-semibold text-gray-500 uppercase tracking-wider\">\n Feature\n </th>\n {offers.map((offer) => (\n <th\n key={offer.slug}\n scope=\"col\"\n aria-label={offer.name}\n className=\"text-center py-4 px-4 text-sm font-semibold text-gray-900\"\n >\n <span aria-hidden=\"true\">{offer.name}</span>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {featureKeys.map((key) => (\n <tr\n key={key}\n data-testid={`comparison-row-${key}`}\n className=\"border-b border-gray-100\"\n >\n <td scope=\"row\" className=\"py-3 px-4 text-sm text-gray-700\">\n {featureNameMap[key]}\n </td>\n {offers.map((offer) => {\n const feature = featureLookup[offer.slug]?.[key];\n return (\n <td\n key={offer.slug}\n className=\"text-center py-3 px-4 text-sm\"\n >\n <ComparisonCellValue feature={feature} />\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction ComparisonCellValue({ feature }: { feature?: OfferFeature }) {\n if (!feature) {\n return <span className=\"text-gray-300\">—</span>;\n }\n\n const { value } = feature;\n\n if (value === true) {\n return (\n <svg role=\"img\" aria-label=\"Included\" className=\"w-5 h-5 text-green-500 mx-auto\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n );\n }\n\n if (value === false) {\n return (\n <svg role=\"img\" aria-label=\"Not included\" className=\"w-5 h-5 text-gray-300 mx-auto\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n );\n }\n\n if (typeof value === \"string\") {\n return <span className=\"text-gray-900 font-medium\">{value}</span>;\n }\n\n if (typeof value === \"number\") {\n return <span className=\"text-gray-900 font-medium\">{value === -1 ? \"Unlimited\" : value}</span>;\n }\n\n return <span className=\"text-gray-500\">{String(value)}</span>;\n}\n","/**\n * ManageSubscription — Button that opens the billing provider's customer portal.\n *\n * Usage:\n * <ManageSubscription returnUrl=\"https://app.example.com/settings\" />\n */\n\nimport React from \"react\";\nimport { usePortal } from \"../hooks/usePortal\";\n\nexport interface ManageSubscriptionProps {\n returnUrl: string;\n buttonText?: string;\n}\n\nexport function ManageSubscription({\n returnUrl,\n buttonText = \"Manage Billing\",\n}: ManageSubscriptionProps) {\n const { openPortal, loading, error } = usePortal();\n\n const handleClick = async () => {\n try {\n const result = await openPortal(returnUrl);\n window.location.href = result.url;\n } catch {\n // Error is captured by the hook's error state\n }\n };\n\n return (\n <div data-testid=\"manage-subscription\">\n <button\n onClick={handleClick}\n disabled={loading}\n className={`\n inline-flex items-center gap-2 px-6 py-3 text-sm font-semibold rounded-xl border transition-colors\n ${loading\n ? \"bg-gray-50 text-gray-400 border-gray-200 cursor-not-allowed\"\n : \"bg-white text-gray-700 border-gray-200 hover:bg-gray-50 hover:border-gray-300 cursor-pointer\"\n }\n `}\n >\n {loading ? \"Loading...\" : buttonText}\n </button>\n {error && (\n <p data-testid=\"portal-error\" className=\"mt-2 text-sm text-red-600\">\n {error.message}\n </p>\n )}\n </div>\n );\n}\n","/**\n * SubscriptionManager — Interactive subscription management widget.\n *\n * Displays the current subscription, available plan options for\n * upgrade/downgrade, and a portal button for billing management.\n *\n * Usage:\n * <SubscriptionManager\n * productId=\"raise-simpli\"\n * returnUrl=\"https://app.example.com/settings\"\n * onPlanChange={(offer) => console.log(offer)}\n * />\n */\n\nimport React from \"react\";\nimport { useSubscription } from \"../hooks/useSubscription\";\nimport { useProduct } from \"../hooks/useProduct\";\nimport { usePortal } from \"../hooks/usePortal\";\nimport type { ProductOffer } from \"../types\";\n\nexport interface SubscriptionManagerProps {\n /** Product slug (e.g., \"raise-simpli\") */\n productId: string;\n\n /** URL to return to after portal session */\n returnUrl: string;\n\n /** Called when user clicks an available plan's CTA button */\n onPlanChange?: (offer: ProductOffer) => void;\n\n /** Optional status message to display (e.g., after checkout redirect) */\n statusMessage?: \"success\" | \"cancelled\" | \"activating\" | null;\n}\n\nfunction formatDate(iso: string): string {\n const d = new Date(iso);\n const year = d.getUTCFullYear();\n const month = String(d.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(d.getUTCDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\nfunction StatusBadge({ status, trialEnd }: { status: string; trialEnd: string | null }) {\n let className = \"inline-block text-xs font-semibold px-3 py-1 rounded-full \";\n switch (status) {\n case \"active\":\n className += \"bg-green-50 text-green-700\";\n break;\n case \"trialing\":\n className += \"bg-blue-50 text-blue-700\";\n break;\n case \"past_due\":\n className += \"bg-yellow-50 text-yellow-700 warning\";\n break;\n case \"cancelled\":\n className += \"bg-gray-100 text-gray-600\";\n break;\n case \"incomplete\":\n className += \"bg-yellow-50 text-yellow-700\";\n break;\n case \"incomplete_expired\":\n className += \"bg-red-50 text-red-700\";\n break;\n case \"unpaid\":\n className += \"bg-red-50 text-red-700\";\n break;\n default:\n className += \"bg-gray-100 text-gray-600\";\n }\n\n const labelMap: Record<string, string> = {\n active: \"Active\",\n trialing: \"Trialing\",\n past_due: \"Past due\",\n cancelled: \"Cancelled\",\n incomplete: \"Incomplete\",\n incomplete_expired: \"Expired\",\n unpaid: \"Unpaid\",\n };\n\n const readableStatus = labelMap[status] ?? status;\n\n return (\n <span data-testid=\"plan-status\" role=\"status\" aria-label={`Subscription status: ${readableStatus}`} className={className}>\n {labelMap[status] ?? status}\n {status === \"trialing\" && trialEnd && (\n <span className=\"ml-1\">until {formatDate(trialEnd)}</span>\n )}\n </span>\n );\n}\n\nexport function SubscriptionManager({\n productId,\n returnUrl,\n onPlanChange,\n statusMessage,\n}: SubscriptionManagerProps) {\n const { subscription, loading: subLoading, error: subError } = useSubscription();\n const { product, loading: productLoading } = useProduct(productId);\n const { openPortal, loading: portalLoading } = usePortal();\n\n const loading = subLoading || productLoading;\n\n if (loading) {\n return (\n <div data-testid=\"subscription-manager\" className=\"max-w-3xl mx-auto px-6 py-12\">\n <p className=\"text-center text-gray-500\">Loading subscription...</p>\n </div>\n );\n }\n\n if (subError) {\n return (\n <div data-testid=\"subscription-manager\" className=\"max-w-3xl mx-auto px-6 py-12\">\n <div className=\"text-center text-red-600\">\n <p className=\"font-semibold\">Something went wrong</p>\n <p className=\"text-sm mt-1\">{subError.message}</p>\n </div>\n </div>\n );\n }\n\n const currentOfferId = subscription?.offer?.id ?? null;\n const availableOffers = product?.offers.filter((o) => o.id !== currentOfferId) ?? [];\n\n const handlePortalClick = async () => {\n try {\n const result = await openPortal(returnUrl);\n window.location.href = result.url;\n } catch {\n // Error captured by hook state\n }\n };\n\n return (\n <div data-testid=\"subscription-manager\" className=\"max-w-3xl mx-auto px-6 py-12 space-y-8\">\n {statusMessage === \"success\" && (\n <div data-testid=\"status-banner-success\" className=\"rounded-xl bg-green-50 border border-green-200 p-4 flex items-center gap-3\">\n <svg className=\"w-5 h-5 text-green-600 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n <p className=\"text-sm font-medium text-green-800\">Subscription activated successfully!</p>\n </div>\n )}\n\n {statusMessage === \"cancelled\" && (\n <div data-testid=\"status-banner-cancelled\" className=\"rounded-xl bg-gray-50 border border-gray-200 p-4 flex items-center gap-3\">\n <svg className=\"w-5 h-5 text-gray-500 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n <p className=\"text-sm font-medium text-gray-700\">Checkout was cancelled. You can try again whenever you're ready.</p>\n </div>\n )}\n\n {statusMessage === \"activating\" && (\n <div data-testid=\"status-banner-activating\" className=\"rounded-xl bg-blue-50 border border-blue-200 p-4 flex items-center gap-3\">\n <svg className=\"w-5 h-5 text-blue-600 shrink-0 animate-spin\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"></path>\n </svg>\n <p className=\"text-sm font-medium text-blue-800\">Activating your subscription...</p>\n </div>\n )}\n\n {subscription ? (\n <div data-testid=\"current-plan\" className=\"rounded-2xl border border-gray-200 bg-white shadow-sm p-8\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-xl font-bold text-gray-900\">{subscription.offer.name}</h2>\n <StatusBadge status={subscription.status} trialEnd={subscription.trial_end} />\n </div>\n\n <div className=\"mb-4\">\n {subscription.offer.is_free ? (\n <span aria-label=\"Free\">\n <span aria-hidden=\"true\" className=\"text-3xl font-extrabold text-gray-900\">Free</span>\n </span>\n ) : (\n <span aria-label={`${Math.floor(parseFloat(subscription.offer.unit_price) || 0)} dollars ${subscription.offer.interval_display}`}>\n <span aria-hidden=\"true\" className=\"text-3xl font-extrabold text-gray-900\">\n ${Math.floor(parseFloat(subscription.offer.unit_price) || 0)}\n </span>\n <span aria-hidden=\"true\" className=\"text-base text-gray-500 ml-1\">\n {subscription.offer.interval_display}\n </span>\n </span>\n )}\n </div>\n\n {subscription.current_period_start && subscription.current_period_end && (\n <p className=\"text-sm text-gray-500\">\n Billing period: {formatDate(subscription.current_period_start)} to{\" \"}\n {formatDate(subscription.current_period_end)}\n </p>\n )}\n </div>\n ) : (\n <div className=\"text-center py-8\">\n <p className=\"text-lg text-gray-600\">No active subscription</p>\n <p className=\"text-sm text-gray-400 mt-1\">Choose a plan below to get started.</p>\n </div>\n )}\n\n {availableOffers.length > 0 && (\n <div data-testid=\"available-plans\" className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold text-gray-900\">\n {subscription ? \"Change Plan\" : \"Available Plans\"}\n </h3>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {availableOffers.map((offer) => (\n <div\n key={offer.id}\n className={`rounded-xl border p-6 ${\n offer.is_featured\n ? \"border-blue-600 shadow-md\"\n : \"border-gray-200 bg-white shadow-sm\"\n }`}\n >\n <h4 className=\"text-lg font-bold text-gray-900 mb-2\">{offer.name}</h4>\n <div className=\"mb-3\">\n {offer.is_free ? (\n <span aria-label=\"Free\">\n <span aria-hidden=\"true\" className=\"text-2xl font-extrabold text-gray-900\">Free</span>\n </span>\n ) : (\n <span aria-label={`${Math.floor(parseFloat(offer.unit_price) || 0)} dollars ${offer.interval_display}`}>\n <span aria-hidden=\"true\" className=\"text-2xl font-extrabold text-gray-900\">\n ${Math.floor(parseFloat(offer.unit_price) || 0)}\n </span>\n <span aria-hidden=\"true\" className=\"text-sm text-gray-500 ml-1\">\n {offer.interval_display}\n </span>\n </span>\n )}\n </div>\n <button\n data-testid={`upgrade-cta-${offer.slug}`}\n onClick={() => onPlanChange?.(offer)}\n className={`w-full py-2.5 px-4 text-sm font-bold rounded-xl cursor-pointer transition-colors ${\n offer.is_featured\n ? \"bg-blue-600 text-white hover:bg-blue-700\"\n : \"bg-gray-100 text-gray-800 hover:bg-gray-200\"\n }`}\n >\n {offer.cta_text}\n </button>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {subscription && subscription.status !== \"cancelled\" && (\n <div className=\"pt-4 border-t border-gray-100\">\n <button\n data-testid=\"portal-button\"\n onClick={handlePortalClick}\n disabled={portalLoading}\n aria-busy={portalLoading || undefined}\n className={`inline-flex items-center gap-2 px-6 py-3 text-sm font-semibold rounded-xl border transition-colors ${\n portalLoading\n ? \"bg-gray-50 text-gray-400 border-gray-200 cursor-not-allowed\"\n : \"bg-white text-gray-700 border-gray-200 hover:bg-gray-50 hover:border-gray-300 cursor-pointer\"\n }`}\n >\n {portalLoading ? \"Loading...\" : \"Manage Billing\"}\n </button>\n </div>\n )}\n </div>\n );\n}\n"]}
|