678 lines
30 KiB
TypeScript
678 lines
30 KiB
TypeScript
// Phase 3B: Staff Training and Adoption System for AI Platform
|
|
import React, { useState, useEffect } from 'react'
|
|
import { motion, AnimatePresence } from 'framer-motion'
|
|
|
|
interface TrainingModule {
|
|
id: string
|
|
title: string
|
|
description: string
|
|
duration: number // in minutes
|
|
difficulty: 'beginner' | 'intermediate' | 'advanced'
|
|
category: 'ai-basics' | 'system-navigation' | 'case-management' | 'reporting' | 'troubleshooting'
|
|
prerequisites: string[]
|
|
learningObjectives: string[]
|
|
completed: boolean
|
|
score?: number
|
|
lastAttempt?: Date
|
|
certificateEarned: boolean
|
|
}
|
|
|
|
interface StaffMember {
|
|
id: string
|
|
name: string
|
|
role: string
|
|
department: string
|
|
email: string
|
|
startDate: Date
|
|
trainingProgress: number
|
|
completedModules: string[]
|
|
certificatesEarned: string[]
|
|
lastLogin?: Date
|
|
proficiencyLevel: 'novice' | 'competent' | 'proficient' | 'expert'
|
|
}
|
|
|
|
// Training session interface for future implementation
|
|
|
|
interface OnboardingChecklist {
|
|
id: string
|
|
staffId: string
|
|
items: ChecklistItem[]
|
|
completedItems: number
|
|
totalItems: number
|
|
assignedMentor?: string
|
|
startDate: Date
|
|
targetCompletionDate: Date
|
|
}
|
|
|
|
interface ChecklistItem {
|
|
id: string
|
|
title: string
|
|
description: string
|
|
category: 'account-setup' | 'training' | 'practice' | 'certification' | 'mentoring'
|
|
completed: boolean
|
|
completedDate?: Date
|
|
notes?: string
|
|
required: boolean
|
|
}
|
|
|
|
const StaffTrainingDashboard: React.FC = () => {
|
|
const [staff, setStaff] = useState<StaffMember[]>([])
|
|
const [modules, setModules] = useState<TrainingModule[]>([])
|
|
const [currentView, setCurrentView] = useState<'overview' | 'training' | 'progress' | 'onboarding'>('overview')
|
|
// const [selectedStaff, setSelectedStaff] = useState<StaffMember | null>(null) // For future staff detail view
|
|
const [selectedModule, setSelectedModule] = useState<TrainingModule | null>(null)
|
|
const [onboardingData, setOnboardingData] = useState<OnboardingChecklist[]>([])
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
useEffect(() => {
|
|
loadTrainingData()
|
|
}, [])
|
|
|
|
const loadTrainingData = async () => {
|
|
setLoading(true)
|
|
|
|
// Simulate loading training modules
|
|
const trainingModules: TrainingModule[] = [
|
|
{
|
|
id: 'mod-001',
|
|
title: 'Introduction to AI-Powered Student Assistance',
|
|
description: 'Learn the basics of how our AI system helps match student needs with available resources.',
|
|
duration: 30,
|
|
difficulty: 'beginner',
|
|
category: 'ai-basics',
|
|
prerequisites: [],
|
|
learningObjectives: [
|
|
'Understand the purpose and benefits of AI assistance',
|
|
'Identify key components of the AI system',
|
|
'Recognize when AI recommendations are most valuable'
|
|
],
|
|
completed: false,
|
|
certificateEarned: false
|
|
},
|
|
{
|
|
id: 'mod-002',
|
|
title: 'Navigating the AI Portal Interface',
|
|
description: 'Master the AI portal interface, including request submission, review queues, and status monitoring.',
|
|
duration: 45,
|
|
difficulty: 'beginner',
|
|
category: 'system-navigation',
|
|
prerequisites: ['mod-001'],
|
|
learningObjectives: [
|
|
'Navigate all sections of the AI portal',
|
|
'Submit and track assistance requests',
|
|
'Interpret AI confidence scores and recommendations'
|
|
],
|
|
completed: false,
|
|
certificateEarned: false
|
|
},
|
|
{
|
|
id: 'mod-003',
|
|
title: 'Case Management with AI Assistance',
|
|
description: 'Learn to effectively manage student cases using AI recommendations and Salesforce integration.',
|
|
duration: 60,
|
|
difficulty: 'intermediate',
|
|
category: 'case-management',
|
|
prerequisites: ['mod-001', 'mod-002'],
|
|
learningObjectives: [
|
|
'Create and update cases in Salesforce',
|
|
'Evaluate AI matching recommendations',
|
|
'Coordinate with volunteers and resource providers',
|
|
'Track case outcomes and impact'
|
|
],
|
|
completed: false,
|
|
certificateEarned: false
|
|
},
|
|
{
|
|
id: 'mod-004',
|
|
title: 'Advanced Analytics and Reporting',
|
|
description: 'Utilize the analytics dashboard to track impact, identify trends, and generate reports.',
|
|
duration: 50,
|
|
difficulty: 'intermediate',
|
|
category: 'reporting',
|
|
prerequisites: ['mod-003'],
|
|
learningObjectives: [
|
|
'Generate impact reports using the dashboard',
|
|
'Identify trends in student assistance needs',
|
|
'Use predictive analytics for resource planning',
|
|
'Create custom reports for stakeholders'
|
|
],
|
|
completed: false,
|
|
certificateEarned: false
|
|
},
|
|
{
|
|
id: 'mod-005',
|
|
title: 'Troubleshooting and System Optimization',
|
|
description: 'Handle common issues, optimize AI performance, and maintain data quality.',
|
|
duration: 40,
|
|
difficulty: 'advanced',
|
|
category: 'troubleshooting',
|
|
prerequisites: ['mod-004'],
|
|
learningObjectives: [
|
|
'Diagnose and resolve common system issues',
|
|
'Optimize AI model performance through feedback',
|
|
'Maintain data quality and integrity',
|
|
'Escalate complex technical problems appropriately'
|
|
],
|
|
completed: false,
|
|
certificateEarned: false
|
|
}
|
|
]
|
|
|
|
// Simulate loading staff data
|
|
const staffMembers: StaffMember[] = [
|
|
{
|
|
id: 'staff-001',
|
|
name: 'Jennifer Martinez',
|
|
role: 'Case Manager',
|
|
department: 'Student Services',
|
|
email: '[email protected]',
|
|
startDate: new Date('2024-01-15'),
|
|
trainingProgress: 80,
|
|
completedModules: ['mod-001', 'mod-002', 'mod-003'],
|
|
certificatesEarned: ['AI Basics Certified'],
|
|
lastLogin: new Date('2024-10-04'),
|
|
proficiencyLevel: 'competent'
|
|
},
|
|
{
|
|
id: 'staff-002',
|
|
name: 'Michael Chen',
|
|
role: 'Volunteer Coordinator',
|
|
department: 'Operations',
|
|
email: '[email protected]',
|
|
startDate: new Date('2023-08-20'),
|
|
trainingProgress: 100,
|
|
completedModules: ['mod-001', 'mod-002', 'mod-003', 'mod-004', 'mod-005'],
|
|
certificatesEarned: ['AI Expert Certified', 'Advanced Analytics Certified'],
|
|
lastLogin: new Date('2024-10-05'),
|
|
proficiencyLevel: 'expert'
|
|
},
|
|
{
|
|
id: 'staff-003',
|
|
name: 'Sarah Williams',
|
|
role: 'Program Manager',
|
|
department: 'Programs',
|
|
email: '[email protected]',
|
|
startDate: new Date('2024-09-01'),
|
|
trainingProgress: 40,
|
|
completedModules: ['mod-001', 'mod-002'],
|
|
certificatesEarned: [],
|
|
lastLogin: new Date('2024-10-03'),
|
|
proficiencyLevel: 'novice'
|
|
},
|
|
{
|
|
id: 'staff-004',
|
|
name: 'David Rodriguez',
|
|
role: 'Data Analyst',
|
|
department: 'Analytics',
|
|
email: '[email protected]',
|
|
startDate: new Date('2024-02-10'),
|
|
trainingProgress: 90,
|
|
completedModules: ['mod-001', 'mod-002', 'mod-003', 'mod-004'],
|
|
certificatesEarned: ['AI Basics Certified', 'Analytics Certified'],
|
|
lastLogin: new Date('2024-10-05'),
|
|
proficiencyLevel: 'proficient'
|
|
}
|
|
]
|
|
|
|
// Simulate onboarding checklists
|
|
const onboardingChecklists: OnboardingChecklist[] = [
|
|
{
|
|
id: 'onboard-003',
|
|
staffId: 'staff-003',
|
|
completedItems: 6,
|
|
totalItems: 12,
|
|
assignedMentor: 'staff-002',
|
|
startDate: new Date('2024-09-01'),
|
|
targetCompletionDate: new Date('2024-10-15'),
|
|
items: [
|
|
{ id: 'check-001', title: 'Complete AI System Account Setup', description: 'Create login credentials and verify access', category: 'account-setup', completed: true, required: true },
|
|
{ id: 'check-002', title: 'Complete Module 1: AI Basics', description: 'Understand fundamental AI concepts', category: 'training', completed: true, required: true },
|
|
{ id: 'check-003', title: 'Complete Module 2: System Navigation', description: 'Learn to navigate the AI portal', category: 'training', completed: true, required: true },
|
|
{ id: 'check-004', title: 'Shadow Experienced Case Manager', description: 'Observe real case management workflows', category: 'mentoring', completed: true, required: true },
|
|
{ id: 'check-005', title: 'Process First Practice Case', description: 'Handle a low-complexity practice case', category: 'practice', completed: true, required: true },
|
|
{ id: 'check-006', title: 'Complete Module 3: Case Management', description: 'Master case management with AI assistance', category: 'training', completed: true, required: true },
|
|
{ id: 'check-007', title: 'Process 5 Real Cases Under Supervision', description: 'Gain hands-on experience with mentor oversight', category: 'practice', completed: false, required: true },
|
|
{ id: 'check-008', title: 'Complete Module 4: Analytics & Reporting', description: 'Learn to generate and interpret reports', category: 'training', completed: false, required: false },
|
|
{ id: 'check-009', title: 'Pass AI Certification Exam', description: 'Demonstrate competency in AI system usage', category: 'certification', completed: false, required: true },
|
|
{ id: 'check-010', title: 'Independent Case Processing Approval', description: 'Get approval for unsupervised case management', category: 'certification', completed: false, required: true },
|
|
{ id: 'check-011', title: 'Complete Troubleshooting Training', description: 'Learn to handle common system issues', category: 'training', completed: false, required: false },
|
|
{ id: 'check-012', title: 'Final Performance Review', description: 'Comprehensive evaluation of skills and readiness', category: 'certification', completed: false, required: true }
|
|
]
|
|
}
|
|
]
|
|
|
|
setModules(trainingModules)
|
|
setStaff(staffMembers)
|
|
setOnboardingData(onboardingChecklists)
|
|
setLoading(false)
|
|
}
|
|
|
|
const getProficiencyColor = (level: string) => {
|
|
switch (level) {
|
|
case 'expert': return 'text-purple-600 bg-purple-100'
|
|
case 'proficient': return 'text-blue-600 bg-blue-100'
|
|
case 'competent': return 'text-green-600 bg-green-100'
|
|
case 'novice': return 'text-orange-600 bg-orange-100'
|
|
default: return 'text-gray-600 bg-gray-100'
|
|
}
|
|
}
|
|
|
|
const getDifficultyColor = (difficulty: string) => {
|
|
switch (difficulty) {
|
|
case 'advanced': return 'bg-red-500'
|
|
case 'intermediate': return 'bg-yellow-500'
|
|
case 'beginner': return 'bg-green-500'
|
|
default: return 'bg-gray-500'
|
|
}
|
|
}
|
|
|
|
const getCategoryIcon = (category: string) => {
|
|
switch (category) {
|
|
case 'ai-basics': return '🧠'
|
|
case 'system-navigation': return '🗺️'
|
|
case 'case-management': return '📋'
|
|
case 'reporting': return '📊'
|
|
case 'troubleshooting': return '🔧'
|
|
default: return '📚'
|
|
}
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-br from-purple-50 to-pink-100 flex items-center justify-center">
|
|
<motion.div
|
|
animate={{ rotate: 360 }}
|
|
transition={{ duration: 2, repeat: Infinity, ease: 'linear' }}
|
|
className="w-12 h-12 border-4 border-purple-500 border-t-transparent rounded-full"
|
|
/>
|
|
<span className="ml-4 text-lg text-purple-700">Loading Training System...</span>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-br from-purple-50 to-pink-100 p-6">
|
|
<div className="max-w-7xl mx-auto">
|
|
{/* Header */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: -20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
className="mb-8"
|
|
>
|
|
<h1 className="text-4xl font-bold text-gray-900 mb-2">AI Training & Adoption Center</h1>
|
|
<p className="text-lg text-gray-600">Empowering our team with comprehensive AI system training</p>
|
|
|
|
<div className="flex gap-4 mt-4">
|
|
{(['overview', 'training', 'progress', 'onboarding'] as const).map((view) => (
|
|
<button
|
|
key={view}
|
|
onClick={() => setCurrentView(view)}
|
|
className={`px-4 py-2 rounded-lg font-medium transition-all ${
|
|
currentView === view
|
|
? 'bg-purple-500 text-white shadow-lg'
|
|
: 'bg-white text-gray-700 hover:bg-purple-50'
|
|
}`}
|
|
>
|
|
{view.charAt(0).toUpperCase() + view.slice(1)}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Overview Dashboard */}
|
|
{currentView === 'overview' && (
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"
|
|
>
|
|
<div className="bg-white rounded-xl p-6 shadow-lg">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="text-lg font-semibold text-gray-700">Total Staff</h3>
|
|
<span className="text-2xl">👥</span>
|
|
</div>
|
|
<div className="text-3xl font-bold text-purple-600 mb-2">{staff.length}</div>
|
|
<div className="text-sm text-gray-500">Across all departments</div>
|
|
</div>
|
|
|
|
<div className="bg-white rounded-xl p-6 shadow-lg">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="text-lg font-semibold text-gray-700">Avg. Progress</h3>
|
|
<span className="text-2xl">📈</span>
|
|
</div>
|
|
<div className="text-3xl font-bold text-green-600 mb-2">
|
|
{Math.round(staff.reduce((acc, s) => acc + s.trainingProgress, 0) / staff.length)}%
|
|
</div>
|
|
<div className="text-sm text-gray-500">Training completion</div>
|
|
</div>
|
|
|
|
<div className="bg-white rounded-xl p-6 shadow-lg">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="text-lg font-semibold text-gray-700">Certificates</h3>
|
|
<span className="text-2xl">🏆</span>
|
|
</div>
|
|
<div className="text-3xl font-bold text-blue-600 mb-2">
|
|
{staff.reduce((acc, s) => acc + s.certificatesEarned.length, 0)}
|
|
</div>
|
|
<div className="text-sm text-gray-500">Total earned</div>
|
|
</div>
|
|
|
|
<div className="bg-white rounded-xl p-6 shadow-lg">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="text-lg font-semibold text-gray-700">Experts</h3>
|
|
<span className="text-2xl">⭐</span>
|
|
</div>
|
|
<div className="text-3xl font-bold text-orange-600 mb-2">
|
|
{staff.filter(s => s.proficiencyLevel === 'expert' || s.proficiencyLevel === 'proficient').length}
|
|
</div>
|
|
<div className="text-sm text-gray-500">Proficient+ level</div>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* Training Modules */}
|
|
{currentView === 'training' && (
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
className="grid grid-cols-1 lg:grid-cols-2 gap-6"
|
|
>
|
|
{modules.map((module) => (
|
|
<div key={module.id} className="bg-white rounded-xl p-6 shadow-lg">
|
|
<div className="flex items-start justify-between mb-4">
|
|
<div className="flex items-center">
|
|
<span className="text-2xl mr-3">{getCategoryIcon(module.category)}</span>
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-gray-900">{module.title}</h3>
|
|
<p className="text-sm text-gray-500">{module.duration} minutes</p>
|
|
</div>
|
|
</div>
|
|
<span className={`px-2 py-1 rounded text-xs text-white ${getDifficultyColor(module.difficulty)}`}>
|
|
{module.difficulty}
|
|
</span>
|
|
</div>
|
|
|
|
<p className="text-gray-600 mb-4 text-sm">{module.description}</p>
|
|
|
|
<div className="mb-4">
|
|
<h4 className="font-medium text-gray-700 mb-2">Learning Objectives:</h4>
|
|
<ul className="text-sm text-gray-600 space-y-1">
|
|
{module.learningObjectives.slice(0, 2).map((objective, index) => (
|
|
<li key={index} className="flex items-start">
|
|
<span className="text-green-500 mr-2">•</span>
|
|
{objective}
|
|
</li>
|
|
))}
|
|
{module.learningObjectives.length > 2 && (
|
|
<li className="text-gray-400">+{module.learningObjectives.length - 2} more...</li>
|
|
)}
|
|
</ul>
|
|
</div>
|
|
|
|
<div className="flex justify-between items-center">
|
|
<div className="text-sm text-gray-500">
|
|
Prerequisites: {module.prerequisites.length > 0 ? module.prerequisites.length : 'None'}
|
|
</div>
|
|
<button
|
|
onClick={() => setSelectedModule(module)}
|
|
className="px-4 py-2 bg-purple-500 text-white rounded-lg font-medium hover:bg-purple-600 transition-colors"
|
|
>
|
|
View Details
|
|
</button>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* Staff Progress */}
|
|
{currentView === 'progress' && (
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
className="bg-white rounded-xl p-6 shadow-lg"
|
|
>
|
|
<h2 className="text-2xl font-bold text-gray-900 mb-6">Staff Training Progress</h2>
|
|
<div className="space-y-4">
|
|
{staff.map((member) => (
|
|
<div key={member.id} className="border rounded-lg p-4">
|
|
<div className="flex items-center justify-between mb-3">
|
|
<div>
|
|
<h3 className="font-semibold text-gray-900">{member.name}</h3>
|
|
<p className="text-sm text-gray-600">{member.role} • {member.department}</p>
|
|
</div>
|
|
<div className="text-right">
|
|
<span className={`px-2 py-1 rounded text-xs font-medium ${getProficiencyColor(member.proficiencyLevel)}`}>
|
|
{member.proficiencyLevel.toUpperCase()}
|
|
</span>
|
|
<div className="text-sm text-gray-500 mt-1">
|
|
Last login: {member.lastLogin?.toLocaleDateString() || 'Never'}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mb-3">
|
|
<div className="flex justify-between text-sm text-gray-600 mb-1">
|
|
<span>Training Progress</span>
|
|
<span>{member.trainingProgress}%</span>
|
|
</div>
|
|
<div className="w-full bg-gray-200 rounded-full h-2">
|
|
<motion.div
|
|
initial={{ width: 0 }}
|
|
animate={{ width: `${member.trainingProgress}%` }}
|
|
transition={{ delay: 0.2, duration: 1 }}
|
|
className="bg-purple-500 h-2 rounded-full"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
|
|
<div>
|
|
<span className="text-gray-500">Modules Completed:</span>
|
|
<div className="font-medium">{member.completedModules.length}/{modules.length}</div>
|
|
</div>
|
|
<div>
|
|
<span className="text-gray-500">Certificates:</span>
|
|
<div className="font-medium">{member.certificatesEarned.length}</div>
|
|
</div>
|
|
<div>
|
|
<span className="text-gray-500">Start Date:</span>
|
|
<div className="font-medium">{member.startDate.toLocaleDateString()}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{member.certificatesEarned.length > 0 && (
|
|
<div className="mt-3">
|
|
<div className="flex flex-wrap gap-2">
|
|
{member.certificatesEarned.map(cert => (
|
|
<span key={cert} className="bg-yellow-100 text-yellow-800 px-2 py-1 rounded text-xs">
|
|
🏆 {cert}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* Onboarding Checklist */}
|
|
{currentView === 'onboarding' && (
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
className="space-y-6"
|
|
>
|
|
{onboardingData.map((checklist) => {
|
|
const staffMember = staff.find(s => s.id === checklist.staffId)
|
|
const mentor = staff.find(s => s.id === checklist.assignedMentor)
|
|
|
|
return (
|
|
<div key={checklist.id} className="bg-white rounded-xl p-6 shadow-lg">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div>
|
|
<h2 className="text-xl font-bold text-gray-900">
|
|
Onboarding: {staffMember?.name}
|
|
</h2>
|
|
<p className="text-gray-600">
|
|
{staffMember?.role} • Mentor: {mentor?.name}
|
|
</p>
|
|
</div>
|
|
<div className="text-right">
|
|
<div className="text-2xl font-bold text-purple-600">
|
|
{checklist.completedItems}/{checklist.totalItems}
|
|
</div>
|
|
<div className="text-sm text-gray-500">Items Complete</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mb-6">
|
|
<div className="flex justify-between text-sm text-gray-600 mb-2">
|
|
<span>Overall Progress</span>
|
|
<span>{Math.round((checklist.completedItems / checklist.totalItems) * 100)}%</span>
|
|
</div>
|
|
<div className="w-full bg-gray-200 rounded-full h-3">
|
|
<motion.div
|
|
initial={{ width: 0 }}
|
|
animate={{ width: `${(checklist.completedItems / checklist.totalItems) * 100}%` }}
|
|
transition={{ delay: 0.3, duration: 1.2 }}
|
|
className="bg-gradient-to-r from-purple-500 to-pink-500 h-3 rounded-full"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid gap-3">
|
|
{checklist.items.map((item) => (
|
|
<div
|
|
key={item.id}
|
|
className={`p-3 rounded-lg border ${
|
|
item.completed
|
|
? 'bg-green-50 border-green-200'
|
|
: item.required
|
|
? 'bg-red-50 border-red-200'
|
|
: 'bg-gray-50 border-gray-200'
|
|
}`}
|
|
>
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex-1">
|
|
<div className="flex items-center">
|
|
<span className={`mr-2 ${item.completed ? '✅' : '⏳'}`}>
|
|
{item.completed ? '✅' : '⏳'}
|
|
</span>
|
|
<h4 className="font-medium text-gray-900">{item.title}</h4>
|
|
{item.required && (
|
|
<span className="ml-2 text-xs bg-red-100 text-red-600 px-1 py-0.5 rounded">
|
|
Required
|
|
</span>
|
|
)}
|
|
</div>
|
|
<p className="text-sm text-gray-600 mt-1">{item.description}</p>
|
|
{item.completed && item.completedDate && (
|
|
<p className="text-xs text-green-600 mt-1">
|
|
Completed: {item.completedDate.toLocaleDateString()}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<span className={`px-2 py-1 rounded text-xs font-medium ${
|
|
item.category === 'certification' ? 'bg-purple-100 text-purple-600' :
|
|
item.category === 'training' ? 'bg-blue-100 text-blue-600' :
|
|
item.category === 'practice' ? 'bg-green-100 text-green-600' :
|
|
item.category === 'mentoring' ? 'bg-orange-100 text-orange-600' :
|
|
'bg-gray-100 text-gray-600'
|
|
}`}>
|
|
{item.category.replace('-', ' ')}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</motion.div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Module Details Modal */}
|
|
<AnimatePresence>
|
|
{selectedModule && (
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50"
|
|
onClick={() => setSelectedModule(null)}
|
|
>
|
|
<motion.div
|
|
initial={{ scale: 0.9, y: 20 }}
|
|
animate={{ scale: 1, y: 0 }}
|
|
exit={{ scale: 0.9, y: 20 }}
|
|
className="bg-white rounded-lg max-w-2xl w-full max-h-[80vh] overflow-y-auto"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="p-6">
|
|
<div className="flex justify-between items-start mb-4">
|
|
<h2 className="text-2xl font-bold text-gray-900">{selectedModule.title}</h2>
|
|
<button
|
|
onClick={() => setSelectedModule(null)}
|
|
className="text-gray-400 hover:text-gray-600"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
|
|
<div className="mb-6">
|
|
<p className="text-gray-600 mb-4">{selectedModule.description}</p>
|
|
|
|
<div className="grid grid-cols-2 gap-4 text-sm">
|
|
<div>
|
|
<span className="font-medium text-gray-700">Duration:</span>
|
|
<div>{selectedModule.duration} minutes</div>
|
|
</div>
|
|
<div>
|
|
<span className="font-medium text-gray-700">Difficulty:</span>
|
|
<div className="capitalize">{selectedModule.difficulty}</div>
|
|
</div>
|
|
<div>
|
|
<span className="font-medium text-gray-700">Category:</span>
|
|
<div className="capitalize">{selectedModule.category.replace('-', ' ')}</div>
|
|
</div>
|
|
<div>
|
|
<span className="font-medium text-gray-700">Prerequisites:</span>
|
|
<div>{selectedModule.prerequisites.length > 0 ? selectedModule.prerequisites.length : 'None'}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mb-6">
|
|
<h3 className="font-semibold text-gray-900 mb-3">Learning Objectives</h3>
|
|
<ul className="space-y-2">
|
|
{selectedModule.learningObjectives.map((objective, index) => (
|
|
<li key={index} className="flex items-start text-sm text-gray-600">
|
|
<span className="text-green-500 mr-2">✓</span>
|
|
{objective}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
<div className="flex gap-3">
|
|
<button className="flex-1 bg-purple-500 text-white py-3 px-4 rounded-lg font-medium hover:bg-purple-600 transition-colors">
|
|
Start Training
|
|
</button>
|
|
<button className="px-4 py-3 border border-gray-300 rounded-lg font-medium text-gray-700 hover:bg-gray-50 transition-colors">
|
|
Preview Content
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default StaffTrainingDashboard |