Add pub hours admin panel, rebuild announcements/users lists on CSS Grid
- Add a Hours admin panel (admin/hours.php, admin/hours.js) for editing the weekly open/close schedule and an optional per-day kitchen closing time, with a live preview of how it'll read on the public site - Store hours in a new pub_hours table (inc/db.php), seeded with the site's existing Thu-Sat/9pm-kitchen schedule; inc/hours.php formats and groups it for display (day ranges, kitchen-close note, footer summary) - Wire the public Visit card and both site footers (index.php, menu.php) to read hours from that data instead of hardcoded copy - Rebuild the Announcements and Users admin tables onto the same CSS Grid list pattern already used for the Menu (admin-table-actions -> row-actions), and make the Announcements status toggle an in-place AJAX action like the menu item's (admin/index.js) - Add the Hours tab to admin nav across all four admin pages Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fd928a24cf
commit
eab20899de
14 files changed
+1224
-441
No files matched your search
+16
-15
@@ -152,8 +152,8 @@ document.getElementById('form-password').addEventListener('submit', async (e) =>
|
||||
}
|
||||
});
|
||||
|
||||
// Delegate table actions: Change Password, Delete
|
||||
document.getElementById('users-tbody').addEventListener('click', async (e) => {
|
||||
// Delegate row actions: Change Password, Delete
|
||||
document.getElementById('users-rows').addEventListener('click', async (e) => {
|
||||
const { target } = e;
|
||||
|
||||
if (target.classList.contains('btn-change-password')) {
|
||||
@@ -163,7 +163,7 @@ document.getElementById('users-tbody').addEventListener('click', async (e) => {
|
||||
|
||||
if (target.classList.contains('btn-delete-user')) {
|
||||
if (!confirm('Are you sure you want to delete this user? This cannot be undone.')) return;
|
||||
const row = target.closest('tr');
|
||||
const row = target.closest('.user-row');
|
||||
|
||||
const fd = new FormData();
|
||||
fd.append('action', 'delete_user');
|
||||
@@ -187,25 +187,26 @@ document.getElementById('users-tbody').addEventListener('click', async (e) => {
|
||||
});
|
||||
|
||||
function insertUserRow(user) {
|
||||
const tbody = document.getElementById('users-tbody');
|
||||
const rowsContainer = document.getElementById('users-rows');
|
||||
|
||||
const tr = document.createElement('tr');
|
||||
tr.id = `user-row-${user.id}`;
|
||||
tr.dataset.userId = user.id;
|
||||
const row = document.createElement('div');
|
||||
row.className = 'user-row';
|
||||
row.id = `user-row-${user.id}`;
|
||||
row.dataset.userId = user.id;
|
||||
|
||||
// data-username is set via dataset below, never interpolated into the
|
||||
// HTML string — escapeHtml() only escapes for text-content positions,
|
||||
// not attribute values, so it can't safely build an attribute string.
|
||||
tr.innerHTML = `
|
||||
<td data-label="Username"><strong>${escapeHtml(user.username)}</strong></td>
|
||||
<td data-label="Role">${escapeHtml(user.role.charAt(0).toUpperCase() + user.role.slice(1))}</td>
|
||||
<td class="font-mono item-sort-cell" data-label="Created">${escapeHtml(user.created_at)}</td>
|
||||
<td data-label="Actions"><div class="admin-table-actions">
|
||||
row.innerHTML = `
|
||||
<div data-label="Username"><strong>${escapeHtml(user.username)}</strong></div>
|
||||
<div data-label="Role">${escapeHtml(user.role.charAt(0).toUpperCase() + user.role.slice(1))}</div>
|
||||
<div class="font-mono timestamp-cell" data-label="Created">${escapeHtml(user.created_at)}</div>
|
||||
<div data-label="Actions"><div class="row-actions">
|
||||
<button type="button" class="btn btn-outline btn-sm btn-change-password" data-id="${user.id}">Change Password</button>
|
||||
<button type="button" class="btn btn-danger btn-sm btn-delete-user" data-id="${user.id}">Delete</button>
|
||||
</div></td>
|
||||
</div></div>
|
||||
`;
|
||||
tr.querySelector('.btn-change-password').dataset.username = user.username;
|
||||
row.querySelector('.btn-change-password').dataset.username = user.username;
|
||||
|
||||
tbody.appendChild(tr);
|
||||
rowsContainer.appendChild(row);
|
||||
}
|
||||
Reference in new issue
Block a user