recreate project
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
$rows = $rows ?? [];
|
||||
$groupedRows = [];
|
||||
$dateOrder = [];
|
||||
|
||||
// Prepare data for grouping and chart
|
||||
foreach ($rows as $r) {
|
||||
$dateKey = trim((string)($r['date'] ?? ''));
|
||||
if ($dateKey === '') $dateKey = 'Unknown Date';
|
||||
if (!array_key_exists($dateKey, $groupedRows)) {
|
||||
$groupedRows[$dateKey] = [];
|
||||
$dateOrder[] = $dateKey;
|
||||
}
|
||||
$groupedRows[$dateKey][] = $r;
|
||||
}
|
||||
|
||||
// Prepare specific arrays for the Bar Chart
|
||||
$chartData = [];
|
||||
foreach ($dateOrder as $date) {
|
||||
$chartData[] = count($groupedRows[$date]);
|
||||
}
|
||||
|
||||
$formatDateKey = function ($value) {
|
||||
if ($value === '' || $value === 'Unknown Date') return $value;
|
||||
if (preg_match('/^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{4})(?:\\s.*)?$/', $value, $m)) {
|
||||
$mm = str_pad($m[1], 2, '0', STR_PAD_LEFT);
|
||||
$dd = str_pad($m[2], 2, '0', STR_PAD_LEFT);
|
||||
return $mm . '-' . $dd . '-' . $m[3];
|
||||
}
|
||||
if (preg_match('/^(\d{4})-(\d{2})-(\d{2})/', $value, $m)) {
|
||||
return $m[2] . '-' . $m[3] . '-' . $m[1];
|
||||
}
|
||||
try {
|
||||
return local_date($value, 'm-d-Y');
|
||||
} catch (Throwable $e) {
|
||||
return $value;
|
||||
}
|
||||
};
|
||||
|
||||
$chartLabels = array_map($formatDateKey, $dateOrder);
|
||||
?>
|
||||
|
||||
<?= $this->extend('layout/management_layout') ?>
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<div class="container-fluid px-0 py-4">
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-3">
|
||||
<div>
|
||||
<h2 class="mb-0">Late Slip Preview</h2>
|
||||
<small class="text-muted">View and print student late slips</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="get" class="row gy-2 gx-3 align-items-end mb-4">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">School Year</label>
|
||||
<input type="text" class="form-control"
|
||||
name="school_year"
|
||||
value="<?= esc($school_year ?? ($_GET['school_year'] ?? '')) ?>"
|
||||
placeholder="e.g. 2025-2026">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Semester</label>
|
||||
<?php $semVal = strtolower(trim((string)($semester ?? ($_GET['semester'] ?? '')))); ?>
|
||||
<select name="semester" class="form-select" onchange="if(!this.value) this.removeAttribute('name')">
|
||||
<option value="">All Semesters</option>
|
||||
<option value="fall" <?= $semVal === 'fall' ? 'selected' : '' ?>>Fall</option>
|
||||
<option value="spring" <?= $semVal === 'spring' ? 'selected' : '' ?>>Spring</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-primary w-100">Filter</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php if (empty($rows)): ?>
|
||||
<div class="alert alert-light border">No slips found.</div>
|
||||
<?php else: ?>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header bg-white py-3">
|
||||
<h5 class="card-title mb-0 fw-bold text-primary">Late Statistics by Date</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div style="position: relative; height: 300px; width: 100%;">
|
||||
<canvas id="lateChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php foreach ($dateOrder as $dateKey): ?>
|
||||
<?php $groupRows = $groupedRows[$dateKey] ?? []; ?>
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<div class="fw-semibold">Date: <?= esc($formatDateKey($dateKey)) ?></div>
|
||||
<span class="badge bg-secondary"><?= count($groupRows) ?> slips</span>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered align-middle w-100 slip-preview-table" data-no-mgmt-sticky>
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Student Name</th>
|
||||
<th>Time In</th>
|
||||
<th>Grade</th>
|
||||
<th>Reason</th>
|
||||
<th>School Year</th>
|
||||
<th>Semester</th>
|
||||
<th>Admin Name</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($groupRows as $r): ?>
|
||||
<?php
|
||||
$sem = strtolower(trim((string)($r['semester'] ?? '')));
|
||||
if ($sem === '1') $sem = 'Fall';
|
||||
elseif ($sem === '2') $sem = 'Spring';
|
||||
elseif ($sem === '') $sem = '-';
|
||||
else $sem = ucfirst($sem);
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc($r['student_name'] ?? '') ?></td>
|
||||
<td><?= esc($r['time_in'] ?? '') ?></td>
|
||||
<td><?= esc($r['grade'] ?? '') ?></td>
|
||||
<td><?= esc($r['reason'] ?? '') ?></td>
|
||||
<td><?= esc($r['school_year'] ?? '') ?></td>
|
||||
<td><?= esc($sem) ?></td>
|
||||
<td><?= esc($r['admin_name'] ?? '') ?></td>
|
||||
<td>
|
||||
<form action="<?= site_url('slips/print') ?>" method="post" class="d-inline">
|
||||
<?= csrf_field() ?>
|
||||
<?php foreach (['student_name', 'date', 'time_in', 'grade', 'reason', 'school_year', 'semester', 'admin_name'] as $f): ?>
|
||||
<input type="hidden" name="<?= esc($f) ?>" value="<?= esc($r[$f] ?? '', 'attr') ?>">
|
||||
<?php endforeach; ?>
|
||||
<button type="submit" class="btn btn-sm btn-primary">Print</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('scripts') ?>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const ctx = document.getElementById('lateChart').getContext('2d');
|
||||
|
||||
// PHP to JS data conversion
|
||||
const labels = <?= json_encode($chartLabels) ?>;
|
||||
const counts = <?= json_encode($chartData) ?>;
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: 'Slips per Day',
|
||||
data: counts,
|
||||
backgroundColor: 'rgba(13, 110, 253, 0.7)', // Bootstrap Primary Blue
|
||||
borderColor: 'rgb(13, 110, 253)',
|
||||
borderWidth: 1,
|
||||
borderRadius: 5,
|
||||
barThickness: 40
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: { display: false }
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: { precision: 0 },
|
||||
title: { display: true, text: 'Total Slips' }
|
||||
},
|
||||
x: {
|
||||
title: { display: true, text: 'Recorded Dates' }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
// Variables: $entry (assoc array), $page (['w_mm'=>float,'h_mm'=>float])
|
||||
$e = $entry ?? [];
|
||||
function esc_html($s)
|
||||
{
|
||||
return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
$schoolYearRaw = (string)($e['school_year'] ?? '');
|
||||
// Reduce school year to "xx-xx" if possible (e.g., 2025-2026 -> 25-26)
|
||||
$schoolYearFmt = $schoolYearRaw;
|
||||
if (preg_match('/(\d{2,4})\D+(\d{2,4})/', $schoolYearRaw, $m)) {
|
||||
$a = substr($m[1], -2);
|
||||
$b = substr($m[2], -2);
|
||||
$schoolYearFmt = $a . '-' . $b;
|
||||
} elseif (preg_match('/^\d{4}$/', $schoolYearRaw)) {
|
||||
$y = (int)$schoolYearRaw;
|
||||
if ($y > 0) {
|
||||
$schoolYearFmt = substr($schoolYearRaw, -2) . '-' . substr((string)($y + 1), -2);
|
||||
}
|
||||
}
|
||||
$schoolYear = esc_html($schoolYearFmt);
|
||||
$studentName = esc_html($e['student_name'] ?? '');
|
||||
$dateRaw = $e['date'] ?? '';
|
||||
// Normalize slip date without flipping month/day.
|
||||
if (!function_exists('format_slip_date')) {
|
||||
function format_slip_date($raw): string
|
||||
{
|
||||
$raw = trim((string)$raw);
|
||||
if ($raw === '') return '';
|
||||
if (preg_match('/^\\d{4}-\\d{2}-\\d{2}$/', $raw)) {
|
||||
$dt = DateTime::createFromFormat('!Y-m-d', $raw);
|
||||
return $dt ? $dt->format('m-d-Y') : $raw;
|
||||
}
|
||||
if (preg_match('/^\\d{1,2}\\/\\d{1,2}\\/\\d{4}$/', $raw)) {
|
||||
$dt = DateTime::createFromFormat('!m/d/Y', $raw);
|
||||
return $dt ? $dt->format('m-d-Y') : $raw;
|
||||
}
|
||||
if (preg_match('/^\\d{1,2}-\\d{1,2}-\\d{4}$/', $raw)) {
|
||||
$dt = DateTime::createFromFormat('!m-d-Y', $raw);
|
||||
return $dt ? $dt->format('m-d-Y') : $raw;
|
||||
}
|
||||
try {
|
||||
return local_date($raw, 'm-d-Y');
|
||||
} catch (Throwable $e) {
|
||||
return $raw;
|
||||
}
|
||||
}
|
||||
}
|
||||
$date = $dateRaw !== '' ? esc_html(format_slip_date($dateRaw)) : '';
|
||||
$timeIn = esc_html($e['time_in'] ?? '');
|
||||
$grade = esc_html($e['grade'] ?? '');
|
||||
$reason = esc_html($e['reason'] ?? '');
|
||||
$adminName = esc_html($e['admin_name'] ?? '');
|
||||
$page = isset($page) && is_array($page) ? $page : ['w_mm' => 85.60, 'h_mm' => 53.98];
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Late Slip</title>
|
||||
<style>
|
||||
/* Page size dynamic based on controller selection */
|
||||
@page {
|
||||
size: <?= number_format((float)$page['w_mm'], 2) ?>mm <?= number_format((float)$page['h_mm'], 2) ?>mm;
|
||||
margin: 3mm;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
font-size: 13pt;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.page { page-break-inside: avoid; }
|
||||
.line { line-height: 2; white-space: nowrap; overflow: hidden; text-overflow: clip; width: 100%; page-break-inside: avoid; }
|
||||
|
||||
.label {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.sp {
|
||||
display: inline-block;
|
||||
width: 4mm;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
text-decoration: underline;
|
||||
font-size: 18pt;
|
||||
margin-bottom: 3mm;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page">
|
||||
<div class="title">Late Slip</div>
|
||||
<div class="line"><span class="label">Al Rahma School at ISGL <?= $schoolYear ?></span></div>
|
||||
<div class="line"><span class="label">Student:</span> <?= $studentName ?></div>
|
||||
<div class="line"><span class="label">Date:</span> <?= $date ?></div>
|
||||
<div class="line"><span class="label">Time In:</span> <?= $timeIn ?></div>
|
||||
<div class="line"><span class="label">Grade:</span> <?= $grade ?></div>
|
||||
<div class="line"><span class="label">Reason:</span> <?= $reason ?></div>
|
||||
<div class="line"><span class="label">Admin:</span> <?= $adminName ?></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user