Pricing Page and Subscription Guard
This commit is contained in:
101
frontend/src/hooks/useSubscriptionGuard.ts
Normal file
101
frontend/src/hooks/useSubscriptionGuard.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSubscription } from '../contexts/SubscriptionContext';
|
||||
|
||||
export interface SubscriptionGuardOptions {
|
||||
requireActive?: boolean;
|
||||
redirectToPricing?: boolean;
|
||||
showModal?: boolean;
|
||||
fallbackComponent?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const useSubscriptionGuard = (options: SubscriptionGuardOptions = {}) => {
|
||||
const { subscription, loading, error, checkSubscription } = useSubscription();
|
||||
const [isGuarded, setIsGuarded] = useState(false);
|
||||
|
||||
const {
|
||||
requireActive = true,
|
||||
redirectToPricing = true,
|
||||
showModal = true,
|
||||
fallbackComponent
|
||||
} = options;
|
||||
|
||||
useEffect(() => {
|
||||
if (loading || !subscription) return;
|
||||
|
||||
if (requireActive && !subscription.active) {
|
||||
setIsGuarded(true);
|
||||
|
||||
if (redirectToPricing) {
|
||||
// Redirect to pricing page or show upgrade modal
|
||||
console.warn('Subscription not active, redirecting to pricing');
|
||||
// For now, just log - in a real app you'd redirect or show modal
|
||||
}
|
||||
|
||||
if (showModal && !fallbackComponent) {
|
||||
// Show upgrade modal
|
||||
console.warn('Showing subscription upgrade modal');
|
||||
}
|
||||
} else {
|
||||
setIsGuarded(false);
|
||||
}
|
||||
}, [subscription, loading, requireActive, redirectToPricing, showModal, fallbackComponent]);
|
||||
|
||||
const checkFeatureAccess = (feature: string, currentUsage?: number, limit?: number): boolean => {
|
||||
if (!subscription?.active) return false;
|
||||
|
||||
if (limit === undefined) {
|
||||
// If no limit specified, assume unlimited or check other conditions
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentUsage === undefined) {
|
||||
// Can't check usage if we don't have current usage data
|
||||
return true; // Allow for now, middleware will enforce
|
||||
}
|
||||
|
||||
return currentUsage < limit;
|
||||
};
|
||||
|
||||
const getRemainingUsage = (feature: string): number => {
|
||||
if (!subscription?.active) return 0;
|
||||
|
||||
// This would typically come from usage tracking
|
||||
// For now, return the limit as remaining usage
|
||||
switch (feature) {
|
||||
case 'gemini_calls':
|
||||
return subscription.limits.gemini_calls;
|
||||
case 'openai_calls':
|
||||
return subscription.limits.openai_calls;
|
||||
case 'anthropic_calls':
|
||||
return subscription.limits.anthropic_calls;
|
||||
case 'mistral_calls':
|
||||
return subscription.limits.mistral_calls;
|
||||
case 'tavily_calls':
|
||||
return subscription.limits.tavily_calls;
|
||||
case 'serper_calls':
|
||||
return subscription.limits.serper_calls;
|
||||
case 'metaphor_calls':
|
||||
return subscription.limits.metaphor_calls;
|
||||
case 'firecrawl_calls':
|
||||
return subscription.limits.firecrawl_calls;
|
||||
case 'stability_calls':
|
||||
return subscription.limits.stability_calls;
|
||||
case 'monthly_cost':
|
||||
return subscription.limits.monthly_cost;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
subscription,
|
||||
loading,
|
||||
error,
|
||||
isGuarded,
|
||||
checkSubscription,
|
||||
checkFeatureAccess,
|
||||
getRemainingUsage,
|
||||
canUseFeature: (feature: string) => checkFeatureAccess(feature),
|
||||
isFeatureAvailable: (feature: string) => subscription?.active && checkFeatureAccess(feature),
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user