593 lines
20 KiB
PHP
593 lines
20 KiB
PHP
|
|
<?php
|
||
|
|
// generate.php - Compact Version
|
||
|
|
require_once '../includes/config.php';
|
||
|
|
|
||
|
|
// Check if student ID is provided
|
||
|
|
if (!isset($_GET['id']) || empty($_GET['id'])) {
|
||
|
|
die('<div style="padding:15px;color:red;font-size:14px;">Error: Student ID required.</div>');
|
||
|
|
}
|
||
|
|
|
||
|
|
$student_id = intval($_GET['id']);
|
||
|
|
|
||
|
|
// Get student data
|
||
|
|
$sql = "SELECT s.*, c.code as course_code, c.name as course_name,
|
||
|
|
d.name as department_name, sc.name as school_name
|
||
|
|
FROM students s
|
||
|
|
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
|
||
|
|
WHERE s.id = ?";
|
||
|
|
|
||
|
|
$stmt = mysqli_prepare($conn, $sql);
|
||
|
|
mysqli_stmt_bind_param($stmt, 'i', $student_id);
|
||
|
|
mysqli_stmt_execute($stmt);
|
||
|
|
$result = mysqli_stmt_get_result($stmt);
|
||
|
|
|
||
|
|
if (!$result || mysqli_num_rows($result) == 0) {
|
||
|
|
die('<div style="padding:15px;color:red;font-size:14px;">Error: Student not found.</div>');
|
||
|
|
}
|
||
|
|
|
||
|
|
$student = mysqli_fetch_assoc($result);
|
||
|
|
mysqli_stmt_close($stmt);
|
||
|
|
|
||
|
|
// Check if download or print is requested
|
||
|
|
$download = isset($_GET['download']) && $_GET['download'] == '1';
|
||
|
|
$print = isset($_GET['print']) && $_GET['print'] == '1';
|
||
|
|
$auto_print = isset($_GET['autoPrint']) && $_GET['autoPrint'] == '1';
|
||
|
|
|
||
|
|
// QR code content
|
||
|
|
$qr_data = [
|
||
|
|
'ID' => $student['student_id'],
|
||
|
|
'Name' => $student['full_name'],
|
||
|
|
'Course' => $student['course_code'],
|
||
|
|
'Dept' => $student['department_name'],
|
||
|
|
'Year' => 'Year ' . $student['year_level'],
|
||
|
|
'Code' => $student['qr_code']
|
||
|
|
];
|
||
|
|
|
||
|
|
$qr_text = "";
|
||
|
|
foreach ($qr_data as $key => $value) {
|
||
|
|
$qr_text .= "$key: $value\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create temp directory
|
||
|
|
$temp_dir = '../temp_qrcodes/';
|
||
|
|
if (!file_exists($temp_dir)) {
|
||
|
|
mkdir($temp_dir, 0777, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Generate QR code
|
||
|
|
$filename = 'qr_' . $student['student_id'] . '_' . time() . '.png';
|
||
|
|
$filepath = $temp_dir . $filename;
|
||
|
|
$qr_size = isset($_GET['size']) ? intval($_GET['size']) : 250;
|
||
|
|
|
||
|
|
// Generate QR code from Google Charts
|
||
|
|
$encoded_text = urlencode(trim($qr_text));
|
||
|
|
$qr_url = "https://chart.googleapis.com/chart?chs={$qr_size}x{$qr_size}&cht=qr&chl={$encoded_text}&choe=UTF-8";
|
||
|
|
$image_data = @file_get_contents($qr_url);
|
||
|
|
|
||
|
|
if ($image_data === false) {
|
||
|
|
// Fallback
|
||
|
|
$qr_url = "https://api.qrserver.com/v1/create-qr-code/?size={$qr_size}x{$qr_size}&data=" . urlencode($qr_text);
|
||
|
|
$image_data = @file_get_contents($qr_url);
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($image_data !== false) {
|
||
|
|
file_put_contents($filepath, $image_data);
|
||
|
|
}
|
||
|
|
|
||
|
|
// If download requested
|
||
|
|
if ($download) {
|
||
|
|
if (file_exists($filepath)) {
|
||
|
|
header('Content-Type: application/octet-stream');
|
||
|
|
header('Content-Disposition: attachment; filename="QR_' . $student['student_id'] . '.png"');
|
||
|
|
header('Content-Length: ' . filesize($filepath));
|
||
|
|
readfile($filepath);
|
||
|
|
cleanupOldQRCodes($temp_dir);
|
||
|
|
exit();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// If print requested
|
||
|
|
if ($print || $auto_print) {
|
||
|
|
?>
|
||
|
|
<!DOCTYPE html>
|
||
|
|
<html>
|
||
|
|
<head>
|
||
|
|
<title>QR - <?php echo $student['full_name']; ?></title>
|
||
|
|
<style>
|
||
|
|
@media print { body { margin: 10px; } }
|
||
|
|
body { font-family: Arial, sans-serif; font-size: 12px; }
|
||
|
|
.container { max-width: 400px; margin: 0 auto; }
|
||
|
|
.header { text-align: center; margin-bottom: 15px; }
|
||
|
|
.qr-img { width: 250px; height: 250px; margin: 0 auto; display: block; }
|
||
|
|
.info { margin: 15px 0; }
|
||
|
|
.footer { text-align: center; margin-top: 10px; font-size: 10px; color: #666; }
|
||
|
|
</style>
|
||
|
|
<script>window.onload = function() { window.print(); setTimeout(() => window.close(), 500); }</script>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="container">
|
||
|
|
<div class="header">
|
||
|
|
<h3 style="margin:0;"><?php echo htmlspecialchars($student['full_name']); ?></h3>
|
||
|
|
<p style="margin:5px 0;"><?php echo htmlspecialchars($student['student_id']); ?></p>
|
||
|
|
</div>
|
||
|
|
<?php if (file_exists($filepath)): ?>
|
||
|
|
<img src="<?php echo $filepath; ?>" class="qr-img" alt="QR Code">
|
||
|
|
<?php else: ?>
|
||
|
|
<div style="border:1px solid #ccc; padding:15px;">
|
||
|
|
<pre><?php echo htmlspecialchars($qr_text); ?></pre>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
<div class="info">
|
||
|
|
<p><strong><?php echo htmlspecialchars($student['course_code']); ?></strong></p>
|
||
|
|
<p>Year <?php echo $student['year_level']; ?> | <?php echo date('m/d/Y'); ?></p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</body>
|
||
|
|
</html>
|
||
|
|
<?php
|
||
|
|
cleanupOldQRCodes($temp_dir);
|
||
|
|
exit();
|
||
|
|
}
|
||
|
|
?>
|
||
|
|
|
||
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<title>QR - <?php echo htmlspecialchars($student['full_name']); ?></title>
|
||
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||
|
|
<style>
|
||
|
|
body {
|
||
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
|
|
background: #f8f9fa;
|
||
|
|
padding: 20px;
|
||
|
|
font-size: 14px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.container {
|
||
|
|
max-width: 800px;
|
||
|
|
margin: 0 auto;
|
||
|
|
background: white;
|
||
|
|
border-radius: 10px;
|
||
|
|
box-shadow: 0 3px 15px rgba(0,0,0,0.08);
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
.header {
|
||
|
|
background:#166b0e;
|
||
|
|
color: white;
|
||
|
|
padding: 15px 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.header h1 {
|
||
|
|
font-size: 1.5rem;
|
||
|
|
margin: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.content {
|
||
|
|
padding: 20px;
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 1fr 1fr;
|
||
|
|
gap: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 768px) {
|
||
|
|
.content {
|
||
|
|
grid-template-columns: 1fr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.qr-card {
|
||
|
|
text-align: center;
|
||
|
|
padding: 15px;
|
||
|
|
background: #f8f9fa;
|
||
|
|
border-radius: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.qr-img {
|
||
|
|
max-width: 250px;
|
||
|
|
width: 100%;
|
||
|
|
height: auto;
|
||
|
|
border-radius: 5px;
|
||
|
|
margin: 0 auto 15px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.qr-code {
|
||
|
|
font-family: 'Courier New', monospace;
|
||
|
|
font-size: 12px;
|
||
|
|
background: white;
|
||
|
|
padding: 8px;
|
||
|
|
border-radius: 5px;
|
||
|
|
word-break: break-all;
|
||
|
|
margin: 10px 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-card {
|
||
|
|
padding: 15px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.student-header {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 15px;
|
||
|
|
margin-bottom: 15px;
|
||
|
|
padding-bottom: 15px;
|
||
|
|
border-bottom: 1px solid #dee2e6;
|
||
|
|
}
|
||
|
|
|
||
|
|
.avatar {
|
||
|
|
width: 60px;
|
||
|
|
height: 60px;
|
||
|
|
border-radius: 50%;
|
||
|
|
object-fit: cover;
|
||
|
|
border: 3px solid #4361ee;
|
||
|
|
}
|
||
|
|
|
||
|
|
.avatar-placeholder {
|
||
|
|
width: 60px;
|
||
|
|
height: 60px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: #166b0e;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
border: 3px solid #cfee43;
|
||
|
|
}
|
||
|
|
|
||
|
|
.avatar-placeholder i {
|
||
|
|
color: white;
|
||
|
|
font-size: 24px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.student-name {
|
||
|
|
font-weight: 600;
|
||
|
|
font-size: 1.1rem;
|
||
|
|
margin: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.student-id {
|
||
|
|
color: #4361ee;
|
||
|
|
font-weight: 500;
|
||
|
|
margin: 0;
|
||
|
|
font-size: 0.9rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 1fr 1fr;
|
||
|
|
gap: 10px;
|
||
|
|
margin-top: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-item {
|
||
|
|
padding: 8px;
|
||
|
|
background: #f8f9fa;
|
||
|
|
border-radius: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-label {
|
||
|
|
font-size: 11px;
|
||
|
|
color: #6c757d;
|
||
|
|
text-transform: uppercase;
|
||
|
|
font-weight: 600;
|
||
|
|
margin-bottom: 3px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-value {
|
||
|
|
font-size: 13px;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-badge {
|
||
|
|
display: inline-block;
|
||
|
|
padding: 3px 10px;
|
||
|
|
border-radius: 12px;
|
||
|
|
font-size: 11px;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
.active { background: #d1fae5; color: #065f46; }
|
||
|
|
.inactive { background: #fee2e2; color: #991b1b; }
|
||
|
|
|
||
|
|
.actions {
|
||
|
|
padding: 15px 20px;
|
||
|
|
background: #f8f9fa;
|
||
|
|
border-top: 1px solid #dee2e6;
|
||
|
|
display: flex;
|
||
|
|
gap: 10px;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
padding: 8px 15px;
|
||
|
|
border: none;
|
||
|
|
border-radius: 6px;
|
||
|
|
font-size: 13px;
|
||
|
|
font-weight: 500;
|
||
|
|
text-decoration: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-primary { background: #4361ee; color: white; }
|
||
|
|
.btn-success { background: #10b981; color: white; }
|
||
|
|
.btn-secondary { background: #6c757d; color: white; }
|
||
|
|
|
||
|
|
.btn:hover {
|
||
|
|
opacity: 0.9;
|
||
|
|
text-decoration: none;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
|
||
|
|
.size-controls {
|
||
|
|
display: flex;
|
||
|
|
gap: 5px;
|
||
|
|
margin-top: 10px;
|
||
|
|
justify-content: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.size-btn {
|
||
|
|
padding: 4px 10px;
|
||
|
|
border: 1px solid #4361ee;
|
||
|
|
background: white;
|
||
|
|
color: #4361ee;
|
||
|
|
border-radius: 4px;
|
||
|
|
font-size: 11px;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
.size-btn.active {
|
||
|
|
background: #4361ee;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timestamp {
|
||
|
|
text-align: center;
|
||
|
|
color: #6c757d;
|
||
|
|
font-size: 12px;
|
||
|
|
margin-top: 15px;
|
||
|
|
padding-top: 10px;
|
||
|
|
border-top: 1px solid #dee2e6;
|
||
|
|
}
|
||
|
|
|
||
|
|
.print-only {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media print {
|
||
|
|
body {
|
||
|
|
background: white !important;
|
||
|
|
padding: 0 !important;
|
||
|
|
}
|
||
|
|
|
||
|
|
.container {
|
||
|
|
box-shadow: none !important;
|
||
|
|
border: 1px solid #ddd !important;
|
||
|
|
}
|
||
|
|
|
||
|
|
.actions, .size-controls {
|
||
|
|
display: none !important;
|
||
|
|
}
|
||
|
|
|
||
|
|
.print-only {
|
||
|
|
display: block;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="container">
|
||
|
|
<div class="header">
|
||
|
|
<h1><i class="bi bi-qr-code-scan me-2"></i>Student QR Code</h1>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="content">
|
||
|
|
<!-- QR Code Section -->
|
||
|
|
<div class="qr-card">
|
||
|
|
<?php if (file_exists($filepath)): ?>
|
||
|
|
<img src="<?php echo $filepath; ?>" class="qr-img" alt="QR Code" id="qrImage">
|
||
|
|
<?php else: ?>
|
||
|
|
<div style="padding:15px; background:#f8d7da; border-radius:5px; color:#721c24;">
|
||
|
|
<i class="bi bi-exclamation-triangle me-2"></i>
|
||
|
|
QR code generation failed
|
||
|
|
<div style="margin-top:10px; font-size:12px;">
|
||
|
|
<pre><?php echo htmlspecialchars($qr_text); ?></pre>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<div class="qr-code">
|
||
|
|
<?php echo htmlspecialchars($student['qr_code']); ?>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="size-controls">
|
||
|
|
<button class="size-btn <?php echo $qr_size == 200 ? 'active' : ''; ?>"
|
||
|
|
onclick="changeSize(200)">200px</button>
|
||
|
|
<button class="size-btn <?php echo $qr_size == 250 ? 'active' : ''; ?>"
|
||
|
|
onclick="changeSize(250)">250px</button>
|
||
|
|
<button class="size-btn <?php echo $qr_size == 300 ? 'active' : ''; ?>"
|
||
|
|
onclick="changeSize(300)">300px</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Student Info Section -->
|
||
|
|
<div class="info-card">
|
||
|
|
<div class="student-header">
|
||
|
|
<?php if (!empty($student['picture_path'])): ?>
|
||
|
|
<img src="../<?php echo htmlspecialchars($student['picture_path']); ?>"
|
||
|
|
alt="Photo" class="avatar">
|
||
|
|
<?php else: ?>
|
||
|
|
<div class="avatar-placeholder">
|
||
|
|
<i class="bi bi-person"></i>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<div class="student-name"><?php echo htmlspecialchars($student['full_name']); ?></div>
|
||
|
|
<div class="student-id"><?php echo htmlspecialchars($student['student_id']); ?></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-grid">
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label">Course</div>
|
||
|
|
<div class="info-value"><?php echo htmlspecialchars($student['course_code']); ?></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label">Department</div>
|
||
|
|
<div class="info-value"><?php echo htmlspecialchars($student['department_name']); ?></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label">Year</div>
|
||
|
|
<div class="info-value">Year <?php echo $student['year_level']; ?></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label">School</div>
|
||
|
|
<div class="info-value"><?php echo htmlspecialchars($student['school_name']); ?></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label">Email</div>
|
||
|
|
<div class="info-value">
|
||
|
|
<?php echo htmlspecialchars($student['email'] ?: '-'); ?>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label">Contact</div>
|
||
|
|
<div class="info-value">
|
||
|
|
<?php echo htmlspecialchars($student['contact_number'] ?: '-'); ?>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label">Status</div>
|
||
|
|
<div class="info-value">
|
||
|
|
<?php if ($student['status'] == 1): ?>
|
||
|
|
<span class="status-badge active">
|
||
|
|
<i class="bi bi-check-circle me-1"></i>Active
|
||
|
|
</span>
|
||
|
|
<?php else: ?>
|
||
|
|
<span class="status-badge inactive">
|
||
|
|
<i class="bi bi-x-circle me-1"></i>Inactive
|
||
|
|
</span>
|
||
|
|
<?php endif; ?>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label">Generated</div>
|
||
|
|
<div class="info-value"><?php echo date('m/d/Y h:i A'); ?></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="timestamp">
|
||
|
|
<i class="bi bi-clock me-1"></i>
|
||
|
|
Last updated: <?php echo date('m/d/Y', strtotime($student['updated_at'])); ?>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="actions">
|
||
|
|
<button class="btn btn-primary" onclick="window.print()">
|
||
|
|
<i class="bi bi-printer me-1"></i>Print
|
||
|
|
</button>
|
||
|
|
|
||
|
|
<button class="btn btn-success" onclick="downloadQR()">
|
||
|
|
<i class="bi bi-download me-1"></i>Download
|
||
|
|
</button>
|
||
|
|
|
||
|
|
<a href="?id=<?php echo $student_id; ?>&print=1" target="_blank" class="btn btn-primary">
|
||
|
|
<i class="bi bi-printer-fill me-1"></i>Quick Print
|
||
|
|
</a>
|
||
|
|
|
||
|
|
<a href="?id=<?php echo $student_id; ?>&download=1" class="btn btn-success">
|
||
|
|
<i class="bi bi-file-arrow-down me-1"></i>Direct Download
|
||
|
|
</a>
|
||
|
|
|
||
|
|
<button class="btn btn-secondary" onclick="window.close()">
|
||
|
|
<i class="bi bi-x-circle me-1"></i>Close
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
// Change QR size
|
||
|
|
function changeSize(size) {
|
||
|
|
const url = new URL(window.location.href);
|
||
|
|
url.searchParams.set('size', size);
|
||
|
|
window.location.href = url.toString();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Download QR code
|
||
|
|
function downloadQR() {
|
||
|
|
<?php if (file_exists($filepath)): ?>
|
||
|
|
const link = document.createElement('a');
|
||
|
|
link.href = '<?php echo $filepath; ?>';
|
||
|
|
link.download = 'QR_<?php echo $student['student_id']; ?>.png';
|
||
|
|
document.body.appendChild(link);
|
||
|
|
link.click();
|
||
|
|
document.body.removeChild(link);
|
||
|
|
|
||
|
|
// Show notification
|
||
|
|
const notification = document.createElement('div');
|
||
|
|
notification.style.cssText = 'position:fixed; top:20px; right:20px; background:#10b981; color:white; padding:10px 15px; border-radius:5px; z-index:9999;';
|
||
|
|
notification.innerHTML = '<i class="bi bi-check-circle me-2"></i>Download started';
|
||
|
|
document.body.appendChild(notification);
|
||
|
|
setTimeout(() => notification.remove(), 2000);
|
||
|
|
<?php endif; ?>
|
||
|
|
}
|
||
|
|
|
||
|
|
// Keyboard shortcuts
|
||
|
|
document.addEventListener('keydown', function(e) {
|
||
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 'p') {
|
||
|
|
e.preventDefault();
|
||
|
|
window.print();
|
||
|
|
}
|
||
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 'd') {
|
||
|
|
e.preventDefault();
|
||
|
|
downloadQR();
|
||
|
|
}
|
||
|
|
if (e.key === 'Escape') {
|
||
|
|
window.close();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Auto-print if requested
|
||
|
|
<?php if ($auto_print): ?>
|
||
|
|
window.onload = function() {
|
||
|
|
setTimeout(() => window.print(), 500);
|
||
|
|
};
|
||
|
|
<?php endif; ?>
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||
|
|
</body>
|
||
|
|
</html>
|
||
|
|
|
||
|
|
<?php
|
||
|
|
// Cleanup function
|
||
|
|
function cleanupOldQRCodes($dir) {
|
||
|
|
if (file_exists($dir)) {
|
||
|
|
$files = glob($dir . '*.png');
|
||
|
|
$now = time();
|
||
|
|
|
||
|
|
foreach ($files as $file) {
|
||
|
|
if (is_file($file) && ($now - filemtime($file) >= 3600)) {
|
||
|
|
@unlink($file);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Run cleanup
|
||
|
|
cleanupOldQRCodes($temp_dir);
|
||
|
|
?>
|