1188 lines
55 KiB
TypeScript
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;
|