Initial commit

This commit is contained in:
Porawit Dongwang
2026-09-16 23:20:08 +07:00
commit 0041668dbb
32577 changed files with 3687927 additions and 0 deletions
@@ -0,0 +1,97 @@
<?php
error_reporting(E_ALL);
ini_set('display_errors', 0); // Prevent PHP errors from breaking JSON format
header('Content-Type: application/json');
try {
require_once '../config.php';
if (!isLoggedIn()) {
echo json_encode(['data' => []]);
exit;
}
$user_id = $_SESSION['user_id'];
$role = $_SESSION['role'] ?? 'student';
$filter = $_GET['filter'] ?? 'urgent';
$days_before = getSetting($pdo, 'days_before_due') ?: 3;
$sql = "SELECT a.id, a.title, a.due_date, a.status, a.created_at, 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
WHERE 1=1";
$params = [];
if ($role !== 'admin') {
$sql .= " AND a.student_id = :student_id";
$params[':student_id'] = $user_id;
}
if ($filter === 'urgent') {
$sql .= " AND a.status = 'pending' AND DATEDIFF(a.due_date, CURDATE()) <= :days_before AND DATEDIFF(a.due_date, CURDATE()) >= 0";
$params[':days_before'] = $days_before;
} elseif ($filter === 'pending') {
$sql .= " AND a.status = 'pending'";
} elseif ($filter === 'completed') {
$sql .= " AND a.status = 'completed'";
}
// "งานที่ถูกเพิ่มล่าสุดอยู่บนสุด"
$sql .= " ORDER BY a.id DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$assignments = $stmt->fetchAll();
$data = [];
foreach ($assignments as $index => $item) {
$status_html = '';
if ($item['status'] === 'pending') {
$status_html = '<span class="bg-yellow-100 text-yellow-800 py-1 px-2 rounded-full text-xs font-semibold">รอดำเนินการ</span>';
} else {
$status_html = '<span class="bg-green-100 text-green-800 py-1 px-2 rounded-full text-xs font-semibold">เสร็จสิ้น</span>';
}
// Date formatting: วัน-เดือน-ปี (พ.ศ.)
$due_timestamp = strtotime($item['due_date']);
$due_date_th = date('d-m-', $due_timestamp) . (date('Y', $due_timestamp) + 543);
$created_timestamp = strtotime($item['created_at']);
$created_date_th = date('d-m-', $created_timestamp) . (date('Y', $created_timestamp) + 543);
$due_html = $due_date_th;
if ($item['status'] === 'pending') {
if ($item['days_left'] < 0) {
// เลยกำหนด สีดำ
$due_html = "<span>{$due_date_th}</span> <span class=\"bg-gray-800 text-white text-xs px-2 py-0.5 rounded ml-2 whitespace-nowrap\">เลยกำหนด " . abs($item['days_left']) . " วัน</span>";
} elseif ($item['days_left'] <= $days_before) {
// อยู่ในช่วงเตือน สีส้ม
$due_html = "<span>{$due_date_th}</span> <span class=\"bg-orange-500 text-white text-xs px-2 py-0.5 rounded ml-2 whitespace-nowrap\">เหลือ {$item['days_left']} วัน</span>";
} else {
// ปกติ
$due_html = "<span>{$due_date_th}</span> <span class=\"bg-gray-100 text-gray-600 text-xs px-2 py-0.5 rounded ml-2 whitespace-nowrap\">เหลือ {$item['days_left']} วัน</span>";
}
}
$row = [
'index' => $index + 1,
'title' => htmlspecialchars($item['title'] ?? ''),
'created_at' => $created_date_th,
'due_date' => $due_html,
'status' => $status_html
];
if ($role === 'admin') {
$row['student'] = htmlspecialchars($item['student_name'] ?? 'ไม่ระบุ');
}
$data[] = $row;
}
echo json_encode(['data' => $data]);
} catch (Exception $e) {
// Return error as JSON so DataTables can at least parse it, or we can see it in network tab
echo json_encode(['error' => $e->getMessage(), 'data' => []]);
}
@@ -0,0 +1,63 @@
<?php
require_once '../config.php';
header('Content-Type: application/json');
if (!isLoggedIn() || !isAdmin()) {
echo json_encode(['data' => []]);
exit;
}
try {
$sql = "SELECT l.id, l.action, l.details, l.ip_address, l.created_at, u.name as user_name, u.role as user_role
FROM activity_logs l
LEFT JOIN users u ON l.user_id = u.id
ORDER BY l.created_at DESC LIMIT 1000"; // limit to prevent huge payloads
$stmt = $pdo->prepare($sql);
$stmt->execute();
$logs = $stmt->fetchAll();
$data = [];
foreach ($logs as $log) {
$actor = '';
if ($log['user_name']) {
$badge = $log['user_role'] === 'admin' ? '<span class="bg-purple-100 text-purple-800 px-2 py-0.5 rounded text-xs ml-1">Admin</span>' : '';
$actor = '<div><strong>' . htmlspecialchars($log['user_name']) . '</strong>' . $badge . '</div>';
} else {
// System or failed login
if (strpos($log['action'], 'CRON') !== false) {
$actor = '<span class="text-gray-500"><i class="fas fa-robot mr-1"></i> System (Cron)</span>';
} else {
$actor = '<span class="text-gray-500"><i class="fas fa-user-secret mr-1"></i> Guest / System</span>';
}
}
// Format action nicely
$action_html = htmlspecialchars($log['action']);
if (strpos($log['action'], 'LOGIN') !== false) {
$action_html = '<span class="text-blue-600 font-semibold"><i class="fas fa-sign-in-alt mr-1"></i> ' . $action_html . '</span>';
} elseif (strpos($log['action'], 'CREATE') !== false) {
$action_html = '<span class="text-green-600 font-semibold"><i class="fas fa-plus-circle mr-1"></i> ' . $action_html . '</span>';
} elseif (strpos($log['action'], 'UPDATE') !== false) {
$action_html = '<span class="text-orange-600 font-semibold"><i class="fas fa-edit mr-1"></i> ' . $action_html . '</span>';
} elseif (strpos($log['action'], 'DELETE') !== false) {
$action_html = '<span class="text-red-600 font-semibold"><i class="fas fa-trash-alt mr-1"></i> ' . $action_html . '</span>';
} elseif (strpos($log['action'], 'CRON') !== false) {
$action_html = '<span class="text-indigo-600 font-semibold"><i class="fas fa-paper-plane mr-1"></i> ' . $action_html . '</span>';
}
$data[] = [
'id' => $log['id'],
'created_at' => date('d/m/Y H:i:s', strtotime($log['created_at'])),
'user' => $actor,
'action' => $action_html,
'details' => '<div class="text-xs text-gray-600 break-words max-w-md">' . htmlspecialchars($log['details']) . '</div>',
'ip_address' => '<span class="text-xs text-gray-500 font-mono">' . htmlspecialchars($log['ip_address']) . '</span>'
];
}
echo json_encode(['data' => $data]);
} catch (Exception $e) {
echo json_encode(['error' => $e->getMessage(), 'data' => []]);
}
?>
@@ -0,0 +1,37 @@
<?php
require_once '../config.php';
header('Content-Type: application/json');
if (!isLoggedIn()) {
echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
exit;
}
$user_id = $_SESSION['user_id'];
$role = $_SESSION['role'];
// Get days before due setting
$days_before_due = getSetting($pdo, 'days_before_due') ?: 3;
$sql = "SELECT id, title, due_date, DATEDIFF(due_date, CURDATE()) as days_left
FROM assignments
WHERE status = 'pending'
AND DATEDIFF(due_date, CURDATE()) <= :days_before_due
AND DATEDIFF(due_date, CURDATE()) >= 0";
$params = [':days_before_due' => $days_before_due];
if ($role !== 'admin') {
$sql .= " AND student_id = :student_id";
$params[':student_id'] = $user_id;
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$assignments = $stmt->fetchAll();
echo json_encode([
'status' => 'success',
'data' => $assignments
]);
?>
@@ -0,0 +1,107 @@
<?php
error_reporting(E_ALL);
ini_set('display_errors', 0); // Don't print errors to output directly to not break JSON
require_once '../config.php';
header('Content-Type: application/json');
if (!function_exists('curl_init')) {
echo json_encode(['status' => 'error', 'message' => 'เซิร์ฟเวอร์ของคุณไม่รองรับ cURL (cURL extension is missing)']);
exit;
}
if (!isLoggedIn() || !isAdmin()) {
echo json_encode(['status' => 'error', 'message' => 'Unauthorized access']);
exit;
}
$type = $_POST['type'] ?? '';
if ($type === 'line') {
$token = $_POST['token'] ?? '';
if (empty($token)) {
echo json_encode(['status' => 'error', 'message' => 'กรุณากรอก Token ก่อนทดสอบ']);
exit;
}
$tomorrow = date('d/m/Y', strtotime('+1 day'));
$message = "⚠️ แจ้งเตือนกำหนดส่งงาน ⚠️\n";
$message .= "เรียนคุณ: นักเรียนทดสอบ (Test)\n";
$message .= "งาน: ทดสอบระบบแจ้งเตือน\n";
$message .= "กำหนดส่ง: {$tomorrow}\n";
$message .= "สถานะ: เหลือเวลาอีก 1 วัน!\n";
$message .= "กรุณาตรวจสอบระบบ";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://notify-api.line.me/api/notify");
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array('message' => $message)));
$headers = array('Content-type: application/x-www-form-urlencoded', 'Authorization: Bearer ' . $token);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
$error_msg = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($result === false) {
echo json_encode(['status' => 'error', 'message' => 'cURL Error: ' . $error_msg]);
} elseif ($httpCode == 200) {
echo json_encode(['status' => 'success', 'message' => 'ส่งข้อความทดสอบ LINE สำเร็จ']);
} else {
$resObj = json_decode($result, true);
$reason = isset($resObj['message']) ? $resObj['message'] : 'HTTP Code ' . $httpCode;
echo json_encode(['status' => 'error', 'message' => 'ไม่สามารถส่งข้อความได้: ' . $reason]);
}
} elseif ($type === 'telegram') {
$bot_token = $_POST['bot_token'] ?? '';
$chat_id = $_POST['chat_id'] ?? '';
if (empty($bot_token) || empty($chat_id)) {
echo json_encode(['status' => 'error', 'message' => 'กรุณากรอก Bot Token และ Chat ID ก่อนทดสอบ']);
exit;
}
$tomorrow = date('d/m/Y', strtotime('+1 day'));
$message = "⚠️ <b>แจ้งเตือนกำหนดส่งงาน (Test)</b> ⚠️\n\n";
$message .= "👤 เรียนคุณ: นักเรียนทดสอบ\n";
$message .= "📝 งาน: <b>ทดสอบระบบการแจ้งเตือน</b>\n";
$message .= "📅 กำหนดส่ง: {$tomorrow}\n";
$message .= "⏳ สถานะ: <b>เหลือเวลาอีก 1 วัน!</b>\n";
$url = "https://api.telegram.org/bot{$bot_token}/sendMessage";
$data = [
'chat_id' => $chat_id,
'text' => $message,
'parse_mode' => 'HTML'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$error_msg = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($result === false) {
echo json_encode(['status' => 'error', 'message' => 'cURL Error: ' . $error_msg]);
} elseif ($httpCode == 200) {
echo json_encode(['status' => 'success', 'message' => 'ส่งข้อความทดสอบ Telegram สำเร็จ']);
} else {
$resObj = json_decode($result, true);
$reason = isset($resObj['description']) ? $resObj['description'] : 'HTTP Code ' . $httpCode;
echo json_encode(['status' => 'error', 'message' => 'ไม่สามารถส่งข้อความได้: ' . $reason]);
}
} else {
echo json_encode(['status' => 'error', 'message' => 'Invalid request type']);
}
?>