recreate project

This commit is contained in:
root
2026-02-10 22:11:06 -05:00
commit 663c0cdbda
10149 changed files with 1379710 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<style>
#adminProgressTable thead th {
position: static !important;
}
</style>
<div class="container py-4">
<div class="mb-4 pb-3 border-bottom">
<div class="d-flex align-items-center justify-content-between">
<div>
<h3 class="mb-0">Class Progress Reports</h3>
<div class="text-muted">Filter by week, class, and status</div>
</div>
</div>
</div>
<form class="card shadow-sm mb-3" method="get" action="<?= base_url('admin/progress') ?>">
<div class="card-body">
<div class="row g-3">
<div class="col-md-3">
<label class="form-label">From</label>
<input type="date" name="from" class="form-control" value="<?= esc($filters['from'] ?? '') ?>">
</div>
<div class="col-md-3">
<label class="form-label">To</label>
<input type="date" name="to" class="form-control" value="<?= esc($filters['to'] ?? '') ?>">
</div>
<div class="col-md-3">
<label class="form-label">Class/Section</label>
<select name="class_section_id" class="form-select">
<option value="">All</option>
<?php foreach ($classSections as $cs): ?>
<option value="<?= esc($cs['class_section_id']) ?>" <?= (isset($filters['class_section_id']) && $filters['class_section_id'] === (string) $cs['class_section_id']) ? 'selected' : '' ?>>
<?= esc($cs['class_section_name']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3">
<label class="form-label">Status</label>
<select name="status" class="form-select">
<option value="">All</option>
<?php foreach ($statusOptions as $value => $label): ?>
<option value="<?= esc($value) ?>" <?= (isset($filters['status']) && $filters['status'] === $value) ? 'selected' : '' ?>><?= esc($label) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="d-flex gap-2 mt-3">
<button class="btn btn-primary" type="submit">Apply</button>
<a class="btn btn-outline-secondary" href="<?= base_url('admin/progress') ?>">Reset</a>
</div>
</div>
</form>
<div class="card shadow-sm mt-5">
<div class="card-body pt-4 px-0">
<div class="table-responsive px-4" style="margin-top: 1.5rem;">
<table id="adminProgressTable" class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th>Week</th>
<th>Subjects</th>
<th>Teacher</th>
<th class="text-end">Action</th>
</tr>
</thead>
<tbody>
<?php
$reportGroups = $reportGroups ?? [];
$subjectSections = $subjectSections ?? [];
?>
<?php if (empty($reportGroups)): ?>
<tr><td colspan="4" class="text-center text-muted py-4">No reports found.</td></tr>
<?php else: ?>
<?php foreach ($reportGroups as $group): ?>
<?php
$weekLabel = $group['week_start'] ? date('M d, Y', strtotime($group['week_start'])) : '-';
if (!empty($group['week_end'])) {
$weekLabel .= ' ' . date('M d, Y', strtotime($group['week_end']));
}
$reports = $group['reports'] ?? [];
$teacherName = '';
foreach ($reports as $report) {
if (!empty($report['teacher_name'])) {
$teacherName = $report['teacher_name'];
break;
}
}
$exampleId = $reports ? reset($reports)['id'] : null;
?>
<tr>
<td>
<div class="fw-semibold"><?= esc($weekLabel) ?></div>
<?php if (!empty($group['class_section_name'])): ?>
<div class="text-muted small">Class: <?= esc($group['class_section_name']) ?></div>
<?php endif; ?>
</td>
<td>
<div class="d-flex flex-column gap-2">
<?php foreach ($subjectSections as $slug => $section): ?>
<?php
$subjectName = $section['db_subject'] ?? $section['label'] ?? $slug;
$report = $reports[$subjectName] ?? null;
$statusTag = $report ? ($report['status_label'] ?? 'Unknown') : 'No entry';
$badgeClass = $report ? 'bg-secondary' : 'bg-light text-muted';
?>
<div class="border rounded-3 p-2">
<div class="d-flex justify-content-between align-items-center">
<strong class="small mb-0"><?= esc($section['label'] ?? $subjectName) ?></strong>
<span class="badge <?= $badgeClass ?>"><?= esc($statusTag) ?></span>
</div>
<div class="small text-muted"><?= $report ? esc($report['unit_title'] ?: '-') : 'No submission' ?></div>
</div>
<?php endforeach; ?>
</div>
</td>
<td><?= esc($teacherName ?: '-') ?></td>
<td class="text-end">
<?php if ($exampleId): ?>
<a class="btn btn-sm btn-outline-primary" href="<?= base_url('admin/progress/view/' . $exampleId) ?>">View</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?= $this->endSection() ?>
+139
View File
@@ -0,0 +1,139 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container py-4">
<div class="d-flex align-items-center justify-content-between mb-3">
<div>
<h3 class="mb-0">Progress Report</h3>
<div class="text-muted">
<?= esc($row['class_section_name'] ?? '-') ?> • <?= esc($row['week_start']) ?> → <?= esc($row['week_end']) ?>
</div>
</div>
<a href="<?= base_url('admin/progress') ?>" class="btn btn-outline-secondary">Back</a>
</div>
<?php
$flagLabels = [
'homework_assigned' => 'Homework assigned',
'quiz_done' => 'Quiz / check-in completed',
'materials_missing' => 'Materials needed',
];
$weeklyReports = $weeklyReports ?? [];
$subjectSections = $subjectSections ?? [];
$reportsBySubject = [];
$attachments = [];
foreach ($weeklyReports as $report) {
$reportsBySubject[$report['subject']] = $report;
foreach (($report['attachments'] ?? []) as $attachment) {
$attachments[] = [
'subject' => $report['subject'] ?? 'Attachment',
'attachment' => $attachment,
'report_id' => $report['id'] ?? null,
];
}
}
?>
<div class="row g-3">
<div class="col-lg-8">
<?php foreach ($subjectSections as $slug => $section): ?>
<?php
$subjectName = $section['db_subject'] ?? $section['label'] ?? $slug;
$isQuran = $subjectName === 'Quran/Arabic';
$unitLabel = $isQuran ? 'Surah / Custom Arabic' : 'Unit / Chapter';
$homeworkLabel = $isQuran ? 'Arabic Practice / Homework' : 'Assigned Homework';
$report = $reportsBySubject[$subjectName] ?? null;
?>
<div class="card shadow-sm mb-3">
<div class="card-header bg-white d-flex align-items-center justify-content-between">
<strong class="mb-0"><?= esc($section['label'] ?? $subjectName) ?></strong>
</div>
<div class="card-body">
<?php if (! $report): ?>
<div class="text-muted">No entry submitted for this subject this week.</div>
<?php else: ?>
<div class="mb-2"><strong><?= $unitLabel ?>:</strong> <?= esc($report['unit_title'] ?: '-') ?></div>
<?php if (!empty($report['materials'])): ?>
<div class="mb-2"><strong>Materials:</strong> <?= esc($report['materials']) ?></div>
<?php endif; ?>
<div class="mb-3">
<strong>Activities</strong>
<div class="mt-1"><?= nl2br(esc($report['covered'] ?? '-')) ?></div>
</div>
<div class="mb-3">
<strong><?= $homeworkLabel ?>:</strong>
<div class="mt-1"><?= nl2br(esc($report['homework'] ?: '-')) ?></div>
</div>
<?php if (!empty($report['attachments'])): ?>
<div class="mt-3">
<strong>Attachments:</strong>
<div class="d-flex flex-column gap-2 mt-2">
<?php foreach ($report['attachments'] as $attachment): ?>
<?php
$linkId = $attachment['id'] ?? $report['id'];
$link = !empty($attachment['legacy'])
? base_url('admin/progress/attachment/' . $linkId)
: base_url('admin/progress/attachment-file/' . $linkId);
?>
<a class="btn btn-sm btn-outline-secondary text-start" href="<?= $link ?>" target="_blank" rel="noreferrer">
<?= esc($attachment['name'] ?? 'Attachment') ?>
</a>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="col-lg-4">
<div class="card shadow-sm mb-3">
<div class="card-header bg-white"><strong>Summary</strong></div>
<div class="card-body">
<div class="mb-2"><strong>Teacher:</strong> <?= esc(trim($row['teacher_name'] ?? '')) ?: '-' ?></div>
<div class="mb-2"><strong>Submitted:</strong> <?= esc($row['created_at'] ? date('M d, Y g:i A', strtotime($row['created_at'])) : '-') ?></div>
<div><strong>Status:</strong> <?= esc($row['status_label'] ?? 'Unknown') ?></div>
</div>
</div>
<?php if (!empty($row['flags'])): ?>
<div class="card shadow-sm mb-3">
<div class="card-header bg-white"><strong>Checklist</strong></div>
<div class="card-body">
<div class="d-flex flex-wrap gap-2">
<?php foreach ($row['flags'] as $flag): ?>
<span class="badge bg-light text-dark border"><?= esc($flagLabels[$flag] ?? str_replace('_', ' ', $flag)) ?></span>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endif; ?>
<?php if (!empty($attachments)): ?>
<div class="card shadow-sm">
<div class="card-header bg-white"><strong>Attachments</strong></div>
<div class="card-body">
<?php foreach ($attachments as $entry): ?>
<?php
$attachment = $entry['attachment'] ?? [];
$linkId = $attachment['id'] ?? ($entry['report_id'] ?? null);
if (!$linkId) {
continue;
}
$link = !empty($attachment['legacy'])
? base_url('admin/progress/attachment/' . $linkId)
: base_url('admin/progress/attachment-file/' . $linkId);
$label = trim(($entry['subject'] ?? 'Attachment') . ' • ' . ($attachment['name'] ?? 'Attachment'));
?>
<a class="btn btn-outline-primary w-100 text-start mb-2" href="<?= $link ?>" target="_blank" rel="noreferrer">
<?= esc($label) ?>
</a>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
<?= $this->endSection() ?>
@@ -0,0 +1,157 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container mt-4">
<?php $isEdit = ($mode ?? 'create') === 'edit'; ?>
<?php $isLocked = $isEdit && !empty($competition['is_locked']); ?>
<?php $lockedAttr = $isLocked ? 'disabled' : ''; ?>
<h3><?= esc($isEdit ? 'Edit Competition' : 'Create Competition') ?></h3>
<?php if ($isLocked): ?>
<div class="alert alert-warning">This competition is locked. Unlock it to make changes.</div>
<?php endif; ?>
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<ul class="mb-0">
<?php foreach ($errors as $e): ?><li><?= esc($e) ?></li><?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="post" action="<?= $isEdit ? '/admin/competition-winners/' . $competition['id'] . '/update' : '/admin/competition-winners/store' ?>" class="row g-3">
<?= csrf_field() ?>
<div class="col-md-8">
<label class="form-label">Title *</label>
<input class="form-control" name="title" value="<?= esc(old('title', $competition['title'] ?? '')) ?>" required <?= $lockedAttr ?>>
</div>
<div class="col-md-6">
<label class="form-label">Class Section (optional)</label>
<?php $oldSection = (string) old('class_section_id', (string) ($competition['class_section_id'] ?? '')); ?>
<select class="form-select" name="class_section_id" <?= $lockedAttr ?>>
<option value="">All classes</option>
<?php foreach ($classSections as $section): ?>
<?php
$value = (string) ($section['class_section_id'] ?? '');
$label = $section['class_section_name'] ?? $value;
$selected = $value !== '' && $value === $oldSection ? 'selected' : '';
?>
<option value="<?= esc($value) ?>" <?= $selected ?>><?= esc($label) ?></option>
<?php endforeach; ?>
</select>
<div class="form-text">Leave empty to manage winners for all classes.</div>
</div>
<div class="col-md-3">
<label class="form-label">Semester</label>
<input class="form-control" name="semester" value="<?= esc(old('semester', $competition['semester'] ?? $defaultSemester ?? '')) ?>" <?= $lockedAttr ?>>
</div>
<div class="col-md-3">
<label class="form-label">School Year</label>
<input class="form-control" name="school_year" value="<?= esc(old('school_year', $competition['school_year'] ?? $defaultSchoolYear ?? '')) ?>" placeholder="2025-2026" <?= $lockedAttr ?>>
<div class="form-text">Counts use the school year above.</div>
</div>
<div class="col-md-4">
<label class="form-label">Start Date</label>
<input class="form-control" name="start_date" type="date" value="<?= esc(old('start_date', $competition['start_date'] ?? '')) ?>" <?= $lockedAttr ?>>
</div>
<div class="col-md-4">
<label class="form-label">End Date</label>
<input class="form-control" name="end_date" type="date" value="<?= esc(old('end_date', $competition['end_date'] ?? '')) ?>" <?= $lockedAttr ?>>
</div>
<div class="col-12">
<h5 class="mt-2">Winners per Class</h5>
<div class="table-responsive">
<table class="table table-bordered table-sm" data-no-mgmt-sticky>
<thead class="table-light">
<tr>
<th>Class</th>
<th style="width:140px;">Students</th>
<th style="width:140px;">Auto Winners</th>
<th style="width:150px;">Questions</th>
<th style="width:120px;">1st</th>
<th style="width:120px;">2nd</th>
<th style="width:120px;">3rd</th>
<th style="width:120px;">4th</th>
<th style="width:120px;">5th</th>
<th style="width:120px;">6th</th>
<th style="width:160px;">Override</th>
<th style="width:140px;">Final Winners</th>
</tr>
</thead>
<tbody>
<?php foreach ($classRows as $row): ?>
<tr>
<td><?= esc($row['class_section_name']) ?></td>
<td><?= esc($row['student_count']) ?></td>
<td><?= esc($row['auto_winners']) ?></td>
<td>
<input class="form-control form-control-sm" type="number" min="1"
name="question_counts[<?= esc($row['class_section_id']) ?>]"
value="<?= esc($row['question_count'] ?? '') ?>"
placeholder="Questions" <?= $lockedAttr ?>>
</td>
<td>
<input class="form-control form-control-sm" type="number" step="0.01" min="0"
name="prizes[<?= esc($row['class_section_id']) ?>][1]"
value="<?= esc($row['prize_1'] ?? '') ?>"
placeholder="$" <?= $lockedAttr ?>>
</td>
<td>
<input class="form-control form-control-sm" type="number" step="0.01" min="0"
name="prizes[<?= esc($row['class_section_id']) ?>][2]"
value="<?= esc($row['prize_2'] ?? '') ?>"
placeholder="$" <?= $lockedAttr ?>>
</td>
<td>
<input class="form-control form-control-sm" type="number" step="0.01" min="0"
name="prizes[<?= esc($row['class_section_id']) ?>][3]"
value="<?= esc($row['prize_3'] ?? '') ?>"
placeholder="$" <?= $lockedAttr ?>>
</td>
<td>
<input class="form-control form-control-sm" type="number" step="0.01" min="0"
name="prizes[<?= esc($row['class_section_id']) ?>][4]"
value="<?= esc($row['prize_4'] ?? '') ?>"
placeholder="$" <?= $lockedAttr ?>>
</td>
<td>
<input class="form-control form-control-sm" type="number" step="0.01" min="0"
name="prizes[<?= esc($row['class_section_id']) ?>][5]"
value="<?= esc($row['prize_5'] ?? '') ?>"
placeholder="$" <?= $lockedAttr ?>>
</td>
<td>
<input class="form-control form-control-sm" type="number" step="0.01" min="0"
name="prizes[<?= esc($row['class_section_id']) ?>][6]"
value="<?= esc($row['prize_6'] ?? '') ?>"
placeholder="$" <?= $lockedAttr ?>>
</td>
<td>
<input class="form-control form-control-sm" type="number" min="1"
name="winner_overrides[<?= esc($row['class_section_id']) ?>]"
value="<?= esc($row['override_winners'] ?? '') ?>"
placeholder="Auto" <?= $lockedAttr ?>>
</td>
<td><?= esc($row['final_winners']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="col-12">
<button class="btn btn-primary" <?= $lockedAttr ?>><?= esc($isEdit ? 'Update' : 'Create') ?></button>
<a class="btn btn-outline-secondary" href="/admin/competition-winners">Cancel</a>
</div>
</form>
</div>
<?= $this->endSection() ?>
@@ -0,0 +1,70 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h3 class="mb-0">Competition Winners</h3>
<a class="btn btn-primary" href="/admin/competition-winners/create">+ New Competition</a>
</div>
<?php if (session('success')): ?>
<div class="alert alert-success"><?= esc(session('success')) ?></div>
<?php endif; ?>
<?php if (session('error')): ?>
<div class="alert alert-danger"><?= esc(session('error')) ?></div>
<?php endif; ?>
<table class="table table-bordered table-sm" data-no-mgmt-sticky>
<thead class="table-light">
<tr>
<th>ID</th>
<th>Title</th>
<th>Class Section</th>
<th>Winners Rule</th>
<th>Published</th>
<th>Locked</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($competitions as $c): ?>
<?php
$sectionId = (int) ($c['class_section_id'] ?? 0);
$sectionName = $sectionId > 0 ? ($sectionMap[$sectionId] ?? $sectionId) : 'All';
$isLocked = !empty($c['is_locked']);
?>
<tr>
<td><?= esc($c['id']) ?></td>
<td><?= esc($c['title']) ?></td>
<td><?= esc($sectionName) ?></td>
<td>Tiered per class</td>
<td><?= $c['is_published'] ? 'Yes' : 'No' ?></td>
<td><?= $isLocked ? 'Yes' : 'No' ?></td>
<td>
<a class="btn btn-sm btn-outline-secondary" href="/admin/competition-winners/<?= $c['id'] ?>/settings">Settings</a>
<a class="btn btn-sm btn-outline-primary" href="/admin/competition-winners/<?= $c['id'] ?>">Enter Scores</a>
<a class="btn btn-sm btn-outline-secondary" href="/admin/competition-winners/<?= $c['id'] ?>/preview">Preview</a>
<a class="btn btn-sm btn-outline-secondary" href="/admin/competition-winners/<?= $c['id'] ?>/winners">Winners</a>
<form method="post" action="/admin/competition-winners/<?= $c['id'] ?>/export-quiz" class="d-inline">
<?= csrf_field() ?>
<button class="btn btn-sm btn-outline-success" type="submit">Export Scores to Quiz</button>
</form>
<?php if ($isLocked): ?>
<form method="post" action="/admin/competition-winners/<?= $c['id'] ?>/unlock" class="d-inline">
<?= csrf_field() ?>
<button class="btn btn-sm btn-outline-warning" type="submit" onclick="return confirm('Unlock this competition to allow edits?')">Unlock</button>
</form>
<?php else: ?>
<form method="post" action="/admin/competition-winners/<?= $c['id'] ?>/lock" class="d-inline">
<?= csrf_field() ?>
<button class="btn btn-sm btn-outline-danger" type="submit" onclick="return confirm('Lock this competition to prevent edits?')">Lock</button>
</form>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?= $this->endSection() ?>
@@ -0,0 +1,86 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-2">
<h3 class="mb-0">Preview Winners</h3>
<div class="d-flex gap-2">
<a class="btn btn-outline-secondary" href="/admin/competition-winners/<?= $competition['id'] ?>">Edit Scores</a>
<a class="btn btn-outline-secondary" href="/admin/competition-winners/<?= $competition['id'] ?>/settings">Settings</a>
<a class="btn btn-outline-secondary" href="/admin/competition-winners">Back</a>
</div>
</div>
<div class="mb-3">
<div><strong>Competition:</strong> <?= esc($competition['title']) ?></div>
<div><strong>School Year:</strong> <?= esc($competition['school_year'] ?? '-') ?></div>
</div>
<?php if (empty($rankedByClass)): ?>
<div class="alert alert-warning">No scores entered yet.</div>
<?php else: ?>
<?php foreach ($rankedByClass as $classId => $rows): ?>
<?php
$classLabel = $classMap[$classId] ?? ('Class ' . $classId);
$topRows = $topByClass[$classId] ?? [];
$winnerPrizeByStudent = [];
foreach ($topRows as $winnerRow) {
$studentId = $winnerRow['student_id'] ?? null;
if ($studentId !== null) {
$winnerPrizeByStudent[(int) $studentId] = $winnerRow['prize_amount'] ?? null;
}
}
$studentCount = $classCounts[$classId] ?? count($rows);
$override = $overrideMap[$classId] ?? null;
$questions = $questionCounts[$classId] ?? null;
$prizes = $prizeMap[$classId] ?? [];
$finalWinners = $winnersCountByClass[$classId] ?? 0;
?>
<h5 class="mt-4">Top Winners - <?= esc($classLabel) ?></h5>
<div class="text-muted mb-2">
Students: <?= esc($studentCount) ?> | Questions: <?= esc($questions ?? '-') ?> | Override: <?= esc($override ?? '-') ?> | Final Winners: <?= esc($finalWinners) ?>
</div>
<table class="table table-bordered table-sm" data-no-mgmt-sticky>
<thead class="table-light">
<tr><th>Rank</th><th>Student</th><th>Score</th><th>Prize</th></tr>
</thead>
<tbody>
<?php foreach ($topRows as $row): ?>
<tr>
<td><?= esc($row['rank']) ?></td>
<td><?= esc($row['name']) ?></td>
<td><?= esc($row['score']) ?></td>
<td><?= esc(!empty($row['prize_amount']) ? $row['prize_amount'] : '-') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<h6>All Ranked Scores - <?= esc($classLabel) ?></h6>
<table class="table table-striped table-sm" data-no-mgmt-sticky>
<thead><tr><th>#</th><th>Student</th><th>Score</th><th>Prize</th></tr></thead>
<tbody>
<?php $i = 1; foreach ($rows as $row): ?>
<?php
$studentId = (int) ($row['student_id'] ?? 0);
$prizeVal = $winnerPrizeByStudent[$studentId] ?? null;
?>
<tr>
<td><?= $i++ ?></td>
<td><?= esc($row['name']) ?></td>
<td><?= esc($row['score']) ?></td>
<td><?= esc(!empty($prizeVal) ? $prizeVal : '-') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endforeach; ?>
<?php endif; ?>
<form method="post" action="/admin/competition-winners/<?= $competition['id'] ?>/publish" class="mt-3">
<?= csrf_field() ?>
<button class="btn btn-success">Publish Winners</button>
</form>
</div>
<?= $this->endSection() ?>
@@ -0,0 +1,135 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-2">
<h3 class="mb-0">Enter Scores</h3>
<a class="btn btn-outline-secondary" href="/admin/competition-winners">Back</a>
</div>
<?php $isLocked = !empty($competition['is_locked']); ?>
<?php $lockedAttr = $isLocked ? 'disabled' : ''; ?>
<?php if ($isLocked): ?>
<div class="alert alert-warning">This competition is locked. Unlock it to update scores.</div>
<?php endif; ?>
<div class="mb-3">
<div><strong>Competition:</strong> <?= esc($competition['title']) ?></div>
<?php if (!empty($classSectionName)): ?>
<div><strong>Class Section:</strong> <?= esc($classSectionName) ?></div>
<div>
<strong>Students:</strong> <?= esc($classStudentCount ?? 0) ?> |
<strong>Auto Winners:</strong> <?= esc($classAutoWinners ?? 0) ?> |
<strong>Override:</strong> <?= esc($classOverrideWinners ?? '-') ?> |
<strong>Final Winners:</strong> <?= esc($classFinalWinners ?? 0) ?> |
<strong>Questions:</strong> <?= esc($classQuestionCount ?? '-') ?>
</div>
<?php endif; ?>
</div>
<?php if (!$classSelectionLocked): ?>
<form method="get" class="row g-2 align-items-end mb-3">
<div class="col-md-6">
<label class="form-label">Select Class Section</label>
<select class="form-select" name="class_section_id" onchange="this.form.submit()" <?= $lockedAttr ?>>
<option value="">Choose a class</option>
<?php foreach ($classSections as $section): ?>
<?php
$value = (string) ($section['class_section_id'] ?? '');
$label = $section['class_section_name'] ?? $value;
$selected = $value !== '' && (int) $value === (int) $activeClassSectionId ? 'selected' : '';
?>
<option value="<?= esc($value) ?>" <?= $selected ?>><?= esc($label) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<div class="form-text">Pick a class to load its students for score entry.</div>
</div>
</form>
<?php endif; ?>
<?php if (session('success')): ?>
<div class="alert alert-success"><?= esc(session('success')) ?></div>
<?php endif; ?>
<form method="post" action="/admin/competition-winners/<?= $competition['id'] ?>/scores">
<?= csrf_field() ?>
<input type="hidden" name="class_section_id" value="<?= esc($activeClassSectionId ?? '') ?>">
<?php if (empty($activeClassSectionId)): ?>
<div class="alert alert-warning">Select a class section to load students.</div>
<?php else: ?>
<link rel="stylesheet" href="https://cdn.datatables.net/v/bs5/dt-2.1.8/r-3.0.3/datatables.min.css">
<?php $scoreMax = ($classQuestionCount !== null && (int) $classQuestionCount > 0) ? (int) $classQuestionCount : null; ?>
<table class="table table-bordered table-sm" data-no-mgmt-sticky id="scoresTable">
<thead class="table-light">
<tr>
<th style="width:140px;">School ID</th>
<th>Student</th>
<th style="width:180px;">
Score<?= $scoreMax !== null ? ' (max ' . esc($scoreMax) . ')' : '' ?>
</th>
</tr>
</thead>
<tbody>
<?php foreach ($students as $s):
$name = trim(($s['firstname'] ?? '') . ' ' . ($s['lastname'] ?? ''));
$studentId = $s['id'] ?? $s['student_id'] ?? null;
$schoolId = $s['school_id'] ?? null;
$val = $studentId !== null ? ($scoreMap[$studentId] ?? '') : '';
?>
<tr>
<td><?= esc($schoolId ?: $studentId) ?></td>
<td><?= esc($name !== '' ? $name : ('Student #' . $studentId)) ?></td>
<td data-order="<?= esc($val) ?>">
<input class="form-control form-control-sm"
name="scores[<?= esc($studentId) ?>]"
type="number" step="0.01" min="0"
value="<?= esc($val) ?>"
<?= $scoreMax !== null ? 'max="' . esc($scoreMax) . '"' : '' ?>
<?= $lockedAttr ?>>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<div class="d-flex gap-2">
<button class="btn btn-primary" <?= $lockedAttr ?>>Save Scores</button>
<a class="btn btn-outline-secondary" href="/admin/competition-winners/<?= $competition['id'] ?>/preview">Preview Winners</a>
</div>
</form>
</div>
<script src="https://cdn.datatables.net/v/bs5/dt-2.1.8/r-3.0.3/datatables.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const tableEl = document.getElementById('scoresTable');
if (!tableEl) {
return;
}
new DataTable(tableEl, {
responsive: true,
paging: false,
searching: false,
info: false,
order: [[1, 'asc']],
});
tableEl.addEventListener('input', function (event) {
const target = event.target;
if (target && target.matches('input')) {
const cell = target.closest('td');
if (cell) {
cell.setAttribute('data-order', target.value.trim());
}
}
});
});
</script>
<?= $this->endSection() ?>
@@ -0,0 +1,110 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-2">
<h3 class="mb-0">School Winners</h3>
<div class="d-flex gap-2">
<a class="btn btn-outline-secondary" href="/admin/competition-winners/<?= $competition['id'] ?>/preview">Preview</a>
<a class="btn btn-outline-secondary" href="/admin/competition-winners">Back</a>
</div>
</div>
<div class="mb-3">
<div><strong>Competition:</strong> <?= esc($competition['title']) ?></div>
<div><strong>School Year:</strong> <?= esc($competition['school_year'] ?? '-') ?></div>
<div><strong>Published:</strong> <?= !empty($competition['is_published']) ? 'Yes' : 'No' ?></div>
</div>
<?php
$palette = [
['bg' => '#fde2c2', 'hover' => '#f8c996'],
['bg' => '#cfe6ff', 'hover' => '#b5d6ff'],
['bg' => '#c9f2e7', 'hover' => '#a6e6d4'],
['bg' => '#f7c8c7', 'hover' => '#f1a6a3'],
['bg' => '#fff1a8', 'hover' => '#ffe38a'],
['bg' => '#e4c7f2', 'hover' => '#d1a9e8'],
['bg' => '#d6d9de', 'hover' => '#c2c8cf'],
['bg' => '#c9efc5', 'hover' => '#aee3a9'],
];
$paletteCount = count($palette);
?>
<style>
<?php foreach ($palette as $index => $colors): ?>
.class-color-<?= $index ?> td { background-color: <?= $colors['bg'] ?>; }
.class-color-<?= $index ?>:hover td { background-color: <?= $colors['hover'] ?>; }
<?php endforeach; ?>
</style>
<?php if (empty($rows)): ?>
<div class="alert alert-warning">No published winners yet. Publish winners to see the list.</div>
<?php else: ?>
<table class="table table-bordered table-sm" data-no-mgmt-sticky>
<thead class="table-light">
<tr>
<th>Class</th>
<th>School ID</th>
<th>Student</th>
<th>Photo Consent</th>
<th>Rank</th>
<th>Score</th>
<th>Prize</th>
</tr>
</thead>
<tbody>
<?php $totalPrize = 0.0; ?>
<?php foreach ($rows as $row): ?>
<?php
$classId = (int) ($row['class_section_id'] ?? 0);
$classLabel = $row['class_section_name'] ?? ($classMap[$classId] ?? ('Class ' . $classId));
$name = trim(($row['firstname'] ?? '') . ' ' . ($row['lastname'] ?? ''));
$studentLabel = $name !== '' ? $name : ('Student #' . ($row['student_id'] ?? ''));
$colorIndex = $paletteCount > 0 ? ($classId % $paletteCount) : 0;
$questionCount = $questionCounts[$classId] ?? null;
$scoreValue = $row['score'] ?? null;
$scoreLabel = '-';
$prizeValue = null;
$photoConsentLabel = '-';
if (array_key_exists('photo_consent', $row)) {
$photoConsentLabel = ((int) $row['photo_consent'] === 1) ? 'Yes' : 'No';
}
if (isset($row['prize_amount']) && $row['prize_amount'] !== '' && is_numeric($row['prize_amount'])) {
$prizeValue = (float) $row['prize_amount'];
$totalPrize += $prizeValue;
}
if ($scoreValue !== null && $scoreValue !== '' && is_numeric($scoreValue)) {
$scoreDisplay = number_format((float) $scoreValue, 0, '.', '');
$scoreLabel = $scoreDisplay;
if ($questionCount !== null) {
$scoreLabel = $scoreDisplay . '/' . $questionCount;
}
}
?>
<tr class="class-color-<?= esc((string) $colorIndex) ?>">
<td><?= esc($classLabel) ?></td>
<td><?= esc($row['school_id'] ?? $row['student_id'] ?? '-') ?></td>
<td><?= esc($studentLabel) ?></td>
<td><?= esc($photoConsentLabel) ?></td>
<td><?= esc($row['rank'] ?? '-') ?></td>
<td><?= esc($scoreLabel) ?></td>
<td><?= esc($prizeValue !== null ? $prizeValue : '-') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<th colspan="6" class="text-end">Total Prizes</th>
<th><?= esc(number_format($totalPrize, 2, '.', '')) ?></th>
</tr>
</tfoot>
</table>
<div class="d-flex justify-content-end mt-3">
<a class="btn btn-primary external-link" href="/admin/competition-winners/<?= $competition['id'] ?>/recognition-pdf" target="_blank" rel="noopener">
Generate Recognition PDF
</a>
</div>
<?php endif; ?>
</div>
<?= $this->endSection() ?>
+145
View File
@@ -0,0 +1,145 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container-fluid py-4">
<style>
.admin-score-table { margin-top: 4px; }
.admin-score-table thead th { position: static; }
</style>
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-3">
<div>
<h2 class="mb-0">Student Score Card (Admin)</h2>
<div class="text-muted small">Search for a student, then open their score card.</div>
</div>
</div>
<div class="card shadow-sm mb-3">
<div class="card-body">
<form id="studentSearchForm" method="get" action="<?= site_url('administrator/student-score-card') ?>">
<div class="row g-2 justify-content-center">
<div class="col-12 col-md-8 col-lg-6">
<div class="input-group">
<span class="input-group-text">Search Student</span>
<input id="globalStudentSearch"
class="form-control"
type="text"
name="q"
placeholder="Type School ID or Student Name"
list="studentSuggestions"
autocomplete="off"
value="<?= esc($query ?? '') ?>" />
<button id="globalStudentSearchClear" class="btn btn-outline-secondary" type="button" title="Clear search">Clear</button>
</div>
<small class="text-muted">Searches all grades.</small>
</div>
</div>
<button type="submit" class="d-none">Search</button>
</form>
</div>
</div>
<datalist id="studentSuggestions">
<?php
$seen = [];
foreach (($suggestions ?? []) as $stu):
$sid = (int)($stu['id'] ?? 0);
if ($sid <= 0) continue;
$schoolId = trim((string)($stu['school_id'] ?? ''));
$label = trim(($stu['firstname'] ?? '') . ' ' . ($stu['lastname'] ?? ''));
$value = trim(($schoolId !== '' ? $schoolId . ' - ' : '') . $label);
if ($value === '' || isset($seen[$value])) continue;
$seen[$value] = true;
?>
<option value="<?= esc($value) ?>"></option>
<?php endforeach; ?>
</datalist>
<?php if (!empty($query) && empty($students)): ?>
<div class="alert alert-warning">No students found.</div>
<?php endif; ?>
<?php if (!empty($students)): ?>
<div class="card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<strong>Results</strong>
<span class="text-muted small">Showing up to 50</span>
</div>
<div class="card-body table-responsive pt-2">
<table class="table table-striped table-hover align-middle admin-score-table no-mgmt-sticky" data-no-mgmt-sticky="1">
<thead class="table-light">
<tr>
<th>School ID</th>
<th>Student</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($students as $s): ?>
<tr>
<td><?= esc($s['school_id'] ?? '') ?></td>
<td><?= esc(($s['firstname'] ?? '') . ' ' . ($s['lastname'] ?? '')) ?></td>
<td>
<?php if ((int)($s['is_active'] ?? 0) === 1): ?>
<span class="badge text-bg-success">Active</span>
<?php else: ?>
<span class="badge text-bg-secondary">Inactive</span>
<?php endif; ?>
</td>
<td class="text-end">
<form method="post" action="<?= site_url('student/score-card') ?>" class="d-inline">
<?= csrf_field() ?>
<input type="hidden" name="student_id" value="<?= (int)($s['id'] ?? 0) ?>">
<button type="submit" class="btn btn-sm btn-outline-primary">Open Score Card</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
</div>
<script>
(function () {
const form = document.getElementById('studentSearchForm');
const input = document.getElementById('globalStudentSearch');
const clr = document.getElementById('globalStudentSearchClear');
const dlist = document.getElementById('studentSuggestions');
const suggestionSet = new Set(Array.from(dlist?.options || []).map(o => (o.value || '').trim()));
let lastAutoQuery = '';
function submitSearch() {
if (!form) return;
form.submit();
}
input?.addEventListener('keydown', e => {
if (e.key === 'Enter') { e.preventDefault(); submitSearch(); }
});
clr?.addEventListener('click', () => {
if (input) input.value = '';
input?.focus();
});
function tryAutoRun() {
const val = (input?.value || '').trim();
if (!val) return;
if (suggestionSet.has(val) && val !== lastAutoQuery) {
lastAutoQuery = val;
submitSearch();
}
}
input?.addEventListener('change', tryAutoRun);
input?.addEventListener('input', () => {
clearTimeout(input.__autoTimer);
input.__autoTimer = setTimeout(tryAutoRun, 50);
});
})();
</script>
<?= $this->endSection() ?>