AVP-78 Feature to check if parents looked at report card
This commit is contained in:
@@ -48,6 +48,7 @@
|
||||
<a id="downloadStudentBtn" href="#" class="btn btn-success external-link" target="_blank">Download</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-muted small text-center" id="ackStatus"></div>
|
||||
</form>
|
||||
|
||||
<div class="card shadow-sm mb-3">
|
||||
@@ -67,10 +68,12 @@
|
||||
<table class="table table-sm table-bordered align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th style="width: 35%;">Student</th>
|
||||
<th style="width: 28%;">Student</th>
|
||||
<th style="width: 15%;">Status</th>
|
||||
<th>Missing</th>
|
||||
<th>Warnings</th>
|
||||
<th style="width: 16%;">Viewed</th>
|
||||
<th style="width: 16%;">Signed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="completenessBody"></tbody>
|
||||
@@ -91,6 +94,7 @@
|
||||
document.addEventListener('DOMContentLoaded', function(){
|
||||
const API = <?= json_encode(site_url('api/printables/report-card/meta')) ?>;
|
||||
const COMPLETENESS_API = <?= json_encode(site_url('api/printables/report-card/completeness')) ?>;
|
||||
const ACK_API = <?= json_encode(site_url('api/printables/report-card/ack')) ?>;
|
||||
|
||||
// add cache-busting cb param
|
||||
const withCB = (u) => u + (u.includes('?') ? '&' : '?') + 'cb=' + Date.now();
|
||||
@@ -119,6 +123,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||
const $completenessSummary = document.getElementById('completenessSummary');
|
||||
const $completenessWrap = document.getElementById('completenessTableWrap');
|
||||
const $completenessBody = document.getElementById('completenessBody');
|
||||
const $ackStatus = document.getElementById('ackStatus');
|
||||
|
||||
function opt(el, val, label) {
|
||||
const o = document.createElement('option'); o.value = String(val); o.textContent = label; el.appendChild(o);
|
||||
@@ -157,10 +162,40 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||
// Classes
|
||||
$class.innerHTML = '';
|
||||
(data.classSections || []).forEach(c => opt($class, c.class_section_id || c.id, c.class_section_name));
|
||||
|
||||
updateAckStatus();
|
||||
}
|
||||
|
||||
async function updateAckStatus() {
|
||||
if (! $ackStatus) return;
|
||||
const sid = $student.value;
|
||||
const y = $year.value || '';
|
||||
const s = $sem.value || '';
|
||||
if (!sid) {
|
||||
$ackStatus.textContent = '';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const url = `${ACK_API}?student_id=${encodeURIComponent(sid)}&school_year=${encodeURIComponent(y)}&semester=${encodeURIComponent(s)}`;
|
||||
const res = await fetch(url, { credentials: 'same-origin' });
|
||||
const data = await res.json();
|
||||
if (!res.ok || data?.ok === false) {
|
||||
$ackStatus.textContent = 'Parent acknowledgement: unavailable';
|
||||
return;
|
||||
}
|
||||
const viewed = data.viewed_at ? `Viewed: ${data.viewed_at}` : 'Viewed: not yet';
|
||||
const signed = data.signed_at
|
||||
? `Signed: ${data.signed_at} (${data.signed_name || 'name missing'})`
|
||||
: 'Signed: not yet';
|
||||
$ackStatus.textContent = `Parent acknowledgement — ${viewed} · ${signed}`;
|
||||
} catch (err) {
|
||||
$ackStatus.textContent = 'Parent acknowledgement: unavailable';
|
||||
}
|
||||
}
|
||||
|
||||
$year.addEventListener('change', function(){ loadMeta(this.value, $sem.value).catch(console.error); });
|
||||
$sem.addEventListener('change', function(){ loadMeta($year.value, this.value).catch(console.error); });
|
||||
$student.addEventListener('change', function(){ updateAckStatus(); });
|
||||
|
||||
$viewS.addEventListener('click', function(){
|
||||
const sid = $student.value; const y = $year.value; const s=$sem.value;
|
||||
@@ -254,10 +289,18 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||
tdMissing.textContent = missing.length ? missing.join(', ') : 'None';
|
||||
const tdWarnings = document.createElement('td');
|
||||
tdWarnings.textContent = warningsList.length ? warningsList.join(', ') : 'None';
|
||||
const tdViewed = document.createElement('td');
|
||||
tdViewed.textContent = row.viewed_at ? row.viewed_at : 'Not viewed';
|
||||
const tdSigned = document.createElement('td');
|
||||
tdSigned.textContent = row.signed_at
|
||||
? `${row.signed_at}${row.signed_name ? ` (${row.signed_name})` : ''}`
|
||||
: 'Not signed';
|
||||
tr.appendChild(tdName);
|
||||
tr.appendChild(tdStatus);
|
||||
tr.appendChild(tdMissing);
|
||||
tr.appendChild(tdWarnings);
|
||||
tr.appendChild(tdViewed);
|
||||
tr.appendChild(tdSigned);
|
||||
$completenessBody.appendChild(tr);
|
||||
});
|
||||
$completenessWrap.hidden = false;
|
||||
|
||||
Reference in New Issue
Block a user