recreate project
This commit is contained in:
@@ -0,0 +1,331 @@
|
||||
<?= $this->extend('layout/main_layout') ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
<div class="container-xxl py-5">
|
||||
<div class="container">
|
||||
<div class="text-center mx-auto mb-5" style="max-width:600px;">
|
||||
<h4 class="text-dark" style="font-family:Arial,sans-serif;">Class Attendance</h4>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$canEdit = isset($canEdit) ? (bool)$canEdit : false;
|
||||
$sundayDates = isset($sunday_dates) && is_array($sunday_dates) ? array_values($sunday_dates) : [];
|
||||
$currentSunday = isset($current_sunday) ? (string)$current_sunday : '';
|
||||
if ($currentSunday === '' && count($sundayDates) > 0) {
|
||||
$currentSunday = $sundayDates[count($sundayDates) - 1];
|
||||
}
|
||||
$historyDates = array_slice($sundayDates, 0, max(0, count($sundayDates) - 1));
|
||||
$historyDates = array_pad($historyDates, 2, '');
|
||||
$no_school_days = isset($no_school_days) && is_array($no_school_days) ? $no_school_days : [];
|
||||
$isNoSchoolToday = $currentSunday !== '' && !empty($no_school_days[$currentSunday]);
|
||||
$canEditToday = $canEdit && !$isNoSchoolToday;
|
||||
$btnDisabledAttr = $canEditToday ? '' : ' disabled="disabled"';
|
||||
$lockedByStudent = isset($locked_by_student) && is_array($locked_by_student) ? $locked_by_student : [];
|
||||
// Derive a header label showing the actual recent dates (instead of generic text)
|
||||
$formatDateLabel = function ($value) {
|
||||
if (!$value) return '—';
|
||||
$value = (string)$value;
|
||||
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;
|
||||
}
|
||||
};
|
||||
$recentHeaderLabel = $currentSunday ? $formatDateLabel($currentSunday) : 'Last Sunday';
|
||||
// Teacher columns follow the computed Sunday dates (oldest → newest)
|
||||
$teacherDateColumns = $sundayDates;
|
||||
|
||||
// unified badge rendering
|
||||
function renderStatusBadge($status)
|
||||
{
|
||||
$status = strtolower(trim((string)$status));
|
||||
if ($status === 'present') return '<span class="badge bg-success">Present</span>';
|
||||
if ($status === 'late') return '<span class="badge bg-warning text-dark">Late</span>';
|
||||
if ($status === 'absent') return '<span class="badge bg-danger">Absent</span>';
|
||||
if ($status === 'no school') return '<span class="badge bg-info text-dark">No School</span>';
|
||||
return '';
|
||||
}
|
||||
|
||||
// blue tint for entire column
|
||||
$noSchoolClass = fn($date) => $date && !empty($no_school_days[$date]) ? ' style="background-color:#cff4fc;"' : '';
|
||||
?>
|
||||
|
||||
<?php if ($isNoSchoolToday): ?>
|
||||
<div class="alert alert-info text-center fw-bold" role="alert">
|
||||
Today is marked as <strong>No School</strong>. Attendance inputs are disabled.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="<?= site_url('/teacher/update_attendance') ?>" method="post" id="attendanceForm">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="class_section_id" value="<?= esc($class_section_id) ?>">
|
||||
<input type="hidden" name="class_id" value="<?= esc($class_id ?? '') ?>">
|
||||
|
||||
<!-- 🔹 TEACHER ATTENDANCE -->
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<div class="card-header bg-light"><strong>Teacher Attendance</strong></div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table id="teachersTable" class="table table-bordered table-striped m-0 align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="text-center" style="width:56px;">#</th>
|
||||
<th>Name</th>
|
||||
<th class="text-center" style="width:120px;">Role</th>
|
||||
<?php foreach ($teacherDateColumns as $d): ?>
|
||||
<th class="text-center" style="width:130px;"><?= esc($formatDateLabel($d)) ?></th>
|
||||
<?php endforeach; ?>
|
||||
<th class="text-center" style="width:160px;">Today</th>
|
||||
<th style="width:240px;">Reason</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (!empty($teachers)): ?>
|
||||
<?php $i=1; foreach($teachers as $t): $todayVal=strtolower($t['today']??''); ?>
|
||||
<tr>
|
||||
<td class="text-center"><?= $i++ ?></td>
|
||||
<td><?= esc($t['name']); ?></td>
|
||||
<td class="text-center"><?= esc($t['position']==='main'?'Main Teacher':'Teacher Assistant'); ?></td>
|
||||
|
||||
<!-- Past Sundays (aligned to computed dates) -->
|
||||
<?php foreach ($teacherDateColumns as $d): ?>
|
||||
<td class="text-center"<?= $noSchoolClass($d) ?>>
|
||||
<?php if ($d && !empty($no_school_days[$d])): ?>
|
||||
<?= renderStatusBadge('no school') ?>
|
||||
<?php else: ?>
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<?= renderStatusBadge($t['sunday_statuses'][$d] ?? '') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<!-- Today -->
|
||||
<td class="text-center"<?= $noSchoolClass($currentSunday) ?>>
|
||||
<?php if ($isNoSchoolToday): ?>
|
||||
<?= renderStatusBadge('no school') ?>
|
||||
<?php else: ?>
|
||||
<input type="hidden" name="teachers[<?= (int)$t['teacher_id'] ?>][teacher_id]" value="<?= (int)$t['teacher_id'] ?>">
|
||||
<input type="hidden" name="teachers[<?= (int)$t['teacher_id'] ?>][position]" value="<?= esc($t['position']) ?>">
|
||||
<select name="teachers[<?= (int)$t['teacher_id'] ?>][status]"
|
||||
<?= $canEditToday?'':'disabled' ?> data-required="1" <?= $canEditToday?'required':'' ?>
|
||||
style="font-size:.9rem; padding:2px 4px; width:120px;">
|
||||
<option value="" disabled <?= empty($t['today'])?'selected':'' ?>>Select</option>
|
||||
<option value="Present" <?= $todayVal==='present'?'selected':'' ?>>Present</option>
|
||||
<option value="Absent" <?= $todayVal==='absent'?'selected':'' ?>>Absent</option>
|
||||
<option value="Late" <?= $todayVal==='late'?'selected':'' ?>>Late</option>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type="text"
|
||||
name="teachers[<?= (int)$t['teacher_id'] ?>][reason]"
|
||||
placeholder="<?= $isNoSchoolToday?'No School':'Reason (if absent/late)' ?>"
|
||||
<?= $canEditToday?'':'disabled' ?>
|
||||
style="font-size:.9rem; padding:4px 6px; width:100%;">
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr><td colspan="8" class="text-center">No teachers assigned.</td></tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 🔹 STUDENT ATTENDANCE -->
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<div class="card-header bg-light"><strong>Students Attendance</strong></div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table id="studentsTable" class="table table-bordered table-striped m-0 align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="text-center">#</th>
|
||||
<th style="min-width:160px;">School ID</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<?php foreach ($historyDates as $d): ?>
|
||||
<th class="text-center"><?= esc($formatDateLabel($d)) ?></th>
|
||||
<?php endforeach; ?>
|
||||
<th class="text-center"><?= esc($recentHeaderLabel) ?></th>
|
||||
<th class="text-center">Today</th>
|
||||
<th>Reason</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (!empty($students)): ?>
|
||||
<?php $n=1; foreach($students as $a): ?>
|
||||
<?php
|
||||
$studentId = (int)($a['student']['id'] ?? 0);
|
||||
$lockInfo = $lockedByStudent[$studentId] ?? ['locked'=>false,'source'=>null,'reason'=>null,'status'=>$a['today'] ?? null];
|
||||
$isLocked = !empty($lockInfo['locked']);
|
||||
$lockSource = $lockInfo['source'] ?? '';
|
||||
$lockLabel = $lockSource === 'parent' ? 'Parent submitted' : ($lockSource === 'admin' ? 'Admin submitted' : 'Locked');
|
||||
$todayStatus = $lockInfo['status'] ?? ($a['today'] ?? null);
|
||||
?>
|
||||
<tr>
|
||||
<input type="hidden" name="attendance[<?= (int)$a['student']['id'] ?>][school_id]" value="<?= esc($a['student']['school_id']) ?>">
|
||||
<input type="hidden" name="attendance[<?= (int)$a['student']['id'] ?>][student_id]" value="<?= (int)$a['student']['id'] ?>">
|
||||
<td class="text-center"><?= $n++ ?></td>
|
||||
<td style="min-width:160px;"><?= esc($a['student']['school_id']); ?></td>
|
||||
<td><?= esc($a['student']['firstname']); ?></td>
|
||||
<td><?= esc($a['student']['lastname']); ?></td>
|
||||
|
||||
<?php foreach ($historyDates as $d): ?>
|
||||
<td class="text-center"<?= $noSchoolClass($d) ?>>
|
||||
<?php if (!empty($no_school_days[$d])): ?>
|
||||
<?= renderStatusBadge('no school') ?>
|
||||
<?php else: ?>
|
||||
<?= renderStatusBadge($a['sunday_statuses'][$d] ?? '') ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<td class="text-center">
|
||||
<?php
|
||||
$currentStatus = $a['sunday_statuses'][$currentSunday] ?? '';
|
||||
$normalizedStatus = strtolower(trim((string)$currentStatus));
|
||||
?>
|
||||
<?php if ($normalizedStatus === '' || $normalizedStatus === 'n/a'): ?>
|
||||
<span class="text-muted small">No data</span>
|
||||
<?php else: ?>
|
||||
<div class="d-flex flex-column gap-1 align-items-start align-items-md-center">
|
||||
<span class="d-flex gap-2 align-items-center">
|
||||
<?= renderStatusBadge($currentStatus) ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
|
||||
<td class="text-center"<?= $noSchoolClass($currentSunday) ?>>
|
||||
<?php if ($isNoSchoolToday): ?>
|
||||
<?= renderStatusBadge('no school') ?>
|
||||
<?php elseif ($isLocked): ?>
|
||||
<input type="hidden" name="attendance[<?= (int)$a['student']['id'] ?>][status]" value="<?= esc(ucfirst(strtolower((string)$todayStatus))) ?>">
|
||||
<div class="d-flex flex-column align-items-center gap-1">
|
||||
<?= renderStatusBadge($todayStatus ?? '') ?>
|
||||
<span class="badge bg-secondary" title="This attendance was submitted externally and cannot be edited.">
|
||||
<?= esc($lockLabel) ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<select name="attendance[<?= (int)$a['student']['id'] ?>][status]"
|
||||
<?= $canEditToday?'':'disabled' ?> data-required="1" <?= $canEditToday?'required':'' ?>
|
||||
style="font-size:.875rem; padding:2px 4px; width:110px;">
|
||||
<option value="" disabled <?= empty($a['today'])?'selected':'' ?>>Select</option>
|
||||
<option value="Present" <?= (strtolower($a['today']??'')==='present')?'selected':'' ?>>Present</option>
|
||||
<option value="Absent" <?= (strtolower($a['today']??'')==='absent')?'selected':'' ?>>Absent</option>
|
||||
<option value="Late" <?= (strtolower($a['today']??'')==='late')?'selected':'' ?>>Late</option>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<?php if ($isLocked): ?>
|
||||
<input type="hidden" name="attendance[<?= (int)$a['student']['id'] ?>][reason]" value="<?= esc($lockInfo['reason'] ?? '') ?>">
|
||||
<div class="text-muted small">
|
||||
<?= esc($lockInfo['reason'] ?? 'Submitted externally.') ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<input type="text"
|
||||
name="attendance[<?= (int)$a['student']['id'] ?>][reason]"
|
||||
placeholder="<?= $isNoSchoolToday?'No School':'Reason if absent/late' ?>"
|
||||
<?= $canEditToday?'':'disabled' ?>
|
||||
style="font-size:.875rem; padding:4px 6px; width:100%;">
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr><td colspan="8" class="text-center">No students found</td></tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-center mt-4 mb-4">
|
||||
<button type="submit" class="btn btn-success btn-lg px-5 shadow" id="submitAttendanceBtn" <?= $btnDisabledAttr ?>>
|
||||
Submit Attendance
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Confirmation Modal -->
|
||||
<div class="modal fade" id="confirmSubmitModal" tabindex="-1" aria-labelledby="confirmSubmitLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-info text-dark">
|
||||
<h5 class="modal-title" id="confirmSubmitLabel">Confirm Submission</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Are you sure you want to submit?<br><strong>Once submitted you cannot make changes.</strong>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" id="cancelSubmitBtn" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-success" id="confirmSubmitBtn">Yes, Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('scripts') ?>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded",()=>{
|
||||
const form=document.getElementById("attendanceForm");
|
||||
const submitBtn=document.getElementById("submitAttendanceBtn");
|
||||
const modal=new bootstrap.Modal(document.getElementById("confirmSubmitModal"));
|
||||
const confirmBtn=document.getElementById("confirmSubmitBtn");
|
||||
const cancelBtn=document.getElementById("cancelSubmitBtn");
|
||||
const isNoSchoolToday=<?= $isNoSchoolToday?'true':'false' ?>;
|
||||
|
||||
function allRequiredFilled(){
|
||||
const selects=form.querySelectorAll('select[data-required="1"]:not([disabled])');
|
||||
for(const s of selects){if(!s.value){s.classList.add('is-invalid');s.focus();return false;}s.classList.remove('is-invalid');}
|
||||
return true;
|
||||
}
|
||||
|
||||
form.addEventListener("submit",e=>{
|
||||
e.preventDefault();
|
||||
if(isNoSchoolToday){alert("Today is marked as No School. Attendance submission is disabled.");return;}
|
||||
if(!allRequiredFilled()){alert("Please fill all required fields.");return;}
|
||||
setTimeout(()=>cancelBtn.focus(),150);
|
||||
modal.show();
|
||||
});
|
||||
|
||||
confirmBtn.addEventListener("click",()=>{
|
||||
confirmBtn.disabled=true;
|
||||
submitBtn.disabled=true;
|
||||
modal.hide();
|
||||
form.submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$(function(){
|
||||
$('#teachersTable').DataTable({
|
||||
pageLength:100,
|
||||
order:[],
|
||||
columnDefs:[{targets:[0,3,4,5,6],className:'text-center'}]
|
||||
});
|
||||
$('#studentsTable').DataTable({
|
||||
pageLength:100,
|
||||
order:[],
|
||||
columnDefs:[{targets:[0,4,5,6,7],className:'text-center'}]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
Reference in New Issue
Block a user