Files
QrCode-Attendance-System/src/admin/attendance.php

132 lines
6.2 KiB
PHP
Raw Normal View History

2026-01-07 14:09:59 +08:00
<?php
require __DIR__ . '/../includes/bootstrap.php';
require_login();
require_admin();
$pdo = db();
$activities = $pdo->query(
'SELECT id, name, date, time_in, time_out
FROM activities
WHERE status = 1 AND date >= CURDATE() - INTERVAL 1 DAY
ORDER BY date DESC, time_in DESC'
)->fetchAll();
$hasActivities = !empty($activities);
$todayAttendance = $pdo->query(
'SELECT att.*, s.full_name, s.student_id, act.name AS activity_name
FROM attendance att
INNER JOIN students s ON att.student_id = s.id
INNER JOIN activities act ON att.activity_id = act.id
WHERE DATE(att.time_in) = CURDATE()
ORDER BY att.time_in DESC'
)->fetchAll();
render_header('Scan Center', ['active' => 'attendance']);
?>
<div class="row g-4">
<div class="col-lg-5">
<div class="scan-panel h-100">
<h2>Admin Scan Center</h2>
<p class="mb-4 text-white-50">Only signed-in administrators can scan QR codes. Use the camera or type the token below.</p>
<?php if (!$hasActivities): ?>
<div class="alert alert-warning bg-warning-subtle text-dark">
No active activities available. Create one first to start scanning.
</div>
<?php endif; ?>
<form data-scan-form data-endpoint="<?= url_for('api/scan.php') ?>" class="v-stack gap-3">
<div>
<label class="form-label text-white">Activity</label>
<select name="activity_id" class="form-select form-select-lg" <?= $hasActivities ? '' : 'disabled' ?> required>
<?php if ($hasActivities): ?>
<?php foreach ($activities as $activity): ?>
<option value="<?= $activity['id'] ?>">
<?= sanitize($activity['name']) ?> — <?= format_date($activity['date'], 'M d') ?>
</option>
<?php endforeach; ?>
<?php else: ?>
<option value="">No activities</option>
<?php endif; ?>
</select>
</div>
<div>
<label class="form-label text-white">QR Token / Student ID</label>
<input type="text" name="qr_token" class="form-control form-control-lg"
placeholder="Scan or type token" autocomplete="off" <?= $hasActivities ? '' : 'disabled' ?> required>
</div>
<div>
<label class="form-label text-white">Notes (optional)</label>
<textarea name="notes" class="form-control" rows="2" placeholder="Remarks for this scan"></textarea>
</div>
<div class="d-flex gap-2 flex-wrap">
<button type="submit" class="btn btn-light btn-lg flex-grow-1" <?= $hasActivities ? '' : 'disabled' ?>>Record Attendance</button>
<button type="button" class="btn btn-outline-light btn-lg flex-grow-1" data-scan-start <?= $hasActivities ? '' : 'disabled' ?>>
Start Camera Scan
</button>
</div>
<p class="text-white-50 small mb-0">
The scanner auto-selects the best camera mode and falls back to a built-in detector if needed.
</p>
</form>
<div class="mt-4">
<p id="scan-status" class="fw-semibold mb-3"></p>
<div id="camera-viewer" class="camera-viewer bg-white rounded shadow-sm">
<div class="text-center text-muted small">Camera idle</div>
</div>
</div>
</div>
</div>
<div class="col-lg-7">
<div class="card shadow-sm h-100">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0">Todays Attendance</h5>
<span class="badge bg-primary-subtle text-primary"><?= count($todayAttendance) ?> captured</span>
</div>
<div class="card-body">
<div id="scan-result" class="mb-4"></div>
<?php if (!$todayAttendance): ?>
<p class="text-muted text-center mb-0">No scans recorded today.</p>
<?php else: ?>
<div class="table-responsive">
<table class="table align-middle">
<thead>
<tr>
<th>Student</th>
<th>Activity</th>
<th>Time In</th>
<th>Time Out</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php foreach ($todayAttendance as $row): ?>
<tr>
<td>
<strong><?= sanitize($row['full_name']) ?></strong><br>
<span class="text-muted-sm"><?= sanitize($row['student_id']) ?></span>
</td>
<td><?= sanitize($row['activity_name']) ?></td>
<td><?= format_datetime($row['time_in'], 'h:i A') ?></td>
<td><?= format_datetime($row['time_out'], 'h:i A') ?></td>
<td>
<span class="badge bg-success-subtle text-success badge-status">
<?= strtoupper(sanitize($row['status'])) ?>
</span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php
render_footer([
'extra_js' => [
'https://unpkg.com/html5-qrcode@2.3.10/html5-qrcode.min.js',
],
]);