import { territoryManagerAPI } from './territory-manager-api'; import { TerritoryManagerAuth } from './territory-manager-auth'; import type { TerritoryManager, TerritoryManagerStats, TerritoryApplication, Lead, Commission, Achievement, ExpenseReport, TMNotification, ReferralLink, MarketingMaterial, LeaderboardEntry, ApplicationFormData, LeadFormData, ExpenseReportFormData } from './territory-manager-types'; /** * Centralized Territory Manager API router * Browser-friendly API router that handles all Territory Manager API calls * This is designed to be used in Astro client-side scripts and React components */ export class TerritoryManagerRouter { /** * Authentication methods */ static async signIn(email: string, password: string) { try { return await TerritoryManagerAuth.signIn(email, password); } catch (error) { throw error; } } static async signOut() { try { return await TerritoryManagerAuth.signOut(); } catch (error) { throw error; } } static async checkAuth(): Promise<{ authenticated: boolean; user: any; territoryManager: TerritoryManager | null; }> { try { const isTM = await TerritoryManagerAuth.isTerritoryManager(); const territoryManager = isTM ? await TerritoryManagerAuth.getCurrentTerritoryManager() : null; return { authenticated: isTM, user: territoryManager ? { email: territoryManager.user_id } : null, territoryManager }; } catch (error) { return { authenticated: false, user: null, territoryManager: null }; } } /** * Dashboard data loading */ static async loadDashboard(): Promise<{ stats: TerritoryManagerStats | null; territoryManager: TerritoryManager | null; recent_activity: any[]; active_leads: Lead[]; achievements: Achievement[]; notifications: TMNotification[]; earnings_history: any[]; error: string | null; }> { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) { return { stats: null, territoryManager: null, recent_activity: [], active_leads: [], achievements: [], notifications: [], earnings_history: [], error: 'Not authenticated as territory manager' }; } // Load all dashboard data in parallel const [ stats, leads, achievements, notifications, commissions ] = await Promise.all([ territoryManagerAPI.getTerritoryManagerStats(territoryManager.id), territoryManagerAPI.getLeads(territoryManager.id), territoryManagerAPI.getAchievements(), territoryManagerAPI.getNotifications(territoryManager.id), territoryManagerAPI.getCommissions(territoryManager.id) ]); // Generate recent activity from commissions and leads const recent_activity = [ ...commissions.slice(0, 3).map(c => ({ type: 'commission', message: `Earned $${c.total_commission} commission`, created_at: c.created_at })), ...leads.slice(0, 2).map(l => ({ type: 'lead', message: `${l.status === 'converted' ? 'Converted' : 'Added'} lead: ${l.event_name}`, created_at: l.created_at })) ].sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); // Generate earnings history from commissions const earnings_history = this.generateEarningsHistory(commissions); return { stats, territoryManager, recent_activity, active_leads: leads.filter(l => l.status !== 'converted' && l.status !== 'dead'), achievements, notifications, earnings_history, error: null }; } catch (error) { return { stats: null, territoryManager: null, recent_activity: [], active_leads: [], achievements: [], notifications: [], earnings_history: [], error: 'Failed to load dashboard data' }; } } /** * Application management */ static async submitApplication(data: ApplicationFormData): Promise<{ success: boolean; applicationId?: string; error?: string; }> { try { const application = await territoryManagerAPI.submitApplication(data); return { success: true, applicationId: application.id }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to submit application' }; } } static async getApplications(status?: string): Promise { try { return await territoryManagerAPI.getApplications(status); } catch (error) { return []; } } static async reviewApplication(id: string, action: 'approve' | 'reject', notes?: string): Promise<{ success: boolean; error?: string; }> { try { await territoryManagerAPI.reviewApplication(id, action, notes); return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to review application' }; } } /** * Lead management */ static async loadLeads(): Promise { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) return []; return await territoryManagerAPI.getLeads(territoryManager.id); } catch (error) { return []; } } static async createLead(data: LeadFormData): Promise<{ success: boolean; lead?: Lead; error?: string; }> { try { const lead = await territoryManagerAPI.createLead(data); return { success: true, lead }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to create lead' }; } } static async updateLead(id: string, data: Partial): Promise<{ success: boolean; lead?: Lead; error?: string; }> { try { const lead = await territoryManagerAPI.updateLead(id, data); return { success: true, lead }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to update lead' }; } } static async deleteLead(id: string): Promise<{ success: boolean; error?: string; }> { try { await territoryManagerAPI.deleteLead(id); return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to delete lead' }; } } /** * Commission management */ static async loadCommissions(): Promise { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) return []; return await territoryManagerAPI.getCommissions(territoryManager.id); } catch (error) { return []; } } /** * Expense management */ static async submitExpenseReport(data: ExpenseReportFormData): Promise<{ success: boolean; expenseReport?: ExpenseReport; error?: string; }> { try { const expenseReport = await territoryManagerAPI.submitExpenseReport(data); return { success: true, expenseReport }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to submit expense report' }; } } static async loadExpenseReports(): Promise { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) return []; return await territoryManagerAPI.getExpenseReports(territoryManager.id); } catch (error) { return []; } } /** * Referral management */ static async generateReferralLink(eventType?: string): Promise<{ success: boolean; referralLink?: ReferralLink; error?: string; }> { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) { return { success: false, error: 'Not authenticated as territory manager' }; } const referralLink = await territoryManagerAPI.generateReferralLink(territoryManager.id, eventType); return { success: true, referralLink }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to generate referral link' }; } } static async loadReferralLinks(): Promise { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) return []; return await territoryManagerAPI.getReferralLinks(territoryManager.id); } catch (error) { return []; } } /** * Training and achievements */ static async loadAchievements(): Promise { try { return await territoryManagerAPI.getAchievements(); } catch (error) { return []; } } static async loadTrainingProgress(): Promise { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) return []; return await territoryManagerAPI.getTrainingProgress(territoryManager.id); } catch (error) { return []; } } static async updateTrainingProgress(moduleId: string, score?: number): Promise<{ success: boolean; error?: string; }> { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) { return { success: false, error: 'Not authenticated as territory manager' }; } await territoryManagerAPI.updateTrainingProgress(territoryManager.id, moduleId, score); return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to update training progress' }; } } /** * Notifications */ static async loadNotifications(): Promise { try { const territoryManager = await TerritoryManagerAuth.getCurrentTerritoryManager(); if (!territoryManager) return []; return await territoryManagerAPI.getNotifications(territoryManager.id); } catch (error) { return []; } } static async markNotificationAsRead(id: string): Promise<{ success: boolean; error?: string; }> { try { await territoryManagerAPI.markNotificationAsRead(id); return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to mark notification as read' }; } } static async markAllNotificationsAsRead(): Promise<{ success: boolean; error?: string; }> { try { const notifications = await this.loadNotifications(); const unreadNotifications = notifications.filter(n => !n.read); await Promise.all( unreadNotifications.map(n => territoryManagerAPI.markNotificationAsRead(n.id)) ); return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to mark all notifications as read' }; } } /** * Leaderboard */ static async loadLeaderboard(period: 'monthly' | 'quarterly' | 'yearly' = 'monthly'): Promise { try { return await territoryManagerAPI.getLeaderboard(period); } catch (error) { return []; } } /** * Marketing materials */ static async loadMarketingMaterials(): Promise { try { return await territoryManagerAPI.getMarketingMaterials(); } catch (error) { return []; } } /** * Utility methods */ static formatCurrency(amount: number): string { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); } static formatDate(dateString: string): string { return new Date(dateString).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); } static formatDateTime(dateString: string): string { return new Date(dateString).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: '2-digit' }); } static getStatusColor(status: string): string { const colors = { 'pending': 'bg-yellow-600 text-white', 'active': 'bg-green-600 text-white', 'suspended': 'bg-red-600 text-white', 'inactive': 'bg-gray-600 text-white', 'cold': 'bg-gray-600 text-white', 'contacted': 'bg-blue-600 text-white', 'confirmed': 'bg-green-600 text-white', 'converted': 'bg-purple-600 text-white', 'dead': 'bg-red-600 text-white' }; return colors[status] || 'bg-gray-600 text-white'; } /** * Private utility methods */ private static generateEarningsHistory(commissions: Commission[]): any[] { const monthlyEarnings = new Map(); commissions.forEach(commission => { const month = commission.created_at.substring(0, 7); // YYYY-MM const current = monthlyEarnings.get(month) || 0; monthlyEarnings.set(month, current + commission.total_commission); }); return Array.from(monthlyEarnings.entries()) .map(([month, amount]) => ({ date: month + '-01', amount })) .sort((a, b) => a.date.localeCompare(b.date)); } } // Export the router for global use export const territoryManagerRouter = TerritoryManagerRouter;