Add subcription feature

This commit is contained in:
Urtzi Alfaro
2026-01-13 22:22:38 +01:00
parent b931a5c45e
commit 6ddf608d37
61 changed files with 7915 additions and 1238 deletions

View File

@@ -36,7 +36,8 @@ export interface AuthState {
}> | null;
primaryTenantId: string | null;
subscription_from_jwt?: boolean;
pendingSubscriptionId?: string | null; // Subscription ID from registration (before tenant creation)
// Actions
login: (email: string, password: string) => Promise<void>;
register: (userData: {
@@ -45,7 +46,6 @@ export interface AuthState {
full_name: string;
tenant_name?: string;
subscription_plan?: string;
use_trial?: boolean;
payment_method_id?: string;
}) => Promise<void>;
logout: () => void;
@@ -54,6 +54,7 @@ export interface AuthState {
clearError: () => void;
setLoading: (loading: boolean) => void;
setDemoAuth: (token: string, demoUser: Partial<User>, subscriptionTier?: string) => void;
setPendingSubscriptionId: (subscriptionId: string | null) => void; // Store subscription ID from registration
// Permission helpers
hasPermission: (permission: string) => boolean;
@@ -73,6 +74,10 @@ export const useAuthStore = create<AuthState>()(
isAuthenticated: false,
isLoading: false,
error: null,
jwtSubscription: null,
jwtTenantAccess: null,
primaryTenantId: null,
pendingSubscriptionId: null,
// Actions
login: async (email: string, password: string) => {
@@ -126,7 +131,6 @@ export const useAuthStore = create<AuthState>()(
full_name: string;
tenant_name?: string;
subscription_plan?: string;
use_trial?: boolean;
payment_method_id?: string;
}) => {
try {
@@ -165,6 +169,60 @@ export const useAuthStore = create<AuthState>()(
}
},
registerWithSubscription: async (userData: {
email: string;
password: string;
full_name: string;
tenant_name?: string;
subscription_plan?: string;
payment_method_id?: string;
billing_cycle?: 'monthly' | 'yearly';
coupon_code?: string;
address?: string;
postal_code?: string;
city?: string;
country?: string;
}) => {
try {
set({ isLoading: true, error: null });
const response = await authService.registerWithSubscription(userData);
if (response && response.access_token) {
// Set the auth tokens on the API client immediately
apiClient.setAuthToken(response.access_token);
if (response.refresh_token) {
apiClient.setRefreshToken(response.refresh_token);
}
// Store subscription ID in state for onboarding flow (instead of localStorage for security)
const pendingSubscriptionId = response.subscription_id || null;
set({
user: response.user || null,
token: response.access_token,
refreshToken: response.refresh_token || null,
isAuthenticated: true,
isLoading: false,
error: null,
pendingSubscriptionId,
});
} else {
throw new Error('Registration with subscription failed');
}
} catch (error) {
set({
user: null,
token: null,
refreshToken: null,
isAuthenticated: false,
isLoading: false,
error: error instanceof Error ? error.message : 'Error de registro con suscripción',
});
throw error;
}
},
logout: () => {
// Clear the auth tokens from API client
apiClient.setAuthToken(null);
@@ -189,6 +247,10 @@ export const useAuthStore = create<AuthState>()(
isAuthenticated: false,
isLoading: false,
error: null,
jwtSubscription: null,
jwtTenantAccess: null,
primaryTenantId: null,
pendingSubscriptionId: null,
});
},
@@ -261,6 +323,10 @@ export const useAuthStore = create<AuthState>()(
set({ isLoading: loading });
},
setPendingSubscriptionId: (subscriptionId: string | null) => {
set({ pendingSubscriptionId: subscriptionId });
},
setDemoAuth: (token: string, demoUser: Partial<User>, subscriptionTier?: string) => {
console.log('🔧 [Auth Store] setDemoAuth called - demo sessions use X-Demo-Session-Id header, not JWT');
// DO NOT set API client token for demo sessions!
@@ -379,6 +445,7 @@ export const usePermissions = () => useAuthStore((state) => ({
export const useAuthActions = () => useAuthStore((state) => ({
login: state.login,
register: state.register,
registerWithSubscription: state.registerWithSubscription,
logout: state.logout,
refreshAuth: state.refreshAuth,
updateUser: state.updateUser,