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

233 lines
9.8 KiB
PHP

<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<div class="container-fluid"
data-template-endpoint="<?= esc($templateEndpoint ?? site_url('api/attendance-templates')) ?>"
data-csrf-name="<?= esc(csrf_token()) ?>"
data-csrf-value="<?= esc(csrf_hash()) ?>">
<div class="wrapper">
<div class="text-center mb-4">
<h2 class="text-center mt-4 mb-3">Attendance Comment Templates</h2>
</div>
<div class="mb-4">
<button id="addNewBtn" class="btn btn-success">Add New Template</button>
</div>
<div class="table-responsive">
<table id="templatesTable" class="display table table-striped align-middle">
<thead>
<tr>
<th>ID</th>
<th>Min Score</th>
<th>Max Score</th>
<th>Template Text</th>
<th>Active</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="6" class="text-center text-muted">Loading templates...</td>
</tr>
</tbody>
</table>
</div>
<div class="modal fade" id="editTemplateModal" tabindex="-1" aria-labelledby="editTemplateModalLabel" aria-hidden="true">
<div class="modal-dialog">
<form id="editTemplateForm" class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editTemplateModalLabel">Edit Template</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="hidden" name="id" id="template_id">
<div class="mb-3">
<label for="min_score" class="form-label">Min Score:</label>
<input type="number" name="min_score" id="min_score" class="form-control" required>
</div>
<div class="mb-3">
<label for="max_score" class="form-label">Max Score:</label>
<input type="number" name="max_score" id="max_score" class="form-control" required>
</div>
<div class="mb-3">
<label for="template_text" class="form-label">Template Text:</label>
<textarea name="template_text" id="template_text" class="form-control" required></textarea>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="is_active" id="is_active" value="on">
<label class="form-check-label" for="is_active">
Active
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</form>
</div>
</div>
</div>
</div>
<?= $this->endSection() ?>
<?= $this->section('scripts') ?>
<script>
document.addEventListener('DOMContentLoaded', () => {
const container = document.querySelector('[data-template-endpoint]');
if (!container) return;
const endpoint = container.dataset.templateEndpoint;
const csrfName = container.dataset.csrfName;
let csrfValue = container.dataset.csrfValue;
const addNewBtn = document.getElementById('addNewBtn');
const tableBody = document.querySelector('#templatesTable tbody');
const editModalElement = document.getElementById('editTemplateModal');
const editForm = document.getElementById('editTemplateForm');
const editModal = new window.bootstrap.Modal(editModalElement);
let templates = [];
const safe = (value, fallback = '') =>
value === undefined || value === null ? fallback : value;
const fetchTemplates = async () => {
tableBody.innerHTML = '<tr><td colspan="6" class="text-center text-muted">Loading templates...</td></tr>';
try {
const response = await fetch(endpoint, {
headers: { 'Accept': 'application/json' },
});
if (!response.ok) throw new Error('Failed to fetch');
const payload = await response.json();
templates = payload.templates || [];
renderTemplates();
} catch (error) {
console.error(error);
tableBody.innerHTML = '<tr><td colspan="6" class="text-center text-danger">Failed to load templates.</td></tr>';
}
};
const renderTemplates = () => {
if (window.jQuery.fn.DataTable.isDataTable('#templatesTable')) {
window.jQuery('#templatesTable').DataTable().destroy();
}
tableBody.innerHTML = '';
if (templates.length === 0) {
tableBody.innerHTML = '<tr><td colspan="6" class="text-center text-muted">No templates found.</td></tr>';
return;
}
templates.forEach(template => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${safe(template.id)}</td>
<td>${safe(template.min_score)}</td>
<td>${safe(template.max_score)}</td>
<td>${safe(template.template_text)}</td>
<td>${template.is_active ? 'Yes' : 'No'}</td>
<td class="d-flex gap-1"></td>
`;
const actionsCell = row.querySelector('td:last-child');
const editButton = document.createElement('button');
editButton.className = 'btn btn-sm btn-warning';
editButton.textContent = 'Edit';
editButton.onclick = () => openEditModal(template);
actionsCell.appendChild(editButton);
const deleteButton = document.createElement('button');
deleteButton.className = 'btn btn-sm btn-danger';
deleteButton.textContent = 'Delete';
deleteButton.onclick = () => deleteTemplate(template.id);
actionsCell.appendChild(deleteButton);
tableBody.appendChild(row);
});
window.jQuery('#templatesTable').DataTable({
pageLength: 25,
lengthMenu: [10, 25, 50, 100],
});
};
const openEditModal = (template = {}) => {
editForm.reset();
editForm.querySelector('#template_id').value = template.id || '';
editForm.querySelector('#min_score').value = template.min_score || '';
editForm.querySelector('#max_score').value = template.max_score || '';
editForm.querySelector('#template_text').value = template.template_text || '';
editForm.querySelector('#is_active').checked = template.is_active || false;
editModal.show();
};
addNewBtn.addEventListener('click', () => openEditModal());
editForm.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(editForm);
const data = Object.fromEntries(formData.entries());
data[csrfName] = csrfValue;
try {
const response = await fetch(`${endpoint}/save`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
},
body: new URLSearchParams(data).toString()
});
const result = await response.json();
if (response.ok && result.status === 'success') {
editModal.hide();
await fetchTemplates(); // Refresh table
} else {
alert('Failed to save template.');
}
} catch (error) {
console.error('Save error:', error);
alert('An error occurred while saving.');
}
});
const deleteTemplate = async (id) => {
if (!confirm('Are you sure you want to delete this template?')) return;
const data = new URLSearchParams();
data.append(csrfName, csrfValue);
data.append('id', id);
try {
const response = await fetch(`${endpoint}/delete`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
},
body: data
});
const result = await response.json();
if (response.ok && result.status === 'success') {
await fetchTemplates(); // Refresh table
} else {
alert('Failed to delete template.');
}
} catch (error) {
console.error('Delete error:', error);
alert('An error occurred while deleting.');
}
};
fetchTemplates();
});
</script>
<?= $this->endSection() ?>