Files
ALwrity/frontend/src/hooks/useSubscriptionGuard.ts
2025-10-13 10:25:57 +05:30

102 lines
3.1 KiB
TypeScript

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),
};
};