Compare commits

..

1 Commits

Author SHA1 Message Date
ي
a0efdb5001 Fix onboarding loading gate for inactive subscriptions 2026-03-31 07:33:17 +05:30
3 changed files with 52 additions and 84 deletions

View File

@@ -280,10 +280,11 @@ const InitialRouteHandler: React.FC = () => {
);
}
// Loading state - only wait for onboarding init, not subscription check
// Subscription check is non-blocking and happens in background
const waitingForOnboardingInit = loading || !data;
if (loading || waitingForOnboardingInit) {
// Only block on onboarding initialization once we know the user has an active subscription.
// This allows no-subscription/inactive flows to continue even when onboarding data is still null.
const isActiveSubscriber = Boolean(subscription && subscription.active && subscription.plan !== 'none');
const waitingForOnboardingInit = isActiveSubscriber && (loading || !data);
if (waitingForOnboardingInit) {
return (
<Box
display="flex"
@@ -295,7 +296,7 @@ const InitialRouteHandler: React.FC = () => {
>
<CircularProgress size={60} />
<Typography variant="h6" color="textSecondary">
{subscriptionLoading ? 'Checking subscription...' : 'Preparing your workspace...'}
Preparing your workspace...
</Typography>
</Box>
);

View File

@@ -52,27 +52,6 @@ export interface SubscriptionPlan {
}
const PricingPage: React.FC = () => {
const pricingMode = (process.env.REACT_APP_PRICING_MODE || 'alpha').toLowerCase();
const isAlphaMode = pricingMode === 'alpha';
const tierPolicyByMode: Record<string, { visible: string[]; selectable: string[]; unavailableLabels: Record<string, string> }> = {
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<SubscriptionPlan[]>([]);
const [loading, setLoading] = useState(true);
@@ -97,11 +76,9 @@ const PricingPage: React.FC = () => {
try {
setLoading(true);
const response = await apiClient.get('/api/subscription/plans');
// Filter out legacy alpha-named plans and enforce tier visibility policy.
// Filter out any alpha plans and ensure we only show the 4 main tiers
const filteredPlans = response.data.data.plans.filter(
(plan: SubscriptionPlan) =>
!plan.name.toLowerCase().includes('alpha') &&
activeTierPolicy.visible.includes(plan.tier)
(plan: SubscriptionPlan) => !plan.name.toLowerCase().includes('alpha')
);
setPlans(filteredPlans);
} catch (err) {
@@ -134,13 +111,10 @@ const PricingPage: React.FC = () => {
return;
}
if (!activeTierPolicy.selectable.includes(plan.tier)) {
// For alpha testing, only allow Free and Basic plans (Pro features not ready)
if (plan.tier !== 'free' && plan.tier !== 'basic') {
console.error('[PricingPage] Plan tier not available:', plan.tier);
setError(
isAlphaMode
? 'This plan is not available during alpha testing'
: 'This plan is currently not available for self-serve checkout'
);
setError('This plan is not available for alpha testing');
return;
}
@@ -377,8 +351,6 @@ 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}
@@ -420,48 +392,42 @@ const PricingPage: React.FC = () => {
}}>
<Typography variant="h6" component="h2" gutterBottom sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Warning sx={{ color: 'warning.main' }} />
{isAlphaMode ? 'Alpha Testing Subscription' : 'Confirm Subscription'}
Alpha Testing Subscription
</Typography>
{isAlphaMode ? (
<>
<Alert severity="warning" sx={{ mb: 2 }}>
<Typography variant="body2" sx={{ fontWeight: 600, mb: 0.5 }}>
⚠️ Alpha Testing Mode - No Payment Required
</Typography>
<Typography variant="caption" sx={{ display: 'block' }}>
Payment integration is coming soon. For now, subscriptions are activated without charge.
</Typography>
</Alert>
<Typography variant="body1" sx={{ mb: 2 }}>
Thank you for participating in our alpha testing! We&apos;re crediting this plan to your account.
</Typography>
<Box sx={{
p: 2,
mb: 3,
bgcolor: 'info.lighter',
borderRadius: 1,
border: '1px solid',
borderColor: 'info.light'
}}>
<Typography variant="body2" color="info.dark">
<strong>Coming in Production:</strong>
</Typography>
<Typography variant="caption" color="info.dark" sx={{ display: 'block', mt: 0.5 }}>
• Secure Stripe/PayPal payment processing<br />
• Automatic renewal management<br />
• Payment verification & receipts<br />
• Upgrade/downgrade options
</Typography>
</Box>
</>
) : (
<Typography variant="body1" sx={{ mb: 3 }}>
Please confirm to continue with your selected subscription plan.
{/* Alpha Testing Notice */}
<Alert severity="warning" sx={{ mb: 2 }}>
<Typography variant="body2" sx={{ fontWeight: 600, mb: 0.5 }}>
⚠️ Alpha Testing Mode - No Payment Required
</Typography>
)}
<Typography variant="caption" sx={{ display: 'block' }}>
Payment integration is coming soon. For now, subscriptions are activated without charge.
</Typography>
</Alert>
<Typography variant="body1" sx={{ mb: 2 }}>
Thank you for participating in our alpha testing! We're crediting the Basic plan ($29 value) to your account.
</Typography>
{/* TODO: Payment Integration Notice */}
<Box sx={{
p: 2,
mb: 3,
bgcolor: 'info.lighter',
borderRadius: 1,
border: '1px solid',
borderColor: 'info.light'
}}>
<Typography variant="body2" color="info.dark">
<strong>Coming in Production:</strong>
</Typography>
<Typography variant="caption" color="info.dark" sx={{ display: 'block', mt: 0.5 }}>
Secure Stripe/PayPal payment processing<br />
Automatic renewal management<br />
Payment verification & receipts<br />
Upgrade/downgrade options
</Typography>
</Box>
{/* Note: Current behavior allows renewal without payment verification */}
{/* This is intentional for alpha testing but will be secured in production */}

View File

@@ -69,8 +69,6 @@ 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;
@@ -81,8 +79,6 @@ const PlanCard: React.FC<PlanCardProps> = ({
yearlyBilling,
selectedPlanId,
subscribing,
canSelectPlan,
unavailableLabel,
onSelectPlan,
onSubscribe,
openKnowMoreModal,
@@ -913,9 +909,13 @@ const PlanCard: React.FC<PlanCardProps> = ({
</CardContent>
<CardActions sx={{ justifyContent: 'center', pb: 3, flexDirection: 'column', gap: 1 }}>
{!canSelectPlan ? (
{plan.tier === 'pro' ? (
<Button variant="outlined" size="large" fullWidth disabled sx={{ mb: 1 }}>
{unavailableLabel || 'Unavailable'}
Coming Soon
</Button>
) : plan.tier === 'enterprise' ? (
<Button variant="outlined" size="large" fullWidth disabled sx={{ mb: 1 }}>
Contact Sales
</Button>
) : (
<>
@@ -951,3 +951,4 @@ const PlanCard: React.FC<PlanCardProps> = ({
};
export default PlanCard;