diff --git a/src/App.tsx b/src/App.tsx index ee0750a..d898f96 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,9 @@ import React, { useEffect } from 'react'; -import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; +import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import { Provider } from 'react-redux'; import { CookiesProvider } from 'react-cookie'; import { store } from './store'; import { setTheme } from './store/slices/themeSlice'; -import { useAppSelector } from './store/hooks'; // Channel Partner Components import Layout from './components/Layout/Layout'; @@ -14,6 +13,11 @@ import PartnershipsPage from './pages/Partnerships'; import DealsPage from './pages/Deals'; import CommissionsPage from './pages/Commissions'; import ProductManagement from './pages/ProductManagement'; +import Training from './pages/Training'; +import Support from './pages/Support'; +import Analytics from './pages/Analytics'; +import Reports from './pages/Reports'; +import Settings from './pages/Settings'; import Login from './pages/Login'; import Signup from './pages/Signup'; @@ -26,6 +30,7 @@ import ResellerDashboardInstances from './pages/reseller/Instances'; import ResellerBilling from './pages/reseller/Billing'; import ResellerSupport from './pages/reseller/Support'; import ResellerReports from './pages/reseller/Reports'; +import ResellerTraining from './pages/reseller/Training'; import ResellerLayout from './components/reseller/layout/ResellerLayout'; import CookieConsent from './components/CookieConsent'; import './index.css'; @@ -117,54 +122,54 @@ function App() { } /> - - - } /> - - - - } /> - - - - } /> - - - - } /> - - - - } /> - - - - } /> - - - - } /> - - - - } /> - - - - } /> - - + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> {/* Reseller Routes */} } /> @@ -221,11 +226,11 @@ function App() { } /> - - - - } /> + + + + } /> @@ -238,7 +243,7 @@ function App() { } /> - + } /> - + } /> ) => void; + onTicketDelete: (id: string) => void; + onFAQAdd: (faq: Omit) => void; + onFAQUpdate: (id: string, updates: Partial) => void; + onFAQDelete: (id: string) => void; + onResourceAdd: (resource: Omit) => void; + onResourceUpdate: (id: string, updates: Partial) => void; + onResourceDelete: (id: string) => void; + onExportReport: (type: 'pdf' | 'excel' | 'csv') => void; +} + +const SupportAdmin: React.FC = ({ + tickets, + faqs, + resources, + onTicketUpdate, + onTicketDelete, + onFAQAdd, + onFAQUpdate, + onFAQDelete, + onResourceAdd, + onResourceUpdate, + onResourceDelete, + onExportReport +}) => { + const [currentView, setCurrentView] = useState<'tickets' | 'faqs' | 'resources' | 'analytics'>('tickets'); + const [selectedTicket, setSelectedTicket] = useState(null); + const [editingFAQ, setEditingFAQ] = useState(null); + const [editingResource, setEditingResource] = useState(null); + const [showAddFAQ, setShowAddFAQ] = useState(false); + const [showAddResource, setShowAddResource] = useState(false); + const [searchQuery, setSearchQuery] = useState(''); + const [filterStatus, setFilterStatus] = useState('all'); + const [filterPriority, setFilterPriority] = useState('all'); + const [filterCategory, setFilterCategory] = useState('all'); + + const getStatusColor = (status: string) => { + switch (status) { + case 'open': return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300'; + case 'in_progress': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300'; + case 'resolved': return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300'; + case 'closed': return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'; + default: return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'; + } + }; + + const getPriorityColor = (priority: string) => { + switch (priority) { + case 'urgent': return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300'; + case 'high': return 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300'; + case 'medium': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300'; + case 'low': return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300'; + default: return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'; + } + }; + + const filteredTickets = tickets.filter(ticket => { + const matchesSearch = ticket.title.toLowerCase().includes(searchQuery.toLowerCase()) || + ticket.description.toLowerCase().includes(searchQuery.toLowerCase()); + const matchesStatus = filterStatus === 'all' || ticket.status === filterStatus; + const matchesPriority = filterPriority === 'all' || ticket.priority === filterPriority; + const matchesCategory = filterCategory === 'all' || ticket.category === filterCategory; + + return matchesSearch && matchesStatus && matchesPriority && matchesCategory; + }); + + const handleFAQSubmit = (e: React.FormEvent) => { + e.preventDefault(); + const formData = new FormData(e.target as HTMLFormElement); + const newFAQ: Omit = { + question: formData.get('question') as string, + answer: formData.get('answer') as string, + category: formData.get('category') as string, + tags: (formData.get('tags') as string).split(',').map(tag => tag.trim()), + helpful: 0, + notHelpful: 0 + }; + onFAQAdd(newFAQ); + setShowAddFAQ(false); + (e.target as HTMLFormElement).reset(); + }; + + const handleResourceSubmit = (e: React.FormEvent) => { + e.preventDefault(); + const formData = new FormData(e.target as HTMLFormElement); + const newResource: Omit = { + title: formData.get('title') as string, + description: formData.get('description') as string, + type: formData.get('type') as 'documentation' | 'video' | 'guide' | 'tutorial', + url: formData.get('url') as string, + category: formData.get('category') as string, + tags: (formData.get('tags') as string).split(',').map(tag => tag.trim()) + }; + onResourceAdd(newResource); + setShowAddResource(false); + (e.target as HTMLFormElement).reset(); + }; + + return ( +
+ {/* Header */} +
+
+
+ +
+
+

Support Administration

+

Manage tickets, FAQs, and resources

+
+
+
+ {/* View Toggle Buttons */} +
+ + + + +
+
+
+ + {/* Content Based on Current View */} + {currentView === 'tickets' && ( +
+ {/* Search and Filters */} +
+
+
+
+ + setSearchQuery(e.target.value)} + className="input pl-10 w-full" + /> +
+
+
+ + + +
+
+
+ + {/* Tickets List */} +
+ {filteredTickets.map((ticket) => ( +
+
+
+
+

{ticket.title}

+ + {ticket.status.replace('_', ' ')} + + + {ticket.priority} + +
+

{ticket.description}

+
+
+ + {ticket.submittedBy} +
+
+ + {new Date(ticket.createdAt).toLocaleDateString()} +
+
+ + {ticket.messages.length} messages +
+
+
+
+ + + +
+
+
+ ))} +
+
+ )} + + {currentView === 'faqs' && ( +
+
+
+

Manage FAQs

+ +
+
+ {faqs.map((faq) => ( +
+
+
+

{faq.question}

+

{faq.answer}

+
+ Category: {faq.category} + Helpful: {faq.helpful} + Not Helpful: {faq.notHelpful} +
+
+
+ + +
+
+
+ ))} +
+
+
+ )} + + {currentView === 'resources' && ( +
+
+
+

Manage Resources

+ +
+
+ {resources.map((resource) => ( +
+
+
+ +
+
+

{resource.title}

+

{resource.type}

+
+
+

{resource.description}

+
+
+ {resource.tags.slice(0, 2).map((tag) => ( + + {tag} + + ))} +
+
+ + +
+
+
+ ))} +
+
+
+ )} + + {currentView === 'analytics' && ( +
+
+

Support Analytics

+
+
+
+
+ +
+
+

Total Tickets

+

{tickets.length}

+
+
+
+
+
+
+ +
+
+

Open Tickets

+

+ {tickets.filter(t => t.status === 'open').length} +

+
+
+
+
+
+
+ +
+
+

Resolved

+

+ {tickets.filter(t => t.status === 'resolved').length} +

+
+
+
+
+
+
+ +
+
+

FAQs

+

{faqs.length}

+
+
+
+
+
+ +
+
+

Quick Actions

+
+ + +
+
+
+ + + +
+
+
+ )} + + {/* Add FAQ Modal */} + {showAddFAQ && ( +
+
+

Add New FAQ

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ )} + + {/* Add Resource Modal */} + {showAddResource && ( +
+
+

Add New Resource

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ )} +
+ ); +}; + +export default SupportAdmin; \ No newline at end of file diff --git a/src/components/TrainingAdmin.tsx b/src/components/TrainingAdmin.tsx new file mode 100644 index 0000000..9e39b90 --- /dev/null +++ b/src/components/TrainingAdmin.tsx @@ -0,0 +1,463 @@ +import React, { useState } from 'react'; +import { + Plus, + Edit, + Trash2, + Save, + X, + Upload, + BookOpen, + Video, + FileText, + Settings +} from 'lucide-react'; + +interface TrainingModule { + id: string; + title: string; + description: string; + duration: string; + level: 'Beginner' | 'Intermediate' | 'Advanced'; + category: string; + videos: TrainingVideo[]; + materials: TrainingMaterial[]; + completed: boolean; +} + +interface TrainingVideo { + id: string; + title: string; + description: string; + youtubeUrl: string; + duration: string; + thumbnail: string; +} + +interface TrainingMaterial { + id: string; + title: string; + description: string; + type: 'PDF' | 'PPT' | 'DOC' | 'VIDEO'; + downloadUrl: string; + size: string; +} + +interface TrainingAdminProps { + modules: TrainingModule[]; + onModuleAdd: (module: Omit) => void; + onModuleUpdate: (id: string, module: Partial) => void; + onModuleDelete: (id: string) => void; + onVideoAdd: (moduleId: string, video: Omit) => void; + onVideoUpdate: (moduleId: string, videoId: string, video: Partial) => void; + onVideoDelete: (moduleId: string, videoId: string) => void; + onMaterialAdd: (moduleId: string, material: Omit) => void; + onMaterialUpdate: (moduleId: string, materialId: string, material: Partial) => void; + onMaterialDelete: (moduleId: string, materialId: string) => void; +} + +const TrainingAdmin: React.FC = ({ + modules, + onModuleAdd, + onModuleUpdate, + onModuleDelete, + onVideoAdd, + onVideoUpdate, + onVideoDelete, + onMaterialAdd, + onMaterialUpdate, + onMaterialDelete +}) => { + const [showAddModule, setShowAddModule] = useState(false); + const [showAddVideo, setShowAddVideo] = useState(false); + const [showAddMaterial, setShowAddMaterial] = useState(false); + const [editingModule, setEditingModule] = useState(null); + const [editingVideo, setEditingVideo] = useState<{ moduleId: string; video: TrainingVideo } | null>(null); + const [editingMaterial, setEditingMaterial] = useState<{ moduleId: string; material: TrainingMaterial } | null>(null); + const [selectedModuleForAdd, setSelectedModuleForAdd] = useState(''); + + const categories = ['Platform Basics', 'Sales & Marketing', 'Technical', 'Business']; + const levels = ['Beginner', 'Intermediate', 'Advanced']; + const materialTypes = ['PDF', 'PPT', 'DOC', 'VIDEO']; + + const handleModuleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + + const newModule: Omit = { + title: formData.get('title') as string, + description: formData.get('description') as string, + duration: formData.get('duration') as string, + level: formData.get('level') as 'Beginner' | 'Intermediate' | 'Advanced', + category: formData.get('category') as string, + videos: [], + materials: [], + completed: false + }; + + onModuleAdd(newModule); + setShowAddModule(false); + (e.target as HTMLFormElement).reset(); + }; + + const handleVideoSubmit = (e: React.FormEvent) => { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + + const newVideo: Omit = { + title: formData.get('title') as string, + description: formData.get('description') as string, + youtubeUrl: formData.get('youtubeUrl') as string, + duration: formData.get('duration') as string, + thumbnail: `https://img.youtube.com/vi/${formData.get('youtubeUrl')?.toString().split('v=')[1]}/maxresdefault.jpg` + }; + + onVideoAdd(selectedModuleForAdd, newVideo); + setShowAddVideo(false); + (e.target as HTMLFormElement).reset(); + }; + + const handleMaterialSubmit = (e: React.FormEvent) => { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + + const newMaterial: Omit = { + title: formData.get('title') as string, + description: formData.get('description') as string, + type: formData.get('type') as 'PDF' | 'PPT' | 'DOC' | 'VIDEO', + downloadUrl: '#', + size: formData.get('size') as string + }; + + onMaterialAdd(selectedModuleForAdd, newMaterial); + setShowAddMaterial(false); + (e.target as HTMLFormElement).reset(); + }; + + return ( +
+ {/* Admin Header */} +
+
+
+ +
+
+

Training Management

+

Manage training modules, videos, and materials

+
+
+ +
+ + {/* Modules List */} +
+ {modules.map((module) => ( +
+
+
+ +
+

{module.title}

+

{module.category} • {module.level} • {module.duration}

+
+
+
+ + +
+
+ +

{module.description}

+ + {/* Videos Section */} +
+
+

+

+ +
+
+ {module.videos.map((video) => ( +
+
+
+
{video.title}
+

{video.duration}

+
+
+ + +
+
+
+ ))} +
+
+ + {/* Materials Section */} +
+
+

+ + Materials ({module.materials.length}) +

+ +
+
+ {module.materials.map((material) => ( +
+
+
+
{material.title}
+

{material.type} • {material.size}

+
+
+ + +
+
+
+ ))} +
+
+
+ ))} +
+ + {/* Add Module Modal */} + {showAddModule && ( +
+
+
+

Add New Training Module

+ +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+
+ )} + + {/* Add Video Modal */} + {showAddVideo && ( +
+
+
+

Add New Video

+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ )} + + {/* Add Material Modal */} + {showAddMaterial && ( +
+
+
+

Add New Material

+ +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
+ +

Click to upload or drag and drop

+
+
+
+ + +
+
+
+
+ )} +
+ ); +}; + +export default TrainingAdmin; \ No newline at end of file diff --git a/src/components/TrainingAnalytics.tsx b/src/components/TrainingAnalytics.tsx new file mode 100644 index 0000000..329688c --- /dev/null +++ b/src/components/TrainingAnalytics.tsx @@ -0,0 +1,386 @@ +import React, { useState } from 'react'; +import { + TrendingUp, + Users, + BookOpen, + Video, + FileText, + Award, + Clock, + BarChart3, + Download, + Calendar, + Filter, + Eye, + EyeOff, + RefreshCw, + Target, + CheckCircle, + XCircle, + AlertCircle, + Play +} from 'lucide-react'; + +interface TrainingAnalytics { + totalModules: number; + totalVideos: number; + totalMaterials: number; + totalResellers: number; + activeResellers: number; + completedModules: number; + averageCompletionTime: string; + popularCategories: Array<{ name: string; count: number; percentage: number }>; + completionRates: Array<{ month: string; rate: number }>; + topPerformingModules: Array<{ name: string; completionRate: number; avgTime: string }>; + resellerProgress: Array<{ name: string; completed: number; total: number; percentage: number }>; + recentActivity: Array<{ type: string; description: string; timestamp: string; user: string }>; +} + +interface TrainingAnalyticsProps { + analytics: TrainingAnalytics; + onExportReport: (type: 'pdf' | 'excel' | 'csv') => void; + onDateRangeChange: (startDate: string, endDate: string) => void; +} + +const TrainingAnalytics: React.FC = ({ + analytics, + onExportReport, + onDateRangeChange +}) => { + const [dateRange, setDateRange] = useState('30d'); + const [showDetailedMetrics, setShowDetailedMetrics] = useState(false); + + const getCompletionRateColor = (rate: number) => { + if (rate >= 80) return 'text-success-600 dark:text-success-400'; + if (rate >= 60) return 'text-warning-600 dark:text-warning-400'; + return 'text-danger-600 dark:text-danger-400'; + }; + + const getProgressColor = (percentage: number) => { + if (percentage >= 80) return 'bg-success-500'; + if (percentage >= 60) return 'bg-warning-500'; + return 'bg-danger-500'; + }; + + return ( +
+ {/* Header */} +
+
+
+ +
+
+

Training Analytics

+

Comprehensive insights into training performance

+
+
+
+ + +
+
+ + {/* Key Metrics */} +
+
+
+
+

Total Modules

+

{analytics.totalModules}

+
+
+ +
+
+
+ + +12% from last month +
+
+ +
+
+
+

Active Resellers

+

{analytics.activeResellers}

+
+
+ +
+
+
+ + +8% from last month +
+
+ +
+
+
+

Completion Rate

+

+ {Math.round((analytics.completedModules / analytics.totalModules) * 100)}% +

+
+
+ +
+
+
+ + Avg: {analytics.averageCompletionTime} +
+
+ +
+
+
+

Total Content

+

+ {analytics.totalVideos + analytics.totalMaterials} +

+
+
+ +
+
+
+
+
+
+ + {/* Detailed Metrics */} + {showDetailedMetrics && ( +
+ {/* Popular Categories */} +
+

Popular Categories

+
+ {analytics.popularCategories.map((category, index) => ( +
+
+
+ {category.name} +
+
+
+
+
+ + {category.percentage}% + +
+
+ ))} +
+
+ + {/* Completion Trends */} +
+

Completion Trends

+
+ {analytics.completionRates.map((item, index) => ( +
+ {item.month} +
+
+
+
+ + {item.rate}% + +
+
+ ))} +
+
+
+ )} + + {/* Top Performing Modules */} +
+
+

Top Performing Modules

+ +
+
+ + + + + + + + + + + {analytics.topPerformingModules.map((module, index) => ( + + + + + + + ))} + +
ModuleCompletion RateAvg TimeStatus
+
+
+ +
+ {module.name} +
+
+
+
+
+
+ + {module.completionRate}% + +
+
+ {module.avgTime} + + = 80 + ? 'bg-success-100 text-success-800 dark:bg-success-900 dark:text-success-300' + : module.completionRate >= 60 + ? 'bg-warning-100 text-warning-800 dark:bg-warning-900 dark:text-warning-300' + : 'bg-danger-100 text-danger-800 dark:bg-danger-900 dark:text-danger-300' + }`}> + {module.completionRate >= 80 ? 'Excellent' : module.completionRate >= 60 ? 'Good' : 'Needs Attention'} + +
+
+
+ + {/* Reseller Progress */} +
+
+

Reseller Progress

+ +
+
+ {analytics.resellerProgress.map((reseller, index) => ( +
+
+
+ +
+
+

{reseller.name}

+

+ {reseller.completed} of {reseller.total} modules completed +

+
+
+
+
+
+
+ + {reseller.percentage}% + +
+
+ ))} +
+
+ + {/* Recent Activity */} +
+

Recent Activity

+
+ {analytics.recentActivity.map((activity, index) => ( +
+
+ {activity.type === 'completion' && } + {activity.type === 'started' && } + {activity.type === 'error' && } + {activity.type === 'warning' && } +
+
+

{activity.description}

+
+ {activity.user} + + {activity.timestamp} +
+
+
+ ))} +
+
+ + {/* Export Options */} +
+
+
+

Export Reports

+

Download analytics data in various formats

+
+
+ + + +
+
+
+
+ ); +}; + +export default TrainingAnalytics; \ No newline at end of file diff --git a/src/pages/Analytics.tsx b/src/pages/Analytics.tsx new file mode 100644 index 0000000..09e4c9d --- /dev/null +++ b/src/pages/Analytics.tsx @@ -0,0 +1,359 @@ +import React, { useState } from 'react'; +import { + BarChart3, + TrendingUp, + Users, + DollarSign, + ShoppingCart, + Award, + Target, + Calendar, + Filter, + Download, + Eye, + EyeOff, + RefreshCw, + ArrowUp, + ArrowDown, + Activity, + PieChart, + LineChart, + BarChart, + AreaChart +} from 'lucide-react'; + +const Analytics: React.FC = () => { + const [dateRange, setDateRange] = useState('30d'); + const [showDetailedMetrics, setShowDetailedMetrics] = useState(false); + + // Mock data + const analyticsData = { + totalRevenue: 1250000, + totalResellers: 156, + activeResellers: 142, + totalDeals: 89, + conversionRate: 23.5, + averageDealSize: 14000, + monthlyGrowth: 12.8, + topPerformingResellers: [ + { name: 'John Smith', revenue: 89000, deals: 12, growth: 15.2 }, + { name: 'Sarah Johnson', revenue: 76000, deals: 9, growth: 8.7 }, + { name: 'Mike Davis', revenue: 68000, deals: 11, growth: 22.1 }, + { name: 'Lisa Wilson', revenue: 54000, deals: 7, growth: 5.3 }, + { name: 'David Brown', revenue: 48000, deals: 6, growth: 18.9 } + ], + revenueByMonth: [ + { month: 'Jan', revenue: 85000, deals: 8 }, + { month: 'Feb', revenue: 92000, deals: 9 }, + { month: 'Mar', revenue: 78000, deals: 7 }, + { month: 'Apr', revenue: 105000, deals: 10 }, + { month: 'May', revenue: 118000, deals: 11 }, + { month: 'Jun', revenue: 125000, deals: 12 } + ], + categoryPerformance: [ + { category: 'Cloud Services', revenue: 450000, percentage: 36 }, + { category: 'Security Solutions', revenue: 320000, percentage: 25.6 }, + { category: 'Data Analytics', revenue: 280000, percentage: 22.4 }, + { category: 'Consulting', revenue: 200000, percentage: 16 } + ], + regionalPerformance: [ + { region: 'North America', revenue: 520000, growth: 15.2 }, + { region: 'Europe', revenue: 380000, growth: 8.7 }, + { region: 'Asia Pacific', revenue: 250000, growth: 22.1 }, + { region: 'Latin America', revenue: 100000, growth: 5.3 } + ] + }; + + const getGrowthColor = (growth: number) => { + return growth >= 0 ? 'text-success-600 dark:text-success-400' : 'text-danger-600 dark:text-danger-400'; + }; + + const getGrowthIcon = (growth: number) => { + return growth >= 0 ? : ; + }; + + return ( +
+ {/* Header */} +
+
+
+ +
+
+

+ Analytics Dashboard +

+

+ Comprehensive insights into your business performance +

+
+
+
+ + +
+
+ + {/* Key Metrics */} +
+
+
+
+

Total Revenue

+

+ ${(analyticsData.totalRevenue / 1000).toFixed(0)}K +

+
+
+ +
+
+
+ + +{analyticsData.monthlyGrowth}% from last month +
+
+ +
+
+
+

Active Resellers

+

{analyticsData.activeResellers}

+
+
+ +
+
+
+ + +8% from last month +
+
+ +
+
+
+

Total Deals

+

{analyticsData.totalDeals}

+
+
+ +
+
+
+ + +15% from last month +
+
+ +
+
+
+

Conversion Rate

+

{analyticsData.conversionRate}%

+
+
+ +
+
+
+ + +2.3% from last month +
+
+
+ + {/* Charts Section */} +
+ {/* Revenue Trend */} +
+
+

Revenue Trend

+ +
+
+
+ +

Revenue trend chart

+

Monthly revenue progression

+
+
+
+ {analyticsData.revenueByMonth.slice(-4).map((item, index) => ( +
+

{item.month}

+

${(item.revenue / 1000).toFixed(0)}K

+
+ ))} +
+
+ + {/* Category Performance */} +
+
+

Category Performance

+ +
+
+
+ +

Category distribution chart

+

Revenue by product category

+
+
+
+ {analyticsData.categoryPerformance.map((category, index) => ( +
+ {category.category} +
+
+
+
+ {category.percentage}% +
+
+ ))} +
+
+
+ + {/* Top Performing Resellers */} +
+
+

Top Performing Resellers

+ +
+
+ + + + + + + + + + + + {analyticsData.topPerformingResellers.map((reseller, index) => ( + + + + + + + + ))} + +
ResellerRevenueDealsGrowthStatus
+
+
+ +
+ {reseller.name} +
+
+ ${(reseller.revenue / 1000).toFixed(0)}K + + {reseller.deals} + +
+ {getGrowthIcon(reseller.growth)} + + {reseller.growth}% + +
+
+ + Active + +
+
+
+ + {/* Regional Performance */} +
+

Regional Performance

+
+ {analyticsData.regionalPerformance.map((region, index) => ( +
+
+

{region.region}

+
+ {getGrowthIcon(region.growth)} + + {region.growth}% + +
+
+

+ ${(region.revenue / 1000).toFixed(0)}K +

+

Revenue

+
+ ))} +
+
+ + {/* Export Options */} +
+
+
+

Export Analytics

+

Download analytics data in various formats

+
+
+ + + +
+
+
+
+ ); +}; + +export default Analytics; \ No newline at end of file diff --git a/src/pages/Reports.tsx b/src/pages/Reports.tsx new file mode 100644 index 0000000..e417e92 --- /dev/null +++ b/src/pages/Reports.tsx @@ -0,0 +1,359 @@ +import React, { useState } from 'react'; +import { + FileText, + Download, + Calendar, + Filter, + Search, + Eye, + EyeOff, + BarChart3, + TrendingUp, + Users, + DollarSign, + ShoppingCart, + Award, + Clock, + CheckCircle, + AlertCircle, + Star, + RefreshCw, + Settings, + Plus +} from 'lucide-react'; + +interface Report { + id: string; + name: string; + type: 'revenue' | 'performance' | 'commission' | 'analytics' | 'custom'; + description: string; + lastGenerated: string; + status: 'ready' | 'generating' | 'failed'; + size: string; + format: 'pdf' | 'excel' | 'csv'; +} + +const Reports: React.FC = () => { + const [selectedReportType, setSelectedReportType] = useState('all'); + const [searchQuery, setSearchQuery] = useState(''); + const [showGenerateReport, setShowGenerateReport] = useState(false); + + // Mock data + const reports: Report[] = [ + { + id: 'REP-001', + name: 'Monthly Revenue Report', + type: 'revenue', + description: 'Comprehensive monthly revenue analysis with growth metrics', + lastGenerated: '2024-01-15T10:30:00Z', + status: 'ready', + size: '2.4 MB', + format: 'pdf' + }, + { + id: 'REP-002', + name: 'Reseller Performance Report', + type: 'performance', + description: 'Detailed performance metrics for all resellers', + lastGenerated: '2024-01-14T14:20:00Z', + status: 'ready', + size: '1.8 MB', + format: 'excel' + }, + { + id: 'REP-003', + name: 'Commission Statement', + type: 'commission', + description: 'Monthly commission calculations and payouts', + lastGenerated: '2024-01-13T09:15:00Z', + status: 'ready', + size: '3.1 MB', + format: 'pdf' + }, + { + id: 'REP-004', + name: 'Sales Analytics Report', + type: 'analytics', + description: 'Advanced sales analytics and trend analysis', + lastGenerated: '2024-01-12T16:45:00Z', + status: 'generating', + size: '4.2 MB', + format: 'excel' + }, + { + id: 'REP-005', + name: 'Custom Performance Report', + type: 'custom', + description: 'Custom report with specific metrics and filters', + lastGenerated: '2024-01-11T11:30:00Z', + status: 'failed', + size: '0 MB', + format: 'csv' + } + ]; + + const reportTypes = [ + { id: 'all', name: 'All Reports', icon: FileText }, + { id: 'revenue', name: 'Revenue Reports', icon: DollarSign }, + { id: 'performance', name: 'Performance Reports', icon: TrendingUp }, + { id: 'commission', name: 'Commission Reports', icon: Award }, + { id: 'analytics', name: 'Analytics Reports', icon: BarChart3 }, + { id: 'custom', name: 'Custom Reports', icon: Settings } + ]; + + const getStatusColor = (status: string) => { + switch (status) { + case 'ready': return 'bg-success-100 text-success-800 dark:bg-success-900 dark:text-success-300'; + case 'generating': return 'bg-warning-100 text-warning-800 dark:bg-warning-900 dark:text-warning-300'; + case 'failed': return 'bg-danger-100 text-danger-800 dark:bg-danger-900 dark:text-danger-300'; + default: return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'; + } + }; + + const getStatusIcon = (status: string) => { + switch (status) { + case 'ready': return ; + case 'generating': return ; + case 'failed': return ; + default: return ; + } + }; + + const getTypeIcon = (type: string) => { + switch (type) { + case 'revenue': return ; + case 'performance': return ; + case 'commission': return ; + case 'analytics': return ; + case 'custom': return ; + default: return ; + } + }; + + const filteredReports = reports.filter(report => { + const matchesSearch = report.name.toLowerCase().includes(searchQuery.toLowerCase()) || + report.description.toLowerCase().includes(searchQuery.toLowerCase()); + const matchesType = selectedReportType === 'all' || report.type === selectedReportType; + + return matchesSearch && matchesType; + }); + + return ( +
+ {/* Header */} +
+
+
+ +
+
+

+ Reports Center +

+

+ Generate and manage business reports +

+
+
+ +
+ + {/* Report Type Filter */} +
+

Report Types

+
+ {reportTypes.map((type) => ( + + ))} +
+
+ + {/* Search and Filters */} +
+
+
+
+ + setSearchQuery(e.target.value)} + className="input pl-10 w-full" + /> +
+
+
+ + +
+
+
+ + {/* Reports List */} +
+ {filteredReports.map((report) => ( +
+
+
+
+
+ {getTypeIcon(report.type)} +
+
+
+
+

{report.name}

+ + {getStatusIcon(report.status)} + {report.status} + +
+

{report.description}

+
+
+ + Generated: {new Date(report.lastGenerated).toLocaleDateString()} +
+
+ + Size: {report.size} +
+
+ {report.format} +
+
+
+
+
+ + {report.status === 'ready' && ( + + )} + +
+
+
+ ))} +
+ + {/* Quick Actions */} +
+

Quick Actions

+
+ + + + +
+
+ + {/* Generate Report Modal */} + {showGenerateReport && ( +
+
+

Generate New Report

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ )} +
+ ); +}; + +export default Reports; \ No newline at end of file diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx new file mode 100644 index 0000000..224d90f --- /dev/null +++ b/src/pages/Settings.tsx @@ -0,0 +1,471 @@ +import React, { useState } from 'react'; +import { + Settings as SettingsIcon, + User, + Shield, + Bell, + Palette, + Globe, + CreditCard, + Database, + Save, + Eye, + EyeOff, + Check, + X, + Plus, + Trash2, + Edit, + Download, + Upload, + Key, + Mail, + Phone, + MapPin +} from 'lucide-react'; + +const Settings: React.FC = () => { + const [activeTab, setActiveTab] = useState('profile'); + const [showPassword, setShowPassword] = useState(false); + const [notifications, setNotifications] = useState({ + email: true, + sms: false, + push: true, + marketing: false + }); + + const tabs = [ + { id: 'profile', name: 'Profile', icon: User }, + { id: 'security', name: 'Security', icon: Shield }, + { id: 'notifications', name: 'Notifications', icon: Bell }, + { id: 'appearance', name: 'Appearance', icon: Palette }, + { id: 'billing', name: 'Billing', icon: CreditCard }, + { id: 'integrations', name: 'Integrations', icon: Database } + ]; + + return ( +
+ {/* Header */} +
+
+
+ +
+
+

+ Settings +

+

+ Manage your account preferences and settings +

+
+
+
+ +
+ {/* Sidebar Navigation */} +
+
+ +
+
+ + {/* Main Content */} +
+ {/* Profile Settings */} + {activeTab === 'profile' && ( +
+
+

Profile Information

+
+
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ +
+
+
+
+ )} + + {/* Security Settings */} + {activeTab === 'security' && ( +
+
+

Password & Security

+
+
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+
+ +
+

Two-Factor Authentication

+
+
+

Add an extra layer of security to your account

+

Currently disabled

+
+ +
+
+ +
+

Active Sessions

+
+
+
+

Chrome on Windows

+

Last active: 2 hours ago

+
+ +
+
+
+

Safari on iPhone

+

Last active: 1 day ago

+
+ +
+
+
+
+ )} + + {/* Notification Settings */} + {activeTab === 'notifications' && ( +
+

Notification Preferences

+
+
+
+
+

Email Notifications

+

Receive notifications via email

+
+ +
+ +
+
+

SMS Notifications

+

Receive notifications via SMS

+
+ +
+ +
+
+

Push Notifications

+

Receive push notifications in browser

+
+ +
+ +
+
+

Marketing Emails

+

Receive marketing and promotional emails

+
+ +
+
+ +
+ +
+
+
+ )} + + {/* Appearance Settings */} + {activeTab === 'appearance' && ( +
+

Appearance & Theme

+
+
+

Theme

+
+ + + +
+
+ +
+

Language

+ +
+ +
+

Time Zone

+ +
+ +
+ +
+
+
+ )} + + {/* Billing Settings */} + {activeTab === 'billing' && ( +
+
+

Billing Information

+
+
+
+

Current Plan

+

Professional Plan - $99/month

+
+ +
+ +
+

Payment Method

+
+
+ +
+

•••• •••• •••• 4242

+

Expires 12/25

+
+
+ +
+
+ +
+

Billing Address

+
+ + + + +
+
+
+
+
+ )} + + {/* Integrations Settings */} + {activeTab === 'integrations' && ( +
+

Integrations

+
+
+
+
+ +
+
+

Salesforce

+

Sync your sales data

+
+
+ +
+ +
+
+
+ +
+
+

Mailchimp

+

Email marketing integration

+
+
+ +
+ +
+
+
+ +
+
+

Zapier

+

Automate workflows

+
+
+ +
+
+
+ )} +
+
+
+ ); +}; + +export default Settings; \ No newline at end of file diff --git a/src/pages/Support.tsx b/src/pages/Support.tsx new file mode 100644 index 0000000..59931f2 --- /dev/null +++ b/src/pages/Support.tsx @@ -0,0 +1,688 @@ +import React, { useState } from 'react'; +import { + Headphones, + MessageCircle, + FileText, + Search, + Plus, + Edit, + Trash2, + Eye, + EyeOff, + Settings, + CheckCircle, + Clock, + AlertCircle, + Star, + Filter, + Download, + Send, + User, + Calendar, + Tag, + X +} from 'lucide-react'; +import SupportAdmin from '../components/SupportAdmin'; + +interface SupportTicket { + id: string; + title: string; + description: string; + status: 'open' | 'in_progress' | 'resolved' | 'closed'; + priority: 'low' | 'medium' | 'high' | 'urgent'; + category: 'technical' | 'billing' | 'account' | 'general'; + submittedBy: string; + assignedTo: string; + createdAt: string; + updatedAt: string; + messages: TicketMessage[]; +} + +interface TicketMessage { + id: string; + content: string; + sender: string; + timestamp: string; + isInternal: boolean; +} + +interface FAQ { + id: string; + question: string; + answer: string; + category: string; + tags: string[]; + helpful: number; + notHelpful: number; +} + +interface SupportResource { + id: string; + title: string; + description: string; + type: 'documentation' | 'video' | 'guide' | 'tutorial'; + url: string; + category: string; + tags: string[]; +} + +const Support: React.FC = () => { + const [currentView, setCurrentView] = useState<'tickets' | 'faqs' | 'resources' | 'admin'>('tickets'); + const [isAdminMode, setIsAdminMode] = useState(false); + const [selectedTicket, setSelectedTicket] = useState(null); + const [showNewTicket, setShowNewTicket] = useState(false); + const [showNewFAQ, setShowNewFAQ] = useState(false); + const [showNewResource, setShowNewResource] = useState(false); + const [searchQuery, setSearchQuery] = useState(''); + const [filterStatus, setFilterStatus] = useState('all'); + const [filterPriority, setFilterPriority] = useState('all'); + const [filterCategory, setFilterCategory] = useState('all'); + + // Mock data + const supportTickets: SupportTicket[] = [ + { + id: 'TICKET-001', + title: 'Commission calculation issue', + description: 'The commission calculation seems incorrect for the last month. Need assistance to verify the calculations.', + status: 'open', + priority: 'high', + category: 'billing', + submittedBy: 'John Smith', + assignedTo: 'Support Team', + createdAt: '2024-01-15T10:30:00Z', + updatedAt: '2024-01-15T14:20:00Z', + messages: [ + { + id: 'MSG-001', + content: 'I noticed that my commission for December 2023 is showing $2,500 but I expected $3,200 based on my sales.', + sender: 'John Smith', + timestamp: '2024-01-15T10:30:00Z', + isInternal: false + }, + { + id: 'MSG-002', + content: 'Thank you for reporting this issue. I\'m investigating the commission calculation for your account.', + sender: 'Support Team', + timestamp: '2024-01-15T11:15:00Z', + isInternal: false + } + ] + }, + { + id: 'TICKET-002', + title: 'Dashboard not loading properly', + description: 'The dashboard is taking too long to load and some widgets are not displaying correctly.', + status: 'in_progress', + priority: 'medium', + category: 'technical', + submittedBy: 'Sarah Johnson', + assignedTo: 'Technical Team', + createdAt: '2024-01-14T09:15:00Z', + updatedAt: '2024-01-15T08:45:00Z', + messages: [ + { + id: 'MSG-003', + content: 'Dashboard has been slow for the past 2 days. Sometimes it takes 30+ seconds to load.', + sender: 'Sarah Johnson', + timestamp: '2024-01-14T09:15:00Z', + isInternal: false + } + ] + } + ]; + + const faqs: FAQ[] = [ + { + id: 'FAQ-001', + question: 'How do I calculate my commission?', + answer: 'Your commission is calculated based on your sales volume and the commission rate for your tier. You can view detailed calculations in the Commission section of your dashboard.', + category: 'billing', + tags: ['commission', 'billing', 'calculation'], + helpful: 45, + notHelpful: 2 + }, + { + id: 'FAQ-002', + question: 'How do I add new resellers to my network?', + answer: 'To add new resellers, go to the Resellers section and click "Add New Reseller". Fill in the required information and submit the form.', + category: 'account', + tags: ['resellers', 'network', 'management'], + helpful: 32, + notHelpful: 1 + } + ]; + + const supportResources: SupportResource[] = [ + { + id: 'RES-001', + title: 'Getting Started Guide', + description: 'Complete guide for new channel partners to get started with the platform.', + type: 'guide', + url: '/guides/getting-started', + category: 'onboarding', + tags: ['beginner', 'setup', 'guide'] + }, + { + id: 'RES-002', + title: 'Commission System Overview', + description: 'Detailed explanation of how the commission system works.', + type: 'documentation', + url: '/docs/commission-system', + category: 'billing', + tags: ['commission', 'billing', 'system'] + } + ]; + + const getStatusColor = (status: string) => { + switch (status) { + case 'open': return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300'; + case 'in_progress': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300'; + case 'resolved': return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300'; + case 'closed': return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'; + default: return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'; + } + }; + + const getPriorityColor = (priority: string) => { + switch (priority) { + case 'urgent': return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300'; + case 'high': return 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300'; + case 'medium': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300'; + case 'low': return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300'; + default: return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'; + } + }; + + const filteredTickets = supportTickets.filter(ticket => { + const matchesSearch = ticket.title.toLowerCase().includes(searchQuery.toLowerCase()) || + ticket.description.toLowerCase().includes(searchQuery.toLowerCase()); + const matchesStatus = filterStatus === 'all' || ticket.status === filterStatus; + const matchesPriority = filterPriority === 'all' || ticket.priority === filterPriority; + const matchesCategory = filterCategory === 'all' || ticket.category === filterCategory; + + return matchesSearch && matchesStatus && matchesPriority && matchesCategory; + }); + + return ( +
+ {/* Header */} +
+
+
+ +
+
+

+ Support Center +

+

+ Manage support tickets, FAQs, and resources +

+
+
+
+ {/* View Toggle Buttons */} +
+ + + + +
+ + {/* Admin Actions */} + {currentView === 'tickets' && ( + + )} +
+
+ + {/* Content Based on Current View */} + {currentView === 'tickets' && ( +
+ {/* Search and Filters */} +
+
+
+
+ + setSearchQuery(e.target.value)} + className="input pl-10 w-full" + /> +
+
+
+ + + +
+
+
+ + {/* Tickets List */} +
+ {filteredTickets.map((ticket) => ( +
setSelectedTicket(ticket)}> +
+
+
+

{ticket.title}

+ + {ticket.status.replace('_', ' ')} + + + {ticket.priority} + +
+

{ticket.description}

+
+
+ + {ticket.submittedBy} +
+
+ + {new Date(ticket.createdAt).toLocaleDateString()} +
+
+ + {ticket.messages.length} messages +
+
+
+
+ + {isAdminMode && ( + <> + + + + )} +
+
+
+ ))} +
+
+ )} + + {currentView === 'faqs' && ( +
+
+
+

Frequently Asked Questions

+ {isAdminMode && ( + + )} +
+
+ {faqs.map((faq) => ( +
+
+
+

{faq.question}

+

{faq.answer}

+
+ Category: {faq.category} + Helpful: {faq.helpful} + Not Helpful: {faq.notHelpful} +
+
+ {isAdminMode && ( +
+ + +
+ )} +
+
+ ))} +
+
+
+ )} + + {currentView === 'resources' && ( +
+
+
+

Support Resources

+ {isAdminMode && ( + + )} +
+
+ {supportResources.map((resource) => ( +
+
+
+ +
+
+

{resource.title}

+

{resource.type}

+
+
+

{resource.description}

+
+
+ {resource.tags.slice(0, 2).map((tag) => ( + + {tag} + + ))} +
+
+ + View + + {isAdminMode && ( + <> + + + + )} +
+
+
+ ))} +
+
+
+ )} + + {currentView === 'admin' && ( + { + console.log('Updating ticket:', id, updates); + // Handle ticket update + }} + onTicketDelete={(id) => { + console.log('Deleting ticket:', id); + // Handle ticket deletion + }} + onFAQAdd={(faq) => { + console.log('Adding FAQ:', faq); + // Handle FAQ addition + }} + onFAQUpdate={(id, updates) => { + console.log('Updating FAQ:', id, updates); + // Handle FAQ update + }} + onFAQDelete={(id) => { + console.log('Deleting FAQ:', id); + // Handle FAQ deletion + }} + onResourceAdd={(resource) => { + console.log('Adding resource:', resource); + // Handle resource addition + }} + onResourceUpdate={(id, updates) => { + console.log('Updating resource:', id, updates); + // Handle resource update + }} + onResourceDelete={(id) => { + console.log('Deleting resource:', id); + // Handle resource deletion + }} + onExportReport={(type) => { + console.log('Exporting report:', type); + // Handle report export + }} + /> + )} + + {/* Ticket Detail Modal */} + {selectedTicket && ( +
+
+
+
+

{selectedTicket.title}

+ +
+
+
+
+
+

Ticket Details

+
+
+ Status: + + {selectedTicket.status.replace('_', ' ')} + +
+
+ Priority: + + {selectedTicket.priority} + +
+
+ Category: + {selectedTicket.category} +
+
+ Submitted by: + {selectedTicket.submittedBy} +
+
+
+
+

Description

+

{selectedTicket.description}

+
+
+ +
+

Messages

+
+ {selectedTicket.messages.map((message) => ( +
+
+
+ +
+
+
+
+

{message.content}

+
+
+ {message.sender} + + {new Date(message.timestamp).toLocaleString()} +
+
+
+ ))} +
+
+
+ + +
+
+
+
+
+
+ )} + + {/* New Ticket Modal */} + {showNewTicket && ( +
+
+

Create New Ticket

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+
+ )} +
+ ); +}; + +export default Support; \ No newline at end of file diff --git a/src/pages/Training.tsx b/src/pages/Training.tsx new file mode 100644 index 0000000..d865c80 --- /dev/null +++ b/src/pages/Training.tsx @@ -0,0 +1,1141 @@ +import React, { useState } from 'react'; +import { + Play, + BookOpen, + Download, + ExternalLink, + CheckCircle, + Clock, + Users, + Award, + Video, + FileText, + Headphones, + Globe, + ChevronDown, + ChevronUp, + Plus, + Edit, + Trash2, + Settings, + Save, + X, + Upload, + Eye, + EyeOff +} from 'lucide-react'; +import TrainingAdmin from '../components/TrainingAdmin'; +import TrainingAnalytics from '../components/TrainingAnalytics'; + +interface TrainingModule { + id: string; + title: string; + description: string; + duration: string; + level: 'Beginner' | 'Intermediate' | 'Advanced'; + category: string; + videos: TrainingVideo[]; + materials: TrainingMaterial[]; + completed: boolean; +} + +interface TrainingVideo { + id: string; + title: string; + description: string; + youtubeUrl: string; + duration: string; + thumbnail: string; +} + +interface TrainingMaterial { + id: string; + title: string; + description: string; + type: 'PDF' | 'PPT' | 'DOC' | 'VIDEO'; + downloadUrl: string; + size: string; +} + +const Training: React.FC = () => { + const [expandedModule, setExpandedModule] = useState(null); + const [selectedCategory, setSelectedCategory] = useState('all'); + const [isAdminMode, setIsAdminMode] = useState(false); + const [editingModule, setEditingModule] = useState(null); + const [editingVideo, setEditingVideo] = useState(null); + const [editingMaterial, setEditingMaterial] = useState(null); + const [showAddModule, setShowAddModule] = useState(false); + const [showAddVideo, setShowAddVideo] = useState(false); + const [showAddMaterial, setShowAddMaterial] = useState(false); + const [selectedModuleForAdd, setSelectedModuleForAdd] = useState(''); + const [showAnalytics, setShowAnalytics] = useState(false); + const [currentView, setCurrentView] = useState<'training' | 'admin' | 'analytics'>('training'); + + const trainingModules: TrainingModule[] = [ + { + id: 'getting-started', + title: 'Getting Started with Cloudtopiaa', + description: 'Learn the basics of the Cloudtopiaa platform and how to navigate the reseller portal.', + duration: '2 hours', + level: 'Beginner', + category: 'Platform Basics', + completed: false, + videos: [ + { + id: 'intro-video', + title: 'Introduction to Cloudtopiaa Reseller Portal', + description: 'Overview of the platform features and navigation', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '15:30', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg' + }, + { + id: 'dashboard-tour', + title: 'Dashboard Tour and Key Features', + description: 'Detailed walkthrough of the dashboard and main features', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '22:15', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg' + } + ], + materials: [ + { + id: 'quick-start-guide', + title: 'Quick Start Guide', + description: 'Step-by-step guide to get started', + type: 'PDF', + downloadUrl: '#', + size: '2.5 MB' + }, + { + id: 'platform-overview', + title: 'Platform Overview Presentation', + description: 'Comprehensive overview of all features', + type: 'PPT', + downloadUrl: '#', + size: '8.1 MB' + } + ] + }, + { + id: 'sales-strategies', + title: 'Sales Strategies and Best Practices', + description: 'Master the art of selling cloud services and maximizing your commissions.', + duration: '4 hours', + level: 'Intermediate', + category: 'Sales & Marketing', + completed: false, + videos: [ + { + id: 'sales-techniques', + title: 'Effective Sales Techniques for Cloud Services', + description: 'Learn proven sales strategies for cloud solutions', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '28:45', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg' + }, + { + id: 'customer-presentation', + title: 'Customer Presentation Skills', + description: 'How to present cloud solutions to potential customers', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '35:20', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg' + } + ], + materials: [ + { + id: 'sales-playbook', + title: 'Sales Playbook', + description: 'Complete sales strategy guide', + type: 'PDF', + downloadUrl: '#', + size: '5.2 MB' + }, + { + id: 'presentation-templates', + title: 'Presentation Templates', + description: 'Ready-to-use presentation templates', + type: 'PPT', + downloadUrl: '#', + size: '12.3 MB' + } + ] + }, + { + id: 'technical-deep-dive', + title: 'Technical Deep Dive: Cloud Services', + description: 'Advanced technical training on cloud infrastructure and services.', + duration: '6 hours', + level: 'Advanced', + category: 'Technical', + completed: false, + videos: [ + { + id: 'cloud-architecture', + title: 'Cloud Architecture Fundamentals', + description: 'Understanding cloud infrastructure and architecture', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '42:10', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg' + }, + { + id: 'security-best-practices', + title: 'Security Best Practices', + description: 'Implementing security measures in cloud environments', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '38:25', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg' + } + ], + materials: [ + { + id: 'technical-whitepaper', + title: 'Technical Whitepaper', + description: 'In-depth technical documentation', + type: 'PDF', + downloadUrl: '#', + size: '15.7 MB' + }, + { + id: 'architecture-diagrams', + title: 'Architecture Diagrams', + description: 'Visual guides for cloud architecture', + type: 'PDF', + downloadUrl: '#', + size: '8.9 MB' + } + ] + }, + { + id: 'commission-system', + title: 'Commission System and Revenue Optimization', + description: 'Understand the commission structure and learn how to maximize your earnings.', + duration: '3 hours', + level: 'Intermediate', + category: 'Business', + completed: false, + videos: [ + { + id: 'commission-structure', + title: 'Understanding Commission Structure', + description: 'Detailed breakdown of commission rates and tiers', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '25:30', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg' + }, + { + id: 'revenue-optimization', + title: 'Revenue Optimization Strategies', + description: 'Tips and tricks to maximize your commission earnings', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '31:45', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg' + } + ], + materials: [ + { + id: 'commission-guide', + title: 'Commission Guide', + description: 'Complete guide to commission structure', + type: 'PDF', + downloadUrl: '#', + size: '3.8 MB' + }, + { + id: 'revenue-calculator', + title: 'Revenue Calculator Tool', + description: 'Excel tool to calculate potential earnings', + type: 'DOC', + downloadUrl: '#', + size: '1.2 MB' + } + ] + } + ]; + + const categories = ['all', 'Platform Basics', 'Sales & Marketing', 'Technical', 'Business']; + + const filteredModules = selectedCategory === 'all' + ? trainingModules + : trainingModules.filter(module => module.category === selectedCategory); + + // Analytics data + const analyticsData = { + totalModules: trainingModules.length, + totalVideos: trainingModules.reduce((acc, module) => acc + module.videos.length, 0), + totalMaterials: trainingModules.reduce((acc, module) => acc + module.materials.length, 0), + totalResellers: 156, + activeResellers: 142, + completedModules: trainingModules.filter(m => m.completed).length, + averageCompletionTime: '2.5 hours', + popularCategories: [ + { name: 'Platform Basics', count: 45, percentage: 35 }, + { name: 'Sales & Marketing', count: 38, percentage: 29 }, + { name: 'Technical', count: 28, percentage: 22 }, + { name: 'Business', count: 18, percentage: 14 } + ], + completionRates: [ + { month: 'Jan', rate: 75 }, + { month: 'Feb', rate: 82 }, + { month: 'Mar', rate: 78 }, + { month: 'Apr', rate: 85 }, + { month: 'May', rate: 88 }, + { month: 'Jun', rate: 91 } + ], + topPerformingModules: [ + { name: 'Getting Started with Cloudtopiaa', completionRate: 95, avgTime: '1.8 hours' }, + { name: 'Sales Strategies and Best Practices', completionRate: 87, avgTime: '3.2 hours' }, + { name: 'Technical Deep Dive: Cloud Services', completionRate: 72, avgTime: '5.1 hours' }, + { name: 'Commission System and Revenue Optimization', completionRate: 89, avgTime: '2.7 hours' } + ], + resellerProgress: [ + { name: 'John Smith', completed: 8, total: 10, percentage: 80 }, + { name: 'Sarah Johnson', completed: 6, total: 10, percentage: 60 }, + { name: 'Mike Davis', completed: 9, total: 10, percentage: 90 }, + { name: 'Lisa Wilson', completed: 7, total: 10, percentage: 70 }, + { name: 'David Brown', completed: 5, total: 10, percentage: 50 } + ], + recentActivity: [ + { type: 'completion', description: 'Completed "Getting Started with Cloudtopiaa" module', timestamp: '2 hours ago', user: 'John Smith' }, + { type: 'started', description: 'Started "Technical Deep Dive" module', timestamp: '4 hours ago', user: 'Sarah Johnson' }, + { type: 'completion', description: 'Completed "Sales Strategies" module', timestamp: '1 day ago', user: 'Mike Davis' }, + { type: 'warning', description: 'Module "Commission System" needs attention', timestamp: '2 days ago', user: 'Lisa Wilson' }, + { type: 'completion', description: 'Completed all modules successfully', timestamp: '3 days ago', user: 'David Brown' } + ] + }; + + const getLevelColor = (level: string) => { + switch (level) { + case 'Beginner': return 'bg-success-100 text-success-800 dark:bg-success-900 dark:text-success-300'; + case 'Intermediate': return 'bg-warning-100 text-warning-800 dark:bg-warning-900 dark:text-warning-300'; + case 'Advanced': return 'bg-danger-100 text-danger-800 dark:bg-danger-900 dark:text-danger-300'; + default: return 'bg-secondary-100 text-secondary-800 dark:bg-secondary-900 dark:text-secondary-300'; + } + }; + + const toggleModule = (moduleId: string) => { + setExpandedModule(expandedModule === moduleId ? null : moduleId); + }; + + const handleDeleteModule = (moduleId: string) => { + if (window.confirm('Are you sure you want to delete this training module? This action cannot be undone.')) { + // Handle module deletion + console.log('Deleting module:', moduleId); + } + }; + + const handleDeleteVideo = (moduleId: string, videoId: string) => { + if (window.confirm('Are you sure you want to delete this video?')) { + // Handle video deletion + console.log('Deleting video:', videoId, 'from module:', moduleId); + } + }; + + const handleDeleteMaterial = (moduleId: string, materialId: string) => { + if (window.confirm('Are you sure you want to delete this material?')) { + // Handle material deletion + console.log('Deleting material:', materialId, 'from module:', moduleId); + } + }; + + // Enhanced CRUD functions + const handleModuleAdd = (module: Omit) => { + const newModule: TrainingModule = { + ...module, + id: `module-${Date.now()}`, + videos: [], + materials: [], + completed: false + }; + console.log('Adding new module:', newModule); + // Here you would typically update your state or make an API call + }; + + const handleModuleUpdate = (id: string, updates: Partial) => { + console.log('Updating module:', id, updates); + // Here you would typically update your state or make an API call + }; + + const handleModuleDelete = (id: string) => { + if (window.confirm('Are you sure you want to delete this module? This action cannot be undone.')) { + console.log('Deleting module:', id); + // Here you would typically update your state or make an API call + } + }; + + const handleVideoAdd = (moduleId: string, video: Omit) => { + const newVideo: TrainingVideo = { + ...video, + id: `video-${Date.now()}`, + thumbnail: `https://img.youtube.com/vi/${video.youtubeUrl.split('v=')[1]}/maxresdefault.jpg` + }; + console.log('Adding video to module:', moduleId, newVideo); + // Here you would typically update your state or make an API call + }; + + const handleVideoUpdate = (moduleId: string, videoId: string, updates: Partial) => { + console.log('Updating video:', moduleId, videoId, updates); + // Here you would typically update your state or make an API call + }; + + const handleVideoDelete = (moduleId: string, videoId: string) => { + if (window.confirm('Are you sure you want to delete this video?')) { + console.log('Deleting video:', moduleId, videoId); + // Here you would typically update your state or make an API call + } + }; + + const handleMaterialAdd = (moduleId: string, material: Omit) => { + const newMaterial: TrainingMaterial = { + ...material, + id: `material-${Date.now()}`, + downloadUrl: '#' + }; + console.log('Adding material to module:', moduleId, newMaterial); + // Here you would typically update your state or make an API call + }; + + const handleMaterialUpdate = (moduleId: string, materialId: string, updates: Partial) => { + console.log('Updating material:', moduleId, materialId, updates); + // Here you would typically update your state or make an API call + }; + + const handleMaterialDelete = (moduleId: string, materialId: string) => { + if (window.confirm('Are you sure you want to delete this material?')) { + console.log('Deleting material:', moduleId, materialId); + // Here you would typically update your state or make an API call + } + }; + + const handleExportReport = (type: 'pdf' | 'excel' | 'csv') => { + console.log(`Exporting ${type} report...`); + // Here you would typically generate and download the report + }; + + const handleDateRangeChange = (startDate: string, endDate: string) => { + console.log('Date range changed:', startDate, endDate); + // Here you would typically filter analytics data + }; + + return ( +
+ {/* Header */} +
+
+
+ +
+
+

+ Training Center +

+

+ Master the Cloudtopiaa platform and maximize your success +

+
+
+
+ {/* View Toggle Buttons */} +
+ + + +
+ + {/* Admin Actions */} + {currentView === 'admin' && ( + + )} +
+
+ + {/* Content Based on Current View */} + {currentView === 'training' && ( + <> + {/* How It Works Section */} +
+

How Training Works

+
+
+
+ +
+

1. Choose Your Path

+

Select from beginner, intermediate, or advanced training modules based on your experience level.

+
+
+
+
+

2. Watch & Learn

+

Access high-quality video tutorials, webinars, and interactive content designed for resellers.

+
+
+
+ +
+

3. Get Certified

+

Complete assessments and earn certifications to demonstrate your expertise to customers.

+
+
+
+ + )} + + {currentView === 'analytics' && ( + + )} + + {currentView === 'admin' && ( + + )} + + {/* Category Filter and Training Modules - Only show in training view */} + {currentView === 'training' && ( + <> + {/* Category Filter */} +
+
+ {categories.map((category) => ( + + ))} +
+
+ + {/* Training Modules */} +
+ {filteredModules.map((module) => ( +
+
toggleModule(module.id)} + > +
+
+
+ {module.completed ? ( + + ) : ( +
+ )} +
+
+
+

{module.title}

+ + {module.level} + +
+

{module.description}

+
+
+ + {module.duration} +
+
+
+
+ + {module.materials.length} materials +
+
+
+
+
+ {isAdminMode && ( +
+ + +
+ )} + {expandedModule === module.id ? ( + + ) : ( + + )} +
+
+
+ + {/* Expanded Content */} + {expandedModule === module.id && ( +
+ {/* Videos Section */} +
+
+

+

+ {isAdminMode && ( + + )} +
+
+ {module.videos.map((video) => ( +
+
+ {video.title} +
+ +
+
+
+
{video.title}
+

{video.description}

+
+ {video.duration} +
+ + Watch + + {isAdminMode && ( + <> + + + + )} +
+
+
+
+ ))} +
+
+ + {/* Materials Section */} +
+
+

+ + Training Materials +

+ {isAdminMode && ( + + )} +
+
+ {module.materials.map((material) => ( +
+
+
+
+ +
+
+
+
{material.title}
+

{material.description}

+
+ {material.size} +
+ + Download + + {isAdminMode && ( + <> + + + + )} +
+
+
+
+
+ ))} +
+
+
+ )} +
+ ))} +
+ + )} + + {/* Additional Resources */} +
+

Additional Resources

+
+
+
+ +

Live Webinars

+
+

Join our weekly live webinars with industry experts and get your questions answered in real-time.

+ +
+ +
+
+ +

Community Forum

+
+

Connect with other resellers, share experiences, and learn from the community.

+ +
+ +
+
+ +

Knowledge Base

+
+

Access comprehensive documentation, FAQs, and troubleshooting guides.

+ +
+
+
+ + {/* Certification Path */} +
+
+ +

Get Certified

+

+ Complete our training modules and earn professional certifications to boost your credibility and sales. +

+
+
+ Beginner Certification +
+
+ Advanced Certification +
+
+ Expert Certification +
+
+
+
+ + {/* Admin Modals */} + {showAddModule && ( +
+
+

Add New Training Module

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+
+ )} + + {showAddVideo && ( +
+
+

Add New Video

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ )} + + {showAddMaterial && ( +
+
+

Add New Material

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
+ +

Click to upload or drag and drop

+
+
+
+ + +
+
+
+
+ )} + + {/* Edit Modals */} + {editingModule && ( +
+
+

Edit Training Module

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+
+ )} + + {editingVideo && ( +
+
+

Edit Video

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ )} + + {editingMaterial && ( +
+
+

Edit Material

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+
+ )} +
+ ); +}; + +export default Training; \ No newline at end of file diff --git a/src/pages/reseller/Training.tsx b/src/pages/reseller/Training.tsx new file mode 100644 index 0000000..ab101d8 --- /dev/null +++ b/src/pages/reseller/Training.tsx @@ -0,0 +1,637 @@ +import React, { useState } from 'react'; +import { + Play, + BookOpen, + Download, + ExternalLink, + CheckCircle, + Clock, + Users, + Award, + Video, + FileText, + Headphones, + Globe, + Star, + ChevronDown, + ChevronUp, + Target, + TrendingUp, + Shield, + Settings, + EyeOff +} from 'lucide-react'; + +interface TrainingModule { + id: string; + title: string; + description: string; + duration: string; + level: 'Beginner' | 'Intermediate' | 'Advanced'; + category: string; + videos: TrainingVideo[]; + materials: TrainingMaterial[]; + completed: boolean; + progress: number; +} + +interface TrainingVideo { + id: string; + title: string; + description: string; + youtubeUrl: string; + duration: string; + thumbnail: string; + watched: boolean; +} + +interface TrainingMaterial { + id: string; + title: string; + description: string; + type: 'PDF' | 'PPT' | 'DOC' | 'VIDEO'; + downloadUrl: string; + size: string; + downloaded: boolean; +} + +const ResellerTraining: React.FC = () => { + const [expandedModule, setExpandedModule] = useState(null); + const [selectedCategory, setSelectedCategory] = useState('all'); + const [isAdminMode, setIsAdminMode] = useState(false); + + const trainingModules: TrainingModule[] = [ + { + id: 'reseller-basics', + title: 'Reseller Portal Mastery', + description: 'Master the reseller dashboard, customer management, and basic operations.', + duration: '3 hours', + level: 'Beginner', + category: 'Portal Basics', + completed: false, + progress: 65, + videos: [ + { + id: 'dashboard-overview', + title: 'Reseller Dashboard Overview', + description: 'Complete tour of your reseller dashboard and key features', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '18:45', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg', + watched: true + }, + { + id: 'customer-management', + title: 'Customer Management Best Practices', + description: 'How to effectively manage your customer base and relationships', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '25:30', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg', + watched: false + } + ], + materials: [ + { + id: 'reseller-handbook', + title: 'Reseller Handbook', + description: 'Complete guide to reseller operations', + type: 'PDF', + downloadUrl: '#', + size: '4.2 MB', + downloaded: true + }, + { + id: 'customer-templates', + title: 'Customer Communication Templates', + description: 'Ready-to-use email and message templates', + type: 'DOC', + downloadUrl: '#', + size: '2.1 MB', + downloaded: false + } + ] + }, + { + id: 'sales-excellence', + title: 'Sales Excellence for Resellers', + description: 'Advanced sales techniques and strategies to boost your revenue.', + duration: '5 hours', + level: 'Intermediate', + category: 'Sales', + completed: false, + progress: 30, + videos: [ + { + id: 'prospecting-techniques', + title: 'Prospecting and Lead Generation', + description: 'Effective techniques for finding and qualifying potential customers', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '32:15', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg', + watched: false + }, + { + id: 'closing-strategies', + title: 'Closing Strategies and Negotiation', + description: 'Master the art of closing deals and negotiating terms', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '28:40', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg', + watched: false + } + ], + materials: [ + { + id: 'sales-playbook', + title: 'Sales Playbook', + description: 'Comprehensive sales strategy guide', + type: 'PDF', + downloadUrl: '#', + size: '6.8 MB', + downloaded: false + }, + { + id: 'pitch-deck', + title: 'Sales Pitch Deck Templates', + description: 'Professional presentation templates', + type: 'PPT', + downloadUrl: '#', + size: '15.3 MB', + downloaded: false + } + ] + }, + { + id: 'technical-expertise', + title: 'Technical Expertise for Resellers', + description: 'Deep dive into cloud technologies and technical sales.', + duration: '8 hours', + level: 'Advanced', + category: 'Technical', + completed: false, + progress: 15, + videos: [ + { + id: 'cloud-architecture', + title: 'Cloud Architecture Fundamentals', + description: 'Understanding cloud infrastructure and deployment models', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '45:20', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg', + watched: false + }, + { + id: 'security-compliance', + title: 'Security and Compliance', + description: 'Security best practices and compliance requirements', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '38:55', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg', + watched: false + } + ], + materials: [ + { + id: 'technical-whitepaper', + title: 'Technical Solutions Guide', + description: 'In-depth technical documentation', + type: 'PDF', + downloadUrl: '#', + size: '18.7 MB', + downloaded: false + }, + { + id: 'case-studies', + title: 'Success Case Studies', + description: 'Real-world implementation examples', + type: 'PDF', + downloadUrl: '#', + size: '12.4 MB', + downloaded: false + } + ] + }, + { + id: 'business-growth', + title: 'Business Growth and Scaling', + description: 'Strategies for scaling your reseller business and maximizing profits.', + duration: '4 hours', + level: 'Intermediate', + category: 'Business', + completed: false, + progress: 0, + videos: [ + { + id: 'business-scaling', + title: 'Scaling Your Reseller Business', + description: 'Strategies for growing your customer base and revenue', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '35:10', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg', + watched: false + }, + { + id: 'profit-optimization', + title: 'Profit Optimization Strategies', + description: 'Maximizing margins and optimizing pricing strategies', + youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + duration: '29:25', + thumbnail: 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg', + watched: false + } + ], + materials: [ + { + id: 'business-plan-template', + title: 'Business Plan Template', + description: 'Template for creating your business growth plan', + type: 'DOC', + downloadUrl: '#', + size: '3.2 MB', + downloaded: false + }, + { + id: 'financial-calculator', + title: 'Financial Planning Calculator', + description: 'Excel tool for financial planning and projections', + type: 'DOC', + downloadUrl: '#', + size: '2.8 MB', + downloaded: false + } + ] + } + ]; + + const categories = ['all', 'Portal Basics', 'Sales', 'Technical', 'Business']; + + const filteredModules = selectedCategory === 'all' + ? trainingModules + : trainingModules.filter(module => module.category === selectedCategory); + + const getLevelColor = (level: string) => { + switch (level) { + case 'Beginner': return 'bg-success-100 text-success-800 dark:bg-success-900 dark:text-success-300'; + case 'Intermediate': return 'bg-warning-100 text-warning-800 dark:bg-warning-900 dark:text-warning-300'; + case 'Advanced': return 'bg-danger-100 text-danger-800 dark:bg-danger-900 dark:text-danger-300'; + default: return 'bg-secondary-100 text-secondary-800 dark:bg-secondary-900 dark:text-secondary-300'; + } + }; + + const toggleModule = (moduleId: string) => { + setExpandedModule(expandedModule === moduleId ? null : moduleId); + }; + + const totalProgress = Math.round( + trainingModules.reduce((acc, module) => acc + module.progress, 0) / trainingModules.length + ); + + return ( +
+ {/* Header */} +
+
+
+ +
+
+

+ Training Center +

+

+ Enhance your skills and grow your reseller business +

+
+
+
+
+
{totalProgress}%
+
Overall Progress
+
+ +
+
+ + {/* How It Works Section */} +
+

How Training Works

+
+
+
+ +
+

1. Set Goals

+

Choose your learning path based on your current skills and business goals.

+
+
+
+
+

2. Learn

+

Watch expert-led videos and access comprehensive training materials.

+
+
+
+ +
+

3. Apply

+

Implement what you learn to grow your business and increase sales.

+
+
+
+ +
+

4. Succeed

+

Earn certifications and achieve your business growth targets.

+
+
+
+ + {/* Progress Overview */} +
+
+
+

Modules Completed

+ +
+
0
+
out of {trainingModules.length}
+
+
+
+

Videos Watched

+
+
+ {trainingModules.reduce((acc, module) => + acc + module.videos.filter(v => v.watched).length, 0 + )} +
+
videos completed
+
+
+
+

Materials Downloaded

+ +
+
+ {trainingModules.reduce((acc, module) => + acc + module.materials.filter(m => m.downloaded).length, 0 + )} +
+
resources saved
+
+
+
+

Certifications

+ +
+
0
+
earned
+
+
+ + {/* Category Filter */} +
+
+ {categories.map((category) => ( + + ))} +
+
+ + {/* Training Modules */} +
+ {filteredModules.map((module) => ( +
+
toggleModule(module.id)} + > +
+
+
+ {module.completed ? ( + + ) : ( +
+ {module.progress}% +
+ )} +
+
+
+

{module.title}

+ + {module.level} + +
+

{module.description}

+
+
+ + {module.duration} +
+
+
+
+ + {module.materials.filter(m => m.downloaded).length}/{module.materials.length} downloaded +
+
+ {/* Progress Bar */} +
+
+
+
+
+
+
+
+ {expandedModule === module.id ? ( + + ) : ( + + )} +
+
+
+ + {/* Expanded Content */} + {expandedModule === module.id && ( +
+ {/* Videos Section */} +
+

+

+
+ {module.videos.map((video) => ( +
+
+ {video.title} +
+ +
+ {video.watched && ( +
+ Watched +
+ )} +
+
{video.title}
+

{video.description}

+
+ {video.duration} + + + Watch on YouTube + +
+
+ ))} +
+
+ + {/* Materials Section */} +
+

+ + Training Materials +

+
+ {module.materials.map((material) => ( +
+
+
+
+ +
+
+
{material.title}
+

{material.description}

+
+ {material.type} + + {material.size} + {material.downloaded && ( + <> + + Downloaded + + )} +
+
+
+ + + Download + +
+
+ ))} +
+
+
+ )} +
+ ))} +
+ + {/* Additional Resources */} +
+

Additional Resources

+
+
+
+ +

Live Q&A Sessions

+
+

Join our bi-weekly live Q&A sessions with product experts and get personalized guidance.

+ View Schedule → +
+ +
+
+ +

Reseller Community

+
+

Connect with fellow resellers, share success stories, and learn from peer experiences.

+ Join Community → +
+ +
+
+ +

Knowledge Base

+
+

Access comprehensive documentation, troubleshooting guides, and best practices.

+ Browse Articles → +
+
+
+ + {/* Certification Path */} +
+
+ +

Earn Your Certifications

+

+ Complete our training modules and earn professional certifications to boost your credibility and sales performance. +

+
+
+ Reseller Certified +
+
+ Sales Expert +
+
+ Technical Specialist +
+
+
+
+
+ ); +}; + +export default ResellerTraining; \ No newline at end of file