From d1ff406d0313325ff4fba8e95f087d15dc42ed32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=8A?= Date: Mon, 30 Mar 2026 07:49:56 +0530 Subject: [PATCH] Feature-flag pricing tier availability for alpha/demo modes --- .../src/components/Pricing/PricingPage.tsx | 112 ++++++++++++------ .../Pricing/PricingPage/PlanCard.tsx | 13 +- 2 files changed, 79 insertions(+), 46 deletions(-) diff --git a/frontend/src/components/Pricing/PricingPage.tsx b/frontend/src/components/Pricing/PricingPage.tsx index 80c4d811..eba7770a 100644 --- a/frontend/src/components/Pricing/PricingPage.tsx +++ b/frontend/src/components/Pricing/PricingPage.tsx @@ -52,6 +52,27 @@ export interface SubscriptionPlan { } const PricingPage: React.FC = () => { + const pricingMode = (process.env.REACT_APP_PRICING_MODE || 'alpha').toLowerCase(); + const isAlphaMode = pricingMode === 'alpha'; + const tierPolicyByMode: Record }> = { + alpha: { + visible: ['free', 'basic', 'pro', 'enterprise'], + selectable: ['free', 'basic'], + unavailableLabels: { pro: 'Coming Soon', enterprise: 'Contact Sales' }, + }, + demo: { + visible: ['free', 'basic', 'pro', 'enterprise'], + selectable: ['free', 'basic', 'pro'], + unavailableLabels: { enterprise: 'Contact Sales' }, + }, + production: { + visible: ['free', 'basic', 'pro', 'enterprise'], + selectable: ['free', 'basic', 'pro'], + unavailableLabels: { enterprise: 'Contact Sales' }, + }, + }; + const activeTierPolicy = tierPolicyByMode[pricingMode] || tierPolicyByMode.alpha; + const navigate = useNavigate(); const [plans, setPlans] = useState([]); const [loading, setLoading] = useState(true); @@ -76,9 +97,11 @@ const PricingPage: React.FC = () => { try { setLoading(true); const response = await apiClient.get('/api/subscription/plans'); - // Filter out any alpha plans and ensure we only show the 4 main tiers + // Filter out legacy alpha-named plans and enforce tier visibility policy. const filteredPlans = response.data.data.plans.filter( - (plan: SubscriptionPlan) => !plan.name.toLowerCase().includes('alpha') + (plan: SubscriptionPlan) => + !plan.name.toLowerCase().includes('alpha') && + activeTierPolicy.visible.includes(plan.tier) ); setPlans(filteredPlans); } catch (err) { @@ -111,10 +134,13 @@ const PricingPage: React.FC = () => { return; } - // For alpha testing, only allow Free and Basic plans (Pro features not ready) - if (plan.tier !== 'free' && plan.tier !== 'basic') { + if (!activeTierPolicy.selectable.includes(plan.tier)) { console.error('[PricingPage] Plan tier not available:', plan.tier); - setError('This plan is not available for alpha testing'); + setError( + isAlphaMode + ? 'This plan is not available during alpha testing' + : 'This plan is currently not available for self-serve checkout' + ); return; } @@ -351,6 +377,8 @@ const PricingPage: React.FC = () => { yearlyBilling={yearlyBilling} selectedPlanId={selectedPlan} subscribing={subscribing} + canSelectPlan={activeTierPolicy.selectable.includes(plan.tier)} + unavailableLabel={activeTierPolicy.unavailableLabels[plan.tier]} onSelectPlan={setSelectedPlan} onSubscribe={handleSubscribe} openKnowMoreModal={openKnowMoreModal} @@ -392,42 +420,48 @@ const PricingPage: React.FC = () => { }}> - Alpha Testing Subscription - - - {/* Alpha Testing Notice */} - - - ⚠️ Alpha Testing Mode - No Payment Required - - - Payment integration is coming soon. For now, subscriptions are activated without charge. - - - - - Thank you for participating in our alpha testing! We're crediting the Basic plan ($29 value) to your account. + {isAlphaMode ? 'Alpha Testing Subscription' : 'Confirm Subscription'} - - {/* TODO: Payment Integration Notice */} - - - Coming in Production: - - - • Secure Stripe/PayPal payment processing
- • Automatic renewal management
- • Payment verification & receipts
- • Upgrade/downgrade options + + {isAlphaMode ? ( + <> + + + ⚠️ Alpha Testing Mode - No Payment Required + + + Payment integration is coming soon. For now, subscriptions are activated without charge. + + + + + Thank you for participating in our alpha testing! We're crediting this plan to your account. + + + + + Coming in Production: + + + • Secure Stripe/PayPal payment processing
+ • Automatic renewal management
+ • Payment verification & receipts
+ • Upgrade/downgrade options +
+
+ + ) : ( + + Please confirm to continue with your selected subscription plan. -
+ )} {/* Note: Current behavior allows renewal without payment verification */} {/* This is intentional for alpha testing but will be secured in production */} diff --git a/frontend/src/components/Pricing/PricingPage/PlanCard.tsx b/frontend/src/components/Pricing/PricingPage/PlanCard.tsx index b49a962b..995ae3f6 100644 --- a/frontend/src/components/Pricing/PricingPage/PlanCard.tsx +++ b/frontend/src/components/Pricing/PricingPage/PlanCard.tsx @@ -69,6 +69,8 @@ interface PlanCardProps { yearlyBilling: boolean; selectedPlanId: number | null; subscribing: boolean; + canSelectPlan: boolean; + unavailableLabel?: string; onSelectPlan: (planId: number) => void; onSubscribe: (planId: number) => void; openKnowMoreModal: (title: string, content: React.ReactNode) => void; @@ -79,6 +81,8 @@ const PlanCard: React.FC = ({ yearlyBilling, selectedPlanId, subscribing, + canSelectPlan, + unavailableLabel, onSelectPlan, onSubscribe, openKnowMoreModal, @@ -909,13 +913,9 @@ const PlanCard: React.FC = ({ - {plan.tier === 'pro' ? ( + {!canSelectPlan ? ( - ) : plan.tier === 'enterprise' ? ( - ) : ( <> @@ -951,4 +951,3 @@ const PlanCard: React.FC = ({ }; export default PlanCard; -