Add DEMO feature to the project
This commit is contained in:
@@ -45,6 +45,7 @@ class ApiClient {
|
||||
private baseURL: string;
|
||||
private authToken: string | null = null;
|
||||
private tenantId: string | null = null;
|
||||
private demoSessionId: string | null = null;
|
||||
private refreshToken: string | null = null;
|
||||
private isRefreshing: boolean = false;
|
||||
private refreshAttempts: number = 0;
|
||||
@@ -74,14 +75,31 @@ class ApiClient {
|
||||
// Request interceptor to add auth headers
|
||||
this.client.interceptors.request.use(
|
||||
(config) => {
|
||||
if (this.authToken) {
|
||||
// Public endpoints that don't require authentication
|
||||
const publicEndpoints = [
|
||||
'/demo/accounts',
|
||||
'/demo/session/create',
|
||||
];
|
||||
|
||||
const isPublicEndpoint = publicEndpoints.some(endpoint =>
|
||||
config.url?.includes(endpoint)
|
||||
);
|
||||
|
||||
// Only add auth token for non-public endpoints
|
||||
if (this.authToken && !isPublicEndpoint) {
|
||||
config.headers.Authorization = `Bearer ${this.authToken}`;
|
||||
}
|
||||
|
||||
if (this.tenantId) {
|
||||
|
||||
if (this.tenantId && !isPublicEndpoint) {
|
||||
config.headers['X-Tenant-ID'] = this.tenantId;
|
||||
}
|
||||
|
||||
// Check demo session ID from memory OR localStorage
|
||||
const demoSessionId = this.demoSessionId || localStorage.getItem('demo_session_id');
|
||||
if (demoSessionId) {
|
||||
config.headers['X-Demo-Session-Id'] = demoSessionId;
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
@@ -317,6 +335,19 @@ class ApiClient {
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
setDemoSessionId(sessionId: string | null) {
|
||||
this.demoSessionId = sessionId;
|
||||
if (sessionId) {
|
||||
localStorage.setItem('demo_session_id', sessionId);
|
||||
} else {
|
||||
localStorage.removeItem('demo_session_id');
|
||||
}
|
||||
}
|
||||
|
||||
getDemoSessionId(): string | null {
|
||||
return this.demoSessionId || localStorage.getItem('demo_session_id');
|
||||
}
|
||||
|
||||
getAuthToken(): string | null {
|
||||
return this.authToken;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,9 @@ export const useSubscription = () => {
|
||||
const analyticsLevel = subscriptionService.getAnalyticsLevelForPlan(planKey);
|
||||
return { hasAccess: true, level: analyticsLevel };
|
||||
}
|
||||
|
||||
// Default fallback when plan is not recognized
|
||||
return { hasAccess: false, level: 'none', reason: 'Unknown plan' };
|
||||
}, [subscriptionInfo.plan]);
|
||||
|
||||
// Check if user can access specific analytics features
|
||||
|
||||
83
frontend/src/api/services/demo.ts
Normal file
83
frontend/src/api/services/demo.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Demo Session API Service
|
||||
* Manages demo session creation, extension, and cleanup
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
|
||||
export interface DemoAccount {
|
||||
account_type: string;
|
||||
email: string;
|
||||
name: string;
|
||||
password: string;
|
||||
description?: string;
|
||||
features?: string[];
|
||||
business_model?: string;
|
||||
}
|
||||
|
||||
export interface DemoSession {
|
||||
session_id: string;
|
||||
virtual_tenant_id: string;
|
||||
base_demo_tenant_id: string;
|
||||
demo_account_type: string;
|
||||
status: 'active' | 'expired' | 'destroyed';
|
||||
created_at: string;
|
||||
expires_at: string;
|
||||
remaining_extensions: number;
|
||||
}
|
||||
|
||||
export interface CreateSessionRequest {
|
||||
demo_account_type: 'individual_bakery' | 'central_baker';
|
||||
}
|
||||
|
||||
export interface ExtendSessionRequest {
|
||||
session_id: string;
|
||||
}
|
||||
|
||||
export interface DestroySessionRequest {
|
||||
session_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available demo accounts
|
||||
*/
|
||||
export const getDemoAccounts = async (): Promise<DemoAccount[]> => {
|
||||
return await apiClient.get<DemoAccount[]>('/demo/accounts');
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new demo session
|
||||
*/
|
||||
export const createDemoSession = async (
|
||||
request: CreateSessionRequest
|
||||
): Promise<DemoSession> => {
|
||||
return await apiClient.post<DemoSession>('/demo/session/create', request);
|
||||
};
|
||||
|
||||
/**
|
||||
* Extend an existing demo session
|
||||
*/
|
||||
export const extendDemoSession = async (
|
||||
request: ExtendSessionRequest
|
||||
): Promise<DemoSession> => {
|
||||
return await apiClient.post<DemoSession>('/demo/session/extend', request);
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy a demo session
|
||||
*/
|
||||
export const destroyDemoSession = async (
|
||||
request: DestroySessionRequest
|
||||
): Promise<{ message: string }> => {
|
||||
return await apiClient.post<{ message: string }>(
|
||||
'/demo/session/destroy',
|
||||
request
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get demo session statistics
|
||||
*/
|
||||
export const getDemoStats = async (): Promise<any> => {
|
||||
return await apiClient.get('/demo/stats');
|
||||
};
|
||||
Reference in New Issue
Block a user