Files
alrahma_sunday_school/app/Views/partials/attendance_notification_modal.php
T
2026-02-10 22:11:06 -05:00

209 lines
7.6 KiB
PHP

<!-- app/Views/partials/attendance_notification_modal.php -->
<div class="modal fade" id="notificationModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form id="notificationForm">
<?= csrf_field() ?>
<input type="hidden" id="modalStudentId" name="student_id" value="">
<input type="hidden" id="modalDate" name="date" value="<?= esc(local_date(utc_now(), 'Y-m-d')) ?>">
<div class="modal-header">
<h5 class="modal-title">Notify Parent</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- Recipient (editable) -->
<div class="mb-3">
<label class="form-label">To (Parent Email)</label>
<input type="email"
class="form-control"
id="parentEmail"
name="to"
required
autocomplete="email"
placeholder="parent@example.com"
list="parentEmailOptions">
<datalist id="parentEmailOptions"></datalist>
<div class="form-text" id="parentNameHelp"></div>
</div>
<!-- Subject Type -->
<div class="row g-3">
<div class="col-md-5">
<label class="form-label">Subject Type</label>
<select class="form-select" id="subjectType" name="subject_type" required>
<option value="Absent">Absent Notice</option>
<option value="Late">Late/Tardy Notice</option>
<option value="General">General Attendance Message</option>
</select>
</div>
<div class="col-md-7">
<label class="form-label">Subject</label>
<input type="text" class="form-control" id="notifySubject" name="subject" required>
</div>
</div>
<!-- Message -->
<div class="mt-3">
<label class="form-label">Message</label>
<textarea class="form-control" id="notifyMessage" name="message" rows="8" required></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" id="sendNotification" class="btn btn-primary">Send Notification</button>
</div>
</form>
</div>
</div>
</div>
<script>
// Templates in the partial for reuse
const formatNoticeDate = (value) => {
if (!value) return '';
const date = new Date(String(value).replace(' ', 'T'));
if (Number.isNaN(date.valueOf())) return String(value);
const pad = (num) => String(num).padStart(2, '0');
return `${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${date.getFullYear()}`;
};
const SUBJECT_TEMPLATES = {
Absent: (p) => {
const name = p.student_name || 'your child';
const date = p.date_fmt || formatNoticeDate(p.date) || '';
const cls = p.class_section_name ? ` (${p.class_section_name})` : '';
const reason = p.reason ? ` Reason: ${p.reason}.` : '';
const teacher = p.teacher_name ? `\nTeacher: ${p.teacher_name}` : '';
const school = p.school_name || 'Our School';
return `Dear Parent/Guardian,
This is to inform you that ${name}${cls} was marked Absent on ${date}.${reason}
If this was an error or there is additional context you would like to share, please reply to this email.
Thank you,
${school}${teacher}
`;
},
Late: (p) => {
const name = p.student_name || 'your child';
const date = p.date_fmt || formatNoticeDate(p.date) || '';
const cls = p.class_section_name ? ` (${p.class_section_name})` : '';
const reason = p.reason ? ` Reason: ${p.reason}.` : '';
const teacher = p.teacher_name ? `\nTeacher: ${p.teacher_name}` : '';
const school = p.school_name || 'Our School';
return `Dear Parent/Guardian,
This is to notify you that ${name}${cls} was marked Late on ${date}.${reason}
Please help ensure timely arrival. If you have questions, reply to this email.
Thank you,
${school}${teacher}
`;
},
General: (p) => {
const name = p.student_name || 'your child';
const date = p.date_fmt || formatNoticeDate(p.date) || '';
const cls = p.class_section_name ? ` (${p.class_section_name})` : '';
const teacher = p.teacher_name ? `\nTeacher: ${p.teacher_name}` : '';
const school = p.school_name || 'Our School';
return `Dear Parent/Guardian,
We are reaching out regarding ${name}${cls} on ${date}. Please see attendance details in the subject line.
If you have any questions, reply to this email.
Thank you,
${school}${teacher}
`;
}
};
window.buildSubject = function(subjectType, p) {
const base = p.student_name ? ` — ${p.student_name}` : '';
const dateLabel = p.date_fmt || formatNoticeDate(p.date);
const date = dateLabel ? ` (${dateLabel})` : '';
if (subjectType === 'Absent') return `Attendance Notice: Absent${base}${date}`;
if (subjectType === 'Late') return `Attendance Notice: Late${base}${date}`;
return `Attendance Notice${base}${date}`;
};
window.buildMessage = function(subjectType, payload) {
const fn = SUBJECT_TEMPLATES[subjectType] || SUBJECT_TEMPLATES.General;
return fn(payload);
};
</script>
<script>
(function () {
// Delegate so it always works, even if the modal is re-rendered
document.addEventListener('click', async function (e) {
if (!e.target || e.target.id !== 'sendNotification') return;
const form = document.getElementById('notificationForm');
if (!form) { console.error('notificationForm not found'); return; }
const toEl = document.getElementById('parentEmail');
const subjEl = document.getElementById('notifySubject');
const msgEl = document.getElementById('notifyMessage');
if (!toEl || !subjEl || !msgEl) {
console.error('Missing email/subject/message fields in the modal.');
alert('Missing fields in the modal.');
return;
}
// Basic front-end validation
if (!toEl.value.trim()) { alert('Please enter parent email'); return; }
if (!subjEl.value.trim()) { alert('Please enter a subject'); return; }
if (!msgEl.value.trim()) { alert('Please enter a message'); return; }
const formData = new FormData(form);
try {
const resp = await fetch('<?= base_url('attendance/notify_parent') ?>', {
method: 'POST',
body: formData,
headers: { 'Accept': 'application/json' }
});
// If server crashed and returned HTML, this will throw:
let data;
try { data = await resp.json(); }
catch (jsonErr) {
const text = await resp.text();
console.error('Non-JSON response', text);
alert('Server error (non-JSON). Check logs.');
return;
}
if (!resp.ok || !data || !data.success) {
console.error('Notify failed', data);
alert('Failed to send: ' + (data && data.message ? data.message : 'Unknown error'));
return;
}
alert('Notification sent successfully');
const modalEl = document.getElementById('notificationModal');
if (modalEl) {
const inst = bootstrap.Modal.getInstance(modalEl) || new bootstrap.Modal(modalEl);
inst.hide();
}
// If CSRF rotates, update hidden input
if (data.csrf) {
const [name, value] = Object.entries(data.csrf)[0];
const tokenInput = form.querySelector('input[name="'+name+'"]');
if (tokenInput) tokenInput.value = value;
}
} catch (err) {
console.error('Fetch error', err);
alert('Network or server error. See console for details.');
}
});
})();
</script>