Cloudtopiaa_Reseller_Frontend/src/pages/Training.tsx
2025-08-11 00:47:45 +05:30

1188 lines
55 KiB
TypeScript

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<string | null>(null);
const [selectedCategory, setSelectedCategory] = useState<string>('all');
const [isAdminMode, setIsAdminMode] = useState(false);
const [editingModule, setEditingModule] = useState<TrainingModule | null>(null);
const [editingVideo, setEditingVideo] = useState<TrainingVideo | null>(null);
const [editingMaterial, setEditingMaterial] = useState<TrainingMaterial | null>(null);
const [showAddModule, setShowAddModule] = useState(false);
const [showAddVideo, setShowAddVideo] = useState(false);
const [showAddMaterial, setShowAddMaterial] = useState(false);
const [selectedModuleForAdd, setSelectedModuleForAdd] = useState<string>('');
const [showAnalytics, setShowAnalytics] = useState(false);
const [currentView, setCurrentView] = useState<'training' | 'admin' | 'analytics'>('training');
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [deletingItem, setDeletingItem] = useState<{ type: 'module' | 'video' | 'material', id: string, moduleId?: string } | null>(null);
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) => {
setDeletingItem({ type: 'module', id: moduleId });
setIsDeleteModalOpen(true);
};
const handleDeleteVideo = (moduleId: string, videoId: string) => {
setDeletingItem({ type: 'video', id: videoId, moduleId });
setIsDeleteModalOpen(true);
};
const handleDeleteMaterial = (moduleId: string, materialId: string) => {
setDeletingItem({ type: 'material', id: materialId, moduleId });
setIsDeleteModalOpen(true);
};
const confirmDelete = async () => {
if (!deletingItem) return;
try {
if (deletingItem.type === 'module') {
// Handle module deletion
console.log('Deleting module:', deletingItem.id);
// Here you would typically make an API call to delete the module
} else if (deletingItem.type === 'video') {
// Handle video deletion
console.log('Deleting video:', deletingItem.id, 'from module:', deletingItem.moduleId);
// Here you would typically make an API call to delete the video
} else if (deletingItem.type === 'material') {
// Handle material deletion
console.log('Deleting material:', deletingItem.id, 'from module:', deletingItem.moduleId);
// Here you would typically make an API call to delete the material
}
// Close modal and reset state
setIsDeleteModalOpen(false);
setDeletingItem(null);
} catch (error) {
console.error('Error deleting item:', error);
}
};
// Enhanced CRUD functions
const handleModuleAdd = (module: Omit<TrainingModule, 'id'>) => {
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<TrainingModule>) => {
console.log('Updating module:', id, updates);
// Here you would typically update your state or make an API call
};
const handleModuleDelete = (id: string) => {
setDeletingItem({ type: 'module', id });
setIsDeleteModalOpen(true);
};
const handleVideoAdd = (moduleId: string, video: Omit<TrainingVideo, 'id'>) => {
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<TrainingVideo>) => {
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) => {
setDeletingItem({ type: 'video', id: videoId, moduleId });
setIsDeleteModalOpen(true);
};
const handleMaterialAdd = (moduleId: string, material: Omit<TrainingMaterial, 'id'>) => {
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<TrainingMaterial>) => {
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) => {
setDeletingItem({ type: 'material', id: materialId, moduleId });
setIsDeleteModalOpen(true);
};
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 (
<div className="space-y-6">
{/* Header */}
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between space-y-4 sm:space-y-0">
<div className="flex items-center space-x-4">
<div className="p-3 bg-primary-100 dark:bg-primary-900 rounded-lg">
<BookOpen className="w-8 h-8 text-primary-600 dark:text-primary-400" />
</div>
<div>
<h1 className="text-2xl sm:text-3xl font-bold text-secondary-900 dark:text-white">
Training Center
</h1>
<p className="text-secondary-600 dark:text-secondary-400 mt-1">
Master the Cloudtopiaa platform and maximize your success
</p>
</div>
</div>
<div className="flex items-center space-x-3">
{/* View Toggle Buttons */}
<div className="flex items-center space-x-2 bg-secondary-100 dark:bg-secondary-800 rounded-lg p-1">
<button
onClick={() => setCurrentView('training')}
className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${
currentView === 'training'
? 'bg-white dark:bg-gray-700 text-secondary-900 dark:text-white shadow-sm'
: 'text-secondary-600 dark:text-secondary-400 hover:text-secondary-900 dark:hover:text-white'
}`}
>
Training
</button>
<button
onClick={() => setCurrentView('analytics')}
className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${
currentView === 'analytics'
? 'bg-white dark:bg-gray-700 text-secondary-900 dark:text-white shadow-sm'
: 'text-secondary-600 dark:text-secondary-400 hover:text-secondary-900 dark:hover:text-white'
}`}
>
Analytics
</button>
<button
onClick={() => setCurrentView('admin')}
className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${
currentView === 'admin'
? 'bg-white dark:bg-gray-700 text-secondary-900 dark:text-white shadow-sm'
: 'text-secondary-600 dark:text-secondary-400 hover:text-secondary-900 dark:hover:text-white'
}`}
>
Admin
</button>
</div>
{/* Admin Actions */}
{currentView === 'admin' && (
<button
onClick={() => setShowAddModule(true)}
className="inline-flex items-center px-4 py-2 bg-success-600 text-white rounded-lg text-sm font-medium hover:bg-success-700 transition-colors"
>
<Plus className="w-4 h-4 mr-2" />
Add Module
</button>
)}
</div>
</div>
{/* Content Based on Current View */}
{currentView === 'training' && (
<>
{/* How It Works Section */}
<div className="card p-6">
<h2 className="text-2xl font-bold text-secondary-900 dark:text-white mb-6">How Training Works</h2>
<div className="grid md:grid-cols-3 gap-6">
<div className="text-center">
<div className="w-16 h-16 bg-primary-100 dark:bg-primary-900 rounded-full flex items-center justify-center mx-auto mb-4">
<BookOpen className="w-8 h-8 text-primary-600 dark:text-primary-400" />
</div>
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-2">1. Choose Your Path</h3>
<p className="text-secondary-600 dark:text-secondary-400">Select from beginner, intermediate, or advanced training modules based on your experience level.</p>
</div>
<div className="text-center">
<div className="w-16 h-16 bg-success-100 dark:bg-success-900 rounded-full flex items-center justify-center mx-auto mb-4">
<Video className="w-8 h-8 text-success-600 dark:text-success-400" />
</div>
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-2">2. Watch & Learn</h3>
<p className="text-secondary-600 dark:text-secondary-400">Access high-quality video tutorials, webinars, and interactive content designed for resellers.</p>
</div>
<div className="text-center">
<div className="w-16 h-16 bg-warning-100 dark:bg-warning-900 rounded-full flex items-center justify-center mx-auto mb-4">
<Award className="w-8 h-8 text-warning-600 dark:text-warning-400" />
</div>
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-2">3. Get Certified</h3>
<p className="text-secondary-600 dark:text-secondary-400">Complete assessments and earn certifications to demonstrate your expertise to customers.</p>
</div>
</div>
</div>
</>
)}
{currentView === 'analytics' && (
<TrainingAnalytics
analytics={analyticsData}
onExportReport={handleExportReport}
onDateRangeChange={handleDateRangeChange}
/>
)}
{currentView === 'admin' && (
<TrainingAdmin
modules={trainingModules}
onModuleAdd={handleModuleAdd}
onModuleUpdate={handleModuleUpdate}
onModuleDelete={handleModuleDelete}
onVideoAdd={handleVideoAdd}
onVideoUpdate={handleVideoUpdate}
onVideoDelete={handleVideoDelete}
onMaterialAdd={handleMaterialAdd}
onMaterialUpdate={handleMaterialUpdate}
onMaterialDelete={handleMaterialDelete}
/>
)}
{/* Category Filter and Training Modules - Only show in training view */}
{currentView === 'training' && (
<>
{/* Category Filter */}
<div className="mb-6">
<div className="flex flex-wrap gap-2">
{categories.map((category) => (
<button
key={category}
onClick={() => setSelectedCategory(category)}
className={`px-4 py-2 rounded-full text-sm font-medium transition-colors ${
selectedCategory === category
? 'bg-primary-600 text-white'
: 'bg-white dark:bg-gray-800 text-secondary-700 dark:text-secondary-300 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700'
}`}
>
{category === 'all' ? 'All Categories' : category}
</button>
))}
</div>
</div>
{/* Training Modules */}
<div className="space-y-6">
{filteredModules.map((module) => (
<div key={module.id} className="card overflow-hidden">
<div
className="p-6 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
onClick={() => toggleModule(module.id)}
>
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<div className="flex-shrink-0">
{module.completed ? (
<CheckCircle className="w-8 h-8 text-success-600 dark:text-success-400" />
) : (
<div className="w-8 h-8 bg-gray-200 dark:bg-gray-700 rounded-full"></div>
)}
</div>
<div className="flex-1">
<div className="flex items-center space-x-3 mb-2">
<h3 className="text-xl font-semibold text-secondary-900 dark:text-white">{module.title}</h3>
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getLevelColor(module.level)}`}>
{module.level}
</span>
</div>
<p className="text-secondary-600 dark:text-secondary-400 mb-3">{module.description}</p>
<div className="flex items-center space-x-6 text-sm text-secondary-500 dark:text-secondary-400">
<div className="flex items-center space-x-1">
<Clock className="w-4 h-4" />
<span>{module.duration}</span>
</div>
<div className="flex items-center space-x-1">
<Video className="w-4 h-4" />
<span>{module.videos.length} videos</span>
</div>
<div className="flex items-center space-x-1">
<FileText className="w-4 h-4" />
<span>{module.materials.length} materials</span>
</div>
</div>
</div>
</div>
<div className="flex items-center space-x-2">
{isAdminMode && (
<div className="flex items-center space-x-2 mr-4">
<button
onClick={(e) => {
e.stopPropagation();
setEditingModule(module);
}}
className="p-2 text-primary-600 hover:bg-primary-100 dark:hover:bg-primary-900 rounded-lg transition-colors"
>
<Edit className="w-4 h-4" />
</button>
<button
onClick={(e) => {
e.stopPropagation();
handleDeleteModule(module.id);
}}
className="p-2 text-danger-600 hover:bg-danger-100 dark:hover:bg-danger-900 rounded-lg transition-colors"
>
<Trash2 className="w-4 h-4" />
</button>
</div>
)}
{expandedModule === module.id ? (
<ChevronUp className="w-5 h-5 text-secondary-400" />
) : (
<ChevronDown className="w-5 h-5 text-secondary-400" />
)}
</div>
</div>
</div>
{/* Expanded Content */}
{expandedModule === module.id && (
<div className="border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 p-6">
{/* Videos Section */}
<div className="mb-8">
<div className="flex items-center justify-between mb-4">
<h4 className="text-lg font-semibold text-secondary-900 dark:text-white flex items-center">
<Video className="w-5 h-5 mr-2" />
Training Videos
</h4>
{isAdminMode && (
<button
onClick={() => {
setSelectedModuleForAdd(module.id);
setShowAddVideo(true);
}}
className="inline-flex items-center px-3 py-1 bg-success-600 text-white text-sm rounded-md hover:bg-success-700 transition-colors"
>
<Plus className="w-4 h-4 mr-1" />
Add Video
</button>
)}
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
{module.videos.map((video) => (
<div key={video.id} className="bg-white dark:bg-gray-700 rounded-lg overflow-hidden shadow-sm">
<div className="aspect-video bg-gray-200 dark:bg-gray-600 relative">
<img
src={video.thumbnail}
alt={video.title}
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-black bg-opacity-20 flex items-center justify-center">
<Play className="w-12 h-12 text-white" />
</div>
</div>
<div className="p-4">
<h5 className="font-medium text-secondary-900 dark:text-white mb-2">{video.title}</h5>
<p className="text-sm text-secondary-600 dark:text-secondary-400 mb-3">{video.description}</p>
<div className="flex items-center justify-between">
<span className="text-sm text-secondary-500 dark:text-secondary-400">{video.duration}</span>
<div className="flex items-center space-x-2">
<a
href={video.youtubeUrl}
target="_blank"
rel="noopener noreferrer"
className="text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 text-sm font-medium"
>
Watch
</a>
{isAdminMode && (
<>
<button
onClick={() => setEditingVideo(video)}
className="text-secondary-600 hover:text-secondary-700 dark:text-secondary-400 dark:hover:text-secondary-300"
>
<Edit className="w-4 h-4" />
</button>
<button
onClick={() => handleDeleteVideo(module.id, video.id)}
className="text-danger-600 hover:text-danger-700 dark:text-danger-400 dark:hover:text-danger-300"
>
<Trash2 className="w-4 h-4" />
</button>
</>
)}
</div>
</div>
</div>
</div>
))}
</div>
</div>
{/* Materials Section */}
<div>
<div className="flex items-center justify-between mb-4">
<h4 className="text-lg font-semibold text-secondary-900 dark:text-white flex items-center">
<FileText className="w-5 h-5 mr-2" />
Training Materials
</h4>
{isAdminMode && (
<button
onClick={() => {
setSelectedModuleForAdd(module.id);
setShowAddMaterial(true);
}}
className="inline-flex items-center px-3 py-1 bg-success-600 text-white text-sm rounded-md hover:bg-success-700 transition-colors"
>
<Plus className="w-4 h-4 mr-1" />
Add Material
</button>
)}
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
{module.materials.map((material) => (
<div key={material.id} className="bg-white dark:bg-gray-700 rounded-lg p-4 shadow-sm">
<div className="flex items-start space-x-3">
<div className="flex-shrink-0">
<div className="w-10 h-10 bg-primary-100 dark:bg-primary-900 rounded-lg flex items-center justify-center">
<FileText className="w-5 h-5 text-primary-600 dark:text-primary-400" />
</div>
</div>
<div className="flex-1 min-w-0">
<h5 className="font-medium text-secondary-900 dark:text-white mb-1">{material.title}</h5>
<p className="text-sm text-secondary-600 dark:text-secondary-400 mb-2">{material.description}</p>
<div className="flex items-center justify-between">
<span className="text-xs text-secondary-500 dark:text-secondary-400">{material.size}</span>
<div className="flex items-center space-x-2">
<a
href={material.downloadUrl}
className="text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 text-sm font-medium"
>
Download
</a>
{isAdminMode && (
<>
<button
onClick={() => setEditingMaterial(material)}
className="text-secondary-600 hover:text-secondary-700 dark:text-secondary-400 dark:hover:text-secondary-300"
>
<Edit className="w-4 h-4" />
</button>
<button
onClick={() => handleDeleteMaterial(module.id, material.id)}
className="text-danger-600 hover:text-danger-700 dark:text-danger-400 dark:hover:text-danger-300"
>
<Trash2 className="w-4 h-4" />
</button>
</>
)}
</div>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
)}
</div>
))}
</div>
</>
)}
{/* Additional Resources */}
<div className="card p-6">
<h2 className="text-2xl font-bold text-secondary-900 dark:text-white mb-6">Additional Resources</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
<div className="bg-gradient-to-br from-primary-50 to-primary-100 dark:from-primary-900 dark:to-primary-800 rounded-lg p-6">
<div className="flex items-center space-x-3 mb-4">
<Headphones className="w-8 h-8 text-primary-600 dark:text-primary-400" />
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white">Live Webinars</h3>
</div>
<p className="text-secondary-600 dark:text-secondary-400 mb-4">Join our weekly live webinars with industry experts and get your questions answered in real-time.</p>
<button className="text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 font-medium">View Schedule </button>
</div>
<div className="bg-gradient-to-br from-success-50 to-success-100 dark:from-success-900 dark:to-success-800 rounded-lg p-6">
<div className="flex items-center space-x-3 mb-4">
<Users className="w-8 h-8 text-success-600 dark:text-success-400" />
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white">Community Forum</h3>
</div>
<p className="text-secondary-600 dark:text-secondary-400 mb-4">Connect with other resellers, share experiences, and learn from the community.</p>
<button className="text-success-600 hover:text-success-700 dark:text-success-400 dark:hover:text-success-300 font-medium">Join Discussion </button>
</div>
<div className="bg-gradient-to-br from-warning-50 to-warning-100 dark:from-warning-900 dark:to-warning-800 rounded-lg p-6">
<div className="flex items-center space-x-3 mb-4">
<Globe className="w-8 h-8 text-warning-600 dark:text-warning-400" />
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white">Knowledge Base</h3>
</div>
<p className="text-secondary-600 dark:text-secondary-400 mb-4">Access comprehensive documentation, FAQs, and troubleshooting guides.</p>
<button className="text-warning-600 hover:text-warning-700 dark:text-warning-400 dark:hover:text-warning-300 font-medium">Browse Articles </button>
</div>
</div>
</div>
{/* Certification Path */}
<div className="bg-gradient-to-r from-primary-600 to-warning-600 rounded-lg p-8 text-white">
<div className="text-center">
<Award className="w-16 h-16 mx-auto mb-4" />
<h2 className="text-3xl font-bold mb-4">Get Certified</h2>
<p className="text-xl mb-6 opacity-90">
Complete our training modules and earn professional certifications to boost your credibility and sales.
</p>
<div className="flex flex-wrap justify-center gap-4">
<div className="bg-white bg-opacity-20 rounded-lg px-4 py-2">
<span className="font-medium">Beginner Certification</span>
</div>
<div className="bg-white bg-opacity-20 rounded-lg px-4 py-2">
<span className="font-medium">Advanced Certification</span>
</div>
<div className="bg-white bg-opacity-20 rounded-lg px-4 py-2">
<span className="font-medium">Expert Certification</span>
</div>
</div>
</div>
</div>
{/* Admin Modals */}
{showAddModule && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-4">Add New Training Module</h3>
<form className="space-y-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Title</label>
<input type="text" className="input w-full" placeholder="Module title" />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Description</label>
<textarea className="input w-full" rows={3} placeholder="Module description"></textarea>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Duration</label>
<input type="text" className="input w-full" placeholder="e.g., 2 hours" />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Level</label>
<select className="input w-full">
<option>Beginner</option>
<option>Intermediate</option>
<option>Advanced</option>
</select>
</div>
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Category</label>
<select className="input w-full">
<option>Platform Basics</option>
<option>Sales & Marketing</option>
<option>Technical</option>
<option>Business</option>
</select>
</div>
<div className="flex justify-end space-x-3">
<button
type="button"
onClick={() => setShowAddModule(false)}
className="px-4 py-2 text-secondary-600 dark:text-secondary-400 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded-lg transition-colors"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
>
Add Module
</button>
</div>
</form>
</div>
</div>
)}
{showAddVideo && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-4">Add New Video</h3>
<form className="space-y-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Title</label>
<input type="text" className="input w-full" placeholder="Video title" />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Description</label>
<textarea className="input w-full" rows={3} placeholder="Video description"></textarea>
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">YouTube URL</label>
<input type="url" className="input w-full" placeholder="https://www.youtube.com/watch?v=..." />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Duration</label>
<input type="text" className="input w-full" placeholder="e.g., 15:30" />
</div>
<div className="flex justify-end space-x-3">
<button
type="button"
onClick={() => setShowAddVideo(false)}
className="px-4 py-2 text-secondary-600 dark:text-secondary-400 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded-lg transition-colors"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
>
Add Video
</button>
</div>
</form>
</div>
</div>
)}
{showAddMaterial && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-4">Add New Material</h3>
<form className="space-y-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Title</label>
<input type="text" className="input w-full" placeholder="Material title" />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Description</label>
<textarea className="input w-full" rows={3} placeholder="Material description"></textarea>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Type</label>
<select className="input w-full">
<option>PDF</option>
<option>PPT</option>
<option>DOC</option>
<option>VIDEO</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Size</label>
<input type="text" className="input w-full" placeholder="e.g., 2.5 MB" />
</div>
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">File Upload</label>
<div className="border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-4 text-center">
<Upload className="w-8 h-8 text-gray-400 mx-auto mb-2" />
<p className="text-sm text-gray-500 dark:text-gray-400">Click to upload or drag and drop</p>
</div>
</div>
<div className="flex justify-end space-x-3">
<button
type="button"
onClick={() => setShowAddMaterial(false)}
className="px-4 py-2 text-secondary-600 dark:text-secondary-400 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded-lg transition-colors"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
>
Add Material
</button>
</div>
</form>
</div>
</div>
)}
{/* Edit Modals */}
{editingModule && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-4">Edit Training Module</h3>
<form className="space-y-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Title</label>
<input type="text" className="input w-full" defaultValue={editingModule.title} />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Description</label>
<textarea className="input w-full" rows={3} defaultValue={editingModule.description}></textarea>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Duration</label>
<input type="text" className="input w-full" defaultValue={editingModule.duration} />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Level</label>
<select className="input w-full" defaultValue={editingModule.level}>
<option>Beginner</option>
<option>Intermediate</option>
<option>Advanced</option>
</select>
</div>
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Category</label>
<select className="input w-full" defaultValue={editingModule.category}>
<option>Platform Basics</option>
<option>Sales & Marketing</option>
<option>Technical</option>
<option>Business</option>
</select>
</div>
<div className="flex justify-end space-x-3">
<button
type="button"
onClick={() => setEditingModule(null)}
className="px-4 py-2 text-secondary-600 dark:text-secondary-400 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded-lg transition-colors"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
>
Save Changes
</button>
</div>
</form>
</div>
</div>
)}
{editingVideo && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-4">Edit Video</h3>
<form className="space-y-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Title</label>
<input type="text" className="input w-full" defaultValue={editingVideo.title} />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Description</label>
<textarea className="input w-full" rows={3} defaultValue={editingVideo.description}></textarea>
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">YouTube URL</label>
<input type="url" className="input w-full" defaultValue={editingVideo.youtubeUrl} />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Duration</label>
<input type="text" className="input w-full" defaultValue={editingVideo.duration} />
</div>
<div className="flex justify-end space-x-3">
<button
type="button"
onClick={() => setEditingVideo(null)}
className="px-4 py-2 text-secondary-600 dark:text-secondary-400 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded-lg transition-colors"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
>
Save Changes
</button>
</div>
</form>
</div>
</div>
)}
{editingMaterial && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
<h3 className="text-lg font-semibold text-secondary-900 dark:text-white mb-4">Edit Material</h3>
<form className="space-y-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Title</label>
<input type="text" className="input w-full" defaultValue={editingMaterial.title} />
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Description</label>
<textarea className="input w-full" rows={3} defaultValue={editingMaterial.description}></textarea>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Type</label>
<select className="input w-full" defaultValue={editingMaterial.type}>
<option>PDF</option>
<option>PPT</option>
<option>DOC</option>
<option>VIDEO</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Size</label>
<input type="text" className="input w-full" defaultValue={editingMaterial.size} />
</div>
</div>
<div className="flex justify-end space-x-3">
<button
type="button"
onClick={() => setEditingMaterial(null)}
className="px-4 py-2 text-secondary-600 dark:text-secondary-400 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded-lg transition-colors"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
>
Save Changes
</button>
</div>
</form>
</div>
</div>
)}
{/* Delete Confirmation Modal */}
{isDeleteModalOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[9999] p-4" style={{ backdropFilter: 'blur(4px)' }}>
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-2xl p-6 w-full max-w-md">
<h2 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">Confirm Delete</h2>
<p className="text-gray-600 dark:text-gray-300 mb-6">
{deletingItem?.type === 'module' && 'Are you sure you want to delete this training module? This action cannot be undone.'}
{deletingItem?.type === 'video' && 'Are you sure you want to delete this video? This action cannot be undone.'}
{deletingItem?.type === 'material' && 'Are you sure you want to delete this material? This action cannot be undone.'}
</p>
<div className="flex justify-end space-x-3">
<button
onClick={() => {
setIsDeleteModalOpen(false);
setDeletingItem(null);
}}
className="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300"
>
Cancel
</button>
<button
onClick={confirmDelete}
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700"
>
Delete {deletingItem?.type === 'module' ? 'Module' : deletingItem?.type === 'video' ? 'Video' : 'Material'}
</button>
</div>
</div>
</div>
)}
</div>
);
};
export default Training;