const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:5000/api'; export interface LoginRequest { email: string; password: string; twoFactorCode?: string; } export interface RegisterRequest { email: string; password: string; firstName: string; lastName: string; phone?: string; company?: string; // Vendor-specific fields companyType?: 'corporation' | 'llc' | 'partnership' | 'sole_proprietorship' | 'other'; registrationNumber?: string; gstNumber?: string; panNumber?: string; address?: string; website?: string; businessLicense?: string; taxId?: string; industry?: string; yearsInBusiness?: string | number; annualRevenue?: string | number; employeeCount?: string | number; role?: 'channel_partner_admin' | 'channel_partner_manager' | 'channel_partner_sales' | 'channel_partner_support' | 'channel_partner_finance' | 'channel_partner_analyst' | 'reseller_admin' | 'reseller_manager' | 'reseller_sales' | 'reseller_support' | 'reseller_finance' | 'reseller_analyst' | 'system_admin' | 'system_support' | 'system_analyst' | 'read_only'; userType?: 'channel_partner' | 'reseller' | 'system'; } export interface AuthResponse { success: boolean; message: string; data?: { user: { id: number; email: string; firstName: string; lastName: string; phone?: string; company?: string; role: string; status: string; emailVerified: boolean; twoFactorEnabled: boolean; lastLogin?: string; roles: Array<{ id: number; name: string; description: string; permissions: string[]; }>; }; accessToken: string; refreshToken: string; sessionId: string; }; } export interface User { id: number; email: string; firstName: string; lastName: string; phone?: string; company?: string; role: string; status: string; emailVerified: boolean; twoFactorEnabled: boolean; lastLogin?: string; roles: Array<{ id: number; name: string; description: string; permissions: string[]; }>; } export interface Product { id: number; name: string; description?: string; category: 'cloud_storage' | 'cloud_computing' | 'cybersecurity' | 'data_analytics' | 'ai_ml' | 'iot' | 'blockchain' | 'other'; subcategory?: string; price: number; currency: string; commissionRate: number; features?: string[]; specifications?: Record; images?: string[]; documents?: string[]; status: 'draft' | 'active' | 'inactive' | 'discontinued'; availability: 'available' | 'out_of_stock' | 'coming_soon' | 'discontinued'; stockQuantity: number; sku: string; tags?: string[]; metadata?: Record; createdBy: number; updatedBy?: number; createdAt: string; updatedAt: string; creator?: { id: number; firstName: string; lastName: string; email: string; company?: string; }; updater?: { id: number; firstName: string; lastName: string; email: string; }; vendor?: { id: number; firstName: string; lastName: string; email: string; company?: string; }; isAdminCreated?: boolean; source?: 'admin' | 'vendor'; purchaseUrl?: string; } export interface TrainingCategory { id: number; name: string; description?: string; icon?: string; color?: string; sortOrder: number; isActive: boolean; createdAt: string; updatedAt: string; } export interface TrainingVideo { id: number; moduleId: number; title: string; description?: string; youtubeUrl?: string; duration?: string; thumbnail?: string; sortOrder: number; isActive: boolean; createdAt: string; updatedAt: string; } export interface TrainingMaterial { id: number; moduleId: number; title: string; description?: string; type: 'PDF' | 'PPT' | 'DOC' | 'VIDEO'; downloadUrl?: string; fileSize?: string; sortOrder: number; isActive: boolean; createdAt: string; updatedAt: string; } export interface TrainingModule { id: number; title: string; description?: string; duration?: string; level: 'Beginner' | 'Intermediate' | 'Advanced'; categoryId?: number; thumbnailUrl?: string; isActive: boolean; sortOrder: number; createdBy?: number; createdAt: string; updatedAt: string; category?: TrainingCategory; videos?: TrainingVideo[]; materials?: TrainingMaterial[]; userProgress?: { status: 'not_started' | 'in_progress' | 'completed'; progressPercentage: number; timeSpent: number; completedAt?: string; }; } export interface TrainingProgress { moduleId: number; videoId?: number; materialId?: number; status: 'not_started' | 'in_progress' | 'completed'; progressPercentage: number; timeSpent: number; } class ApiService { private baseURL: string; constructor() { this.baseURL = API_BASE_URL; } private async request( endpoint: string, options: RequestInit = {} ): Promise { const url = `${this.baseURL}${endpoint}`; const config: RequestInit = { headers: { 'Content-Type': 'application/json', ...options.headers, }, ...options, }; // Add auth token if available const token = localStorage.getItem('accessToken'); if (token) { config.headers = { ...config.headers, Authorization: `Bearer ${token}`, }; } try { const response = await fetch(url, config); const data = await response.json(); if (!response.ok) { // Handle account status errors if (response.status === 403 && data.errorCode) { const error = new Error(data.message || 'Account is not active'); (error as any).errorCode = data.errorCode; (error as any).status = data.status; throw error; } throw new Error(data.message || 'API request failed'); } return data; } catch (error) { console.error('API request failed:', error); throw error; } } // Authentication endpoints async login(credentials: LoginRequest): Promise { return this.request('/auth/login', { method: 'POST', body: JSON.stringify(credentials), }); } async register(userData: RegisterRequest): Promise { return this.request('/auth/register', { method: 'POST', body: JSON.stringify(userData), }); } async verifyEmail(email: string, otp: string): Promise { return this.request('/auth/verify-email', { method: 'POST', body: JSON.stringify({ email, otp }), }); } async resendVerificationEmail(email: string): Promise { return this.request('/auth/resend-verification', { method: 'POST', body: JSON.stringify({ email }), }); } async refreshToken(refreshToken: string): Promise { return this.request('/auth/refresh-token', { method: 'POST', body: JSON.stringify({ refreshToken }), }); } async getCurrentUser(): Promise<{ success: boolean; data: User }> { return this.request<{ success: boolean; data: User }>('/auth/me'); } async logout(sessionId: string): Promise { return this.request('/auth/logout', { method: 'POST', body: JSON.stringify({ sessionId }), }); } async forgotPassword(email: string): Promise { return this.request('/auth/forgot-password', { method: 'POST', body: JSON.stringify({ email }), }); } async resetPassword(token: string, password: string): Promise { return this.request('/auth/reset-password', { method: 'POST', body: JSON.stringify({ token, password }), }); } // Two-factor authentication async setupTwoFactor(): Promise { return this.request('/auth/setup-2fa', { method: 'POST', }); } async enableTwoFactor(code: string): Promise { return this.request('/auth/enable-2fa', { method: 'POST', body: JSON.stringify({ code }), }); } async disableTwoFactor(code: string): Promise { return this.request('/auth/disable-2fa', { method: 'POST', body: JSON.stringify({ code }), }); } // Profile management async updateProfile(profileData: Partial): Promise<{ success: boolean; data: User }> { return this.request<{ success: boolean; data: User }>('/auth/profile', { method: 'PUT', body: JSON.stringify(profileData), }); } async changePassword(currentPassword: string, newPassword: string): Promise<{ success: boolean; message: string }> { return this.request<{ success: boolean; message: string }>('/auth/change-password', { method: 'POST', body: JSON.stringify({ currentPassword, newPassword }), }); } // Vendor operations async getAvailableVendorCompanies(): Promise<{ success: boolean; data: Array<{ id: number; company: string; firstName: string; lastName: string; email: string }> }> { return this.request<{ success: boolean; data: Array<{ id: number; company: string; firstName: string; lastName: string; email: string }> }>('/public/vendors/available-companies'); } // Reseller operations async getResellerUserTypes(): Promise<{ success: boolean; data: Array<{ value: string; label: string; description: string; permissions: string[] }> }> { return this.request<{ success: boolean; data: Array<{ value: string; label: string; description: string; permissions: string[] }> }>('/public/reseller/user-types'); } async getPendingResellerRequests(): Promise<{ success: boolean; data: User[] }> { return this.request<{ success: boolean; data: User[] }>('/vendors/pending-resellers'); } async getVendorResellers(): Promise<{ success: boolean; data: User[] }> { return this.request<{ success: boolean; data: User[] }>('/vendors/resellers'); } async createReseller(resellerData: { firstName: string; lastName: string; email: string; phone: string; company: string; userType: 'reseller_admin' | 'reseller_sales' | 'reseller_support' | 'read_only'; region: string; businessType: string; address?: string; }): Promise<{ success: boolean; message: string; data: any }> { return this.request<{ success: boolean; message: string; data: any }>('/vendors/resellers', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(resellerData), }); } async getVendorDashboardStats(): Promise<{ success: boolean; data: any }> { return this.request<{ success: boolean; data: any }>('/vendors/dashboard/stats'); } async getVendorProducts(params?: { page?: number; limit?: number; category?: string; status?: string; search?: string; }): Promise<{ success: boolean; data: { products: Product[]; pagination: any } }> { const queryParams = new URLSearchParams(); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined) queryParams.append(key, value.toString()); }); } return this.request<{ success: boolean; data: { products: Product[]; pagination: any } }>(`/vendors/products?${queryParams}`); } async getVendorCommissions(params?: { page?: number; limit?: number; status?: string; dateRange?: string; }): Promise<{ success: boolean; data: { commissions: any[]; pagination: any } }> { const queryParams = new URLSearchParams(); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined) queryParams.append(key, value.toString()); }); } return this.request<{ success: boolean; data: { commissions: any[]; pagination: any } }>(`/vendors/commissions?${queryParams}`); } async approveResellerRequest(userId: number): Promise<{ success: boolean; message: string }> { return this.request<{ success: boolean; message: string }>(`/vendors/resellers/${userId}/approve`, { method: 'POST' }); } async rejectResellerRequest(userId: number, reason: string): Promise<{ success: boolean; message: string }> { return this.request<{ success: boolean; message: string }>(`/vendors/resellers/${userId}/reject`, { method: 'POST', body: JSON.stringify({ reason }) }); } // Product management async getAllProducts(params?: { page?: number; limit?: number; category?: string; status?: string; search?: string; vendor?: string; sortBy?: string; sortOrder?: string; }): Promise<{ success: boolean; data: { products: Product[]; pagination: any } }> { const queryParams = new URLSearchParams(); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined) queryParams.append(key, value.toString()); }); } return this.request<{ success: boolean; data: { products: Product[]; pagination: any } }>(`/products?${queryParams}`); } async getProductById(id: number): Promise<{ success: boolean; data: Product }> { return this.request<{ success: boolean; data: Product }>(`/products/${id}`); } async createProduct(productData: Partial): Promise<{ success: boolean; data: Product }> { return this.request<{ success: boolean; data: Product }>('/products', { method: 'POST', body: JSON.stringify(productData), }); } async updateProduct(id: number, productData: Partial): Promise<{ success: boolean; data: Product }> { return this.request<{ success: boolean; data: Product }>(`/products/${id}`, { method: 'PUT', body: JSON.stringify(productData), }); } async deleteProduct(id: number): Promise<{ success: boolean; message: string }> { return this.request<{ success: boolean; message: string }>(`/products/${id}`, { method: 'DELETE', }); } async getProductCategories(): Promise<{ success: boolean; data: string[] }> { return this.request<{ success: boolean; data: string[] }>('/products/categories'); } async getProductStats(): Promise<{ success: boolean; data: any }> { return this.request<{ success: boolean; data: any }>('/products/stats'); } async getActiveVendors(): Promise<{ success: boolean; data: Array<{ id: number; firstName: string; lastName: string; company?: string }> }> { return this.request<{ success: boolean; data: Array<{ id: number; firstName: string; lastName: string; company?: string }> }>('/products/vendors'); } async getVendorById(id: number): Promise<{ success: boolean; data: { id: number; firstName: string; lastName: string; email: string; company?: string } }> { return this.request<{ success: boolean; data: { id: number; firstName: string; lastName: string; email: string; company?: string } }>(`/vendors/${id}`); } // Receipt management async uploadReceipt(data: FormData): Promise<{ success: boolean; data: any; message: string }> { return this.request<{ success: boolean; data: any; message: string }>('/receipts/upload', { method: 'POST', body: data, }); } async getResellerReceipts(params?: { page?: number; limit?: number; status?: string; startDate?: string; endDate?: string; }): Promise<{ success: boolean; data: any[]; pagination?: any }> { const queryParams = new URLSearchParams(); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined) queryParams.append(key, value.toString()); }); } return this.request<{ success: boolean; data: any[]; pagination?: any }>(`/receipts/reseller?${queryParams}`); } async getVendorReceipts(params?: { page?: number; limit?: number; status?: string; resellerId?: number; startDate?: string; endDate?: string; }): Promise<{ success: boolean; data: any[]; pagination?: any }> { const queryParams = new URLSearchParams(); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined) queryParams.append(key, value.toString()); }); } return this.request<{ success: boolean; data: any[]; pagination?: any }>(`/receipts/vendor?${queryParams}`); } async getReceiptById(id: number): Promise<{ success: boolean; data: any }> { return this.request<{ success: boolean; data: any }>(`/receipts/reseller/${id}`); } async getVendorReceiptById(id: number): Promise<{ success: boolean; data: any }> { return this.request<{ success: boolean; data: any }>(`/receipts/vendor/${id}`); } async updateReceiptStatus(id: number, statusUpdate: { status: string; rejectionReason?: string }): Promise<{ success: boolean; data: any; message: string }> { return this.request<{ success: boolean; data: any; message: string }>(`/receipts/vendor/${id}/status`, { method: 'PUT', body: JSON.stringify(statusUpdate), }); } async downloadReceipt(id: number): Promise { const response = await fetch(`${this.baseURL}/receipts/${id}/download`, { method: 'GET', headers: { 'Authorization': `Bearer ${localStorage.getItem('accessToken')}`, 'Content-Type': 'application/json', }, }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.blob(); } async deleteReceipt(id: number): Promise<{ success: boolean; message: string }> { return this.request<{ success: boolean; message: string }>(`/receipts/reseller/${id}`, { method: 'DELETE', }); } // Get vendor products with current stock quantities async getVendorProductsWithStock(params?: { page?: number; limit?: number; category?: string; status?: string; search?: string; }): Promise<{ success: boolean; data: { products: any[]; pagination: any } }> { const queryParams = new URLSearchParams(); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined) queryParams.append(key, value.toString()); }); } return this.request<{ success: boolean; data: { products: any[]; pagination: any } }>(`/receipts/vendor/products/stock?${queryParams}`); } // Get products shared by vendor for reseller with current stock async getResellerVendorProducts(params: { vendorId: number; page?: number; limit?: number; category?: string; status?: string; search?: string; }): Promise<{ success: boolean; data: { products: any[]; pagination: any } }> { const queryParams = new URLSearchParams(); Object.entries(params).forEach(([key, value]) => { if (value !== undefined) queryParams.append(key, value.toString()); }); return this.request<{ success: boolean; data: { products: any[]; pagination: any } }>(`/receipts/reseller/vendor/products?${queryParams}`); } // Manually update product stock quantity async updateProductStock(productId: number, stockQuantity: number): Promise<{ success: boolean; data: any; message: string }> { return this.request<{ success: boolean; data: any; message: string }>(`/receipts/vendor/products/${productId}/stock`, { method: 'PUT', body: JSON.stringify({ stockQuantity }), }); } } export const apiService = new ApiService(); export default apiService;