Add Stripe payment integration for AI subscriptions
Implement subscription-based AI access with 250 generations/month at $5/month or $50/year. Changes: - Backend: Stripe service, payment routes, webhook handlers, generation tracking - Frontend: Upgrade page with pricing, payment success/cancel pages, UI prompts - Database: Add subscription fields to users, payments table, migrations - Config: Stripe env vars to .env.example, docker-compose.prod.yml, PRODUCTION.md - Tests: Payment route tests, component tests, subscription hook tests Users without AI access see upgrade prompts; subscribers see remaining generation count.
This commit is contained in:
parent
3c54a0f4d9
commit
2e12edc249
22 changed files with 2866 additions and 21 deletions
|
|
@ -16,9 +16,18 @@ export const applyColorScheme = (schemeId: string) => {
|
|||
document.documentElement.style.setProperty('--theme-primary-darker', scheme.primaryDarker);
|
||||
};
|
||||
|
||||
interface SubscriptionInfo {
|
||||
hasAccess: boolean;
|
||||
accessType: 'group' | 'subscription' | 'none';
|
||||
generationCount: number | null;
|
||||
generationLimit: number | null;
|
||||
generationsRemaining: number | null;
|
||||
}
|
||||
|
||||
interface UseUserPreferencesReturn {
|
||||
preferences: UserPreferences;
|
||||
hasAIAccess: boolean;
|
||||
subscription: SubscriptionInfo | null;
|
||||
loading: boolean;
|
||||
saving: boolean;
|
||||
fetchPreferences: () => Promise<void>;
|
||||
|
|
@ -30,6 +39,7 @@ export const useUserPreferences = (): UseUserPreferencesReturn => {
|
|||
const { authFetch, isAuthenticated } = useAuthenticatedFetch();
|
||||
const [preferences, setPreferences] = useState<UserPreferences>(DEFAULT_PREFERENCES);
|
||||
const [hasAIAccess, setHasAIAccess] = useState(false);
|
||||
const [subscription, setSubscription] = useState<SubscriptionInfo | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
|
|
@ -54,6 +64,23 @@ export const useUserPreferences = (): UseUserPreferencesReturn => {
|
|||
setPreferences(prefs);
|
||||
setHasAIAccess(data.hasAIAccess || false);
|
||||
applyColorScheme(prefs.colorScheme);
|
||||
|
||||
const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3001';
|
||||
try {
|
||||
const subResponse = await authFetch(`${backendUrl}/api/payments/status`);
|
||||
if (subResponse.ok) {
|
||||
const subData = await subResponse.json();
|
||||
setSubscription({
|
||||
hasAccess: subData.hasAccess,
|
||||
accessType: subData.accessType,
|
||||
generationCount: subData.generationCount,
|
||||
generationLimit: subData.generationLimit,
|
||||
generationsRemaining: subData.generationsRemaining,
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// Payments not configured, ignore
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
} finally {
|
||||
|
|
@ -92,6 +119,7 @@ export const useUserPreferences = (): UseUserPreferencesReturn => {
|
|||
return {
|
||||
preferences,
|
||||
hasAIAccess,
|
||||
subscription,
|
||||
loading,
|
||||
saving,
|
||||
fetchPreferences,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue