356 lines
13 KiB
PHP
356 lines
13 KiB
PHP
|
|
<?php
|
||
|
|
require_once '../includes/config.php';
|
||
|
|
|
||
|
|
// Check if user is logged in
|
||
|
|
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
|
||
|
|
header('Location: ../auth/login.php');
|
||
|
|
exit();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if report data exists
|
||
|
|
if (!isset($_SESSION['report_data'])) {
|
||
|
|
header('Location: students_report.php');
|
||
|
|
exit();
|
||
|
|
}
|
||
|
|
|
||
|
|
$report_data = $_SESSION['report_data'];
|
||
|
|
$students = $report_data['students'] ?? [];
|
||
|
|
$filters = $report_data['filters'] ?? [];
|
||
|
|
|
||
|
|
unset($_SESSION['report_data']);
|
||
|
|
|
||
|
|
// Get report type
|
||
|
|
$type = $_GET['type'] ?? 'print';
|
||
|
|
|
||
|
|
// For PDF generation, you would use a library like TCPDF
|
||
|
|
if ($type === 'pdf') {
|
||
|
|
require_once '../vendor/autoload.php';
|
||
|
|
|
||
|
|
// TCPDF implementation would go here
|
||
|
|
// For now, we'll output HTML that can be printed as PDF
|
||
|
|
|
||
|
|
header('Content-Type: application/pdf');
|
||
|
|
header('Content-Disposition: attachment; filename="students_report_' . date('Y-m-d') . '.pdf"');
|
||
|
|
|
||
|
|
// In production, generate actual PDF
|
||
|
|
// $pdf = new TCPDF();
|
||
|
|
// $pdf->AddPage();
|
||
|
|
// $pdf->writeHTML($html);
|
||
|
|
// $pdf->Output();
|
||
|
|
exit();
|
||
|
|
}
|
||
|
|
?>
|
||
|
|
|
||
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<title>Student Report</title>
|
||
|
|
<style>
|
||
|
|
@media print {
|
||
|
|
.no-print { display: none !important; }
|
||
|
|
body { font-size: 12pt; }
|
||
|
|
.container { width: 100% !important; max-width: none !important; }
|
||
|
|
table { page-break-inside: auto; }
|
||
|
|
tr { page-break-inside: avoid; page-break-after: auto; }
|
||
|
|
thead { display: table-header-group; }
|
||
|
|
tfoot { display: table-footer-group; }
|
||
|
|
}
|
||
|
|
|
||
|
|
body {
|
||
|
|
font-family: Arial, sans-serif;
|
||
|
|
line-height: 1.6;
|
||
|
|
color: #333;
|
||
|
|
}
|
||
|
|
|
||
|
|
.report-header {
|
||
|
|
text-align: center;
|
||
|
|
margin-bottom: 30px;
|
||
|
|
padding-bottom: 20px;
|
||
|
|
border-bottom: 2px solid #333;
|
||
|
|
}
|
||
|
|
|
||
|
|
.report-title {
|
||
|
|
font-size: 24px;
|
||
|
|
font-weight: bold;
|
||
|
|
margin-bottom: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.report-subtitle {
|
||
|
|
font-size: 16px;
|
||
|
|
color: #666;
|
||
|
|
}
|
||
|
|
|
||
|
|
.report-info {
|
||
|
|
margin-bottom: 20px;
|
||
|
|
padding: 15px;
|
||
|
|
background-color: #f8f9fa;
|
||
|
|
border-radius: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-row {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
margin-bottom: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
table {
|
||
|
|
width: 100%;
|
||
|
|
border-collapse: collapse;
|
||
|
|
margin-bottom: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
th, td {
|
||
|
|
border: 1px solid #ddd;
|
||
|
|
padding: 8px;
|
||
|
|
text-align: left;
|
||
|
|
}
|
||
|
|
|
||
|
|
th {
|
||
|
|
background-color: #f2f2f2;
|
||
|
|
font-weight: bold;
|
||
|
|
}
|
||
|
|
|
||
|
|
tr:nth-child(even) {
|
||
|
|
background-color: #f9f9f9;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-active {
|
||
|
|
color: green;
|
||
|
|
font-weight: bold;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-inactive {
|
||
|
|
color: red;
|
||
|
|
font-weight: bold;
|
||
|
|
}
|
||
|
|
|
||
|
|
.print-options {
|
||
|
|
margin-bottom: 20px;
|
||
|
|
padding: 15px;
|
||
|
|
background-color: #e9ecef;
|
||
|
|
border-radius: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.summary-box {
|
||
|
|
margin-top: 30px;
|
||
|
|
padding: 15px;
|
||
|
|
background-color: #f8f9fa;
|
||
|
|
border-left: 4px solid #007bff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.footer {
|
||
|
|
margin-top: 50px;
|
||
|
|
padding-top: 20px;
|
||
|
|
border-top: 1px solid #ddd;
|
||
|
|
text-align: center;
|
||
|
|
font-size: 12px;
|
||
|
|
color: #666;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="container">
|
||
|
|
<!-- Print Options -->
|
||
|
|
<div class="print-options no-print">
|
||
|
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||
|
|
<div>
|
||
|
|
<button onclick="window.print()" class="btn" style="background-color: #007bff; color: white; padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer;">
|
||
|
|
<i class="bi bi-printer"></i> Print Report
|
||
|
|
</button>
|
||
|
|
<button onclick="window.close()" class="btn" style="background-color: #6c757d; color: white; padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; margin-left: 10px;">
|
||
|
|
Close
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<button onclick="saveAsPDF()" class="btn" style="background-color: #dc3545; color: white; padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer;">
|
||
|
|
<i class="bi bi-file-pdf"></i> Save as PDF
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Report Header -->
|
||
|
|
<div class="report-header">
|
||
|
|
<div class="report-title">Student Report</div>
|
||
|
|
<div class="report-subtitle">Generated on <?php echo date('F j, Y, h:i A'); ?></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Report Info -->
|
||
|
|
<div class="report-info">
|
||
|
|
<div class="info-row">
|
||
|
|
<div><strong>Total Students:</strong> <?php echo count($students); ?></div>
|
||
|
|
<div><strong>Page:</strong> 1 of 1</div>
|
||
|
|
</div>
|
||
|
|
<div class="info-row">
|
||
|
|
<div>
|
||
|
|
<strong>Filters Applied:</strong>
|
||
|
|
<?php
|
||
|
|
$filter_text = [];
|
||
|
|
if ($filters['status'] !== 'all') {
|
||
|
|
$filter_text[] = 'Status: ' . ($filters['status'] == 1 ? 'Active' : 'Inactive');
|
||
|
|
}
|
||
|
|
if ($filters['year_level'] !== 'all') {
|
||
|
|
$filter_text[] = 'Year Level: ' . $filters['year_level'];
|
||
|
|
}
|
||
|
|
if ($filters['course'] !== 'all') {
|
||
|
|
$filter_text[] = 'Course Filtered';
|
||
|
|
}
|
||
|
|
if ($filters['date_from']) {
|
||
|
|
$filter_text[] = 'From: ' . date('M j, Y', strtotime($filters['date_from']));
|
||
|
|
}
|
||
|
|
if ($filters['date_to']) {
|
||
|
|
$filter_text[] = 'To: ' . date('M j, Y', strtotime($filters['date_to']));
|
||
|
|
}
|
||
|
|
|
||
|
|
echo empty($filter_text) ? 'No filters applied' : implode(', ', $filter_text);
|
||
|
|
?>
|
||
|
|
</div>
|
||
|
|
<div><strong>Generated By:</strong> <?php echo $_SESSION['full_name'] ?? 'Admin'; ?></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Students Table -->
|
||
|
|
<?php if (!empty($students)): ?>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>#</th>
|
||
|
|
<th>Student ID</th>
|
||
|
|
<th>Full Name</th>
|
||
|
|
<th>Gender</th>
|
||
|
|
<th>Year Level</th>
|
||
|
|
<th>Course</th>
|
||
|
|
<th>Email</th>
|
||
|
|
<th>Contact</th>
|
||
|
|
<th>Status</th>
|
||
|
|
<th>Date Registered</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<?php
|
||
|
|
$counter = 1;
|
||
|
|
$active_count = 0;
|
||
|
|
$inactive_count = 0;
|
||
|
|
$year_counts = [1 => 0, 2 => 0, 3 => 0, 4 => 0];
|
||
|
|
|
||
|
|
foreach ($students as $student):
|
||
|
|
if ($student['status'] == 1) $active_count++;
|
||
|
|
else $inactive_count++;
|
||
|
|
|
||
|
|
$year_counts[$student['year_level']]++;
|
||
|
|
?>
|
||
|
|
<tr>
|
||
|
|
<td><?php echo $counter++; ?></td>
|
||
|
|
<td><?php echo $student['student_id']; ?></td>
|
||
|
|
<td><?php echo $student['full_name']; ?></td>
|
||
|
|
<td><?php echo $student['gender']; ?></td>
|
||
|
|
<td>Year <?php echo $student['year_level']; ?></td>
|
||
|
|
<td><?php echo $student['course_code'] ?? ''; ?></td>
|
||
|
|
<td><?php echo $student['email']; ?></td>
|
||
|
|
<td><?php echo $student['contact_number']; ?></td>
|
||
|
|
<td>
|
||
|
|
<?php if ($student['status'] == 1): ?>
|
||
|
|
<span class="status-active">Active</span>
|
||
|
|
<?php else: ?>
|
||
|
|
<span class="status-inactive">Inactive</span>
|
||
|
|
<?php endif; ?>
|
||
|
|
</td>
|
||
|
|
<td><?php echo date('M j, Y', strtotime($student['created_at'])); ?></td>
|
||
|
|
</tr>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<!-- Summary -->
|
||
|
|
<div class="summary-box">
|
||
|
|
<h4>Summary</h4>
|
||
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
|
||
|
|
<div>
|
||
|
|
<strong>Total Students:</strong> <?php echo count($students); ?>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<strong>Active:</strong> <?php echo $active_count; ?>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<strong>Inactive:</strong> <?php echo $inactive_count; ?>
|
||
|
|
</div>
|
||
|
|
<?php foreach ($year_counts as $year => $count): ?>
|
||
|
|
<div>
|
||
|
|
<strong>Year <?php echo $year; ?>:</strong> <?php echo $count; ?>
|
||
|
|
</div>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<?php else: ?>
|
||
|
|
<div style="text-align: center; padding: 40px;">
|
||
|
|
<h4>No students found matching the selected criteria</h4>
|
||
|
|
<p>Try adjusting your filters.</p>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<!-- Footer -->
|
||
|
|
<div class="footer">
|
||
|
|
<div>Student Management System</div>
|
||
|
|
<div>Report generated electronically - <?php echo date('F j, Y, h:i:s A'); ?></div>
|
||
|
|
<div>Page 1 of 1</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
function saveAsPDF() {
|
||
|
|
// In production, use a proper PDF generation library
|
||
|
|
// For now, we'll use browser's print to PDF
|
||
|
|
|
||
|
|
const originalTitle = document.title;
|
||
|
|
document.title = 'Student Report - <?php echo date('Y-m-d'); ?>';
|
||
|
|
|
||
|
|
window.print();
|
||
|
|
|
||
|
|
document.title = originalTitle;
|
||
|
|
}
|
||
|
|
|
||
|
|
function downloadCSV() {
|
||
|
|
// Create CSV content
|
||
|
|
let csvContent = "data:text/csv;charset=utf-8,";
|
||
|
|
|
||
|
|
// Headers
|
||
|
|
csvContent += "Student ID,Full Name,Gender,Year Level,Course,Email,Contact,Status,Date Registered\n";
|
||
|
|
|
||
|
|
// Data
|
||
|
|
<?php foreach ($students as $student): ?>
|
||
|
|
csvContent += "<?php
|
||
|
|
echo addslashes($student['student_id']) . ',' .
|
||
|
|
addslashes($student['full_name']) . ',' .
|
||
|
|
addslashes($student['gender']) . ',' .
|
||
|
|
'Year ' . $student['year_level'] . ',' .
|
||
|
|
addslashes(($student['course_code'] ?? '') . ' - ' . ($student['course_name'] ?? '')) . ',' .
|
||
|
|
addslashes($student['email']) . ',' .
|
||
|
|
addslashes($student['contact_number']) . ',' .
|
||
|
|
($student['status'] == 1 ? 'Active' : 'Inactive') . ',' .
|
||
|
|
date('Y-m-d', strtotime($student['created_at']));
|
||
|
|
?>\n";
|
||
|
|
<?php endforeach; ?>
|
||
|
|
|
||
|
|
// Create download link
|
||
|
|
const encodedUri = encodeURI(csvContent);
|
||
|
|
const link = document.createElement("a");
|
||
|
|
link.setAttribute("href", encodedUri);
|
||
|
|
link.setAttribute("download", "students_<?php echo date('Y-m-d'); ?>.csv");
|
||
|
|
document.body.appendChild(link);
|
||
|
|
link.click();
|
||
|
|
document.body.removeChild(link);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Auto-print if specified
|
||
|
|
<?php if ($type === 'print'): ?>
|
||
|
|
window.onload = function() {
|
||
|
|
setTimeout(function() {
|
||
|
|
window.print();
|
||
|
|
}, 500);
|
||
|
|
};
|
||
|
|
<?php endif; ?>
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|