39496-vm/teacher.php
2026-04-06 13:49:07 +00:00

506 lines
28 KiB
PHP

<?php
require_once __DIR__ . '/includes/app.php';
// Mock teacher authentication for now
$teacher_id = 1;
$db = db();
$action = $_GET['action'] ?? 'list';
$course_id = (int)($_GET['course_id'] ?? 0);
$activity_id = (int)($_GET['activity_id'] ?? 0);
// Helper to check course ownership
function owns_course($db, $course_id, $teacher_id) {
$stmt = $db->prepare("SELECT id, name_en, name_ar FROM courses WHERE id = ? AND teacher_id = ?");
$stmt->execute([$course_id, $teacher_id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
// Handle POST actions for activities and assessments
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$post_action = $_POST['action'] ?? '';
if ($post_action === 'add_activity' || $post_action === 'edit_activity') {
$c_id = (int)$_POST['course_id'];
$course = owns_course($db, $c_id, $teacher_id);
if ($course) {
$act_id = (int)($_POST['activity_id'] ?? 0);
$title_en = $_POST['title_en'] ?? '';
$title_ar = $_POST['title_ar'] ?? '';
$desc_en = $_POST['description_en'] ?? '';
$desc_ar = $_POST['description_ar'] ?? '';
if ($post_action === 'add_activity') {
$stmt = $db->prepare("INSERT INTO course_activities (course_id, title_en, title_ar, description_en, description_ar) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$c_id, $title_en, $title_ar, $desc_en, $desc_ar]);
} else if ($post_action === 'edit_activity' && $act_id > 0) {
$stmt = $db->prepare("UPDATE course_activities SET title_en = ?, title_ar = ?, description_en = ?, description_ar = ? WHERE id = ? AND course_id = ?");
$stmt->execute([$title_en, $title_ar, $desc_en, $desc_ar, $act_id, $c_id]);
}
}
header("Location: " . app_url('teacher.php', ['action' => 'activities', 'course_id' => $c_id]));
exit;
}
if ($post_action === 'add_live' || $post_action === 'edit_live') {
$c_id = (int)$_POST['course_id'];
$live_id = (int)($_POST['live_id'] ?? 0);
$title = $_POST['title'] ?? '';
$scheduled_at = $_POST['scheduled_at'] ?? '';
if (owns_course($db, $c_id, $teacher_id)) {
if ($post_action === 'add_live') {
$room_name = 'room_' . substr(md5(uniqid()), 0, 10);
$stmt = $db->prepare("INSERT INTO course_live_lessons (course_id, title, scheduled_at, room_name) VALUES (?, ?, ?, ?)");
$stmt->execute([$c_id, $title, $scheduled_at, $room_name]);
} else if ($post_action === 'edit_live' && $live_id > 0) {
$stmt = $db->prepare("UPDATE course_live_lessons SET title = ?, scheduled_at = ? WHERE id = ? AND course_id = ?");
$stmt->execute([$title, $scheduled_at, $live_id, $c_id]);
}
}
header("Location: " . app_url('teacher.php', ['action' => 'live', 'course_id' => $c_id]));
exit;
}
if ($post_action === 'delete_live') {
$c_id = (int)$_POST['course_id'];
$live_id = (int)$_POST['live_id'];
if (owns_course($db, $c_id, $teacher_id)) {
$stmt = $db->prepare("DELETE FROM course_live_lessons WHERE id = ? AND course_id = ?");
$stmt->execute([$live_id, $c_id]);
}
header("Location: " . app_url('teacher.php', ['action' => 'live', 'course_id' => $c_id]));
exit;
}
if ($post_action === 'delete_activity') {
$c_id = (int)$_POST['course_id'];
$act_id = (int)$_POST['activity_id'];
if (owns_course($db, $c_id, $teacher_id)) {
$stmt = $db->prepare("DELETE FROM course_activities WHERE id = ? AND course_id = ?");
$stmt->execute([$act_id, $c_id]);
}
header("Location: " . app_url('teacher.php', ['action' => 'activities', 'course_id' => $c_id]));
exit;
}
if ($post_action === 'save_assessments') {
$c_id = (int)$_POST['course_id'];
$act_id = (int)$_POST['activity_id'];
if (owns_course($db, $c_id, $teacher_id)) {
$scores = $_POST['scores'] ?? [];
$feedbacks = $_POST['feedbacks'] ?? [];
$stmt = $db->prepare("INSERT INTO student_assessments (activity_id, student_id, score, feedback) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE score = VALUES(score), feedback = VALUES(feedback)");
foreach ($scores as $s_id => $score) {
$s_id = (int)$s_id;
$score_val = ($score !== '') ? (float)$score : null;
$fb = $feedbacks[$s_id] ?? '';
$stmt->execute([$act_id, $s_id, $score_val, $fb]);
}
}
header("Location: " . app_url('teacher.php', ['action' => 'assessments', 'course_id' => $c_id, 'activity_id' => $act_id]));
exit;
}
}
render_head(
t('Teacher workspace', 'مساحة المعلم'),
t('Manage your courses, students, and activities.', 'إدارة دوراتك وطلابك وأنشطتك.')
);
render_nav('teacher.php');
?>
<main class="py-5">
<div class="container">
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<span class="eyebrow"><?= h(t('Teacher workspace', 'مساحة المعلم')) ?></span>
<h1 class="section-title mb-0"><?= h(t('My Courses', 'دوراتي')) ?></h1>
</div>
<?php if ($action !== 'list'): ?>
<a href="teacher.php" class="btn btn-outline-dark"><?= h(t('Back', 'العودة للدورات')) ?></a>
<?php endif; ?>
</div>
<?php if ($action === 'list'): ?>
<?php
$stmt = $db->prepare("SELECT c.*, (SELECT COUNT(*) FROM course_students cs WHERE cs.course_id = c.id) as students_count FROM courses c WHERE c.teacher_id = ? AND c.status = 'active'");
$stmt->execute([$teacher_id]);
$courses = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<div class="row g-4">
<?php foreach ($courses as $c): ?>
<div class="col-md-6 col-lg-4">
<article class="panel-card h-100">
<?php if ($c['picture']): ?>
<img src="<?= h($c['picture']) ?>" class="img-fluid rounded mb-3" style="object-fit:cover; height:150px; width:100%;" alt="">
<?php else: ?>
<div class="bg-light rounded mb-3 d-flex align-items-center justify-content-center" style="height:150px;">
<span class="text-muted">No Image</span>
</div>
<?php endif; ?>
<h2 class="h5 mb-2"><?= h(t($c['name_en'], $c['name_ar'])) ?></h2>
<div class="d-flex justify-content-between text-secondary small mb-3">
<span><?= h(t('Students:', 'الطلاب:')) ?> <?= h($c['students_count']) ?></span>
</div>
<div class="d-flex flex-column gap-2">
<a href="<?= app_url('teacher.php', ['action' => 'students', 'course_id' => $c['id']]) ?>" class="btn btn-sm btn-outline-dark"><?= h(t('View Students', 'عرض الطلاب')) ?></a>
<a href="<?= app_url('teacher.php', ['action' => 'activities', 'course_id' => $c['id']]) ?>" class="btn btn-sm btn-outline-dark"><?= h(t('Manage Activities', 'إدارة الأنشطة')) ?></a>
</div>
</article>
</div>
<?php endforeach; ?>
<?php if (empty($courses)): ?>
<div class="col-12"><div class="alert alert-info"><?= h(t('No active courses found assigned to you.', 'لم يتم العثور على دورات نشطة مخصصة لك.')) ?></div></div>
<?php endif; ?>
</div>
<?php elseif ($action === 'students' && $course_id > 0): ?>
<?php
$course = owns_course($db, $course_id, $teacher_id);
if (!$course) die('Unauthorized');
$stmt = $db->prepare("
SELECT s.id, s.full_name, s.email, s.whatsapp, cs.assigned_at
FROM course_students cs
JOIN student_subscriptions s ON cs.student_id = s.id
WHERE cs.course_id = ?
ORDER BY cs.assigned_at DESC
");
$stmt->execute([$course_id]);
$students = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<h2 class="h4 mb-4"><?= h(t($course['name_en'], $course['name_ar'])) ?> - <?= h(t('Students', 'الطلاب')) ?></h2>
<div class="panel-card">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead>
<tr>
<th><?= h(t('Name', 'الاسم')) ?></th>
<th><?= h(t('Email', 'البريد الإلكتروني')) ?></th>
<th><?= h(t('WhatsApp', 'واتساب')) ?></th>
<th><?= h(t('Enrolled At', 'تاريخ التسجيل')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach($students as $s): ?>
<tr>
<td><?= h($s['full_name']) ?></td>
<td><?= h($s['email']) ?></td>
<td><?= h($s['whatsapp']) ?></td>
<td><?= h(date('Y-m-d', strtotime($s['assigned_at']))) ?></td>
</tr>
<?php endforeach; ?>
<?php if(empty($students)): ?>
<tr><td colspan="4" class="text-center text-muted"><?= h(t('No students enrolled yet.', 'لم يقم أي طالب بالتسجيل بعد.')) ?></td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<?php elseif ($action === 'activities' && $course_id > 0): ?>
<?php
$course = owns_course($db, $course_id, $teacher_id);
if (!$course) die('Unauthorized');
$stmt = $db->prepare("SELECT * FROM course_activities WHERE course_id = ? ORDER BY created_at DESC");
$stmt->execute([$course_id]);
$activities = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="h4 mb-0"><?= h(t($course['name_en'], $course['name_ar'])) ?> - <?= h(t('Activities', 'الأنشطة')) ?></h2>
<button class="btn btn-dark" data-bs-toggle="modal" data-bs-target="#activityModal" onclick="resetActivityForm()">
<?= h(t('+ Add Activity', '+ إضافة نشاط')) ?>
</button>
</div>
<div class="panel-card">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead>
<tr>
<th><?= h(t('Title (EN)', 'العنوان (إنجليزي)')) ?></th>
<th><?= h(t('Title (AR)', 'العنوان (عربي)')) ?></th>
<th><?= h(t('Date', 'التاريخ')) ?></th>
<th><?= h(t('Actions', 'الإجراءات')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach($activities as $act): ?>
<tr>
<td><?= h($act['title_en']) ?></td>
<td><?= h($act['title_ar']) ?></td>
<td><?= h(date('Y-m-d', strtotime($act['created_at']))) ?></td>
<td>
<div class="d-flex gap-2">
<a href="<?= app_url('teacher.php', ['action' => 'assessments', 'course_id' => $course_id, 'activity_id' => $act['id']]) ?>" class="btn btn-sm btn-info text-white"><?= h(t('Assess', 'تقييم')) ?></a>
<button class="btn btn-sm btn-outline-secondary" onclick="editActivity(<?= htmlspecialchars(json_encode($act)) ?>)"><?= h(t('Edit', 'تعديل')) ?></button>
<form method="post" class="d-inline" onsubmit="return confirm('<?= h(t('Are you sure?', 'هل أنت متأكد؟')) ?>')">
<input type="hidden" name="action" value="delete_activity">
<input type="hidden" name="course_id" value="<?= $course_id ?>">
<input type="hidden" name="activity_id" value="<?= $act['id'] ?>">
<button type="submit" class="btn btn-sm btn-outline-danger"><?= h(t('Del', 'حذف')) ?></button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php if(empty($activities)): ?>
<tr><td colspan="4" class="text-center text-muted"><?= h(t('No activities found.', 'لم يتم العثور على أنشطة.')) ?></td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<!-- Activity Modal -->
<div class="modal fade" id="activityModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form method="post">
<div class="modal-header">
<h5 class="modal-title" id="activityModalLabel"><?= h(t('Activity', 'النشاط')) ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="hidden" name="action" id="modal_action" value="add_activity">
<input type="hidden" name="course_id" value="<?= $course_id ?>">
<input type="hidden" name="activity_id" id="modal_activity_id" value="">
<div class="mb-3">
<label class="form-label">Title (EN)</label>
<input type="text" name="title_en" id="modal_title_en" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Title (AR)</label>
<input type="text" name="title_ar" id="modal_title_ar" class="form-control" required dir="rtl">
</div>
<div class="mb-3">
<label class="form-label">Description (EN)</label>
<textarea name="description_en" id="modal_desc_en" class="form-control" rows="3"></textarea>
</div>
<div class="mb-3">
<label class="form-label">Description (AR)</label>
<textarea name="description_ar" id="modal_desc_ar" class="form-control" rows="3" dir="rtl"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= h(t('Cancel', 'إلغاء')) ?></button>
<button type="submit" class="btn btn-dark"><?= h(t('Save', 'حفظ')) ?></button>
</div>
</form>
</div>
</div>
</div>
<script>
function resetActivityForm() {
document.getElementById('modal_action').value = 'add_activity';
document.getElementById('modal_activity_id').value = '';
document.getElementById('modal_title_en').value = '';
document.getElementById('modal_title_ar').value = '';
document.getElementById('modal_desc_en').value = '';
document.getElementById('modal_desc_ar').value = '';
}
function editActivity(act) {
document.getElementById('modal_action').value = 'edit_activity';
document.getElementById('modal_activity_id').value = act.id;
document.getElementById('modal_title_en').value = act.title_en;
document.getElementById('modal_title_ar').value = act.title_ar;
document.getElementById('modal_desc_en').value = act.description_en;
document.getElementById('modal_desc_ar').value = act.description_ar;
var modal = new bootstrap.Modal(document.getElementById('activityModal'));
modal.show();
}
</script>
<?php elseif ($action === 'live' && $course_id > 0): ?>
<?php
$course = owns_course($db, $course_id, $teacher_id);
if (!$course) die('Unauthorized');
$stmt = $db->prepare("SELECT * FROM course_live_lessons WHERE course_id = ? ORDER BY scheduled_at ASC");
$stmt->execute([$course_id]);
$lessons = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="h4 mb-0"><?= h(t($course['name_en'], $course['name_ar'])) ?> - <?= h(t('Live Lessons', 'دروس البث المباشر')) ?></h2>
<button class="btn btn-danger text-white" data-bs-toggle="modal" data-bs-target="#liveModal" onclick="resetLiveForm()">
<?= h(t('+ Schedule Lesson', '+ جدولة درس')) ?>
</button>
</div>
<div class="panel-card">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead>
<tr>
<th><?= h(t('Title', 'العنوان')) ?></th>
<th><?= h(t('Scheduled At', 'موعد الدرس')) ?></th>
<th><?= h(t('Status', 'الحالة')) ?></th>
<th><?= h(t('Actions', 'الإجراءات')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach($lessons as $les): ?>
<tr>
<td><?= h($les['title']) ?></td>
<td><?= h(date('Y-m-d H:i', strtotime($les['scheduled_at']))) ?></td>
<td>
<?php if($les['status'] === 'scheduled'): ?>
<span class="badge bg-warning text-dark"><?= h(t('Scheduled', 'مجدول')) ?></span>
<?php elseif($les['status'] === 'live'): ?>
<span class="badge bg-danger animate-pulse"><?= h(t('LIVE', 'مباشر')) ?></span>
<?php else: ?>
<span class="badge bg-secondary"><?= h(t('Ended', 'منتهي')) ?></span>
<?php endif; ?>
</td>
<td>
<div class="d-flex gap-2">
<?php if($les['status'] !== 'ended'): ?>
<a href="live_lesson.php?id=<?= $les['id'] ?>&as=teacher" class="btn btn-sm btn-success text-white">
<?= h(t('Enter Studio', 'دخول الاستوديو')) ?>
</a>
<?php endif; ?>
<button class="btn btn-sm btn-outline-secondary" onclick="editLive(<?= htmlspecialchars(json_encode($les)) ?>)"><?= h(t('Edit', 'تعديل')) ?></button>
<form method="post" class="d-inline" onsubmit="return confirm('<?= h(t('Are you sure?', 'هل أنت متأكد؟')) ?>')">
<input type="hidden" name="action" value="delete_live">
<input type="hidden" name="course_id" value="<?= $course_id ?>">
<input type="hidden" name="live_id" value="<?= $les['id'] ?>">
<button type="submit" class="btn btn-sm btn-outline-danger"><?= h(t('Del', 'حذف')) ?></button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php if(empty($lessons)): ?>
<tr><td colspan="4" class="text-center text-muted"><?= h(t('No live lessons scheduled.', 'لا يوجد دروس مجدولة.')) ?></td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<!-- Live Modal -->
<div class="modal fade" id="liveModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form method="post">
<div class="modal-header">
<h5 class="modal-title"><?= h(t('Live Lesson', 'الدرس المباشر')) ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="hidden" name="action" id="modal_live_action" value="add_live">
<input type="hidden" name="course_id" value="<?= $course_id ?>">
<input type="hidden" name="live_id" id="modal_live_id" value="">
<div class="mb-3">
<label class="form-label"><?= h(t('Lesson Title', 'عنوان الدرس')) ?></label>
<input type="text" name="title" id="modal_live_title" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label"><?= h(t('Scheduled Time', 'وقت الدرس')) ?></label>
<input type="datetime-local" name="scheduled_at" id="modal_live_time" class="form-control" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= h(t('Cancel', 'إلغاء')) ?></button>
<button type="submit" class="btn btn-danger"><?= h(t('Save', 'حفظ')) ?></button>
</div>
</form>
</div>
</div>
</div>
<script>
function resetLiveForm() {
document.getElementById('modal_live_action').value = 'add_live';
document.getElementById('modal_live_id').value = '';
document.getElementById('modal_live_title').value = '';
document.getElementById('modal_live_time').value = '';
}
function editLive(les) {
document.getElementById('modal_live_action').value = 'edit_live';
document.getElementById('modal_live_id').value = les.id;
document.getElementById('modal_live_time').value = les.scheduled_at.replace(' ', 'T').substring(0, 16);
var modal = new bootstrap.Modal(document.getElementById('liveModal'));
modal.show();
}
</script>
<?php elseif ($action === 'assessments' && $course_id > 0 && $activity_id > 0): ?>
<?php
$course = owns_course($db, $course_id, $teacher_id);
if (!$course) die('Unauthorized');
$stmt = $db->prepare("SELECT title_en, title_ar FROM course_activities WHERE id = ? AND course_id = ?");
$stmt->execute([$activity_id, $course_id]);
$activity = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$activity) die('Activity not found');
$stmt = $db->prepare("
SELECT s.id as student_id, s.full_name, sa.score, sa.feedback
FROM course_students cs
JOIN student_subscriptions s ON cs.student_id = s.id
LEFT JOIN student_assessments sa ON sa.student_id = s.id AND sa.activity_id = ?
WHERE cs.course_id = ?
ORDER BY s.full_name ASC
");
$stmt->execute([$activity_id, $course_id]);
$students = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h2 class="h4 mb-1"><?= h(t($activity['title_en'], $activity['title_ar'])) ?> - <?= h(t('Assessments', 'التقييمات')) ?></h2>
<p class="text-secondary mb-0"><?= h(t($course['name_en'], $course['name_ar'])) ?></p>
</div>
<a href="<?= app_url('teacher.php', ['action' => 'activities', 'course_id' => $course_id]) ?>" class="btn btn-outline-dark"><?= h(t('Back to Activities', 'العودة للأنشطة')) ?></a>
</div>
<div class="panel-card">
<form method="post">
<input type="hidden" name="action" value="save_assessments">
<input type="hidden" name="course_id" value="<?= $course_id ?>">
<input type="hidden" name="activity_id" value="<?= $activity_id ?>">
<div class="table-responsive mb-3">
<table class="table table-hover align-middle mb-0">
<thead>
<tr>
<th style="width: 30%"><?= h(t('Student', 'الطالب')) ?></th>
<th style="width: 20%"><?= h(t('Score', 'الدرجة')) ?></th>
<th style="width: 50%"><?= h(t('Feedback', 'الملاحظات')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach($students as $s): ?>
<tr>
<td><?= h($s['full_name']) ?></td>
<td>
<input type="number" step="0.01" class="form-control" name="scores[<?= $s['student_id'] ?>]" value="<?= h($s['score'] !== null ? $s['score'] : '') ?>" placeholder="0.00">
</td>
<td>
<input type="text" class="form-control" name="feedbacks[<?= $s['student_id'] ?>]" value="<?= h($s['feedback']) ?>" placeholder="<?= h(t('Optional note...', 'ملاحظة اختيارية...')) ?>">
</td>
</tr>
<?php endforeach; ?>
<?php if(empty($students)): ?>
<tr><td colspan="3" class="text-center text-muted"><?= h(t('No students found to assess.', 'لا يوجد طلاب لتقييمهم.')) ?></td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
<?php if(!empty($students)): ?>
<div class="text-end">
<button type="submit" class="btn btn-dark px-4"><?= h(t('Save All Grades', 'حفظ كل الدرجات')) ?></button>
</div>
<?php endif; ?>
</form>
</div>
<?php endif; ?>
</div>
</main>
<?php render_footer(); ?>