recreate project
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
<?= $this->extend('layout/management_layout') ?>
|
||||
<?= $this->section('content') ?>
|
||||
<style>
|
||||
/* Make the Parents multi-select significantly taller */
|
||||
#parentPicker .form-select[multiple] {
|
||||
height: clamp(420px, 65vh, 820px);
|
||||
/* min 420px, prefer 65% of viewport height, cap 820px */
|
||||
min-height: 420px;
|
||||
}
|
||||
|
||||
/* Slightly smaller option text helps fit more names on screen */
|
||||
#parentPicker .form-select[multiple] option {
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container my-4">
|
||||
<h2 class="mb-3">WhatsApp Group Links</h2>
|
||||
<?= view('partials/flash_messages') ?>
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
|
||||
<a href="<?= site_url('whatsapp/parent-contacts-by-class') ?>" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-people"></i> Parent Contacts by Class
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="row g-4">
|
||||
<!-- Left: Link per Class -->
|
||||
<div class="col-lg-7">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
Set / Update Links (<?= esc($schoolYear) ?><?= trim((string)$semester) !== '' ? ' - ' . esc($semester) : '' ?>)
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if (!empty($sections)): ?>
|
||||
<?php foreach ($sections as $sec):
|
||||
$sid = (int)($sec['class_section_id'] ?? $sec['id']);
|
||||
$sname = $sec['class_section_name'] ?? ($sec['name'] ?? ('Section ' . $sid));
|
||||
$existing = $linksBySection[$sid] ?? null;
|
||||
?>
|
||||
<form class="row gy-2 align-items-end border-bottom pb-3 mb-3"
|
||||
method="post"
|
||||
action="<?= site_url('whatsapp/saveLink') ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="class_section_id" value="<?= esc($sid) ?>">
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label">Class / Section</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="class_section_name"
|
||||
value="<?= esc($sname) ?>"
|
||||
readonly>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label">Invite Link</label>
|
||||
<input type="url"
|
||||
class="form-control"
|
||||
name="invite_link"
|
||||
placeholder="https://chat.whatsapp.com/..."
|
||||
value="<?= esc($existing['invite_link'] ?? '') ?>"
|
||||
required>
|
||||
<?php if (!empty($existing['invite_link'])): ?>
|
||||
<small class="text-success d-block mt-1">Link set.</small>
|
||||
<?php else: ?>
|
||||
<small class="text-muted d-block mt-1">No link set yet.</small>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-check mt-2">
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
name="active"
|
||||
id="active<?= $sid ?>"
|
||||
<?= !empty($existing) && (int)$existing['active'] === 1 ? 'checked' : '' ?>>
|
||||
<label class="form-check-label" for="active<?= $sid ?>">Active</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 text-end">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<p class="text-muted">No sections found for this term.</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right: Send Invites -->
|
||||
<div class="col-lg-5">
|
||||
<div class="card">
|
||||
<div class="card-header">Send Invites</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="<?= site_url('whatsapp/sendInvites') ?>" id="sendInvitesForm">
|
||||
<?= csrf_field() ?>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mode</label>
|
||||
|
||||
<select class="form-select" name="mode" id="modeSelect" required>
|
||||
<option value="all">All parents</option>
|
||||
<option value="class">Parents in a class</option>
|
||||
<option value="parents">Specific parent(s)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 d-none" id="classPicker">
|
||||
<label class="form-label">Class / Section</label>
|
||||
<select id="class_section_id_select"
|
||||
name="class_section_id"
|
||||
class="form-select">
|
||||
<option value="">-- Select Class / Section --</option>
|
||||
<?php foreach ($sections as $s): ?>
|
||||
<option value="<?= (int)$s['class_section_id'] ?>">
|
||||
<?= esc($s['class_section_name']) ?>
|
||||
<?php if (!empty($linksBySection[(int)$s['class_section_id']]['invite_link'])): ?>
|
||||
(has link)
|
||||
<?php endif; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 d-none" id="parentPicker">
|
||||
<label class="form-label">Parents</label>
|
||||
<select class="form-select" name="parent_ids[]" multiple size="25">
|
||||
<?php if (!empty($parents)): ?>
|
||||
<?php foreach ($parents as $p):
|
||||
$label = ($p['lastname'] ?? '') . ', ' . ($p['firstname'] ?? '');
|
||||
if (!empty($p['email'])) $label .= ' — ' . $p['email'];
|
||||
$label .= ($p['source'] ?? '') === 'parents' ? ' (Second Parent)' : ' (Primary)';
|
||||
?>
|
||||
<option value="<?= (int)$p['id'] ?>"><?= esc($label) ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<option disabled>No parents available</option>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
<small class="text-muted">Hold Ctrl/Cmd to select multiple.</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="text-end">
|
||||
<button class="btn btn-success">Send Emails</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('scripts') ?>
|
||||
<script>
|
||||
(function() {
|
||||
const form = document.getElementById('sendInvitesForm');
|
||||
const mode = document.getElementById('modeSelect');
|
||||
const classPicker = document.getElementById('classPicker');
|
||||
const classSelect = document.getElementById('class_section_id_select');
|
||||
const parentPicker = document.getElementById('parentPicker');
|
||||
const parentSelect = parentPicker ? parentPicker.querySelector('select[name="parent_ids[]"]') : null;
|
||||
|
||||
function clearParentsSelection() {
|
||||
if (!parentSelect) return;
|
||||
for (const opt of parentSelect.options) opt.selected = false;
|
||||
}
|
||||
|
||||
function setRequired(el, on) {
|
||||
if (!el) return;
|
||||
if (on) el.setAttribute('required', 'required');
|
||||
else el.removeAttribute('required');
|
||||
}
|
||||
|
||||
function sync() {
|
||||
const v = mode.value;
|
||||
|
||||
// Hide both pickers by default
|
||||
classPicker.classList.add('d-none');
|
||||
parentPicker.classList.add('d-none');
|
||||
|
||||
// Not required by default
|
||||
setRequired(classSelect, false);
|
||||
setRequired(parentSelect, false);
|
||||
|
||||
if (v === 'class') {
|
||||
classPicker.classList.remove('d-none');
|
||||
setRequired(classSelect, true);
|
||||
// Default to first non-placeholder option if none chosen
|
||||
if (!classSelect.value && classSelect.options.length > 1) {
|
||||
classSelect.selectedIndex = 1;
|
||||
}
|
||||
if (parentSelect) clearParentsSelection();
|
||||
|
||||
} else if (v === 'parents') {
|
||||
parentPicker.classList.remove('d-none');
|
||||
setRequired(parentSelect, true);
|
||||
if (classSelect) classSelect.value = '';
|
||||
|
||||
} else { // 'all'
|
||||
if (classSelect) classSelect.value = '';
|
||||
if (parentSelect) clearParentsSelection();
|
||||
}
|
||||
}
|
||||
|
||||
mode.addEventListener('change', sync);
|
||||
document.addEventListener('DOMContentLoaded', sync);
|
||||
})();
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
@@ -0,0 +1,81 @@
|
||||
<?= $this->extend('layout/management_layout') ?>
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<div class="container my-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
|
||||
<h2 class="mb-0">Parent Contacts</h2>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<?php if (!empty($schoolYear)): ?>
|
||||
<span class="badge bg-primary">School Year: <?= esc($schoolYear) ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($semester)): ?>
|
||||
<span class="badge bg-info text-dark">Semester: <?= esc($semester) ?></span>
|
||||
<?php endif; ?>
|
||||
<a href="<?= site_url('whatsapp') ?>" class="btn btn-outline-secondary btn-sm">
|
||||
Back
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (empty($contacts)): ?>
|
||||
<div class="alert alert-warning">No parent contacts found for the selected term.</div>
|
||||
<?php else: ?>
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle" id="parentContactsTable">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th style="width: 14rem;">Name</th>
|
||||
<th style="width: 10rem;">Type</th>
|
||||
<th style="width: 14rem;">Phone</th>
|
||||
<th style="width: 18rem;">Email</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($contacts as $row): ?>
|
||||
<tr>
|
||||
<td><?= esc(trim(($row['lastname'] ?? '') . ', ' . ($row['firstname'] ?? ''))) ?></td>
|
||||
<td>
|
||||
<span class="badge <?= ($row['type'] === 'Second Parent') ? 'bg-secondary' : 'bg-success' ?>">
|
||||
<?= esc($row['type']) ?>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<?php if (!empty($row['phone'])): ?>
|
||||
<a href="tel:<?= esc(preg_replace('/\D+/', '', $row['phone'])) ?>">
|
||||
<?= esc($row['phone']) ?>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">—</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if (!empty($row['email'])): ?>
|
||||
<a href="mailto:<?= esc($row['email']) ?>"><?= esc($row['email']) ?></a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">—</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="small text-muted mt-2">
|
||||
Tip: Click a phone to dial, email to compose.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('scripts') ?>
|
||||
<script>
|
||||
// If you use DataTables elsewhere, init it the same way here:
|
||||
// $('#parentContactsTable').DataTable();
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
@@ -0,0 +1,317 @@
|
||||
<?= $this->extend('layout/management_layout') ?>
|
||||
<?= $this->section('content') ?>
|
||||
<div class="container-fluid">
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
|
||||
<h2 class="text-center mt-4 mb-3">Parent Contacts by Class</h2>
|
||||
<a href="<?= site_url('whatsapp/') ?>" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-people"></i> WhatsApp Group Links
|
||||
</a>
|
||||
<?php if (session()->getFlashdata('message')): ?>
|
||||
<div class="alert alert-success">
|
||||
<?= session()->getFlashdata('message') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (session()->getFlashdata('error')): ?>
|
||||
<div class="alert alert-danger">
|
||||
<?= session()->getFlashdata('error') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($classSections)): ?>
|
||||
<div id="classAccordion">
|
||||
<?php foreach ($classSections as $index => $classSection): ?>
|
||||
<div class="card">
|
||||
<div class="card-header" id="heading<?= $index ?>">
|
||||
<h2 class="mb-0">
|
||||
<button class="btn btn-link w-100 text-start" type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapse<?= $index ?>"
|
||||
aria-expanded="<?= $index === 0 ? 'true' : 'false' ?>"
|
||||
aria-controls="collapse<?= $index ?>">
|
||||
Grade : <?= esc($classSection['class_section_name']) ?>
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div id="collapse<?= $index ?>" class="collapse <?= $index === 0 ? 'show' : '' ?>" aria-labelledby="heading<?= $index ?>" data-bs-parent="#classAccordion">
|
||||
<div class="card-body">
|
||||
|
||||
<!--h5>Semester: <--?= esc($classSection['semester'] ?? '') ?></h5-->
|
||||
<!--h5>School Year: <--?= esc($classSection['school_year'] ?? '') ?></h5-->
|
||||
<!--p><--?= esc($classSection['description'] ?? '') ?></p-->
|
||||
|
||||
<?php if (!empty($classSection['parents'])): ?>
|
||||
<div class="table-responsive">
|
||||
<table id="parentsTable<?= $index ?>" class="display table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Primary Parent</th>
|
||||
<th>Phone</th>
|
||||
<th>
|
||||
In Group (Primary)
|
||||
<div class="form-check d-inline-block ms-2">
|
||||
<input class="form-check-input" type="checkbox" id="selectAllPrimary<?= $index ?>" title="Set all primary parents: checked=Yes, unchecked=No">
|
||||
<label for="selectAllPrimary<?= $index ?>" class="form-check-label small">All</label>
|
||||
</div>
|
||||
</th>
|
||||
<!--th>Email</th-->
|
||||
<th>Second Parent</th>
|
||||
<th>Phone</th>
|
||||
<!--th>Email</th-->
|
||||
<th>
|
||||
In Group (Second)
|
||||
<div class="form-check d-inline-block ms-2">
|
||||
<input class="form-check-input" type="checkbox" id="selectAllSecond<?= $index ?>" title="Set all second parents: checked=Yes, unchecked=No">
|
||||
<label for="selectAllSecond<?= $index ?>" class="form-check-label small">All</label>
|
||||
</div>
|
||||
</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($classSection['parents'] as $rIdx => $p): ?>
|
||||
<?php $formId = 'mform-' . $index . '-' . $rIdx; ?>
|
||||
<tr>
|
||||
<td><?= esc($p['primary_name']) ?></td>
|
||||
<td>
|
||||
<?php if (!empty($p['primary_phone'])): ?>
|
||||
<a href="tel:<?= esc(preg_replace('/\D+/', '', $p['primary_phone'])) ?>">
|
||||
<?= esc($p['primary_phone']) ?>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">—</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<select name="primary_member" form="<?= $formId ?>" class="form-select form-select-sm mem-select" aria-label="Primary in group">
|
||||
<?php $pm = $p['primary_member'] ?? null; ?>
|
||||
<option value="" <?= ($pm === null || $pm === '') ? 'selected' : '' ?>>—</option>
|
||||
<option value="1" <?= ((string)$pm === '1') ? 'selected' : '' ?>>Yes</option>
|
||||
<option value="0" <?= ((string)$pm === '0') ? 'selected' : '' ?>>No</option>
|
||||
</select>
|
||||
</td>
|
||||
<!--td>
|
||||
<--?php if (!empty($p['primary_email'])): ?>
|
||||
<a href="mailto:<--?= esc($p['primary_email']) ?>"><--?= esc($p['primary_email']) ?></a>
|
||||
<--?php else: ?>
|
||||
<span class="text-muted">—</span>
|
||||
<--?php endif; ?>
|
||||
</td-->
|
||||
<td><?= esc($p['second_name']) ?></td>
|
||||
<td>
|
||||
<?php if (!empty($p['second_phone'])): ?>
|
||||
<a href="tel:<?= esc(preg_replace('/\D+/', '', $p['second_phone'])) ?>">
|
||||
<?= esc($p['second_phone']) ?>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">—</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<!--td>
|
||||
<--?php if (!empty($p['second_email'])): ?>
|
||||
<--a href="mailto:<--?= esc($p['second_email']) ?>"><--?= esc($p['second_email']) ?></a>
|
||||
<--?php else: ?>
|
||||
<--span class="text-muted">—</span>
|
||||
<--?php endif; ?>
|
||||
</td-->
|
||||
|
||||
<td class="text-center">
|
||||
<?php if (!empty($p['second_id'])): ?>
|
||||
<?php $sm = $p['second_member'] ?? null; ?>
|
||||
<select name="second_member" form="<?= $formId ?>" class="form-select form-select-sm mem-select" aria-label="Second in group">
|
||||
<option value="" <?= ($sm === null || $sm === '') ? 'selected' : '' ?>>—</option>
|
||||
<option value="1" <?= ((string)$sm === '1') ? 'selected' : '' ?>>Yes</option>
|
||||
<option value="0" <?= ((string)$sm === '0') ? 'selected' : '' ?>>No</option>
|
||||
</select>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">—</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<form id="<?= $formId ?>" method="post" action="<?= site_url('whatsapp/update-membership') ?>" class="d-inline wa-membership-form">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="class_section_id" value="<?= (int)($p['class_section_id'] ?? $classSection['class_section_id']) ?>">
|
||||
<input type="hidden" name="school_year" value="<?= esc($classSection['school_year'] ?? '') ?>">
|
||||
<input type="hidden" name="semester" value="<?= esc($classSection['semester'] ?? '') ?>">
|
||||
<input type="hidden" name="primary_id" value="<?= (int)($p['primary_id'] ?? 0) ?>">
|
||||
<input type="hidden" name="second_id" value="<?= (int)($p['second_id'] ?? 0) ?>">
|
||||
<!--button type="submit" class="btn btn-sm btn-primary wa-save-btn">Save</button-->
|
||||
<span class="ms-2 small wa-status" aria-live="polite"></span>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<p>No parents found for this class section.</p>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<p>No class sections available.</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('scripts') ?>
|
||||
<style>
|
||||
/* Narrow In Group columns (header + cells) */
|
||||
th.col-in-group, td.col-in-group {
|
||||
width: 72px;
|
||||
max-width: 72px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
th.col-in-group {
|
||||
vertical-align: middle;
|
||||
}
|
||||
th.col-in-group .form-check-label.small { font-size: 0.7rem; }
|
||||
th.col-in-group .form-check-input { width: .9rem; height: .9rem; }
|
||||
|
||||
.mem-select.form-select.form-select-sm {
|
||||
display: inline-block; /* override Bootstrap block width */
|
||||
width: auto; /* no full-width selects */
|
||||
min-width: 52px; /* compact but readable */
|
||||
font-size: 0.75rem; /* smaller text */
|
||||
padding-left: 4px;
|
||||
padding-right: 12px; /* smaller chevron space */
|
||||
line-height: 1;
|
||||
border: 1px solid #adb5bd;
|
||||
transition: background-color .12s ease, border-color .12s ease, color .12s ease, box-shadow .12s ease;
|
||||
}
|
||||
.mem-select.mem-yes {
|
||||
background: #157347;
|
||||
color: #fff;
|
||||
border-color: #0f5132;
|
||||
box-shadow: 0 0 0 1px rgba(21, 115, 71, .18); /* thinner highlight */
|
||||
}
|
||||
.mem-select.mem-no {
|
||||
background: #bb2d3b;
|
||||
color: #fff;
|
||||
border-color: #842029;
|
||||
box-shadow: 0 0 0 1px rgba(187, 45, 59, .18); /* thinner highlight */
|
||||
}
|
||||
.mem-select.mem-none {
|
||||
background: #fff;
|
||||
color: #212529;
|
||||
border-color: #adb5bd;
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
<?php if (!empty($classSections)): ?>
|
||||
<?php foreach ($classSections as $index => $section): ?>
|
||||
$('#parentsTable<?= $index ?>').DataTable({
|
||||
paging: true,
|
||||
lengthChange: true,
|
||||
pageLength: 50,
|
||||
info: true,
|
||||
autoWidth: false,
|
||||
language: {
|
||||
info: "Showing _START_ to _END_ of _TOTAL_ entries (Page _PAGE_ of _PAGES_)",
|
||||
infoEmpty: "No entries to show",
|
||||
infoFiltered: "(filtered from _MAX_ total entries)",
|
||||
lengthMenu: "Show _MENU_ entries per page"
|
||||
},
|
||||
columnDefs: [
|
||||
{ targets: [2,5], width: '72px', className: 'dt-head-center dt-body-center' }
|
||||
],
|
||||
order: [
|
||||
[0, 'asc']
|
||||
]
|
||||
});
|
||||
|
||||
// Select-all toggles for this class section's table (set Yes/No on selects)
|
||||
$('#selectAllPrimary<?= $index ?>').on('change', function() {
|
||||
const yesNo = $(this).is(':checked') ? '1' : '0';
|
||||
$('#parentsTable<?= $index ?> tbody select[name="primary_member"]').val(yesNo).each(function(){
|
||||
applyMemAppearance(this);
|
||||
$(this).trigger('change'); // auto-save per row
|
||||
});
|
||||
});
|
||||
$('#selectAllSecond<?= $index ?>').on('change', function() {
|
||||
const yesNo = $(this).is(':checked') ? '1' : '0';
|
||||
$('#parentsTable<?= $index ?> tbody select[name="second_member"]').val(yesNo).each(function(){
|
||||
applyMemAppearance(this);
|
||||
$(this).trigger('change'); // auto-save per row
|
||||
});
|
||||
});
|
||||
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
// Apply colored appearance to selects
|
||||
function applyMemAppearance(el) {
|
||||
if (!el) return;
|
||||
el.classList.remove('mem-none','mem-yes','mem-no');
|
||||
const v = (el.value || '').toString();
|
||||
if (v === '1') el.classList.add('mem-yes');
|
||||
else if (v === '0') el.classList.add('mem-no');
|
||||
else el.classList.add('mem-none');
|
||||
}
|
||||
document.querySelectorAll('.mem-select').forEach(applyMemAppearance);
|
||||
$(document).on('change', '.mem-select', function(){
|
||||
applyMemAppearance(this);
|
||||
// Auto-save this row, similar to teacher attendance page
|
||||
const $tr = $(this).closest('tr');
|
||||
const $form = $tr.find('form.wa-membership-form');
|
||||
if ($form.length) {
|
||||
$form.trigger('submit');
|
||||
}
|
||||
});
|
||||
|
||||
// Bind once: ensure values are submitted with the form (for controls using the form="id" attribute)
|
||||
if (!window._waMembershipBind) {
|
||||
window._waMembershipBind = true;
|
||||
|
||||
// Ensure selected values are submitted even if controls sit outside the form cell
|
||||
$(document).on('submit', 'form[id^="mform-"]', function(e) {
|
||||
const $form = $(this);
|
||||
const $tr = $form.closest('tr');
|
||||
const pVal = ($tr.find('select[name="primary_member"]').val() || '').toString();
|
||||
const sVal = ($tr.find('select[name="second_member"]').val() || '').toString();
|
||||
// Remove any previous hidden overrides
|
||||
$form.find('input[type="hidden"][name="primary_member"]').remove();
|
||||
$form.find('input[type="hidden"][name="second_member"]').remove();
|
||||
// Include explicit values to avoid browser quirks with form="id"
|
||||
$form.append('<input type="hidden" name="primary_member" value="' + pVal + '">');
|
||||
$form.append('<input type="hidden" name="second_member" value="' + sVal + '">');
|
||||
|
||||
// AJAX submit for immediate feedback
|
||||
e.preventDefault();
|
||||
const $btn = $form.find('.wa-save-btn');
|
||||
const $status = $form.find('.wa-status');
|
||||
$btn.prop('disabled', true).text('Saving...');
|
||||
$status.removeClass('text-danger text-success').text('');
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
method: 'POST',
|
||||
data: $form.serialize(),
|
||||
dataType: 'json'
|
||||
}).done(function(res){
|
||||
if (res && res.status === 'ok') {
|
||||
$status.addClass('text-success').text('Saved');
|
||||
} else if (res && res.status === 'noop') {
|
||||
$status.addClass('text-danger').text(res.message || 'Nothing to save');
|
||||
} else {
|
||||
$status.addClass('text-danger').text('Save failed');
|
||||
}
|
||||
}).fail(function(){
|
||||
$status.addClass('text-danger').text('Save failed');
|
||||
}).always(function(){
|
||||
$btn.prop('disabled', false).text('Save');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
Reference in New Issue
Block a user