388 lines
21 KiB
PHP
388 lines
21 KiB
PHP
<?php
|
|
require_once 'config.php';
|
|
requireLogin();
|
|
requireAdmin();
|
|
|
|
$action = $_GET['action'] ?? 'list';
|
|
$error = '';
|
|
$success = '';
|
|
|
|
// Handle form submissions
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$title = $_POST['title'] ?? '';
|
|
$description = $_POST['description'] ?? '';
|
|
$due_date = $_POST['due_date'] ?? '';
|
|
$student_id = $_POST['student_id'] ?? '';
|
|
|
|
if (isset($_POST['add'])) {
|
|
$student_ids = $_POST['student_ids'] ?? [];
|
|
if (empty($title) || empty($due_date) || empty($student_ids)) {
|
|
$error = 'กรุณากรอกข้อมูลให้ครบถ้วน (เลือกนักเรียนอย่างน้อย 1 คน)';
|
|
} else {
|
|
$stmt = $pdo->prepare("INSERT INTO assignments (title, description, due_date, student_id) VALUES (?, ?, ?, ?)");
|
|
$success_count = 0;
|
|
foreach ($student_ids as $sid) {
|
|
if ($stmt->execute([$title, $description, $due_date, $sid])) {
|
|
$new_id = $pdo->lastInsertId();
|
|
logActivity($pdo, 'CREATE_ASSIGNMENT', "Created assignment ID: $new_id, Title: $title, Student ID: $sid");
|
|
$success_count++;
|
|
}
|
|
}
|
|
if ($success_count > 0) {
|
|
$success = "เพิ่มงานสำเร็จให้แก่ $success_count คน";
|
|
$action = 'list';
|
|
} else {
|
|
$error = 'เกิดข้อผิดพลาดในการเพิ่มงาน';
|
|
}
|
|
}
|
|
} elseif (isset($_POST['edit'])) {
|
|
$id = $_POST['id'] ?? '';
|
|
$status = $_POST['status'] ?? 'pending';
|
|
$student_ids = $_POST['student_ids'] ?? [];
|
|
|
|
if (empty($title) || empty($due_date) || empty($student_ids)) {
|
|
$error = 'กรุณากรอกข้อมูลให้ครบถ้วน (เลือกนักเรียนอย่างน้อย 1 คน)';
|
|
} else {
|
|
// Update the current assignment with the FIRST selected student
|
|
$first_student_id = array_shift($student_ids);
|
|
|
|
$stmt = $pdo->prepare("UPDATE assignments SET title=?, description=?, due_date=?, student_id=?, status=? WHERE id=?");
|
|
if ($stmt->execute([$title, $description, $due_date, $first_student_id, $status, $id])) {
|
|
logActivity($pdo, 'UPDATE_ASSIGNMENT', "Updated assignment ID: $id, Title: $title, Status: $status");
|
|
$success = 'แก้ไขงานสำเร็จ';
|
|
|
|
// If more students were checked, insert them as new assignments (cloning)
|
|
if (!empty($student_ids)) {
|
|
$insert_stmt = $pdo->prepare("INSERT INTO assignments (title, description, due_date, student_id, status) VALUES (?, ?, ?, ?, ?)");
|
|
$added_count = 0;
|
|
foreach ($student_ids as $sid) {
|
|
if ($insert_stmt->execute([$title, $description, $due_date, $sid, $status])) {
|
|
$added_count++;
|
|
}
|
|
}
|
|
if ($added_count > 0) {
|
|
$success .= " และเพิ่มงานใหม่ให้กับนักเรียนที่เลือกเพิ่มอีก $added_count คน";
|
|
}
|
|
}
|
|
$action = 'list';
|
|
} else {
|
|
$error = 'เกิดข้อผิดพลาดในการแก้ไขงาน';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle delete
|
|
if (isset($_GET['delete'])) {
|
|
$id = $_GET['delete'];
|
|
|
|
// Get assignment info before deleting for log
|
|
$stmt_info = $pdo->prepare("SELECT title FROM assignments WHERE id=?");
|
|
$stmt_info->execute([$id]);
|
|
$assign_info = $stmt_info->fetch();
|
|
|
|
$stmt = $pdo->prepare("DELETE FROM assignments WHERE id=?");
|
|
if ($stmt->execute([$id])) {
|
|
$title = $assign_info ? $assign_info['title'] : 'Unknown';
|
|
logActivity($pdo, 'DELETE_ASSIGNMENT', "Deleted assignment ID: $id, Title: $title");
|
|
$success = 'ลบงานสำเร็จ';
|
|
}
|
|
}
|
|
|
|
// Fetch students for dropdowns
|
|
$stmt = $pdo->query("SELECT id, name FROM users WHERE role = 'student' ORDER BY name");
|
|
$students = $stmt->fetchAll();
|
|
|
|
include 'includes/header.php';
|
|
include 'includes/sidebar.php';
|
|
?>
|
|
|
|
<div class="mb-6 flex justify-between items-center">
|
|
<div>
|
|
<h2 class="text-2xl font-bold text-gray-800">จัดการงาน</h2>
|
|
<p class="text-gray-600 mt-1">เพิ่ม แก้ไข และลบงานที่มอบหมายให้นักเรียน</p>
|
|
</div>
|
|
<?php if ($action === 'list'): ?>
|
|
<a href="?action=add" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded shadow">
|
|
<i class="fas fa-plus mr-2"></i> เพิ่มงานใหม่
|
|
</a>
|
|
<?php else: ?>
|
|
<a href="assignments.php" class="bg-gray-500 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded shadow">
|
|
<i class="fas fa-arrow-left mr-2"></i> กลับ
|
|
</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-6 rounded shadow-sm">
|
|
<p><i class="fas fa-exclamation-circle mr-2"></i> <?= htmlspecialchars($error) ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($success): ?>
|
|
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-6 rounded shadow-sm">
|
|
<p><i class="fas fa-check-circle mr-2"></i> <?= htmlspecialchars($success) ?></p>
|
|
</div>
|
|
<script>
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'สำเร็จ',
|
|
text: '<?= addslashes($success) ?>',
|
|
timer: 2000,
|
|
showConfirmButton: false
|
|
});
|
|
</script>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($action === 'list'): ?>
|
|
<div class="bg-white rounded-lg shadow-md p-6">
|
|
<table class="dataTable display w-full text-sm text-left text-gray-500">
|
|
<thead class="text-xs text-gray-700 uppercase bg-gray-50">
|
|
<tr>
|
|
<th class="text-center w-16">ลำดับ</th>
|
|
<th class="text-center">ชื่องาน/ชื่อวิชา</th>
|
|
<th class="text-center">นักเรียน</th>
|
|
<th class="text-center w-32">วันที่เพิ่มข้อมูล</th>
|
|
<th class="text-center">กำหนดส่ง</th>
|
|
<th class="text-center w-24">สถานะ</th>
|
|
<th class="text-center">จัดการ</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$days_before = getSetting($pdo, 'days_before_due') ?: 3;
|
|
$stmt = $pdo->query("SELECT a.*, u.name as student_name, DATEDIFF(a.due_date, CURDATE()) as days_left FROM assignments a LEFT JOIN users u ON a.student_id = u.id ORDER BY a.id DESC");
|
|
$index = 1;
|
|
while ($row = $stmt->fetch()):
|
|
// Get all assigned students for this specific task
|
|
$stmt_group = $pdo->prepare("SELECT u.name FROM assignments a JOIN users u ON a.student_id = u.id WHERE a.title = ? AND a.due_date = ?");
|
|
$stmt_group->execute([$row['title'], $row['due_date']]);
|
|
$assigned_names = $stmt_group->fetchAll(PDO::FETCH_COLUMN);
|
|
$assigned_list = implode(', ', $assigned_names);
|
|
|
|
// Format Created At
|
|
$created_timestamp = strtotime($row['created_at']);
|
|
$created_date_th = date('d-m-', $created_timestamp) . (date('Y', $created_timestamp) + 543);
|
|
|
|
// Format Due Date
|
|
$due_timestamp = strtotime($row['due_date']);
|
|
$due_date_th = date('d-m-', $due_timestamp) . (date('Y', $due_timestamp) + 543);
|
|
|
|
$due_html = "<span>{$due_date_th}</span>";
|
|
$status_text = "รอดำเนินการ";
|
|
if ($row['status'] === 'pending') {
|
|
if ($row['days_left'] < 0) {
|
|
$due_html .= " <span class=\"bg-gray-800 text-white text-xs px-2 py-0.5 rounded ml-2 whitespace-nowrap\">เลยกำหนด " . abs($row['days_left']) . " วัน</span>";
|
|
} elseif ($row['days_left'] <= $days_before) {
|
|
$due_html .= " <span class=\"bg-orange-500 text-white text-xs px-2 py-0.5 rounded ml-2 whitespace-nowrap\">เหลือ {$row['days_left']} วัน</span>";
|
|
} else {
|
|
$due_html .= " <span class=\"bg-gray-100 text-gray-600 text-xs px-2 py-0.5 rounded ml-2 whitespace-nowrap\">เหลือ {$row['days_left']} วัน</span>";
|
|
}
|
|
} else {
|
|
$status_text = "เสร็จสิ้น";
|
|
}
|
|
?>
|
|
<tr class="bg-white border-b hover:bg-gray-50">
|
|
<td class="text-center"><?= $index++ ?></td>
|
|
<td class="font-medium text-gray-900"><?= htmlspecialchars($row['title']) ?></td>
|
|
<td><?= htmlspecialchars($row['student_name']) ?></td>
|
|
<td class="text-center"><?= $created_date_th ?></td>
|
|
<td class="text-center"><?= $due_html ?></td>
|
|
<td class="text-center">
|
|
<?php if ($row['status'] === 'submitted' || $row['status'] === 'completed'): ?>
|
|
<span class="bg-green-100 text-green-800 py-1 px-2 rounded-full text-xs font-semibold">เสร็จสิ้น</span>
|
|
<?php else: ?>
|
|
<span class="bg-yellow-100 text-yellow-800 py-1 px-2 rounded-full text-xs font-semibold">รอดำเนินการ</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="text-center whitespace-nowrap">
|
|
<button type="button"
|
|
onclick="showDetails(
|
|
'<?= htmlspecialchars(addslashes($row['title'])) ?>',
|
|
'<?= htmlspecialchars(addslashes($row['description'] ?: '-')) ?>',
|
|
'<?= htmlspecialchars(addslashes($assigned_list)) ?>',
|
|
'<?= $due_date_th ?>',
|
|
'<?= $status_text ?>'
|
|
)"
|
|
class="text-white bg-blue-500 hover:bg-blue-600 font-medium rounded-lg text-sm px-3 py-1 mr-1" title="ดูรายละเอียด"><i class="fas fa-eye"></i></button>
|
|
<a href="?action=edit&id=<?= $row['id'] ?>" class="text-white bg-yellow-400 hover:bg-yellow-500 font-medium rounded-lg text-sm px-3 py-1 mr-1" title="แก้ไข"><i class="fas fa-edit"></i></a>
|
|
<button onclick="confirmDelete(<?= $row['id'] ?>)" class="text-white bg-red-600 hover:bg-red-700 font-medium rounded-lg text-sm px-3 py-1" title="ลบ"><i class="fas fa-trash"></i></button>
|
|
</td>
|
|
</tr>
|
|
<?php endwhile; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<script>
|
|
function showDetails(title, desc, assignedTo, dueDate, status) {
|
|
const statusColor = status === 'เสร็จสิ้น' ? 'text-green-600' : 'text-yellow-600';
|
|
|
|
let htmlContent = `
|
|
<div class="text-left space-y-4 text-sm mt-4">
|
|
<div class="bg-gray-50 p-3 rounded border">
|
|
<p class="text-gray-500 mb-1"><i class="fas fa-align-left mr-2"></i><strong>รายละเอียดงาน:</strong></p>
|
|
<p class="text-gray-800 whitespace-pre-wrap">${desc}</p>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between border-b pb-2">
|
|
<span class="text-gray-500"><i class="fas fa-users mr-2"></i><strong>ผู้ที่ถูกมอบหมาย:</strong></span>
|
|
<span class="text-gray-800 text-right ml-4">${assignedTo}</span>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between border-b pb-2">
|
|
<span class="text-gray-500"><i class="far fa-calendar-alt mr-2"></i><strong>วันที่กำหนดส่ง:</strong></span>
|
|
<span class="text-gray-800 font-medium">${dueDate}</span>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between pb-2">
|
|
<span class="text-gray-500"><i class="fas fa-info-circle mr-2"></i><strong>สถานะปัจจุบัน:</strong></span>
|
|
<span class="font-bold ${statusColor}">${status}</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
Swal.fire({
|
|
title: `<div class="text-xl text-blue-700 font-bold border-b pb-3">${title}</div>`,
|
|
html: htmlContent,
|
|
width: 600,
|
|
showCloseButton: true,
|
|
confirmButtonText: 'ปิดหน้าต่าง',
|
|
confirmButtonColor: '#3085d6',
|
|
customClass: {
|
|
title: 'mb-0'
|
|
}
|
|
});
|
|
}
|
|
|
|
function confirmDelete(id) {
|
|
Swal.fire({
|
|
title: 'ยืนยันการลบ?',
|
|
text: "คุณไม่สามารถกู้คืนข้อมูลนี้ได้!",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#d33',
|
|
cancelButtonColor: '#3085d6',
|
|
confirmButtonText: 'ใช่, ลบเลย!',
|
|
cancelButtonText: 'ยกเลิก'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
window.location.href = `assignments.php?delete=${id}`;
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<?php elseif ($action === 'add' || $action === 'edit'):
|
|
$editMode = ($action === 'edit' && isset($_GET['id']));
|
|
$item = null;
|
|
if ($editMode) {
|
|
$stmt = $pdo->prepare("SELECT * FROM assignments WHERE id = ?");
|
|
$stmt->execute([$_GET['id']]);
|
|
$item = $stmt->fetch();
|
|
if (!$item) {
|
|
echo "<script>window.location.href='assignments.php';</script>";
|
|
exit;
|
|
}
|
|
}
|
|
?>
|
|
<div class="bg-white rounded-lg shadow-md p-6 max-w-2xl mx-auto">
|
|
<h3 class="text-xl font-bold mb-4 border-b pb-2"><?= $editMode ? 'แก้ไขงาน' : 'เพิ่มงานใหม่' ?></h3>
|
|
|
|
<form method="POST" action="assignments.php">
|
|
<?php if ($editMode): ?>
|
|
<input type="hidden" name="id" value="<?= $item['id'] ?>">
|
|
<?php endif; ?>
|
|
|
|
<div class="mb-4">
|
|
<label class="block text-gray-700 text-sm font-bold mb-2" for="title">ชื่องาน/ชื่อวิชา <span class="text-red-500">*</span></label>
|
|
<input type="text" name="title" id="title" value="<?= $editMode ? htmlspecialchars($item['title']) : '' ?>" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500" required>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label class="block text-gray-700 text-sm font-bold mb-2" for="description">รายละเอียดงาน</label>
|
|
<textarea name="description" id="description" rows="3" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500"><?= $editMode ? htmlspecialchars($item['description']) : '' ?></textarea>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-2" for="due_date">วันที่กำหนดส่ง <span class="text-red-500">*</span></label>
|
|
<input type="date" name="due_date" id="due_date" value="<?= $editMode ? $item['due_date'] : '' ?>" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500" required>
|
|
</div>
|
|
<div class="md:col-span-2">
|
|
<label class="block text-gray-700 text-sm font-bold mb-2" for="student_ids">มอบหมายให้นักเรียน <span class="text-red-500">*</span></label>
|
|
<div class="border rounded shadow-sm">
|
|
<div class="p-2 border-b bg-gray-50 flex justify-between items-center">
|
|
<input type="text" id="search_student" placeholder="ค้นหาชื่อ-สกุล..." class="text-sm px-2 py-1 border rounded w-2/3 focus:outline-none focus:border-blue-500">
|
|
<label class="flex items-center text-sm font-bold text-blue-600 cursor-pointer">
|
|
<input type="checkbox" id="select_all_students" class="mr-2"> เลือกทั้งหมด
|
|
</label>
|
|
</div>
|
|
<div class="max-h-48 overflow-y-auto p-2" id="student_list">
|
|
<?php foreach ($students as $student): ?>
|
|
<label class="flex items-center p-2 hover:bg-blue-50 rounded cursor-pointer student-item">
|
|
<input type="checkbox" name="student_ids[]" value="<?= $student['id'] ?>" class="mr-3 student-checkbox" <?= ($editMode && $item['student_id'] == $student['id']) ? 'checked' : '' ?>>
|
|
<span class="student-name text-gray-700"><?= htmlspecialchars($student['name']) ?></span>
|
|
</label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($editMode): ?>
|
|
<div class="mb-6">
|
|
<label class="block text-gray-700 text-sm font-bold mb-2" for="status">สถานะ</label>
|
|
<select name="status" id="status" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="pending" <?= $item['status'] === 'pending' ? 'selected' : '' ?>>รอดำเนินการ</option>
|
|
<option value="submitted" <?= $item['status'] === 'submitted' ? 'selected' : '' ?>>ส่งแล้ว</option>
|
|
</select>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="flex items-center justify-end border-t pt-4 mt-6">
|
|
<a href="assignments.php" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded mr-2">ยกเลิก</a>
|
|
<button type="submit" name="<?= $editMode ? 'edit' : 'add' ?>" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
|
|
<?= $editMode ? 'บันทึกการแก้ไข' : 'เพิ่มงาน' ?>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const searchInput = document.getElementById('search_student');
|
|
const selectAllCheckbox = document.getElementById('select_all_students');
|
|
const studentItems = document.querySelectorAll('.student-item');
|
|
const studentCheckboxes = document.querySelectorAll('.student-checkbox');
|
|
|
|
if (searchInput) {
|
|
searchInput.addEventListener('input', function(e) {
|
|
const term = e.target.value.toLowerCase();
|
|
studentItems.forEach(item => {
|
|
const name = item.querySelector('.student-name').textContent.toLowerCase();
|
|
if (name.includes(term)) {
|
|
item.style.display = 'flex';
|
|
} else {
|
|
item.style.display = 'none';
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
if (selectAllCheckbox) {
|
|
selectAllCheckbox.addEventListener('change', function(e) {
|
|
const isChecked = e.target.checked;
|
|
studentCheckboxes.forEach(cb => {
|
|
const parent = cb.closest('.student-item');
|
|
if (parent.style.display !== 'none') {
|
|
cb.checked = isChecked;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
<?php include 'includes/footer.php'; ?>
|