256 lines
11 KiB
PHP
256 lines
11 KiB
PHP
<?php
|
|
// admin_assignments.php
|
|
require_once __DIR__ . '/includes/app.php';
|
|
require_once __DIR__ . '/includes/auth.php';
|
|
|
|
require_permission('assignments', 'view');
|
|
|
|
// Initialize table if not exists
|
|
db()->exec("CREATE TABLE IF NOT EXISTS teacher_assignments (
|
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
teacher_id INT NOT NULL,
|
|
class_id INT NOT NULL,
|
|
subject_id INT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE KEY unique_assignment (teacher_id, class_id, subject_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
|
|
|
|
$action = $_GET['action'] ?? 'list';
|
|
$id = (int)($_GET['id'] ?? 0);
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$post_action = $_POST['action'] ?? $action;
|
|
$post_id = (int)($_POST['id'] ?? $id);
|
|
|
|
if ($post_action === 'delete' && $post_id > 0) {
|
|
require_permission('assignments', 'delete');
|
|
$stmt = db()->prepare("DELETE FROM teacher_assignments WHERE id = ?");
|
|
$stmt->execute([$post_id]);
|
|
header('Location: ' . app_url('admin.php', ['page' => 'assignments']));
|
|
exit;
|
|
}
|
|
|
|
if ($post_action === 'add') {
|
|
$teacher_id = (int)($_POST['teacher_id'] ?? 0);
|
|
$class_id = (int)($_POST['class_id'] ?? 0);
|
|
$subject_id = (int)($_POST['subject_id'] ?? 0);
|
|
|
|
if ($teacher_id > 0 && $class_id > 0) {
|
|
try {
|
|
$stmt = db()->prepare("INSERT INTO teacher_assignments (teacher_id, class_id, subject_id) VALUES (?, ?, ?)");
|
|
$stmt->execute([$teacher_id, $class_id, $subject_id]);
|
|
} catch (PDOException $e) {
|
|
// Ignore duplicate key error
|
|
}
|
|
}
|
|
header('Location: ' . app_url('admin.php', ['page' => 'assignments']));
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Fetch all for dropdowns
|
|
$teachers = db()->query("SELECT id, name FROM teachers ORDER BY name")->fetchAll(PDO::FETCH_ASSOC);
|
|
$classes = db()->query("SELECT id, name_en, name_ar FROM classes ORDER BY name_en")->fetchAll(PDO::FETCH_ASSOC);
|
|
$subjects = db()->query("SELECT id, title_en, title_ar, class_id FROM subjects ORDER BY title_en")->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Fetch assignments for table
|
|
$search = $_GET['search'] ?? '';
|
|
$page_num = max(1, (int)($_GET['p'] ?? 1));
|
|
$limit = 10;
|
|
$offset = ($page_num - 1) * $limit;
|
|
|
|
$where = "";
|
|
$params = [];
|
|
if ($search !== '') {
|
|
$where = "WHERE t.name LIKE ? OR c.name_en LIKE ? OR s.title_en LIKE ?";
|
|
$params[] = "%$search%";
|
|
$params[] = "%$search%";
|
|
$params[] = "%$search%";
|
|
}
|
|
|
|
$count_sql = "
|
|
SELECT COUNT(*)
|
|
FROM teacher_assignments ta
|
|
JOIN teachers t ON ta.teacher_id = t.id
|
|
JOIN classes c ON ta.class_id = c.id
|
|
LEFT JOIN subjects s ON ta.subject_id = s.id
|
|
$where
|
|
";
|
|
$total_stmt = db()->prepare($count_sql);
|
|
$total_stmt->execute($params);
|
|
$total = $total_stmt->fetchColumn();
|
|
$pages = ceil($total / $limit);
|
|
|
|
$sql = "
|
|
SELECT ta.id, t.name as teacher_name, c.name_en as class_name_en, c.name_ar as class_name_ar, s.title_en as subject_title_en, s.title_ar as subject_title_ar, ta.subject_id
|
|
FROM teacher_assignments ta
|
|
JOIN teachers t ON ta.teacher_id = t.id
|
|
JOIN classes c ON ta.class_id = c.id
|
|
LEFT JOIN subjects s ON ta.subject_id = s.id
|
|
$where
|
|
ORDER BY ta.id DESC
|
|
LIMIT $limit OFFSET $offset
|
|
";
|
|
$stmt = db()->prepare($sql);
|
|
$stmt->execute($params);
|
|
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
?>
|
|
<div class="section-header mb-4 d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h1 class="section-title mb-2"><?= h(t('Teacher Assignments', 'تعيينات المعلمين')) ?></h1>
|
|
</div>
|
|
<?php if (has_permission('assignments', 'add')): ?>
|
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addAssignmentModal" style="background-color: var(--accent); border-color: var(--accent);">+ <?= h(t('Add Assignment', 'إضافة تعيين')) ?></button>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="panel-card mb-4">
|
|
<form method="get" class="d-flex gap-2 align-items-center">
|
|
<input type="hidden" name="page" value="assignments">
|
|
<input type="text" name="search" class="form-control w-auto" placeholder="<?= h(t('Search...', 'بحث...')) ?>" value="<?= h($search) ?>">
|
|
<button type="submit" class="btn btn-outline-secondary"><?= h(t('Filter', 'تصفية')) ?></button>
|
|
<?php if ($search): ?>
|
|
<a href="<?= h(app_url('admin.php', ['page'=>'assignments'])) ?>" class="btn btn-link text-secondary text-decoration-none"><?= h(t('Clear', 'مسح')) ?></a>
|
|
<?php endif; ?>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="panel-card">
|
|
<div class="table-responsive">
|
|
<table class="table align-middle dashboard-table mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th><?= h(t('Teacher', 'المعلم')) ?></th>
|
|
<th><?= h(t('Class', 'الصف')) ?></th>
|
|
<th><?= h(t('Subject', 'المادة')) ?></th>
|
|
<th><?= h(t('Actions', 'إجراءات')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if(empty($items)): ?>
|
|
<tr>
|
|
<td colspan="4" class="text-center text-muted py-4"><?= h(t('No assignments found.', 'لا توجد تعيينات.')) ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
<?php foreach($items as $row): ?>
|
|
<tr>
|
|
<td>
|
|
<div class="fw-semibold"><?= h($row['teacher_name']) ?></div>
|
|
</td>
|
|
<td>
|
|
<div class="text-secondary"><?= h(current_lang() === 'ar' ? $row['class_name_ar'] : $row['class_name_en']) ?></div>
|
|
</td>
|
|
<td>
|
|
<div class="text-secondary">
|
|
<?php if ($row['subject_id'] > 0): ?>
|
|
<?= h(current_lang() === 'ar' ? $row['subject_title_ar'] : $row['subject_title_en']) ?>
|
|
<?php else: ?>
|
|
<span class="badge bg-secondary"><?= h(t('All Subjects', 'كل المواد')) ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<form method="post" action="<?= h(app_url('admin.php', ['page'=>'assignments'])) ?>" style="display:inline;" onsubmit="return confirm('<?= h(t('Are you sure you want to remove this assignment?', 'هل أنت متأكد من إزالة هذا التعيين؟')) ?>');">
|
|
<input type="hidden" name="action" value="delete">
|
|
<input type="hidden" name="id" value="<?= h((string)$row['id']) ?>">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger">
|
|
<?= h(t('Remove', 'إزالة')) ?>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($pages > 1): ?>
|
|
<nav class="mt-4">
|
|
<ul class="pagination pagination-sm">
|
|
<?php for ($i = 1; $i <= $pages; $i++): ?>
|
|
<li class="page-item <?= $i === $page_num ? 'active' : '' ?>">
|
|
<a class="page-link" href="<?= h(app_url('admin.php', ['page'=>'assignments', 'p'=>$i, 'search'=>$search])) ?>">
|
|
<?= $i ?>
|
|
</a>
|
|
</li>
|
|
<?php endfor; ?>
|
|
</ul>
|
|
</nav>
|
|
<?php endif; ?>
|
|
|
|
<!-- Add Assignment Modal -->
|
|
<div class="modal fade" id="addAssignmentModal" tabindex="-1" aria-labelledby="addAssignmentModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content border-0 shadow">
|
|
<div class="modal-header border-0 bg-dark-blue">
|
|
<h5 class="modal-title section-title text-white" id="addAssignmentModalLabel"><?= h(t('Add Assignment', 'إضافة تعيين')) ?></h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form method="post" action="<?= h(app_url('admin.php', ['page'=>'assignments'])) ?>">
|
|
<input type="hidden" name="action" value="add">
|
|
<div class="mb-3">
|
|
<label class="form-label"><?= h(t('Teacher', 'المعلم')) ?></label>
|
|
<select name="teacher_id" class="form-select" required>
|
|
<option value=""><?= h(t('Select a teacher...', 'اختر معلماً...')) ?></option>
|
|
<?php foreach($teachers as $t): ?>
|
|
<option value="<?= h((string)$t['id']) ?>"><?= h($t['name']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label"><?= h(t('Class', 'الصف')) ?></label>
|
|
<select name="class_id" id="classSelect" class="form-select" required onchange="filterSubjects()">
|
|
<option value=""><?= h(t('Select a class...', 'اختر صفاً...')) ?></option>
|
|
<?php foreach($classes as $c): ?>
|
|
<option value="<?= h((string)$c['id']) ?>"><?= h(current_lang() === 'ar' ? $c['name_ar'] : $c['name_en']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label class="form-label"><?= h(t('Subject (Optional)', 'المادة (اختياري)')) ?></label>
|
|
<select name="subject_id" id="subjectSelect" class="form-select">
|
|
<option value="0" class="default-opt"><?= h(t('All Subjects / Not Specified', 'كل المواد / غير محدد')) ?></option>
|
|
<?php foreach($subjects as $s): ?>
|
|
<option value="<?= h((string)$s['id']) ?>" data-class-id="<?= h((string)$s['class_id']) ?>" style="display:none;">
|
|
<?= h(current_lang() === 'ar' ? $s['title_ar'] : $s['title_en']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<small class="text-muted d-block mt-1"><?= h(t('Select a class first to view its specific subjects.', 'اختر الصف أولاً لرؤية مواده المحددة.')) ?></small>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-end gap-2">
|
|
<button type="button" class="btn btn-light" data-bs-dismiss="modal"><?= h(t('Cancel', 'إلغاء')) ?></button>
|
|
<button type="submit" class="btn btn-primary" style="background-color: var(--accent); border-color: var(--accent);"><?= h(t('Save', 'حفظ')) ?></button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function filterSubjects() {
|
|
var classId = document.getElementById('classSelect').value;
|
|
var subjectSelect = document.getElementById('subjectSelect');
|
|
var options = subjectSelect.getElementsByTagName('option');
|
|
|
|
// reset selection to default
|
|
subjectSelect.value = "0";
|
|
|
|
for (var i = 0; i < options.length; i++) {
|
|
var opt = options[i];
|
|
if (opt.classList.contains('default-opt')) continue;
|
|
|
|
if (opt.getAttribute('data-class-id') === classId && classId !== "") {
|
|
opt.style.display = '';
|
|
} else {
|
|
opt.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
</script>
|