Files
2026-04-11 20:08:47 -04:00

452 lines
21 KiB
PHP

<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container-fluid px-4 py-4 teacher-submissions-page">
<div class="card shadow-sm">
<div class="card-header bg-light d-flex justify-content-between align-items-center">
<div>
<strong>Teacher Submission Dashboard</strong>
</div>
<?php if (!empty($semester) || !empty($schoolYear)): ?>
<span class="small text-muted">
<?= esc(ucfirst($semester)) ?> <?= esc($schoolYear) ?>
</span>
<?php endif; ?>
</div>
<?php
$notificationHistory = $notificationHistory ?? [];
$summary = $summary ?? [];
$completionPercent = max(0, min(100, (int)($summary['submission_percentage'] ?? 0)));
$missingItemsCount = max(0, (int)($summary['missing_items'] ?? 0));
$submittedItems = max(0, (int)($summary['submitted_items'] ?? 0));
$totalItems = max(0, (int)($summary['total_items'] ?? 0));
?>
<div class="card-body">
<?php
$termExamLabel = (isset($semester) && strtolower((string) $semester) === 'spring') ? 'Final' : 'Midterm';
$lowProgressSectionIds = $lowProgressSectionIds ?? [];
$flaggedClasses = count($lowProgressSectionIds);
$pageNotifications = [];
if ($missingItemsCount > 0) {
$pageNotifications[] = [
'level' => 'danger',
'message' => "{$missingItemsCount} missing item" . ($missingItemsCount === 1 ? '' : 's') . " awaiting teacher uploads.",
];
}
if ($completionPercent < 70) {
$pageNotifications[] = [
'level' => 'warning',
'message' => "Submission completion is below 70% — follow up with remaining teachers.",
];
}
if ($flaggedClasses > 0) {
$pageNotifications[] = [
'level' => 'warning',
'message' => "Progress is under 50% for {$flaggedClasses} class section" . ($flaggedClasses === 1 ? '' : 's') . ".",
];
}
if (empty($rows)) {
$pageNotifications[] = [
'level' => 'info',
'message' => 'No class-section assignments submitted yet; encourage teachers to upload drafts.',
];
}
if (empty($pageNotifications)) {
$pageNotifications[] = [
'level' => 'info',
'message' => 'All tracked classes are current. Use the controls below to send reminders.',
];
}
$examDraftDeadlineConfig = $examDraftDeadlineConfig ?? '';
$examDraftDeadlineFormatted = $examDraftDeadlineFormatted ?? '';
?>
<?php if (session()->getFlashdata('success')): ?>
<div class="alert alert-success">
<?= esc(session()->getFlashdata('success')) ?>
</div>
<?php elseif (session()->getFlashdata('warning')): ?>
<div class="alert alert-warning">
<?= esc(session()->getFlashdata('warning')) ?>
</div>
<?php elseif (session()->getFlashdata('info')): ?>
<div class="alert alert-info">
<?= esc(session()->getFlashdata('info')) ?>
</div>
<?php endif; ?>
<?php
$groupedRows = [];
foreach ($rows as $idx => $row) {
$classKey = (string) ($row['class_section_id'] ?? $row['class_section'] ?? 'class_' . $idx);
$groupedRows[$classKey][] = $row;
}
?>
<div class="row g-3 mb-4 align-items-stretch">
<div class="col-lg-8">
<div class="row g-3 summary-row">
<div class="col-12 col-sm-6 col-xl-3">
<div class="summary-card h-100 shadow-sm border-0">
<div class="summary-card-body">
<div class="summary-label text-uppercase">Completion</div>
<div class="summary-value"><?= esc($completionPercent) ?>%</div>
<div class="progress summary-progress">
<div
class="progress-bar"
role="progressbar"
style="width: <?= esc($completionPercent) ?>%;"
aria-valuenow="<?= esc($completionPercent) ?>"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="summary-card h-100 shadow-sm border-0">
<div class="summary-card-body">
<div class="summary-label text-uppercase">Missing items</div>
<div class="summary-value <?= $missingItemsCount > 0 ? 'text-danger' : '' ?>"><?= esc($missingItemsCount) ?></div>
<div class="summary-note"><?= esc($submittedItems) ?> submitted / <?= esc($totalItems) ?> total</div>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="summary-card h-100 shadow-sm border-0">
<div class="summary-card-body">
<div class="summary-label text-uppercase">Submissions</div>
<div class="summary-value"><?= esc($submittedItems) ?></div>
<div class="summary-note"><?= esc($totalItems) ?> teachers tracked</div>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="summary-card h-100 shadow-sm border-0">
<div class="summary-card-body">
<div class="summary-label text-uppercase">Flagged</div>
<div class="summary-value"><?= esc($flaggedClasses) ?></div>
<div class="summary-note">Sections under 50% complete</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card page-notifications-card h-100 shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<span>Page notifications</span>
<span class="badge bg-light text-dark"><?= count($pageNotifications) ?> alerts</span>
</div>
<div class="card-body">
<ul class="page-notifications-list mb-0">
<?php foreach ($pageNotifications as $notification): ?>
<li class="page-notification-item page-notification-<?= esc($notification['level']) ?>">
<span class="notification-indicator" aria-hidden="true"></span>
<span><?= esc($notification['message']) ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
<form method="post" action="<?= site_url('administrator/teacher-submissions/notify') ?>">
<?= csrf_field() ?>
<?php if (empty($rows)): ?>
<p class="text-center text-muted mt-4">No teacher-class assignments found for this term.</p>
<?php else: ?>
<div class="table-control-bar mb-3 d-flex flex-wrap align-items-center gap-3">
<div class="d-flex flex-wrap align-items-center gap-3">
<label class="form-check form-check-inline mb-0">
<input class="form-check-input" type="checkbox" name="notify_midterm_score" value="1">
<span class="form-check-label small">Include <?= esc($termExamLabel) ?> score</span>
</label>
<label class="form-check form-check-inline mb-0">
<input class="form-check-input" type="checkbox" name="notify_midterm_comment" value="1">
<span class="form-check-label small">Include <?= esc($termExamLabel) ?> comment</span>
</label>
<label class="form-check form-check-inline mb-0">
<input class="form-check-input" type="checkbox" name="notify_participation" value="1">
<span class="form-check-label small">Include participation</span>
</label>
<label class="form-check form-check-inline mb-0">
<input class="form-check-input" type="checkbox" name="notify_ptap_comment" value="1">
<span class="form-check-label small">Include PTAP comment</span>
</label>
<label class="form-check form-check-inline mb-0">
<input class="form-check-input" type="checkbox" name="notify_class_progress" value="1">
<span class="form-check-label small">Include class progress</span>
</label>
<label class="form-check form-check-inline mb-0">
<input class="form-check-input" type="checkbox" name="notify_exam_draft" value="1">
<span class="form-check-label small">Include exam draft</span>
</label>
<label class="form-check form-check-inline mb-0">
<input class="form-check-input" type="checkbox" name="homework_notify_all" value="1">
<span class="form-check-label small">Include homework</span>
</label>
</div>
<div class="small text-muted">
<span class="text-uppercase" style="font-size:0.65rem;">Exam draft deadline</span><br>
<?php if ($examDraftDeadlineConfig !== ''): ?>
<?= esc($examDraftDeadlineConfig) ?>
<?php if ($examDraftDeadlineFormatted !== ''): ?>
<span class="text-muted"> → <?= esc($examDraftDeadlineFormatted) ?></span>
<?php endif; ?>
<?php else: ?>
<span class="text-warning">Not set</span>
<?php endif; ?>
</div>
</div>
<div class="accordion" id="teacherSubmissionAccordion">
<?php foreach ($groupedRows as $sectionKey => $sectionRows): ?>
<?php
$firstRow = $sectionRows[0] ?? [];
$sectionLabel = esc($firstRow['class_section'] ?? 'Class section');
$collapseId = 'teacherSectionCollapse_' . md5($sectionKey);
$badgeStatus = count($sectionRows) === 1 ? 'submission' : 'submissions';
?>
<div class="accordion-item">
<h2 class="accordion-header" id="heading_<?= esc($collapseId) ?>">
<button
class="accordion-button collapsed d-flex justify-content-between align-items-center"
type="button"
data-bs-toggle="collapse"
data-bs-target="#<?= esc($collapseId) ?>"
aria-expanded="false"
aria-controls="<?= esc($collapseId) ?>"
>
<div>
<strong><?= $sectionLabel ?></strong>
<div class="small text-muted"><?= esc(count($sectionRows)) ?> <?= $badgeStatus ?></div>
</div>
<span class="badge bg-primary-subtle text-primary"><?= count($sectionRows) ?> rows</span>
</button>
</h2>
<div id="<?= esc($collapseId) ?>" class="accordion-collapse collapse" aria-labelledby="heading_<?= esc($collapseId) ?>">
<div class="accordion-body p-0">
<div class="table-responsive">
<table
class="table table-striped table-bordered m-0 align-middle teacher-submissions-table mb-0"
data-no-mgmt-sticky
data-no-dt-fixedheader
>
<thead class="table-light">
<tr>
<th>Class-Section</th>
<th>Teachers Name</th>
<th class="text-center"><?= esc($termExamLabel) ?> Score</th>
<th class="text-center"><?= esc($termExamLabel) ?> Comment</th>
<th class="text-center">Participation</th>
<th class="text-center">PTAP Comment</th>
<th class="text-center">Class Progress</th>
<th class="text-center">Exam Draft</th>
<th class="text-center">Homework</th>
<th class="text-center">Notifications</th>
</tr>
</thead>
<tbody>
<?php foreach ($sectionRows as $row): ?>
<tr>
<td><?= esc($row['class_section']) ?></td>
<td>
<?php if (!empty($row['teachers'])): ?>
<?php foreach ($row['teachers'] as $teacher): ?>
<div><?= esc($teacher['label'] ?? 'Teacher') ?></div>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted small">Unassigned</span>
<?php endif; ?>
</td>
<?php foreach ([
'midterm_score_status',
'midterm_comment_status',
'participation_status',
'ptap_comment_status',
'class_progress_status',
'exam_draft_status',
] as $statusKey): ?>
<?php $status = $row[$statusKey] ?? ['label' => 'N/A', 'badge' => 'bg-secondary']; ?>
<td class="text-center">
<span class="badge <?= esc($status['badge'] ?? 'bg-secondary') ?>">
<?= esc($status['label'] ?? 'N/A') ?>
</span>
<?php if (!empty($status['detail'])): ?>
<div class="small text-muted"><?= esc($status['detail']) ?></div>
<?php endif; ?>
</td>
<?php endforeach; ?>
<?php $homeworkStatus = $row['homework_status'] ?? ['label' => 'N/A', 'badge' => 'bg-secondary']; ?>
<td class="text-center">
<span class="badge <?= esc($homeworkStatus['badge'] ?? 'bg-secondary') ?>">
<?= esc($homeworkStatus['label'] ?? 'N/A') ?>
</span>
<?php if (!empty($homeworkStatus['detail'])): ?>
<div class="small text-muted"><?= esc($homeworkStatus['detail']) ?></div>
<?php endif; ?>
</td>
<td>
<?php if (!empty($row['teachers'])): ?>
<?php $missingPayload = base64_encode(json_encode($row['missing_items'] ?? [])); ?>
<?php foreach ($row['teachers'] as $teacher): ?>
<?php $history = $notificationHistory[$row['class_section_id']][$teacher['id']] ?? []; ?>
<?php $lastEntry = $history[0] ?? null; ?>
<div class="mb-2">
<label class="d-flex align-items-center gap-2 mb-1">
<input
type="checkbox"
class="form-check-input"
name="notify[<?= esc($row['class_section_id']) ?>][<?= esc($teacher['id']) ?>]"
value="1"
/>
<span class="fw-semibold"><?= esc($teacher['label'] ?? 'Teacher') ?></span>
</label>
<input
type="hidden"
name="missing_items[<?= esc($row['class_section_id']) ?>][<?= esc($teacher['id']) ?>]"
value="<?= esc($missingPayload) ?>"
/>
<div class="small text-muted">
<?php if ($lastEntry !== null): ?>
<span>
Last <?= esc($lastEntry['status'] === 'sent' ? 'sent' : 'attempted') ?> on <?= esc($lastEntry['sent_at_text'] ?: 'N/A') ?>
by <?= esc($lastEntry['admin_name'] ?? '') ?>
</span>
<?php if (count($history) > 1): ?>
<div>History: <?= count($history) ?> entries</div>
<?php endif; ?>
<?php else: ?>
<span>No notifications sent yet</span>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted small">No teacher assigned</span>
<?php endif; ?>
<?php if (!empty($row['missing_items'])): ?>
<div class="small text-danger mt-1">
Outstanding: <?= esc(implode(', ', $row['missing_items'])) ?>
</div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="mt-3 text-end">
<button type="submit" class="btn btn-primary">
Send notifications to selected teachers
</button>
</div>
<?php endif; ?>
</form>
</div>
</div>
</div>
<?= $this->endSection() ?>
<?= $this->section('styles') ?>
<style>
.teacher-submissions-page {
width: 100%;
max-width: 100%;
}
.teacher-submissions-page .card {
width: 100%;
}
.teacher-submissions-page .table-responsive {
max-width: none;
}
.card-body .table-responsive table thead th {
position: static !important;
top: auto !important;
}
.card-body .table-responsive .teacher-submissions-table {
width: 100% !important;
min-width: 100%;
table-layout: auto;
}
.card-body .table-responsive .teacher-submissions-table th,
.card-body .table-responsive .teacher-submissions-table td {
white-space: normal;
}
.summary-card {
background: var(--bs-white);
border-radius: 0.75rem;
}
.summary-card-body {
padding: 1.25rem;
}
.summary-label {
font-size: 0.7rem;
letter-spacing: 0.08em;
color: #6c757d;
}
.summary-value {
font-size: 1.75rem;
font-weight: 600;
margin-top: 0.35rem;
}
.summary-note {
font-size: 0.85rem;
color: #6c757d;
}
.summary-progress {
height: 6px;
margin-top: 0.65rem;
}
.summary-progress .progress-bar {
background: var(--bs-primary);
}
.page-notifications-card {
border-radius: 0.75rem;
}
.page-notifications-list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.page-notification-item {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.85rem;
}
.page-notification-info .notification-indicator {
background: #0dcaf0;
}
.page-notification-warning .notification-indicator {
background: #ffc107;
}
.page-notification-danger .notification-indicator {
background: #dc3545;
}
.notification-indicator {
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
display: inline-block;
}
.table-control-bar {
border: 1px solid rgba(0,0,0,0.08);
border-radius: 0.75rem;
padding: 0.75rem 1rem;
background: #f8f9fa;
}
.table-control-bar .form-check-label {
font-size: 0.8rem;
margin-left: 0.15rem;
text-transform: none;
}
</style>
<?= $this->endSection() ?>