File: /var/www/html/obaasimaghana/app/views/courses/learn.php
<?php
$title = $course['title'] . ' - Learning';
ob_start();
?>
<div class="flex min-h-screen pt-16">
<div class="bg-white text-white py-12">
<div class="container mx-auto px-4">
<!-- Course Content Sidebar -->
<div id="course-sidebar"
class="fixed inset-y-0 left-64 transform -translate-x-full md:translate-x-0 md:static md:w-64 border-r transition-transform duration-300 ease-in-out z-30 pt-16">
<div class="h-full overflow-y-auto">
<div class="p-4">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-semibold text-gray-900">Course Content</h2>
<button id="close-sidebar" class="md:hidden text-gray-500 hover:text-gray-700 transition-colors">
<i class="fas fa-times"></i>
</button>
</div>
<!-- Progress Bar - Mobile -->
<div class="md:hidden mb-4">
<div class="w-full h-2 bg-emerald-100 rounded-full">
<div class="h-full bg-emerald-500 rounded-full transition-all duration-500 ease-in-out"
style="width: <?php echo isset($courseProgress) ? $courseProgress : 0; ?>%">
</div>
</div>
<div class="text-sm text-emerald-700 font-medium mt-1">
<?php echo isset($courseProgress) ? $courseProgress : 0; ?>% complete
</div>
</div>
<!-- Course Sections -->
<div class="space-y-3">
<?php
$sections = [
['title' => 'Introduction', 'materials' => array_slice($materials, 0, 3)],
['title' => 'Main Content', 'materials' => array_slice($materials, 3)]
];
foreach ($sections as $sectionIndex => $section):
?>
<div class="border border-gray-200 rounded-lg shadow-sm">
<button class="w-full px-4 py-3 flex items-center justify-between text-left hover:bg-gray-50 transition-colors"
onclick="toggleSection(<?php echo $sectionIndex; ?>)">
<span class="font-medium text-gray-900"><?php echo $section['title']; ?></span>
<i class="fas fa-chevron-down transform transition-transform"
id="section-icon-<?php echo $sectionIndex; ?>"></i>
</button>
<div class="hidden" id="section-content-<?php echo $sectionIndex; ?>">
<?php foreach ($section['materials'] as $material): ?>
<a href="<?php echo APP_URL; ?>/courses/learn/<?php echo $course['id']; ?>/material/<?php echo $material['id']; ?>"
class="flex items-center px-4 py-3 hover:bg-gray-50 border-t border-gray-100 transition-colors <?php echo isset($currentMaterial) && $currentMaterial['id'] == $material['id'] ? 'bg-emerald-50' : ''; ?>">
<div class="mr-3">
<?php if ($material['type'] === 'video'): ?>
<i class="fas fa-play-circle text-emerald-500"></i>
<?php elseif ($material['type'] === 'pdf'): ?>
<i class="fas fa-file-pdf text-red-500"></i>
<?php else: ?>
<i class="fas fa-file-alt text-blue-500"></i>
<?php endif; ?>
</div>
<div class="flex-1">
<div class="text-sm font-medium text-gray-900">
<?php echo htmlspecialchars($material['title']); ?>
</div>
<?php if (isset($material['status'])): ?>
<div class="text-xs text-gray-500 flex items-center mt-1">
<?php if ($material['status'] === 'completed'): ?>
<i class="fas fa-check-circle text-emerald-500 mr-1"></i>
Completed
<?php else: ?>
<i class="far fa-circle text-gray-400 mr-1"></i>
Not completed
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</a>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Main Content Area -->
<div class="flex-1 bg-gray-50">
<!-- Course Header -->
<div class="bg-white border-b shadow-sm mb-6">
<div class="container mx-auto px-4 py-3">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<a href="<?php echo APP_URL; ?>/courses/show/<?php echo $course['id']; ?>"
class="text-gray-500 hover:text-gray-700 transition-colors">
<i class="fas fa-arrow-left"></i>
</a>
<div>
<h1 class="text-lg font-semibold text-gray-900 truncate max-w-xl">
<?php echo htmlspecialchars($course['title']); ?>
</h1>
<?php if (isset($course['rating'])): ?>
<div class="flex items-center mt-1">
<div class="flex items-center">
<?php
$rating = $course['rating'];
for ($i = 1; $i <= 5; $i++) {
if ($i <= $rating) {
echo '<i class="fas fa-star text-yellow-400 text-sm"></i>';
} elseif ($i - 0.5 <= $rating) {
echo '<i class="fas fa-star-half-alt text-yellow-400 text-sm"></i>';
} else {
echo '<i class="far fa-star text-yellow-400 text-sm"></i>';
}
}
?>
</div>
<span class="text-sm text-gray-500 ml-2"><?php echo number_format($course['rating'], 1); ?> (<?php echo $course['total_ratings']; ?> ratings)</span>
</div>
<?php endif; ?>
</div>
</div>
<div class="flex items-center space-x-4">
<!-- Progress Badge -->
<div class="hidden md:flex items-center bg-gradient-to-r from-emerald-50 to-emerald-100 rounded-full px-4 py-1.5 shadow-sm">
<div class="w-24 h-2 bg-emerald-200 rounded-full mr-2">
<div class="h-full bg-emerald-500 rounded-full transition-all duration-500 ease-in-out"
style="width: <?php echo isset($courseProgress) ? $courseProgress : 0; ?>%">
</div>
</div>
<span class="text-sm font-medium text-emerald-700">
<?php echo isset($courseProgress) ? $courseProgress : 0; ?>% complete
</span>
</div>
<!-- Share Button -->
<button onclick="toggleShareMenu()"
class="p-2 text-gray-500 hover:text-gray-700 focus:outline-none relative transition-colors">
<i class="fas fa-share-alt"></i>
</button>
<!-- Leave Rating Button -->
<?php if ($enrollmentStatus === 'completed' && !$hasUserReviewed): ?>
<button onclick="openRatingModal()"
class="hidden md:flex items-center px-4 py-2 bg-gradient-to-r from-emerald-500 to-emerald-600 text-white rounded-lg hover:from-emerald-600 hover:to-emerald-700 transition-all duration-300 text-sm shadow-sm">
<i class="fas fa-star mr-2"></i>
Leave Rating
</button>
<?php endif; ?>
<!-- Mobile Menu Toggle -->
<button id="mobile-content-toggle"
class="md:hidden p-2 text-gray-500 hover:text-gray-700 focus:outline-none transition-colors">
<i class="fas fa-bars"></i>
</button>
</div>
</div>
</div>
</div>
<div class="max-w-4xl mx-auto px-4 py-8">
<?php if (isset($currentMaterial)): ?>
<!-- Course Completion Notification -->
<?php
$isLastMaterial = false;
$allMaterialsCompleted = true;
// Check if this is the last material and if all materials are completed
if (isset($materials) && !empty($materials)) {
$lastMaterial = end($materials);
$isLastMaterial = $currentMaterial['id'] == $lastMaterial['id'];
// Check if all materials are completed
foreach ($materials as $material) {
if (!isset($material['status']) || $material['status'] !== 'completed') {
$allMaterialsCompleted = false;
break;
}
}
}
if ($isLastMaterial && $allMaterialsCompleted && $enrollmentStatus !== 'completed'):
?>
<div class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center">
<div class="bg-white rounded-2xl shadow-2xl max-w-2xl w-full mx-4 transform transition-all">
<div class="p-8">
<div class="text-center">
<div class="mx-auto w-24 h-24 bg-gradient-to-r from-emerald-100 to-emerald-50 rounded-full flex items-center justify-center mb-6">
<i class="fas fa-trophy text-4xl text-emerald-600"></i>
</div>
<h2 class="text-3xl font-bold text-gray-900 mb-4">Course Progress Update</h2>
<p class="text-lg text-gray-600 mb-6">You've completed all currently available materials in this course.</p>
<div class="bg-emerald-50 rounded-xl p-6 mb-6">
<div class="flex items-center justify-between mb-4">
<span class="text-emerald-700 font-medium">Current Progress</span>
<span class="text-emerald-700 font-bold">100%</span>
</div>
<div class="w-full h-2 bg-emerald-200 rounded-full">
<div class="h-full bg-emerald-500 rounded-full" style="width: 100%"></div>
</div>
</div>
<div class="space-y-4">
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<form action="<?php echo APP_URL; ?>/courses/complete/<?php echo $course['id']; ?>" method="POST" class="flex-1">
<button type="submit"
class="w-full px-6 py-3 bg-gradient-to-r from-emerald-500 to-emerald-600 text-white rounded-xl hover:from-emerald-600 hover:to-emerald-700 transition-all duration-300 shadow-lg font-medium">
Complete Course Now
</button>
</form>
<button onclick="closeCompletionModal()"
class="flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl hover:bg-gray-200 transition-all duration-300 shadow-lg font-medium">
Wait for More Content
</button>
</div>
<div class="text-sm text-gray-500 space-y-2">
<p>• Completing now will grant you a certificate for the current materials.</p>
<p>• Waiting allows you to access future materials when they're added.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<?php endif; ?>
<?php if ($enrollmentStatus === 'completed' && !$hasUserReviewed): ?>
<!-- Review Prompt -->
<div class="bg-white rounded-xl shadow-lg mb-6 p-6 border-2 border-purple-500">
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="bg-gradient-to-r from-purple-100 to-purple-50 p-4 rounded-full mr-4">
<i class="fas fa-star text-2xl text-purple-600"></i>
</div>
<div>
<h3 class="text-xl font-semibold text-gray-900">Share Your Experience</h3>
<p class="text-gray-600 mt-1">Help others by leaving a review for this course.</p>
</div>
</div>
<button onclick="openRatingModal()" class="px-4 py-2 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-lg hover:from-purple-600 hover:to-purple-700 transition-all duration-300 shadow-sm">
Write a Review
</button>
</div>
</div>
<?php endif; ?>
<div class="bg-white rounded-xl shadow-lg mb-6">
<?php if ($currentMaterial['type'] === 'video'): ?>
<div class="aspect-w-16 aspect-h-9 bg-black rounded-t-lg overflow-hidden">
<video id="course-video" class="w-full h-full" controls playsinline>
<source src="<?php echo APP_URL; ?>/uploads/<?php echo htmlspecialchars($currentMaterial['content_url']); ?>" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
<?php elseif ($currentMaterial['type'] === 'audio'): ?>
<div class="bg-gray-100 rounded-t-lg p-6">
<div class="flex items-center justify-center">
<audio id="course-audio" class="w-full" controls>
<source src="<?php echo APP_URL; ?>/uploads/<?php echo htmlspecialchars($currentMaterial['content_url']); ?>" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
</div>
</div>
<?php elseif ($currentMaterial['type'] === 'pdf'): ?>
<div class="bg-gray-100 rounded-t-lg p-6">
<div class="flex flex-col items-center justify-center">
<div class="w-full h-[600px] border border-gray-300 rounded-lg overflow-hidden">
<iframe src="<?php echo APP_URL; ?>/uploads/<?php echo htmlspecialchars($currentMaterial['content_url']); ?>"
class="w-full h-full"
type="application/pdf">
Your browser does not support embedded PDFs.
<a href="<?php echo APP_URL; ?>/uploads/<?php echo htmlspecialchars($currentMaterial['content_url']); ?>" target="_blank">
Click here to download the PDF
</a>
</iframe>
</div>
</div>
</div>
<?php elseif ($currentMaterial['type'] === 'text'): ?>
<div class="bg-gray-100 rounded-t-lg p-6">
<div class="prose max-w-none">
<?php
$textFilePath = APP_PATH . '/public/uploads/' . $currentMaterial['content_url'];
if (file_exists($textFilePath)) {
$textContent = file_get_contents($textFilePath);
if ($textContent) {
echo nl2br(htmlspecialchars($textContent));
} else {
echo '<p class="text-gray-500">No text content available.</p>';
}
} else {
echo '<p class="text-gray-500">Text file not found. Please contact the course administrator.</p>';
}
?>
</div>
</div>
<?php endif; ?>
<div class="p-6">
<div class="flex items-center justify-between mb-6">
<h2 class="text-2xl font-bold"><?php echo htmlspecialchars($currentMaterial['title']); ?></h2>
<!-- Material Progress Button -->
<form action="<?php echo APP_URL; ?>/courses/updateMaterialProgress" method="POST" class="inline">
<input type="hidden" name="material_id" value="<?php echo $currentMaterial['id']; ?>">
<input type="hidden" name="course_id" value="<?php echo $course['id']; ?>">
<input type="hidden" name="status" value="<?php echo $currentMaterial['status'] === 'completed' ? 'not_started' : 'completed'; ?>">
<button type="submit"
class="inline-flex items-center px-4 py-2 rounded-lg transition-colors <?php echo $currentMaterial['status'] === 'completed' ? 'bg-gray-100 text-gray-700 hover:bg-gray-200' : 'bg-emerald-600 text-white hover:bg-emerald-700'; ?>">
<?php if ($currentMaterial['status'] === 'completed'): ?>
<i class="fas fa-check mr-2"></i> Completed
<?php else: ?>
Mark as Complete
<?php endif; ?>
</button>
</form>
</div>
<!-- Navigation -->
<div class="flex items-center justify-between mt-8 pt-6 border-t">
<?php if (isset($previousMaterial)): ?>
<a href="<?php echo APP_URL; ?>/courses/learn/<?php echo $course['id']; ?>/material/<?php echo $previousMaterial['id']; ?>"
class="flex items-center text-gray-600 hover:text-gray-900">
<i class="fas fa-arrow-left mr-2"></i>
<span class="text-sm">Previous</span>
</a>
<?php else: ?>
<div></div>
<?php endif; ?>
<?php if (isset($nextMaterial)): ?>
<a href="<?php echo APP_URL; ?>/courses/learn/<?php echo $course['id']; ?>/material/<?php echo $nextMaterial['id']; ?>"
class="flex items-center text-emerald-600 hover:text-emerald-700">
<span class="text-sm">Next</span>
<i class="fas fa-arrow-right ml-2"></i>
</a>
<?php endif; ?>
</div>
</div>
</div>
<!-- Tabs Navigation -->
<div class="border-b border-gray-200">
<nav class="flex space-x-8" aria-label="Tabs">
<button onclick="switchTab('overview')"
class="tab-button active border-b-2 border-emerald-500 py-4 px-1 text-sm font-medium text-emerald-600"
data-tab="overview">
<i class="fas fa-info-circle mr-2"></i>
Overview
</button>
<button onclick="switchTab('notes')"
class="tab-button border-b-2 border-transparent py-4 px-1 text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300"
data-tab="notes">
<i class="fas fa-sticky-note mr-2"></i>
Notes
</button>
<button onclick="switchTab('chats')"
class="tab-button border-b-2 border-transparent py-4 px-1 text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300"
data-tab="chats">
<i class="fas fa-comments mr-2"></i>
Discussion
<?php if (isset($unreadMessages) && $unreadMessages > 0): ?>
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-emerald-100 text-emerald-800">
<?php echo $unreadMessages; ?>
</span>
<?php endif; ?>
</button>
<button onclick="switchTab('tools')"
class="tab-button border-b-2 border-transparent py-4 px-1 text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300"
data-tab="tools">
<i class="fas fa-tools mr-2"></i>
Learning Tools
</button>
</nav>
</div>
<!-- Tab Content -->
<div class="mt-6">
<!-- Overview Tab -->
<div id="overview-tab" class="tab-content active">
<div class="prose max-w-none">
<h3 class="text-lg font-semibold mb-4">About This Material</h3>
<?php if (!empty($currentMaterial['description'])): ?>
<?php echo nl2br(htmlspecialchars($currentMaterial['description'])); ?>
<?php else: ?>
<p class="text-gray-500">No description available for this material.</p>
<?php endif; ?>
<?php if (!empty($currentMaterial['learning_objectives'])): ?>
<h4 class="text-lg font-semibold mt-6 mb-4">Learning Objectives</h4>
<ul class="list-disc pl-5 space-y-2">
<?php foreach ($currentMaterial['learning_objectives'] as $objective): ?>
<li><?php echo htmlspecialchars($objective); ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
</div>
<!-- Notes Tab -->
<div id="notes-tab" class="tab-content hidden">
<div class="bg-white rounded-lg shadow-sm p-6">
<?php if (isset($_SESSION['user_id'])): ?>
<div class="mb-6">
<form id="noteForm" action="<?php echo APP_URL; ?>/courses/saveNote" method="POST" onsubmit="return saveNote(event)">
<input type="hidden" name="material_id" value="<?php echo $currentMaterial['id']; ?>">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">
Add Note
</label>
<textarea name="content"
rows="4"
class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500"
placeholder="Type your notes here..."></textarea>
</div>
<div class="flex justify-end">
<button type="submit"
class="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors">
Save Note
</button>
</div>
</form>
</div>
<?php if (isset($userNotes) && !empty($userNotes)): ?>
<div>
<h3 class="text-lg font-semibold mb-4">Your Notes</h3>
<div id="notes-container" class="space-y-4 h-[400px] overflow-y-auto border border-gray-200 rounded-lg p-4 custom-scrollbar">
<?php foreach ($userNotes as $note): ?>
<div class="bg-gray-50 rounded-lg p-4" id="note-<?php echo $note['id']; ?>">
<div class="flex justify-between items-start mb-2">
<div class="text-sm text-gray-500">
<?php echo date('M j, Y g:i A', strtotime($note['created_at'])); ?>
</div>
<div class="flex space-x-2">
<button onclick="editNote(<?php echo $note['id']; ?>, '<?php echo htmlspecialchars(addslashes($note['content'])); ?>')"
class="text-gray-400 hover:text-gray-600">
<i class="fas fa-edit"></i>
</button>
<button onclick="deleteNote(<?php echo $note['id']; ?>)"
class="text-gray-400 hover:text-red-600">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<div class="prose prose-sm note-content">
<?php echo nl2br(htmlspecialchars($note['content'])); ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php else: ?>
<div class="text-center text-gray-500 py-8">
<i class="fas fa-sticky-note text-4xl mb-4"></i>
<p>You haven't added any notes yet.</p>
</div>
<?php endif; ?>
<?php else: ?>
<div class="text-center py-8">
<i class="fas fa-lock text-4xl text-gray-400 mb-4"></i>
<p class="text-gray-600 mb-4">Please log in to add notes</p>
<a href="<?php echo APP_URL; ?>/auth/login"
class="inline-block px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors">
Log In
</a>
</div>
<?php endif; ?>
</div>
</div>
<!-- Edit Note Modal -->
<div id="editNoteModal" class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl w-full max-w-md">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">Edit Note</h3>
<button onclick="closeEditModal()" class="text-gray-400 hover:text-gray-600">
<i class="fas fa-times"></i>
</button>
</div>
<form id="editNoteForm" onsubmit="return updateNote(event)">
<input type="hidden" id="editNoteId" name="note_id">
<div class="mb-4">
<textarea id="editNoteContent"
name="content"
rows="4"
class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500"
required></textarea>
</div>
<div class="flex justify-end space-x-3">
<button type="button"
onclick="closeEditModal()"
class="px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200">
Cancel
</button>
<button type="submit"
class="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700">
Save Changes
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Chats Tab -->
<div id="chats-tab" class="tab-content hidden">
<div class="bg-white rounded-lg shadow-sm p-6">
<div class="mb-6">
<h3 class="text-md font-semibold mb-4">Discussion</h3>
<div id="discussion-messages" class="space-y-4 mb-6 max-h-96 overflow-y-auto">
<?php if (isset($discussions) && !empty($discussions)): ?>
<?php foreach ($discussions as $message): ?>
<div class="flex space-x-3">
<div class="flex-shrink-0">
<?php if (!empty($message['user_avatar'])): ?>
<img src="<?php echo $message['user_avatar']; ?>"
alt=""
class="h-10 w-10 rounded-full">
<?php else: ?>
<div class="h-10 w-10 rounded-full bg-emerald-100 flex items-center justify-center">
<span class="text-emerald-600 font-semibold">
<?php echo strtoupper(substr($message['user_name'], 0, 1)); ?>
</span>
</div>
<?php endif; ?>
</div>
<div class="flex-1">
<div class="flex items-center justify-between">
<div class="text-sm font-medium text-gray-900">
<?php echo htmlspecialchars($message['user_name']); ?>
</div>
<div class="text-sm text-gray-500">
<?php echo date('M j, Y g:i A', strtotime($message['created_at'])); ?>
</div>
</div>
<div class="mt-1 text-sm text-gray-700">
<?php echo nl2br(htmlspecialchars($message['content'])); ?>
</div>
<?php if (isset($_SESSION['user_id'])): ?>
<div class="mt-2 flex items-center space-x-4 text-sm">
<button onclick="replyToMessage(<?php echo $message['id']; ?>)"
class="text-gray-500 hover:text-gray-700">
<i class="fas fa-reply mr-1"></i> Reply
</button>
<?php if ($_SESSION['user_id'] == $message['user_id']): ?>
<button onclick="deleteMessage(<?php echo $message['id']; ?>)"
class="text-gray-500 hover:text-red-600">
<i class="fas fa-trash mr-1"></i> Delete
</button>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="text-center text-gray-500 py-8">
<i class="fas fa-comments text-4xl mb-4"></i>
<p>No discussions yet. Be the first to start a conversation!</p>
</div>
<?php endif; ?>
</div>
<?php if (isset($_SESSION['user_id'])): ?>
<form id="discussionForm" action="<?php echo APP_URL; ?>/courses/addDiscussion" method="POST" onsubmit="return submitDiscussion(event)">
<input type="hidden" name="material_id" value="<?php echo $currentMaterial['id']; ?>">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">
Add to the discussion
</label>
<textarea name="content"
rows="3"
class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500"
placeholder="Share your thoughts..."></textarea>
</div>
<div class="flex justify-end">
<button type="submit"
class="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors">
Post Comment
</button>
</div>
</form>
<?php endif; ?>
</div>
</div>
</div>
<!-- Learning Tools Tab -->
<div id="tools-tab" class="tab-content hidden">
<div class="bg-white rounded-lg shadow-sm p-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Prerequisites -->
<div>
<h3 class="text-lg font-semibold mb-4">Prerequisites</h3>
<?php if (!empty($course['prerequisites'])): ?>
<ul class="space-y-3">
<?php foreach ($course['prerequisites'] as $prereq): ?>
<li class="flex items-start">
<i class="fas fa-check-circle text-emerald-500 mt-1 mr-2"></i>
<span><?php echo htmlspecialchars($prereq); ?></span>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="text-gray-500">No prerequisites required for this course.</p>
<?php endif; ?>
</div>
<!-- Additional Resources -->
<div>
<h3 class="text-lg font-semibold mb-4">Additional Resources</h3>
<?php if (!empty($resources)): ?>
<ul class="space-y-3">
<?php foreach ($resources as $resource): ?>
<li>
<a href="<?php echo htmlspecialchars($resource['url']); ?>"
target="_blank"
class="flex items-center text-emerald-600 hover:text-emerald-700">
<i class="fas fa-external-link-alt mr-2"></i>
<?php echo htmlspecialchars($resource['title']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="text-gray-500">No additional resources available.</p>
<?php endif; ?>
</div>
<!-- Downloads -->
<div>
<h3 class="text-lg font-semibold mb-4">Downloads</h3>
<?php if (!empty($downloads)): ?>
<ul class="space-y-3">
<?php foreach ($downloads as $download): ?>
<li>
<a href="<?php echo APP_URL; ?>/courses/download/<?php echo $download['id']; ?>"
class="flex items-center text-emerald-600 hover:text-emerald-700">
<i class="fas fa-download mr-2"></i>
<?php echo htmlspecialchars($download['title']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="text-gray-500">No downloadable resources available.</p>
<?php endif; ?>
</div>
<!-- Related Materials -->
<div>
<h3 class="text-lg font-semibold mb-4">Related Materials</h3>
<?php if (!empty($relatedMaterials)): ?>
<ul class="space-y-3">
<?php foreach ($relatedMaterials as $material): ?>
<li>
<a href="<?php echo APP_URL; ?>/courses/learn/<?php echo $course['id']; ?>/material/<?php echo $material['id']; ?>"
class="flex items-center text-emerald-600 hover:text-emerald-700">
<i class="fas fa-play-circle mr-2"></i>
<?php echo htmlspecialchars($material['title']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="text-gray-500">No related materials available.</p>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<?php else: ?>
<div class="bg-white rounded-lg shadow-sm p-8 text-center">
<i class="fas fa-book-open text-4xl text-gray-400 mb-4"></i>
<h2 class="text-xl font-bold mb-2">Start Learning</h2>
<p class="text-gray-600">Select a material from the course content to begin learning.</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
<!-- JavaScript for Sidebar Toggle -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const sidebar = document.getElementById('course-sidebar');
const mobileToggle = document.getElementById('mobile-content-toggle');
const closeButton = document.getElementById('close-sidebar');
// Toggle sidebar on mobile
mobileToggle.addEventListener('click', () => {
sidebar.classList.toggle('-translate-x-full');
});
// Close sidebar on mobile
closeButton.addEventListener('click', () => {
sidebar.classList.add('-translate-x-full');
});
// Handle section toggles
window.toggleSection = function(sectionIndex) {
const content = document.getElementById(`section-content-${sectionIndex}`);
const icon = document.getElementById(`section-icon-${sectionIndex}`);
content.classList.toggle('hidden');
icon.classList.toggle('rotate-180');
}
// Auto-expand section containing current material
if (document.querySelector('.bg-emerald-50')) {
const currentMaterial = document.querySelector('.bg-emerald-50');
const section = currentMaterial.closest('[id^="section-content"]');
if (section) {
section.classList.remove('hidden');
const sectionIndex = section.id.split('-')[2];
document.getElementById(`section-icon-${sectionIndex}`).classList.add('rotate-180');
}
}
});
</script>
<!-- Share functionality -->
<script>
function toggleShareMenu() {
const menu = document.getElementById('shareMenu');
menu.classList.toggle('hidden');
}
function shareTo(platform) {
const url = encodeURIComponent(window.location.href);
const title = encodeURIComponent('<?php echo htmlspecialchars($course['title']); ?>');
let shareUrl = '';
switch(platform) {
case 'facebook':
shareUrl = `https://www.facebook.com/sharer/sharer.php?u=${url}`;
break;
case 'twitter':
shareUrl = `https://twitter.com/intent/tweet?url=${url}&text=${title}`;
break;
case 'linkedin':
shareUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${url}`;
break;
}
if (shareUrl) {
window.open(shareUrl, '_blank', 'width=600,height=400');
}
toggleShareMenu();
}
function copyLink() {
navigator.clipboard.writeText(window.location.href).then(() => {
alert('Link copied to clipboard!');
toggleShareMenu();
});
}
// Rating functionality
function openRatingModal() {
document.getElementById('ratingModal').classList.remove('hidden');
}
function closeRatingModal() {
document.getElementById('ratingModal').classList.add('hidden');
}
function setRating(rating) {
document.getElementById('ratingInput').value = rating;
const stars = document.querySelectorAll('.star-rating i');
stars.forEach((star, index) => {
if (index < rating) {
star.classList.remove('far');
star.classList.add('fas');
} else {
star.classList.remove('fas');
star.classList.add('far');
}
});
}
// Close modals when clicking outside
window.addEventListener('click', function(event) {
const shareMenu = document.getElementById('shareMenu');
const ratingModal = document.getElementById('ratingModal');
if (!event.target.closest('#shareMenu') && !event.target.closest('button')) {
shareMenu.classList.add('hidden');
}
if (event.target === ratingModal) {
closeRatingModal();
}
});
// Initialize tooltips
document.addEventListener('DOMContentLoaded', function() {
const stars = document.querySelectorAll('.star-rating');
stars.forEach(star => {
star.addEventListener('mouseover', function() {
const rating = this.dataset.rating;
const stars = document.querySelectorAll('.star-rating i');
stars.forEach((star, index) => {
if (index < rating) {
star.classList.remove('far');
star.classList.add('fas');
}
});
});
star.addEventListener('mouseout', function() {
const currentRating = document.getElementById('ratingInput').value;
const stars = document.querySelectorAll('.star-rating i');
stars.forEach((star, index) => {
if (index < currentRating) {
star.classList.remove('far');
star.classList.add('fas');
} else {
star.classList.remove('fas');
star.classList.add('far');
}
});
});
});
});
</script>
<!-- Add this to your existing JavaScript section -->
<script>
// Define APP_URL constant
const APP_URL = '<?php echo APP_URL; ?>';
// Notes functionality
function saveNote() {
const noteForm = document.getElementById('noteForm');
const formData = new FormData(noteForm);
fetch(`${APP_URL}/courses/saveNote`, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
const notesContainer = document.getElementById('notes-container');
const noteElement = createNoteElement(data.note);
notesContainer.appendChild(noteElement);
noteForm.reset();
} else {
alert('Error saving note');
}
});
return false;
}
function editNote(noteId, content) {
const noteForm = document.getElementById('noteForm');
const textarea = noteForm.querySelector('textarea[name="content"]');
const submitBtn = noteForm.querySelector('button[type="submit"]');
textarea.value = content;
noteForm.querySelector('input[name="note_id"]').value = noteId;
submitBtn.textContent = 'Update Note';
textarea.focus();
}
function deleteNote(noteId) {
if (confirm('Are you sure you want to delete this note?')) {
fetch(`${APP_URL}/courses/deleteNote/${noteId}`, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
const noteElement = document.getElementById(`note-${noteId}`);
noteElement.remove();
} else {
alert('Error deleting note');
}
});
}
}
// ... existing code ...
function switchTab(tabName) {
// Remove active class from all tabs and content
document.querySelectorAll('.tab-button').forEach(tab => {
tab.classList.remove('active', 'border-emerald-500', 'text-emerald-600');
tab.classList.add('border-transparent', 'text-gray-500');
});
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.add('hidden');
});
// Add active class to selected tab and show content
const selectedTab = document.querySelector(`[data-tab="${tabName}"]`);
selectedTab.classList.add('active', 'border-emerald-500', 'text-emerald-600');
selectedTab.classList.remove('border-transparent', 'text-gray-500');
document.getElementById(`${tabName}-tab`).classList.remove('hidden');
}
// Notes functionality
function editNote(noteId, content) {
document.getElementById('editNoteId').value = noteId;
document.getElementById('editNoteContent').value = content;
document.getElementById('editNoteModal').classList.remove('hidden');
}
function closeEditModal() {
document.getElementById('editNoteModal').classList.add('hidden');
}
function updateNote(event) {
event.preventDefault();
const form = event.target;
const formData = new FormData(form);
const noteId = formData.get('note_id');
fetch(`${APP_URL}/courses/updateNote/${noteId}`, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
const noteElement = document.getElementById(`note-${noteId}`);
const contentElement = noteElement.querySelector('.note-content');
contentElement.innerHTML = data.note.content.replace(/\n/g, '<br>');
closeEditModal();
} else {
alert(data.message || 'Error updating note');
}
})
.catch(error => {
console.error('Error:', error);
alert('Error updating note');
});
return false;
}
function deleteNote(noteId) {
if (confirm('Are you sure you want to delete this note?')) {
fetch(`${APP_URL}/courses/deleteNote/${noteId}`, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
const noteElement = document.getElementById(`note-${noteId}`);
noteElement.remove();
} else {
alert(data.message || 'Error deleting note');
}
})
.catch(error => {
console.error('Error:', error);
alert('Error deleting note');
});
}
}
function saveNote(event) {
event.preventDefault();
const form = event.target;
const formData = new FormData(form);
fetch(form.action, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Clear the form
form.reset();
// Add the new note to the list
const notesContainer = document.querySelector('.space-y-4');
const newNote = createNoteElement(data.note);
notesContainer.insertBefore(newNote, notesContainer.firstChild);
} else {
alert(data.message || 'Error saving note');
}
})
.catch(error => {
console.error('Error:', error);
alert('Error saving note');
});
return false;
}
function createNoteElement(note) {
const div = document.createElement('div');
div.className = 'bg-gray-50 rounded-lg p-4';
div.id = `note-${note.id}`;
const date = new Date(note.created_at);
const formattedDate = date.toLocaleString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true
});
div.innerHTML = `
<div class="flex justify-between items-start mb-2">
<div class="text-sm text-gray-500">
${formattedDate}
</div>
<div class="flex space-x-2">
<button onclick="editNote(${note.id}, '${note.content.replace(/'/g, "\\'")}')"
class="text-gray-400 hover:text-gray-600">
<i class="fas fa-edit"></i>
</button>
<button onclick="deleteNote(${note.id})"
class="text-gray-400 hover:text-red-600">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<div class="prose prose-sm note-content">
${note.content.replace(/\n/g, '<br>')}
</div>
`;
return div;
}
// Discussion functionality
function replyToMessage(messageId) {
const textarea = document.querySelector('#discussionForm textarea');
textarea.focus();
textarea.value = `@message-${messageId} `;
}
function deleteMessage(messageId) {
if (confirm('Are you sure you want to delete this message?')) {
fetch(`${APP_URL}/courses/deleteDiscussion/${messageId}`, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Error deleting message');
}
});
}
}
// Auto-scroll discussion to bottom when new messages are added
const discussionMessages = document.getElementById('discussion-messages');
if (discussionMessages) {
discussionMessages.scrollTop = discussionMessages.scrollHeight;
}
function submitDiscussion(event) {
event.preventDefault();
const form = event.target;
const formData = new FormData(form);
fetch(form.action, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Clear the form
form.reset();
// Update the discussions container
const discussionsContainer = document.getElementById('discussion-messages');
discussionsContainer.innerHTML = ''; // Clear existing discussions
// Add all discussions including the new one
data.discussions.forEach(discussion => {
const discussionElement = createDiscussionElement(discussion);
discussionsContainer.appendChild(discussionElement);
});
// Scroll to the bottom of the discussions
discussionsContainer.scrollTop = discussionsContainer.scrollHeight;
} else {
alert('Error posting discussion');
}
})
.catch(error => {
console.error('Error:', error);
alert('Error posting discussion');
});
return false;
}
function createDiscussionElement(discussion) {
const div = document.createElement('div');
div.className = 'flex space-x-3';
div.id = `discussion-${discussion.id}`;
const date = new Date(discussion.created_at);
const formattedDate = date.toLocaleString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true
});
div.innerHTML = `
<div class="flex-shrink-0">
${discussion.user_avatar ?
`<img src="${discussion.user_avatar}" alt="" class="h-10 w-10 rounded-full">` :
`<div class="h-10 w-10 rounded-full bg-emerald-100 flex items-center justify-center">
<span class="text-emerald-600 font-semibold">
${discussion.user_name.charAt(0).toUpperCase()}
</span>
</div>`
}
</div>
<div class="flex-1">
<div class="flex items-center justify-between">
<div class="text-sm font-medium text-gray-900">
${discussion.user_name}
</div>
<div class="text-sm text-gray-500">
${formattedDate}
</div>
</div>
<div class="mt-1 text-sm text-gray-700">
${discussion.content.replace(/\n/g, '<br>')}
</div>
<div class="mt-2 flex items-center space-x-4 text-sm">
<button onclick="replyToMessage(${discussion.id})"
class="text-gray-500 hover:text-gray-700">
<i class="fas fa-reply mr-1"></i> Reply
</button>
${discussion.user_id == <?php echo $_SESSION['user_id'] ?? 0; ?> ?
`<button onclick="deleteMessage(${discussion.id})"
class="text-gray-500 hover:text-red-600">
<i class="fas fa-trash mr-1"></i> Delete
</button>` : ''
}
</div>
${discussion.replies && discussion.replies.length > 0 ?
`<div class="mt-4 space-y-4 pl-4 border-l-2 border-gray-200">
${discussion.replies.map(reply => createReplyElement(reply)).join('')}
</div>` : ''
}
</div>
`;
return div;
}
function createReplyElement(reply) {
const date = new Date(reply.created_at);
const formattedDate = date.toLocaleString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true
});
return `
<div class="flex space-x-3" id="reply-${reply.id}">
<div class="flex-shrink-0">
${reply.user_avatar ?
`<img src="${reply.user_avatar}" alt="" class="h-8 w-8 rounded-full">` :
`<div class="h-8 w-8 rounded-full bg-emerald-100 flex items-center justify-center">
<span class="text-emerald-600 font-semibold text-sm">
${reply.user_name.charAt(0).toUpperCase()}
</span>
</div>`
}
</div>
<div class="flex-1">
<div class="flex items-center justify-between">
<div class="text-sm font-medium text-gray-900">
${reply.user_name}
</div>
<div class="text-sm text-gray-500">
${formattedDate}
</div>
</div>
<div class="mt-1 text-sm text-gray-700">
${reply.content.replace(/\n/g, '<br>')}
</div>
${reply.user_id == <?php echo $_SESSION['user_id'] ?? 0; ?> ?
`<div class="mt-2">
<button onclick="deleteMessage(${reply.id})"
class="text-gray-500 hover:text-red-600 text-sm">
<i class="fas fa-trash mr-1"></i> Delete
</button>
</div>` : ''
}
</div>
</div>
`;
}
</script>
<style>
/* Custom scrollbar styles */
.custom-scrollbar::-webkit-scrollbar {
width: 8px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: #10b981;
border-radius: 4px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: #059669;
}
/* For Firefox */
.custom-scrollbar {
scrollbar-width: thin;
scrollbar-color: #10b981 #f1f1f1;
}
</style>
<!-- Add this to your JavaScript section -->
<script>
function closeCompletionModal() {
const modal = document.querySelector('.fixed.inset-0');
if (modal) {
modal.remove();
}
}
</script>
<?php
$content = ob_get_clean();
require APP_PATH . '/views/layouts/dashboard.php';
?>