Files
QrCode-Attendance-System/src-backup/admin/manage_students.php
2026-01-07 14:09:59 +08:00

1207 lines
57 KiB
PHP

<?php
require_once '../includes/config.php';
// Check if user is logged in and is admin
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true || $_SESSION['role'] !== 'admin') {
header('Location: ../auth/login.php');
exit();
}
$title = "Manage Students";
// Initialize variables
$action = $_GET['action'] ?? '';
$student_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$message = '';
$message_type = '';
// CSRF token for POST actions
$csrf_token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $csrf_token;
// ==================== HELPER FUNCTIONS ====================
function sanitizeInput($input) {
return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
}
function exportToExcel($conn) {
$filename = "students_" . date('Y-m-d') . ".csv";
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Pragma: no-cache');
header('Expires: 0');
$output = fopen('php://output', 'w');
// Add BOM for UTF-8
fputs($output, chr(0xEF) . chr(0xBB) . chr(0xBF));
// Header row
fputcsv($output, [
'Student ID', 'Full Name', 'Gender', 'Year Level', 'Course',
'Department', 'School', 'Email', 'Contact', 'Status'
]);
// Get all students
$sql = "SELECT s.*, g.name as gender, c.code as course_code, c.name as course_name,
d.code as department_code, d.name as department_name,
sc.code as school_code, sc.name as school_name
FROM students s
LEFT JOIN genders g ON s.gender_id = g.id
LEFT JOIN courses c ON s.course_id = c.id
LEFT JOIN departments d ON s.department_id = d.id
LEFT JOIN schools sc ON s.school_id = sc.id
ORDER BY s.created_at DESC";
$result = mysqli_query($conn, $sql);
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
fputcsv($output, [
$row['student_id'],
$row['full_name'],
$row['gender'],
'Year ' . $row['year_level'],
$row['course_code'] . ' - ' . $row['course_name'],
$row['department_name'],
$row['school_name'],
$row['email'],
$row['contact_number'],
$row['status'] == 1 ? 'Active' : 'Inactive'
]);
}
}
fclose($output);
exit();
}
// ==================== HANDLE FORM SUBMISSIONS ====================
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// --- Add Student (Modal) ---
if (isset($_POST['modal_add_student'])) {
$sid = trim($_POST['student_id'] ?? '');
$full = trim($_POST['full_name'] ?? '');
$gender_id = intval($_POST['gender_id'] ?? 0);
$year_level = intval($_POST['year_level'] ?? 0);
$course_id = intval($_POST['course_id'] ?? 0);
$department_id = intval($_POST['department_id'] ?? 0);
$school_id = intval($_POST['school_id'] ?? 0);
$birth_date = ($_POST['birth_date'] ?? '') ?: null;
if ($birth_date === '0000-00-00') { $birth_date = null; }
$contact = trim($_POST['contact_number'] ?? '');
$email = trim($_POST['email'] ?? '');
$address = trim($_POST['address'] ?? '');
$status = isset($_POST['status']) ? 1 : 1; // default active
// basic required validation
if ($sid === '' || $full === '' || $gender_id === 0 || $year_level === 0 || $course_id === 0 || $department_id === 0 || $school_id === 0) {
$message = 'Please fill in all required fields.';
$message_type = 'danger';
} else {
// duplicate check
$dup = mysqli_prepare($conn, "SELECT id FROM students WHERE student_id = ?");
mysqli_stmt_bind_param($dup, 's', $sid);
mysqli_stmt_execute($dup);
mysqli_stmt_store_result($dup);
if (mysqli_stmt_num_rows($dup) > 0) {
$message = 'Student ID already exists.';
$message_type = 'danger';
} else {
$qr = 'STU_' . $sid . '_' . uniqid();
$sql = "INSERT INTO students (student_id, qr_code, full_name, gender_id, year_level, course_id, department_id, school_id, birth_date, contact_number, email, address, created_at, updated_at, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW(), ?)";
$stmt = mysqli_prepare($conn, $sql);
// null-safe birth_date
$bd = $birth_date ?: null;
mysqli_stmt_bind_param($stmt, 'sssiiiiissssi', $sid, $qr, $full, $gender_id, $year_level, $course_id, $department_id, $school_id, $bd, $contact, $email, $address, $status);
if (mysqli_stmt_execute($stmt)) {
$_SESSION['flash_message'] = 'Student added successfully!';
$_SESSION['flash_type'] = 'success';
header('Location: manage_students.php');
exit();
} else {
$message = 'Error adding student: ' . mysqli_error($conn);
$message_type = 'danger';
}
mysqli_stmt_close($stmt);
}
mysqli_stmt_close($dup);
}
}
// --- Update Student (Modal) ---
elseif (isset($_POST['modal_update_student'])) {
$id = intval($_POST['id'] ?? 0);
$sid = trim($_POST['student_id'] ?? '');
$full = trim($_POST['full_name'] ?? '');
$gender_id = intval($_POST['gender_id'] ?? 0);
$year_level = intval($_POST['year_level'] ?? 0);
$course_id = intval($_POST['course_id'] ?? 0);
$department_id = intval($_POST['department_id'] ?? 0);
$school_id = intval($_POST['school_id'] ?? 0);
$birth_date = ($_POST['birth_date'] ?? '') ?: null;
if ($birth_date === '0000-00-00') { $birth_date = null; }
$contact = trim($_POST['contact_number'] ?? '');
$email = trim($_POST['email'] ?? '');
$address = trim($_POST['address'] ?? '');
$status = isset($_POST['status']) ? 1 : 0;
if ($id <= 0) {
$message = 'Invalid student id.';
$message_type = 'danger';
} elseif ($sid === '' || $full === '' || $gender_id === 0 || $year_level === 0 || $course_id === 0 || $department_id === 0 || $school_id === 0) {
$message = 'Please fill in all required fields.';
$message_type = 'danger';
} else {
// duplicate student_id check excluding current id
$dup = mysqli_prepare($conn, "SELECT id FROM students WHERE student_id = ? AND id != ?");
mysqli_stmt_bind_param($dup, 'si', $sid, $id);
mysqli_stmt_execute($dup);
mysqli_stmt_store_result($dup);
if (mysqli_stmt_num_rows($dup) > 0) {
$message = 'Student ID already exists.';
$message_type = 'danger';
} else {
// Build dynamic update allowing NULLs
$set = 'student_id = ?, full_name = ?, gender_id = ?, year_level = ?, course_id = ?, department_id = ?, school_id = ?, status = ?, updated_at = NOW()';
$types = 'ssiiiiii';
$params = [$sid, $full, $gender_id, $year_level, $course_id, $department_id, $school_id, $status];
if ($birth_date) { $set .= ', birth_date = ?'; $types .= 's'; $params[] = $birth_date; } else { $set .= ', birth_date = NULL'; }
if ($contact !== '') { $set .= ', contact_number = ?'; $types .= 's'; $params[] = $contact; } else { $set .= ', contact_number = NULL'; }
if ($email !== '') { $set .= ', email = ?'; $types .= 's'; $params[] = $email; } else { $set .= ', email = NULL'; }
if ($address !== '') { $set .= ', address = ?'; $types .= 's'; $params[] = $address; } else { $set .= ', address = NULL'; }
$sql = "UPDATE students SET $set WHERE id = ?";
$types .= 'i';
$params[] = $id;
$stmt = mysqli_prepare($conn, $sql);
if ($stmt && mysqli_stmt_bind_param($stmt, $types, ...$params) && mysqli_stmt_execute($stmt)) {
$_SESSION['flash_message'] = 'Student updated successfully!';
$_SESSION['flash_type'] = 'success';
header('Location: manage_students.php');
exit();
} else {
$message = 'Error updating student: ' . mysqli_error($conn);
$message_type = 'danger';
}
if ($stmt) { mysqli_stmt_close($stmt); }
}
mysqli_stmt_close($dup);
}
}
// --- Delete Student ---
if (isset($_POST['delete_student'])) {
$student_id = isset($_POST['id']) ? intval($_POST['id']) : 0;
if ($student_id > 0) {
// Check if student exists
$check_sql = "SELECT id, full_name FROM students WHERE id = ?";
$stmt = mysqli_prepare($conn, $check_sql);
mysqli_stmt_bind_param($stmt, 'i', $student_id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result)) {
$student_name = $row['full_name'];
// Remove associated files before deletion
$fetch_sql = "SELECT picture_path, qr_code_image, full_name FROM students WHERE id = ?";
$stmtf = mysqli_prepare($conn, $fetch_sql);
mysqli_stmt_bind_param($stmtf, 'i', $student_id);
mysqli_stmt_execute($stmtf);
$resf = mysqli_stmt_get_result($stmtf);
if ($fileRow = mysqli_fetch_assoc($resf)) {
if (!empty($fileRow['picture_path']) && file_exists('../' . $fileRow['picture_path'])) {
@unlink('../' . $fileRow['picture_path']);
}
if (!empty($fileRow['qr_code_image']) && file_exists('../' . $fileRow['qr_code_image'])) {
@unlink('../' . $fileRow['qr_code_image']);
}
// Ensure we have name
$student_name = $fileRow['full_name'];
}
mysqli_stmt_close($stmtf);
// Delete the student; related attendance/logs cascade via FK constraints
$sql = "DELETE FROM students WHERE id = ?";
$stmt3 = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt3, 'i', $student_id);
if (mysqli_stmt_execute($stmt3)) {
$affected_rows = mysqli_stmt_affected_rows($stmt3);
if ($affected_rows > 0) {
$_SESSION['flash_message'] = "Student '$student_name' deleted successfully!";
$_SESSION['flash_type'] = 'success';
header("Location: manage_students.php?msg=deleted");
exit();
} else {
$message = 'No student was deleted. Student might not exist or there was an error.';
$message_type = 'warning';
error_log("No rows affected when deleting student ID: $student_id");
}
} else {
$error = mysqli_error($conn);
$message = 'Error deleting student: ' . $error;
$message_type = 'danger';
error_log("SQL Error deleting student: $error");
}
mysqli_stmt_close($stmt3);
} else {
$message = 'Student not found!';
$message_type = 'danger';
error_log("Student ID $student_id not found");
}
mysqli_stmt_close($stmt);
}
}
// --- Export to Excel ---
elseif (isset($_POST['export_excel'])) {
exportToExcel($conn);
exit();
}
// --- Bulk Actions ---
elseif (isset($_POST['bulk_action']) && isset($_POST['selected_students'])) {
$bulk_action = sanitizeInput($_POST['bulk_action']);
$selected_students = $_POST['selected_students'];
// Validate selected students
if (empty($selected_students) || !is_array($selected_students)) {
$message = 'No students selected.';
$message_type = 'warning';
} else {
// Sanitize all IDs
$sanitized_ids = array_map('intval', $selected_students);
$ids = implode(',', $sanitized_ids);
$count = count($sanitized_ids);
// Check if force delete is requested
$force_delete = isset($_POST['force_bulk_delete']) && $_POST['force_bulk_delete'] == 1;
// Prepare SQL based on action
if ($bulk_action === 'activate') {
$sql = "UPDATE students SET status = 1, updated_at = NOW() WHERE id IN ($ids)";
$success_msg = "$count student(s) activated successfully!";
} elseif ($bulk_action === 'deactivate') {
$sql = "UPDATE students SET status = 0, updated_at = NOW() WHERE id IN ($ids)";
$success_msg = "$count student(s) deactivated successfully!";
} elseif ($bulk_action === 'delete') {
// Direct bulk delete; related attendance and logs cascade via FK constraints
$sql = "DELETE FROM students WHERE id IN ($ids)";
$success_msg = "$count student(s) deleted successfully!";
}
if (isset($sql) && empty($message)) {
// If deleting, clean up files first
if ($bulk_action === 'delete') {
$files_sql = "SELECT id, picture_path, qr_code_image FROM students WHERE id IN ($ids)";
$files_result = mysqli_query($conn, $files_sql);
if ($files_result) {
while ($f = mysqli_fetch_assoc($files_result)) {
if (!empty($f['picture_path']) && file_exists('../' . $f['picture_path'])) {
@unlink('../' . $f['picture_path']);
}
if (!empty($f['qr_code_image']) && file_exists('../' . $f['qr_code_image'])) {
@unlink('../' . $f['qr_code_image']);
}
}
}
}
error_log("Executing SQL: $sql");
if (mysqli_query($conn, $sql)) {
$affected_rows = mysqli_affected_rows($conn);
error_log("Bulk action affected $affected_rows row(s)");
$_SESSION['flash_message'] = $success_msg;
$_SESSION['flash_type'] = 'success';
header("Location: manage_students.php?msg=bulk");
exit();
} else {
$error = mysqli_error($conn);
$message = 'Error performing bulk action: ' . $error;
$message_type = 'danger';
error_log("SQL Error in bulk action: $error");
}
}
}
}
}
// Check for flash messages from session
if (isset($_SESSION['flash_message'])) {
$message = $_SESSION['flash_message'];
$message_type = $_SESSION['flash_type'];
unset($_SESSION['flash_message']);
unset($_SESSION['flash_type']);
}
// ==================== GET STUDENTS DATA ====================
$students = [];
$sql = "SELECT s.*, g.name as gender, c.code as course_code, c.name as course_name,
d.code as department_code, d.name as department_name,
sc.code as school_code, sc.name as school_name
FROM students s
LEFT JOIN genders g ON s.gender_id = g.id
LEFT JOIN courses c ON s.course_id = c.id
LEFT JOIN departments d ON s.department_id = d.id
LEFT JOIN schools sc ON s.school_id = sc.id
ORDER BY s.created_at DESC";
$result = mysqli_query($conn, $sql);
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
$students[] = $row;
}
} else {
error_log("Error fetching students: " . mysqli_error($conn));
}
// Dropdown data for modals
$genders = [];
$courses = [];
$departments = [];
$schools = [];
$r = mysqli_query($conn, "SELECT * FROM genders ORDER BY id");
if ($r) { while ($row = mysqli_fetch_assoc($r)) { $genders[] = $row; } }
$r = mysqli_query($conn, "SELECT * FROM courses WHERE status = 1 ORDER BY code");
if ($r) { while ($row = mysqli_fetch_assoc($r)) { $courses[] = $row; } }
$r = mysqli_query($conn, "SELECT * FROM departments WHERE status = 1 ORDER BY code");
if ($r) { while ($row = mysqli_fetch_assoc($r)) { $departments[] = $row; } }
$r = mysqli_query($conn, "SELECT * FROM schools WHERE status = 1 ORDER BY code");
if ($r) { while ($row = mysqli_fetch_assoc($r)) { $schools[] = $row; } }
// ==================== INCLUDE HEADER ====================
include '../includes/header.php';
?>
<style>
/* Compact Styles */
body { font-size: 0.9rem; }
.table-sm th { padding: 6px 8px; font-size: 0.8rem; }
.table-sm td { padding: 4px 8px; font-size: 0.85rem; }
.btn-xs { padding: 0.15rem 0.5rem; font-size: 0.75rem; }
.badge-sm { font-size: 0.7rem; padding: 2px 5px; }
.search-box input { font-size: 0.85rem; height: 32px; }
.stat-card { padding: 10px; }
.stat-card h3 { font-size: 1.3rem; margin-bottom: 0.2rem; }
.stat-card h6 { font-size: 0.75rem; margin-bottom: 0.3rem; }
.avatar { width: 30px !important; height: 30px !important; font-size: 0.8rem; }
.avatar i { font-size: 0.8rem; }
.dropdown-menu { font-size: 0.85rem; min-width: 180px; }
.alert form { display: inline; }
.debug-info { font-size: 0.7rem; color: #666; margin-top: 5px; }
</style>
<!-- Page Header -->
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<h1 class="h4 mb-1">Manage Students</h1>
<small class="text-muted">Manage student records</small>
<?php if (isset($_GET['debug'])): ?>
<div class="debug-info">
PHP Version: <?php echo phpversion(); ?> |
DB Connected: <?php echo mysqli_ping($conn) ? 'Yes' : 'No'; ?>
</div>
<?php endif; ?>
</div>
<div>
<button type="button" class="btn btn-primary btn-sm" id="openAddModal">
<i class="bi bi-person-plus me-1"></i> Add
</button>
<a href="?debug=1" class="btn btn-outline-info btn-sm ms-1" title="Debug Info">
<i class="bi bi-bug"></i>
</a>
<form method="POST" action="" class="d-inline">
<button type="submit" name="export_excel" class="btn btn-outline-success btn-sm ms-1">
<i class="bi bi-file-excel me-1"></i> Export
</button>
</form>
</div>
</div>
<!-- Message Alert -->
<?php
// Check for URL messages
if (isset($_GET['msg'])) {
switch ($_GET['msg']) {
case 'added':
$message = 'Student added successfully!';
$message_type = 'success';
break;
case 'updated':
$message = 'Student updated successfully!';
$message_type = 'success';
break;
case 'deleted':
$message = 'Student deleted successfully!';
$message_type = 'success';
break;
case 'bulk':
$message = 'Bulk action completed!';
$message_type = 'success';
break;
case 'notfound':
$message = 'Student not found!';
$message_type = 'danger';
break;
}
}
if ($message): ?>
<div class="alert alert-<?php echo $message_type; ?> alert-dismissible fade show py-2 mb-3" role="alert" style="font-size: 0.85rem;">
<i class="bi bi-<?php echo $message_type == 'success' ? 'check-circle' : 'exclamation-triangle'; ?> me-1"></i>
<?php echo $message; ?>
<?php if ($message_type != 'danger' && $message_type != 'warning'): ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close" style="font-size: 0.7rem;"></button>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- Statistics Cards - Compact -->
<div class="row g-2 mb-3">
<div class="col-md-3">
<div class="card stat-card border-start-primary py-2">
<div class="card-body p-2">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-0" style="font-size: 0.75rem;">Total</h6>
<h4 class="mb-0" style="font-size: 1.2rem;"><?php echo number_format(count($students)); ?></h4>
</div>
<i class="bi bi-people text-primary" style="font-size: 1.8rem; opacity: 0.7;"></i>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card border-start-success py-2">
<div class="card-body p-2">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-0" style="font-size: 0.75rem;">Active</h6>
<h4 class="mb-0" style="font-size: 1.2rem;">
<?php
$active_count = 0;
foreach ($students as $student) {
$active_count += $student['status'];
}
echo number_format($active_count);
?>
</h4>
</div>
<i class="bi bi-person-check text-success" style="font-size: 1.8rem; opacity: 0.7;"></i>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card border-start-info py-2">
<div class="card-body p-2">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-0" style="font-size: 0.75rem;">Inactive</h6>
<h4 class="mb-0" style="font-size: 1.2rem;">
<?php
$inactive_count = count($students) - $active_count;
echo number_format($inactive_count);
?>
</h4>
</div>
<i class="bi bi-person-x text-info" style="font-size: 1.8rem; opacity: 0.7;"></i>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card border-start-warning py-2">
<div class="card-body p-2">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-0" style="font-size: 0.75rem;">Departments</h6>
<h4 class="mb-0" style="font-size: 1.2rem;">
<?php
$sql = "SELECT COUNT(*) as count FROM departments WHERE status = 1";
$result = mysqli_query($conn, $sql);
echo $result ? mysqli_fetch_assoc($result)['count'] : 0;
?>
</h4>
</div>
<i class="bi bi-building text-warning" style="font-size: 1.8rem; opacity: 0.7;"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Students Table -->
<form method="POST" action="" id="bulkForm">
<input type="hidden" name="csrf_token" value="<?php echo $csrf_token; ?>">
<div class="card shadow-sm mb-4">
<div class="card-header py-2">
<div class="d-flex justify-content-between align-items-center">
<h6 class="mb-0" style="font-size: 0.9rem;">
<i class="bi bi-people me-1"></i> Student List
</h6>
<div class="d-flex">
<input type="text" id="searchInput" class="form-control form-control-sm me-2"
placeholder="Search..." style="width: 180px; height: 28px; font-size: 0.8rem;">
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-secondary btn-xs" type="button" onclick="printReport()" title="Print">
<i class="bi bi-printer"></i>
</button>
<button type="submit" name="export_excel" class="btn btn-outline-primary btn-xs" title="Export">
<i class="bi bi-download"></i>
</button>
</div>
</div>
</div>
</div>
<div class="card-body p-0">
<!-- Bulk Actions Bar -->
<div class="bulk-actions-bar p-2 bg-light border-bottom" style="display: none; font-size: 0.8rem;">
<div class="d-flex align-items-center">
<div class="form-check me-2">
<input class="form-check-input" type="checkbox" id="selectAll" style="transform: scale(0.8);">
<label class="form-check-label" for="selectAll">
<span id="selectedCount">0</span> selected
</label>
</div>
<select class="form-select form-select-sm me-2" name="bulk_action" style="width: 130px; height: 26px; font-size: 0.8rem;">
<option value="">Bulk Actions</option>
<option value="activate">Activate</option>
<option value="deactivate">Deactivate</option>
<option value="delete">Delete</option>
</select>
<button type="submit" class="btn btn-primary btn-sm py-0 px-2" style="font-size: 0.8rem;">Apply</button>
<button type="button" class="btn btn-outline-secondary btn-sm py-0 px-2 ms-1" style="font-size: 0.8rem;" onclick="clearBulkSelection()">
Cancel
</button>
</div>
</div>
<div class="table-responsive">
<table class="table table-hover table-sm mb-0" id="studentsTable">
<thead class="table-light">
<tr>
<th width="20">
<input type="checkbox" id="toggleAll" style="transform: scale(0.8);">
</th>
<th width="30">#</th>
<th width="90">Student ID</th>
<th>Student</th>
<th width="150">Course</th>
<th width="60">Year</th>
<th width="80">Status</th>
<th width="120" class="text-center">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($students)): ?>
<tr>
<td colspan="8" class="text-center py-3">
<i class="bi bi-people text-muted" style="font-size: 2rem;"></i>
<p class="mt-1 mb-0" style="font-size: 0.85rem;">No students found.</p>
<a href="add_student.php" class="btn btn-primary btn-sm mt-2">
<i class="bi bi-person-plus me-1"></i> Add First Student
</a>
</td>
</tr>
<?php else: ?>
<?php $counter = 1; ?>
<?php foreach ($students as $student): ?>
<tr>
<td>
<input type="checkbox" class="student-check" name="selected_students[]"
value="<?php echo $student['id']; ?>" style="transform: scale(0.8);">
</td>
<td class="text-muted"><?php echo $counter++; ?></td>
<td>
<small class="text-primary fw-bold"><?php echo htmlspecialchars($student['student_id']); ?></small>
</td>
<td>
<div class="d-flex align-items-center">
<div class="avatar me-2">
<?php if (!empty($student['picture_path']) && file_exists('../' . $student['picture_path'])): ?>
<img src="../<?php echo htmlspecialchars($student['picture_path']); ?>"
alt="<?php echo htmlspecialchars($student['full_name']); ?>"
class="rounded-circle"
style="width: 30px; height: 30px; object-fit: cover;">
<?php else: ?>
<div class="bg-primary rounded-circle d-flex align-items-center justify-content-center"
style="width: 30px; height: 30px;">
<i class="bi bi-person text-white" style="font-size: 0.8rem;"></i>
</div>
<?php endif; ?>
</div>
<div style="font-size: 0.85rem;">
<div class="fw-bold mb-0" style="font-size: 0.85rem;"><?php echo htmlspecialchars($student['full_name']); ?></div>
<small class="text-muted"><?php echo htmlspecialchars($student['gender']); ?></small>
</div>
</div>
</td>
<td style="font-size: 0.8rem;">
<div class="fw-bold"><?php echo htmlspecialchars($student['course_code']); ?></div>
<small class="text-muted"><?php echo htmlspecialchars($student['department_name']); ?></small>
</td>
<td>
<span class="badge bg-info badge-sm">Yr <?php echo $student['year_level']; ?></span>
</td>
<td>
<?php if ($student['status'] == 1): ?>
<span class="badge bg-success badge-sm">
<i class="bi bi-check-circle me-1"></i> Active
</span>
<?php else: ?>
<span class="badge bg-danger badge-sm">
<i class="bi bi-x-circle me-1"></i> Inactive
</span>
<?php endif; ?>
</td>
<td class="text-center">
<div class="btn-group btn-group-sm">
<a href="view_student.php?id=<?php echo $student['id']; ?>"
class="btn btn-info btn-xs" title="View">
<i class="bi bi-eye"></i>
</a>
<button type="button"
class="btn btn-warning btn-xs edit-student" title="Edit"
data-id="<?php echo $student['id']; ?>"
data-student_id="<?php echo htmlspecialchars($student['student_id']); ?>"
data-full_name="<?php echo htmlspecialchars($student['full_name']); ?>"
data-gender_id="<?php echo $student['gender_id']; ?>"
data-year_level="<?php echo $student['year_level']; ?>"
data-course_id="<?php echo $student['course_id']; ?>"
data-department_id="<?php echo $student['department_id']; ?>"
data-school_id="<?php echo $student['school_id']; ?>"
data-birth_date="<?php echo $student['birth_date']; ?>"
data-contact_number="<?php echo htmlspecialchars($student['contact_number']); ?>"
data-email="<?php echo htmlspecialchars($student['email']); ?>"
data-address="<?php echo htmlspecialchars($student['address']); ?>"
data-status="<?php echo $student['status']; ?>">
<i class="bi bi-pencil"></i>
</button>
<div class="btn-group">
<a href="../qr/generate.php?id=<?php echo $student['id']; ?>"
class="btn btn-primary btn-xs" title="QR Code" target="_blank">
<i class="bi bi-qr-code"></i>
</a>
<button type="button" class="btn btn-primary btn-xs dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown" style="padding: 0 4px;">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item py-1" href="../qr/generate.php?id=<?php echo $student['id']; ?>&print=1" target="_blank">
<i class="bi bi-printer me-2"></i> Print QR
</a>
</li>
<li>
<a class="dropdown-item py-1" href="../qr/generate.php?id=<?php echo $student['id']; ?>&download=1">
<i class="bi bi-download me-2"></i> Download QR
</a>
</li>
<li>
<a class="dropdown-item py-1" href="../qr/generate.php?id=<?php echo $student['id']; ?>&autoPrint=1" target="_blank">
<i class="bi bi-printer-fill me-2"></i> Auto Print
</a>
</li>
</ul>
</div>
<button type="button" class="btn btn-danger btn-xs delete-student"
data-id="<?php echo $student['id']; ?>"
data-name="<?php echo htmlspecialchars($student['full_name']); ?>"
title="Delete">
<i class="bi bi-trash"></i>
</button>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<div class="card-footer py-1">
<div class="row">
<div class="col-md-6">
<small class="text-muted" style="font-size: 0.75rem;">
<i class="bi bi-info-circle me-1"></i> Showing <?php echo count($students); ?> student(s)
</small>
</div>
<div class="col-md-6 text-md-end">
<small class="text-muted" style="font-size: 0.75rem;">
<i class="bi bi-clock me-1"></i> Updated: <?php echo date('h:i A'); ?>
</small>
</div>
</div>
</div>
</div>
</form>
<!-- Add Student Modal -->
<div class="modal fade" id="addStudentModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-primary text-white py-2">
<h6 class="modal-title mb-0"><i class="bi bi-person-plus me-1"></i> Add Student</h6>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<form method="POST" action="">
<div class="modal-body">
<div class="row g-2">
<div class="col-md-6">
<label class="form-label">Student ID *</label>
<input class="form-control" name="student_id" required>
</div>
<div class="col-md-6">
<label class="form-label">Full Name *</label>
<input class="form-control" name="full_name" required>
</div>
<div class="col-md-6">
<label class="form-label">Gender *</label>
<select class="form-select" name="gender_id" required>
<option value="">Select Gender</option>
<?php foreach ($genders as $g): ?>
<option value="<?php echo $g['id']; ?>"><?php echo htmlspecialchars($g['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Year Level *</label>
<select class="form-select" name="year_level" required>
<option value="">Select</option>
<?php for ($i=1;$i<=4;$i++): ?>
<option value="<?php echo $i; ?>">Year <?php echo $i; ?></option>
<?php endfor; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">School *</label>
<select class="form-select" name="school_id" required>
<option value="">Select School</option>
<?php foreach ($schools as $s): ?>
<option value="<?php echo $s['id']; ?>"><?php echo htmlspecialchars($s['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Department *</label>
<select class="form-select" name="department_id" required>
<option value="">Select Department</option>
<?php foreach ($departments as $d): ?>
<option value="<?php echo $d['id']; ?>"><?php echo htmlspecialchars($d['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Course *</label>
<select class="form-select" name="course_id" required>
<option value="">Select Course</option>
<?php foreach ($courses as $c): ?>
<option value="<?php echo $c['id']; ?>"><?php echo htmlspecialchars($c['code']); ?> - <?php echo htmlspecialchars($c['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Birth Date</label>
<input type="date" class="form-control" name="birth_date" max="<?php echo date('Y-m-d'); ?>">
</div>
<div class="col-md-6">
<label class="form-label">Email</label>
<input class="form-control" name="email">
</div>
<div class="col-md-6">
<label class="form-label">Contact</label>
<input class="form-control" name="contact_number">
</div>
<div class="col-12">
<label class="form-label">Address</label>
<textarea class="form-control" name="address" rows="2"></textarea>
</div>
</div>
</div>
<div class="modal-footer py-2">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary btn-sm" name="modal_add_student">Save</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Student Modal -->
<div class="modal fade" id="editStudentModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-warning py-2">
<h6 class="modal-title mb-0"><i class="bi bi-pencil me-1"></i> Edit Student</h6>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST" action="">
<div class="modal-body">
<input type="hidden" name="id" id="edit_id">
<div class="row g-2">
<div class="col-md-6">
<label class="form-label">Student ID *</label>
<input class="form-control" name="student_id" id="edit_student_id" required>
</div>
<div class="col-md-6">
<label class="form-label">Full Name *</label>
<input class="form-control" name="full_name" id="edit_full_name" required>
</div>
<div class="col-md-6">
<label class="form-label">Gender *</label>
<select class="form-select" name="gender_id" id="edit_gender_id" required>
<option value="">Select Gender</option>
<?php foreach ($genders as $g): ?>
<option value="<?php echo $g['id']; ?>"><?php echo htmlspecialchars($g['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Year Level *</label>
<select class="form-select" name="year_level" id="edit_year_level" required>
<option value="">Select</option>
<?php for ($i=1;$i<=4;$i++): ?>
<option value="<?php echo $i; ?>">Year <?php echo $i; ?></option>
<?php endfor; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">School *</label>
<select class="form-select" name="school_id" id="edit_school_id" required>
<option value="">Select School</option>
<?php foreach ($schools as $s): ?>
<option value="<?php echo $s['id']; ?>"><?php echo htmlspecialchars($s['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Department *</label>
<select class="form-select" name="department_id" id="edit_department_id" required>
<option value="">Select Department</option>
<?php foreach ($departments as $d): ?>
<option value="<?php echo $d['id']; ?>"><?php echo htmlspecialchars($d['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Course *</label>
<select class="form-select" name="course_id" id="edit_course_id" required>
<option value="">Select Course</option>
<?php foreach ($courses as $c): ?>
<option value="<?php echo $c['id']; ?>"><?php echo htmlspecialchars($c['code']); ?> - <?php echo htmlspecialchars($c['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Birth Date</label>
<input type="date" class="form-control" name="birth_date" id="edit_birth_date" max="<?php echo date('Y-m-d'); ?>">
</div>
<div class="col-md-6">
<label class="form-label">Email</label>
<input class="form-control" name="email" id="edit_email">
</div>
<div class="col-md-6">
<label class="form-label">Contact</label>
<input class="form-control" name="contact_number" id="edit_contact_number">
</div>
<div class="col-12">
<label class="form-label">Address</label>
<textarea class="form-control" name="address" id="edit_address" rows="2"></textarea>
</div>
<div class="col-12">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="status" id="edit_status" value="1">
<label class="form-check-label" for="edit_status">Active</label>
</div>
</div>
</div>
</div>
<div class="modal-footer py-2">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-warning btn-sm" name="modal_update_student">Update</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteStudentModal" tabindex="-1" aria-labelledby="deleteStudentModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header bg-danger text-white py-2">
<h6 class="modal-title mb-0" id="deleteStudentModalLabel"><i class="bi bi-exclamation-triangle me-1"></i>Confirm Delete</h6>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST" action="">
<div class="modal-body p-3" style="font-size: 0.9rem;">
<p class="mb-2">Delete student: <strong id="modalStudentName"></strong>?</p>
<p class="text-danger mb-0"><small>This action cannot be undone.</small></p>
<input type="hidden" name="delete_student" value="1">
<input type="hidden" name="id" id="modalStudentId" value="">
</div>
<div class="modal-footer py-2">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-danger btn-sm" id="modalConfirmDelete">Delete</button>
</div>
</form>
</div>
</div>
</div>
<?php
$page_scripts = '
<script>
$(document).ready(function() {
// Initialize DataTable
const table = $("#studentsTable").DataTable({
pageLength: 25,
lengthMenu: [[15, 25, 50, 100, -1], [15, 25, 50, 100, "All"]],
order: [[2, "asc"]], // Sort by Student ID
responsive: true,
columnDefs: [
{ orderable: false, targets: [0, 1, 7] },
{ searchable: false, targets: [0, 1, 5, 6, 7] },
{ visible: false, targets: [0] }
],
language: {
search: "_INPUT_",
searchPlaceholder: "Search...",
lengthMenu: "Show _MENU_",
info: "Showing _START_ to _END_ of _TOTAL_",
infoEmpty: "No students",
infoFiltered: "(filtered from _MAX_ total)"
}
});
// Open Add modal
document.getElementById('openAddModal').addEventListener('click', function(){
const form = document.querySelector('#addStudentModal form');
form.reset();
const addModal = new bootstrap.Modal(document.getElementById('addStudentModal'));
addModal.show();
});
// Open Edit modal and populate
$(document).on('click', '.edit-student', function(){
const d = $(this).data();
$('#edit_id').val(d.id);
$('#edit_student_id').val(d.student_id);
$('#edit_full_name').val(d.full_name);
$('#edit_gender_id').val(String(d.gender_id));
$('#edit_year_level').val(String(d.year_level));
$('#edit_course_id').val(String(d.course_id));
$('#edit_department_id').val(String(d.department_id));
$('#edit_school_id').val(String(d.school_id));
$('#edit_birth_date').val(d.birth_date && d.birth_date !== '0000-00-00' ? d.birth_date : '');
$('#edit_contact_number').val(d.contact_number || '');
$('#edit_email').val(d.email || '');
$('#edit_address').val(d.address || '');
$('#edit_status').prop('checked', Number(d.status) === 1);
const editModal = new bootstrap.Modal(document.getElementById('editStudentModal'));
editModal.show();
});
// Custom search
$("#searchInput").on("keyup", function() {
table.search($(this).val()).draw();
});
// Bulk selection functionality
$("#toggleAll").change(function() {
$(".student-check").prop("checked", this.checked);
updateBulkSelection();
});
$(document).on("change", ".student-check", function() {
if (!this.checked) {
$("#toggleAll").prop("checked", false);
}
updateBulkSelection();
});
// Delete confirmation
$(document).on("click", ".delete-student", function(e) {
e.preventDefault();
const studentId = $(this).data("id");
const studentName = $(this).data("name");
// Create confirmation dialog
const confirmed = confirm(`Are you sure you want to delete student "${studentName}"?\\nThis action cannot be undone.`);
if (confirmed) {
// Create and submit form
const form = document.createElement("form");
form.method = "POST";
form.action = "";
const deleteInput = document.createElement("input");
deleteInput.type = "hidden";
deleteInput.name = "delete_student";
deleteInput.value = "1";
form.appendChild(deleteInput);
const idInput = document.createElement("input");
idInput.type = "hidden";
idInput.name = "id";
idInput.value = studentId;
form.appendChild(idInput);
const csrfInput = document.createElement("input");
csrfInput.type = "hidden";
csrfInput.name = "csrf_token";
csrfInput.value = "<?php echo $csrf_token; ?>";
form.appendChild(csrfInput);
document.body.appendChild(form);
form.submit();
}
});
// Bulk form validation
$("#bulkForm").submit(function(e) {
const selectedCount = $(".student-check:checked").length;
const action = $("select[name=\'bulk_action\']").val();
if (selectedCount === 0) {
e.preventDefault();
alert("Please select at least one student.");
return false;
}
if (!action) {
e.preventDefault();
alert("Please select a bulk action.");
return false;
}
if (action === "delete") {
e.preventDefault();
if (confirm(`Delete ${selectedCount} student(s)?\\nThis action cannot be undone.`)) {
return true;
}
return false;
}
return true;
});
});
// Bulk selection functions
function updateBulkSelection() {
const selectedCount = $(".student-check:checked").length;
$("#selectedCount").text(selectedCount);
if (selectedCount > 0) {
$(".bulk-actions-bar").show();
$("#studentsTable_wrapper .col-sm-12:first").css("margin-top", "50px");
} else {
$(".bulk-actions-bar").hide();
$("#studentsTable_wrapper .col-sm-12:first").css("margin-top", "0");
}
const totalCheckboxes = $(".student-check").length;
$("#toggleAll").prop("checked", selectedCount === totalCheckboxes && totalCheckboxes > 0);
}
function clearBulkSelection() {
$(".student-check").prop("checked", false);
$("#toggleAll").prop("checked", false);
updateBulkSelection();
}
// Print Report
function printReport() {
const table = $("#studentsTable").DataTable();
const data = table.rows({ search: \'applied\' }).data().toArray();
if (data.length === 0) {
alert("No data to print.");
return;
}
const printWindow = window.open("", "_blank");
printWindow.document.write(`
<!DOCTYPE html>
<html>
<head>
<title>Student List - <?php echo date("Y-m-d"); ?></title>
<style>
body { font-family: Arial, sans-serif; margin: 15px; font-size: 12px; }
h1 { text-align: center; margin-bottom: 20px; font-size: 16px; }
.report-info { margin-bottom: 15px; font-size: 11px; }
table { width: 100%; border-collapse: collapse; margin-bottom: 15px; font-size: 11px; }
th, td { border: 1px solid #ddd; padding: 5px; text-align: left; }
th { background-color: #f2f2f2; }
.footer { text-align: center; margin-top: 20px; font-size: 10px; color: #666; }
@media print { .no-print { display: none; } button { display: none; } }
</style>
</head>
<body>
<h1>Student List</h1>
<div class="report-info">
<p><strong>Date:</strong> <?php echo date("m/d/Y h:i A"); ?></p>
<p><strong>Total:</strong> ${data.length} students</p>
</div>
<table>
<thead>
<tr>
<th>#</th>
<th>Student ID</th>
<th>Name</th>
<th>Course</th>
<th>Year</th>
<th>Status</th>
</tr>
</thead>
<tbody>
${data.map((row, index) => {
const studentId = $(row[2]).find(".text-primary").text() || row[2];
const studentName = $(row[3]).find(".fw-bold").text() || row[3];
const course = $(row[4]).text();
const year = $(row[5]).text();
const status = $(row[6]).text();
return `
<tr>
<td>${index + 1}</td>
<td>${studentId}</td>
<td>${studentName}</td>
<td>${course}</td>
<td>${year}</td>
<td>${status}</td>
</tr>
`;
}).join("")}
</tbody>
</table>
<div class="footer">
Student Management System
</div>
<div class="no-print" style="text-align: center; margin-top: 15px;">
<button onclick="window.print()">Print</button>
<button onclick="window.close()" style="margin-left: 10px;">Close</button>
</div>
<script>window.onload = function() { window.print(); };<\/script>
</body>
</html>
`);
printWindow.document.close();
}
</script>
';
$page_scripts .= '\n<script>\n$(document).off("click", ".delete-student").on("click", ".delete-student", function(e){ e.preventDefault(); const studentId = $(this).data("id"); const studentName = $(this).data("name"); document.getElementById("modalStudentId").value = studentId; document.getElementById("modalStudentName").textContent = studentName; const modalEl = document.getElementById("deleteStudentModal"); const deleteModal = new bootstrap.Modal(modalEl); deleteModal.show(); });\n<\/script>\n';
include '../includes/footer.php';
?>