Cloudtopiaa_Reseller_Frontend/src/services/api.ts
2025-08-11 00:47:45 +05:30

620 lines
19 KiB
TypeScript

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<string, any>;
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<string, any>;
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<T>(
endpoint: string,
options: RequestInit = {}
): Promise<T> {
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<AuthResponse> {
return this.request<AuthResponse>('/auth/login', {
method: 'POST',
body: JSON.stringify(credentials),
});
}
async register(userData: RegisterRequest): Promise<AuthResponse> {
return this.request<AuthResponse>('/auth/register', {
method: 'POST',
body: JSON.stringify(userData),
});
}
async verifyEmail(email: string, otp: string): Promise<AuthResponse> {
return this.request<AuthResponse>('/auth/verify-email', {
method: 'POST',
body: JSON.stringify({ email, otp }),
});
}
async resendVerificationEmail(email: string): Promise<AuthResponse> {
return this.request<AuthResponse>('/auth/resend-verification', {
method: 'POST',
body: JSON.stringify({ email }),
});
}
async refreshToken(refreshToken: string): Promise<AuthResponse> {
return this.request<AuthResponse>('/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<AuthResponse> {
return this.request<AuthResponse>('/auth/logout', {
method: 'POST',
body: JSON.stringify({ sessionId }),
});
}
async forgotPassword(email: string): Promise<AuthResponse> {
return this.request<AuthResponse>('/auth/forgot-password', {
method: 'POST',
body: JSON.stringify({ email }),
});
}
async resetPassword(token: string, password: string): Promise<AuthResponse> {
return this.request<AuthResponse>('/auth/reset-password', {
method: 'POST',
body: JSON.stringify({ token, password }),
});
}
// Two-factor authentication
async setupTwoFactor(): Promise<AuthResponse> {
return this.request<AuthResponse>('/auth/setup-2fa', {
method: 'POST',
});
}
async enableTwoFactor(code: string): Promise<AuthResponse> {
return this.request<AuthResponse>('/auth/enable-2fa', {
method: 'POST',
body: JSON.stringify({ code }),
});
}
async disableTwoFactor(code: string): Promise<AuthResponse> {
return this.request<AuthResponse>('/auth/disable-2fa', {
method: 'POST',
body: JSON.stringify({ code }),
});
}
// Profile management
async updateProfile(profileData: Partial<User>): 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<Product>): 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<Product>): 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<Blob> {
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;