Autosave: 20260406-130252

This commit is contained in:
Flatlogic Bot 2026-04-06 13:02:53 +00:00
parent 0798a850bb
commit 9838df1125

View File

@ -1,51 +1,361 @@
<?php
require_once __DIR__ . '/includes/app.php';
$subjects = subjects_catalog();
$metrics = subscription_metrics();
// 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 === '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('Preview the teacher-side classroom view with upcoming live rooms and student demand signals.', 'عاين واجهة المعلم مع الغرف المباشرة القادمة ومؤشرات طلب الطلاب.')
t('Manage your courses, students, and activities.', 'إدارة دوراتك وطلابك وأنشطتك.')
);
render_nav('teacher.php');
?>
<main class="py-5">
<div class="container">
<div class="section-header mb-4">
<div>
<span class="eyebrow"><?= h(t('Teacher workspace', 'مساحة المعلم')) ?></span>
<h1 class="section-title mb-2"><?= h(t('Operate subjects, cohorts, and live classrooms', 'شغّل المواد والمجموعات والفصول المباشرة')) ?></h1>
<p class="text-secondary mb-0"><?= h(t('This role-focused page previews how teachers can manage subject delivery, meeting cadence, and student demand.', 'تعرض هذه الصفحة الموجهة للدور كيف يمكن للمعلمين إدارة تقديم المواد وإيقاع الاجتماعات وطلب الطلاب.')) ?></p>
</div>
<span class="badge bg-dark-subtle text-dark-emphasis border"><?= h(t('Preview UI', 'واجهة معاينة')) ?></span>
</div>
<div class="row g-3 mb-4">
<div class="col-md-4"><div class="metric-card tall"><strong><?= h((string) count($subjects)) ?></strong><span><?= h(t('subjects assigned', 'مواد مخصصة')) ?></span></div></div>
<div class="col-md-4"><div class="metric-card tall"><strong><?= h((string) $metrics['active']) ?></strong><span><?= h(t('active subscribers', 'مشتركين نشطين')) ?></span></div></div>
<div class="col-md-4"><div class="metric-card tall"><strong>4</strong><span><?= h(t('Meet rooms this week', 'غرف Meet هذا الأسبوع')) ?></span></div></div>
</div>
<div class="row g-3">
<?php foreach ($subjects as $subject): ?>
<div class="col-lg-6">
<article class="panel-card h-100">
<div class="d-flex justify-content-between gap-3 align-items-start mb-3">
<div>
<h2 class="h5 mb-1"><?= h(subject_title($subject)) ?></h2>
<p class="small text-secondary mb-0"><?= h(subject_teacher($subject)) ?></p>
</div>
<span class="mini-tag"><?= h(t('Live ready', 'جاهزة للبث')) ?></span>
</div>
<div class="detail-meta-grid mb-3">
<div><strong><?= h(t('Next room', 'الغرفة القادمة')) ?></strong><span><?= h(subject_next_live($subject)) ?></span></div>
<div><strong><?= h(t('Delivery', 'التقديم')) ?></strong><span><?= h(t('Google Meet + async tasks', 'Google Meet + مهام غير متزامنة')) ?></span></div>
</div>
<div class="d-flex gap-2 flex-wrap">
<a class="btn btn-sm btn-dark" href="<?= h($subject['meet_url']) ?>" target="_blank" rel="noreferrer"><?= h(t('Open Meet', 'افتح Meet')) ?></a>
<a class="btn btn-sm btn-outline-dark" href="<?= h(app_url('subject.php', ['slug' => $subject['slug']])) ?>"><?= h(t('Review page', 'راجع الصفحة')) ?></a>
</div>
</article>
<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 endforeach; ?>
<?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 === '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(); ?>
<?php render_footer(); ?>