214 lines
8.3 KiB
PHP
214 lines
8.3 KiB
PHP
<?= $this->extend('layout/management_layout') ?>
|
||
<?= $this->section('content') ?>
|
||
<div class="container my-4">
|
||
<h2 class="mb-3">Family Communications</h2>
|
||
<?= view('partials/flash_messages') ?>
|
||
|
||
<?php
|
||
$prefillStudentId = isset($_GET['student_id']) ? (int)$_GET['student_id'] : 0;
|
||
$prefillTemplate = isset($_GET['template_key']) ? trim((string)$_GET['template_key']) : '';
|
||
?>
|
||
<div class="card">
|
||
<div class="card-header">Compose</div>
|
||
<div class="card-body">
|
||
<form id="comm-form" method="post" action="<?= site_url('communications/send') ?>">
|
||
<?= csrf_field() ?>
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label class="form-label">Student</label>
|
||
<select class="form-select" id="student_id" name="student_id" required>
|
||
<option value="">Select…</option>
|
||
<?php foreach ($students as $st): ?>
|
||
<?php $sid = (int)($st['id'] ?? 0); ?>
|
||
<option value="<?= esc($sid) ?>" <?= ($prefillStudentId === $sid ? 'selected' : '') ?>>
|
||
<?= esc(($st['lastname'] ?? '').', '.($st['firstname'] ?? '')) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label">Family (if multiple)</label>
|
||
<select class="form-select" id="family_id" name="family_id" required>
|
||
<option value="">Select a student first…</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label">Subject Category</label>
|
||
<select class="form-select" id="template_key" name="template_key" required>
|
||
<option value="">Select…</option>
|
||
<?php foreach ($templates as $t): ?>
|
||
<?php
|
||
$tkey = (string)($t['template_key'] ?? '');
|
||
$tname = (string)($t['name'] ?? '');
|
||
$label = $tname !== '' ? $tname : $tkey;
|
||
?>
|
||
<option value="<?= esc($tkey) ?>" <?= ($prefillTemplate !== '' && $prefillTemplate === $tkey ? 'selected' : '') ?>>
|
||
<?= esc($label) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mt-3">
|
||
<label class="form-label">Recipients (Guardians)</label>
|
||
<div id="recipientPills" class="d-flex flex-wrap gap-2"></div>
|
||
</div>
|
||
|
||
<hr/>
|
||
<div class="row g-3">
|
||
<div class="col-md-8">
|
||
<label class="form-label">Email Subject</label>
|
||
<input type="text" class="form-control" id="subject" name="subject" required>
|
||
</div>
|
||
<div class="col-md-4 d-flex align-items-end">
|
||
<button type="button" id="btnPreview" class="btn btn-outline-secondary ms-auto">Refresh Preview</button>
|
||
</div>
|
||
<div class="col-12">
|
||
<label class="form-label">Email Body (editable)</label>
|
||
<textarea class="form-control" id="body" name="body" rows="10" required></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<input type="hidden" name="recipients" id="recipients_json">
|
||
<input type="hidden" name="cc" id="cc_json">
|
||
<input type="hidden" name="bcc" id="bcc_json">
|
||
|
||
<div class="mt-3 d-flex gap-2">
|
||
<button type="submit" class="btn btn-primary">Send</button>
|
||
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#previewModal">Preview</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Preview Modal -->
|
||
<div class="modal fade" id="previewModal" tabindex="-1">
|
||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title">Email Preview</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<h6 id="pvSubject" class="mb-3"></h6>
|
||
<div id="pvBody"></div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?= $this->endSection() ?>
|
||
|
||
<?= $this->section('scripts') ?>
|
||
<script>
|
||
(function(){
|
||
const $student = document.getElementById('student_id');
|
||
const $family = document.getElementById('family_id');
|
||
const $template = document.getElementById('template_key');
|
||
const $recipientPills = document.getElementById('recipientPills');
|
||
const $subject = document.getElementById('subject');
|
||
const $body = document.getElementById('body');
|
||
const $recipientsJson = document.getElementById('recipients_json');
|
||
|
||
let recipients = [];
|
||
|
||
function renderRecipients(){
|
||
$recipientPills.innerHTML = '';
|
||
recipients.forEach((em, idx) => {
|
||
const span = document.createElement('span');
|
||
span.className = 'badge bg-light text-dark border';
|
||
span.innerHTML = em + ' <button data-i="'+idx+'" type="button" class="btn btn-sm btn-link p-0 ms-1">×</button>';
|
||
$recipientPills.appendChild(span);
|
||
});
|
||
$recipientsJson.value = JSON.stringify(recipients);
|
||
}
|
||
|
||
$recipientPills.addEventListener('click', (e)=>{
|
||
if (e.target.tagName === 'BUTTON') {
|
||
recipients.splice(parseInt(e.target.getAttribute('data-i')),1);
|
||
renderRecipients();
|
||
}
|
||
});
|
||
|
||
async function loadFamilies(studentId){
|
||
$family.innerHTML = '<option value="">Loading…</option>';
|
||
recipients = []; renderRecipients();
|
||
if(!studentId){ $family.innerHTML = '<option value="">Select a student first…</option>'; return; }
|
||
const res = await fetch('<?= site_url('api/students') ?>/'+studentId+'/families');
|
||
const data = await res.json();
|
||
const list = data.data || [];
|
||
if (!list.length){ $family.innerHTML = '<option value="">No families found</option>'; return; }
|
||
let html = '';
|
||
list.forEach(f => {
|
||
const name = f.household_name || ('Family #' + f.id);
|
||
html += `<option value="${f.id}">${name}${f.is_primary_home ? ' (primary)' : ''}</option>`;
|
||
});
|
||
$family.innerHTML = '<option value="">Select…</option>' + html;
|
||
// Auto-select the first (primary) family
|
||
$family.selectedIndex = 1;
|
||
loadGuardians($family.value);
|
||
}
|
||
|
||
async function loadGuardians(familyId){
|
||
recipients = []; renderRecipients();
|
||
if(!familyId) return;
|
||
const res = await fetch('<?= site_url('api/families') ?>/'+familyId+'/guardians');
|
||
const data = await res.json();
|
||
(data.data || []).forEach(g => { if (g.receive_emails && g.email) recipients.push(g.email); });
|
||
recipients = Array.from(new Set(recipients));
|
||
renderRecipients();
|
||
}
|
||
|
||
async function refreshPreview(){
|
||
const student_id = $student.value;
|
||
const family_id = $family.value;
|
||
const template_key = $template.value;
|
||
if (!student_id || !family_id || !template_key) return;
|
||
|
||
const vars = {
|
||
school_name: 'Al Rahma Sunday School',
|
||
teacher_name: '<?= esc(session('display_name') ?? 'Teacher') ?>',
|
||
class_section: '',
|
||
student_grade: '',
|
||
attendance_message: '',
|
||
assessment_name: '',
|
||
score_obtained: '',
|
||
score_total: '',
|
||
teacher_comments: '',
|
||
behavior_summary: '',
|
||
actions_taken: '',
|
||
next_steps: ''
|
||
};
|
||
|
||
const form = new FormData();
|
||
form.append('<?= csrf_token() ?>', '<?= csrf_hash() ?>');
|
||
form.append('student_id', student_id);
|
||
form.append('family_id', family_id);
|
||
form.append('template_key', template_key);
|
||
form.append('vars', JSON.stringify(vars));
|
||
|
||
const res = await fetch('<?= site_url('communications/preview') ?>', { method: 'POST', body: form });
|
||
const data = await res.json();
|
||
|
||
if (data.subject) $subject.value = data.subject;
|
||
if (data.html) $body.value = data.html.replace(/<br\s*\/?>/g, "\n");
|
||
|
||
document.getElementById('pvSubject').textContent = $subject.value;
|
||
document.getElementById('pvBody').innerHTML = data.html || '';
|
||
}
|
||
|
||
document.getElementById('btnPreview').addEventListener('click', refreshPreview);
|
||
$student.addEventListener('change', e => loadFamilies(e.target.value));
|
||
$family.addEventListener('change', e => loadGuardians(e.target.value));
|
||
$template.addEventListener('change', refreshPreview);
|
||
|
||
// Init
|
||
if ($student.value) loadFamilies($student.value);
|
||
})();
|
||
</script>
|
||
<?= $this->endSection() ?>
|