Enhance person editing functionality and birthday reminders
- Added a modal for editing person details, including name, role, favorite color, birthday, and description. - Implemented visibility toggling for PIN input based on role selection, ensuring security for Head of Household. - Introduced birthday reminder functionality in the calendar, generating events for upcoming birthdays with appropriate notifications. - Updated calendar and settings UI to accommodate new features, improving user experience and data management.
This commit is contained in:
+175
-51
@@ -177,6 +177,124 @@
|
||||
});
|
||||
}
|
||||
|
||||
function toggleEditPersonPinVisibility() {
|
||||
var initial = $('#edit_person_initial_role').val() || '';
|
||||
var role = $('#edit_role').val() || '';
|
||||
var $wrap = $('#edit_pin_wrap');
|
||||
var $pin = $('#edit_pin');
|
||||
var needPin = role === 'head_of_household' && initial !== 'head_of_household';
|
||||
if (needPin) {
|
||||
$wrap.show();
|
||||
$pin.prop('required', true);
|
||||
} else {
|
||||
$wrap.hide();
|
||||
$pin.prop('required', false);
|
||||
$pin.val('');
|
||||
}
|
||||
}
|
||||
|
||||
function bindEditPersonForm() {
|
||||
var $form = $('#editPersonForm');
|
||||
if (!$form.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var peopleById = {};
|
||||
var $payloadEl = $('#settingsPeopleEditPayload');
|
||||
if ($payloadEl.length) {
|
||||
try {
|
||||
var plist = JSON.parse($payloadEl.text());
|
||||
if (Array.isArray(plist)) {
|
||||
plist.forEach(function (row) {
|
||||
if (row && row.id) {
|
||||
peopleById[row.id] = row;
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (ignoreErr) {
|
||||
peopleById = {};
|
||||
}
|
||||
}
|
||||
|
||||
var editModal = null;
|
||||
if (typeof bootstrap !== 'undefined') {
|
||||
var modalEl = document.getElementById('editPersonModal');
|
||||
if (modalEl) {
|
||||
editModal = new bootstrap.Modal(modalEl, { backdrop: false });
|
||||
}
|
||||
}
|
||||
|
||||
$('#edit_role').on('change', toggleEditPersonPinVisibility);
|
||||
|
||||
$(document).on('click', '.btn-edit-person', function () {
|
||||
var id = $(this).data('person-id');
|
||||
if (!id || !peopleById[id]) {
|
||||
window.alert('Could not load this person for editing.');
|
||||
return;
|
||||
}
|
||||
var p = peopleById[id];
|
||||
$('#edit_person_id').val(p.id);
|
||||
$('#edit_person_initial_role').val(p.role || '');
|
||||
$('#edit_name').val(p.name || '');
|
||||
$('#edit_role').val(p.role || 'child');
|
||||
var fc = String(p.favoriteColor || '').trim();
|
||||
if (!/^#[0-9A-Fa-f]{6}$/.test(fc)) {
|
||||
fc = '#4a90e2';
|
||||
}
|
||||
$('#edit_favoriteColor').val(fc);
|
||||
$('#edit_birthday').val(String(p.birthday || '').trim());
|
||||
$('#edit_description').val(p.description || '');
|
||||
$('#edit_pin').val('');
|
||||
$('#editPersonFeedback').addClass('d-none').removeClass('alert-success alert-danger alert-warning').text('');
|
||||
toggleEditPersonPinVisibility();
|
||||
if (editModal) {
|
||||
editModal.show();
|
||||
}
|
||||
});
|
||||
|
||||
$form.on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var id = ($('#edit_person_id').val() || '').trim();
|
||||
var initial = $('#edit_person_initial_role').val() || '';
|
||||
var role = $('#edit_role').val() || '';
|
||||
var name = ($('#edit_name').val() || '').trim();
|
||||
if (!id || name === '') {
|
||||
return;
|
||||
}
|
||||
var needPin = role === 'head_of_household' && initial !== 'head_of_household';
|
||||
var pin = needPin ? ($('#edit_pin').val() || '') : '';
|
||||
if (needPin && pin.length < 4) {
|
||||
showAlert($('#editPersonFeedback'), 'danger', 'PIN must be at least 4 characters for a new Head of household.');
|
||||
$('#editPersonFeedback').removeClass('d-none');
|
||||
return;
|
||||
}
|
||||
if (initial === 'head_of_household' && role !== 'head_of_household') {
|
||||
if (!window.confirm('Demote this Head of household? Their PIN will be cleared until they are promoted again.')) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var payload = {
|
||||
id: id,
|
||||
name: name,
|
||||
role: role,
|
||||
favoriteColor: $('#edit_favoriteColor').val() || '#4a90e2',
|
||||
birthday: ($('#edit_birthday').val() || '').trim(),
|
||||
description: ($('#edit_description').val() || '').trim()
|
||||
};
|
||||
if (needPin) {
|
||||
payload.pin = pin;
|
||||
}
|
||||
postJson('/people_update.php', payload)
|
||||
.then(function () {
|
||||
window.location.reload();
|
||||
})
|
||||
.catch(function (err) {
|
||||
showAlert($('#editPersonFeedback'), 'danger', err.message || 'Could not save changes');
|
||||
$('#editPersonFeedback').removeClass('d-none');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function bindFamilySettingsForm() {
|
||||
var $form = $('#familySettingsForm');
|
||||
if (!$form.length) {
|
||||
@@ -308,59 +426,11 @@
|
||||
}
|
||||
|
||||
function bindChoresPage() {
|
||||
var $choresTab = $('#chores');
|
||||
var $form = $('#choreForm');
|
||||
if (!$form.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#chore_schedule').on('change', toggleChoreRecurrence);
|
||||
toggleChoreRecurrence();
|
||||
|
||||
$form.on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var assignees = [];
|
||||
$('.chore-assignee:checked').each(function () {
|
||||
assignees.push($(this).val());
|
||||
});
|
||||
var due = $('#chore_due_date').val() || '';
|
||||
var payload = {
|
||||
id: ($('#chore_id').val() || '').trim(),
|
||||
title: $('#chore_title').val(),
|
||||
description: $('#chore_description').val(),
|
||||
image: $('#chore_image').val(),
|
||||
value: Number($('#chore_value').val()) || 0,
|
||||
due_date: due,
|
||||
schedule: $('#chore_schedule').val(),
|
||||
recurrence_days: parseInt($('#chore_recurrence_days').val(), 10) || 7,
|
||||
assignee_ids: assignees,
|
||||
anyone_can_complete: $('#chore_anyone_can_complete').is(':checked'),
|
||||
lists: choreListPayloadFromForm()
|
||||
};
|
||||
postJson('/chore_save.php', payload)
|
||||
.then(function () {
|
||||
window.location.href = window.location.pathname + '?tab=chores';
|
||||
})
|
||||
.catch(function (err) {
|
||||
var $fb = $('#choreFormFeedback');
|
||||
showAlert($fb, 'danger', err.message || 'Could not save chore');
|
||||
$fb.removeClass('d-none');
|
||||
});
|
||||
});
|
||||
|
||||
$('#choreDeleteBtn').on('click', function () {
|
||||
var id = $(this).data('id');
|
||||
if (!id || !window.confirm('Delete this chore?')) {
|
||||
return;
|
||||
}
|
||||
postJson('/chore_delete.php', { id: id })
|
||||
.then(function () {
|
||||
window.location.href = window.location.pathname + '?tab=chores';
|
||||
})
|
||||
.catch(function (err) {
|
||||
window.alert(err.message || 'Could not delete');
|
||||
});
|
||||
});
|
||||
|
||||
// Add/edit form exists only for HoH (or when editing). Cards and pending list still need handlers for everyone.
|
||||
if ($choresTab.length) {
|
||||
$(document).on('click', '.btn-chore-submit', function () {
|
||||
var id = $(this).data('id');
|
||||
if (!id || !window.confirm('Submit this chore as done? A Head of household will approve it before the reward is paid.')) {
|
||||
@@ -463,6 +533,59 @@
|
||||
$('#chore_nfc_feedback_' + id).removeClass('d-none');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!$form.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#chore_schedule').on('change', toggleChoreRecurrence);
|
||||
toggleChoreRecurrence();
|
||||
|
||||
$form.on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var assignees = [];
|
||||
$('.chore-assignee:checked').each(function () {
|
||||
assignees.push($(this).val());
|
||||
});
|
||||
var due = $('#chore_due_date').val() || '';
|
||||
var payload = {
|
||||
id: ($('#chore_id').val() || '').trim(),
|
||||
title: $('#chore_title').val(),
|
||||
description: $('#chore_description').val(),
|
||||
image: $('#chore_image').val(),
|
||||
value: Number($('#chore_value').val()) || 0,
|
||||
due_date: due,
|
||||
schedule: $('#chore_schedule').val(),
|
||||
recurrence_days: parseInt($('#chore_recurrence_days').val(), 10) || 7,
|
||||
assignee_ids: assignees,
|
||||
anyone_can_complete: $('#chore_anyone_can_complete').is(':checked'),
|
||||
lists: choreListPayloadFromForm()
|
||||
};
|
||||
postJson('/chore_save.php', payload)
|
||||
.then(function () {
|
||||
window.location.href = window.location.pathname + '?tab=chores';
|
||||
})
|
||||
.catch(function (err) {
|
||||
var $fb = $('#choreFormFeedback');
|
||||
showAlert($fb, 'danger', err.message || 'Could not save chore');
|
||||
$fb.removeClass('d-none');
|
||||
});
|
||||
});
|
||||
|
||||
$('#choreDeleteBtn').on('click', function () {
|
||||
var id = $(this).data('id');
|
||||
if (!id || !window.confirm('Delete this chore?')) {
|
||||
return;
|
||||
}
|
||||
postJson('/chore_delete.php', { id: id })
|
||||
.then(function () {
|
||||
window.location.href = window.location.pathname + '?tab=chores';
|
||||
})
|
||||
.catch(function (err) {
|
||||
window.alert(err.message || 'Could not delete');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function groceryReloadKeepParams() {
|
||||
@@ -1256,6 +1379,7 @@
|
||||
bindPersonaSwitcher();
|
||||
bindFirstHeadForm();
|
||||
bindAddPersonForm();
|
||||
bindEditPersonForm();
|
||||
bindFamilySettingsForm();
|
||||
bindCalendarSettingsForm();
|
||||
bindPeopleTable();
|
||||
|
||||
Reference in New Issue
Block a user