Enhance billing and subscription management: Added payment method checks in ProtectedRoute, improved error handling in billing components, and optimized API calls to reduce throttling. Updated user account handling in various components to ensure accurate plan and subscription data display.
This commit is contained in:
@@ -25,6 +25,7 @@ interface User {
|
||||
slug: string;
|
||||
credits: number;
|
||||
status: string;
|
||||
plan?: any; // plan info is optional but required for access gating
|
||||
};
|
||||
}
|
||||
|
||||
@@ -143,11 +144,15 @@ export const useAuthStore = create<AuthState>()(
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
// Store user and JWT tokens
|
||||
// Store user and JWT tokens (handle nested tokens structure)
|
||||
const responseData = data.data || data;
|
||||
const tokens = responseData.tokens || {};
|
||||
const userData = responseData.user || data.user;
|
||||
|
||||
set({
|
||||
user: data.user,
|
||||
token: data.data?.access || data.access || null,
|
||||
refreshToken: data.data?.refresh || data.refresh || null,
|
||||
user: userData,
|
||||
token: tokens.access || responseData.access || data.access || null,
|
||||
refreshToken: tokens.refresh || responseData.refresh || data.refresh || null,
|
||||
isAuthenticated: true,
|
||||
loading: false
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ export const useBillingStore = create<BillingState>((set, get) => ({
|
||||
const balance = await getCreditBalance();
|
||||
set({ balance, loading: false, error: null, lastUpdated: new Date().toISOString() });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Balance unavailable', loading: false });
|
||||
set({ error: error.message || 'Balance unavailable', loading: false, balance: null });
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ export const useSettingsStore = create<SettingsState>()(
|
||||
moduleEnableSettings: null,
|
||||
loading: false,
|
||||
error: null,
|
||||
_moduleEnableLastFetched: 0 as number | undefined,
|
||||
_moduleEnableInFlight: null as Promise<ModuleEnableSettings> | null,
|
||||
|
||||
loadAccountSettings: async () => {
|
||||
set({ loading: true, error: null });
|
||||
@@ -179,12 +181,32 @@ export const useSettingsStore = create<SettingsState>()(
|
||||
},
|
||||
|
||||
loadModuleEnableSettings: async () => {
|
||||
const state = get() as any;
|
||||
const now = Date.now();
|
||||
// Use cached value if fetched within last 60s
|
||||
if (state.moduleEnableSettings && state._moduleEnableLastFetched && now - state._moduleEnableLastFetched < 60000) {
|
||||
return;
|
||||
}
|
||||
// Coalesce concurrent calls
|
||||
if (state._moduleEnableInFlight) {
|
||||
await state._moduleEnableInFlight;
|
||||
return;
|
||||
}
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const settings = await fetchModuleEnableSettings();
|
||||
set({ moduleEnableSettings: settings, loading: false });
|
||||
const inFlight = fetchModuleEnableSettings();
|
||||
(state as any)._moduleEnableInFlight = inFlight;
|
||||
const settings = await inFlight;
|
||||
set({ moduleEnableSettings: settings, loading: false, _moduleEnableLastFetched: Date.now() });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message, loading: false });
|
||||
// On 429/403, avoid loops; cache the failure timestamp and do not retry automatically
|
||||
if (error?.status === 429 || error?.status === 403) {
|
||||
set({ loading: false, _moduleEnableLastFetched: Date.now() });
|
||||
return;
|
||||
}
|
||||
set({ error: error.message, loading: false, _moduleEnableLastFetched: Date.now() });
|
||||
} finally {
|
||||
(get() as any)._moduleEnableInFlight = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user