273 lines
11 KiB
JavaScript
273 lines
11 KiB
JavaScript
$(document).ready(function () {
|
|
|
|
$.ajaxSetup({
|
|
headers: {
|
|
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
|
|
'Accept': 'application/json'
|
|
}
|
|
});
|
|
|
|
const phoneInstances = {};
|
|
|
|
function initPhoneInput(selector) {
|
|
const input = document.querySelector(selector);
|
|
if (!input) return null;
|
|
|
|
// If it was already initialized, don't do it again
|
|
if (phoneInstances[selector]) return phoneInstances[selector];
|
|
|
|
phoneInstances[selector] = window.intlTelInput(input, {
|
|
initialCountry: "gh",
|
|
onlyCountries: ["gh"],
|
|
nationalMode: true, // ALLOW users to type 024... natively
|
|
autoPlaceholder: "polite",
|
|
utilsScript: "https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.19/js/utils.js"
|
|
});
|
|
|
|
// Auto-format on blur using the plugin's built-in engine
|
|
input.addEventListener("blur", function () {
|
|
if (phoneInstances[selector].isValidNumber()) {
|
|
// Reformats to local standard (e.g., 024 123 4567) for UI
|
|
phoneInstances[selector].setNumber(phoneInstances[selector].getNumber());
|
|
}
|
|
});
|
|
|
|
return phoneInstances[selector];
|
|
}
|
|
|
|
// Initialize inputs when their respective modals open
|
|
$('#editUserModal').on('shown.bs.modal', () => initPhoneInput("#editPhone"));
|
|
$('#addUserModal').on('shown.bs.modal', () => initPhoneInput("#addUserphone"));
|
|
|
|
$('#editAllowedApps, #inputPermissions').select2({
|
|
dropdownParent: $('#editUserModal'),
|
|
placeholder: "Select options, multiple allowed"
|
|
});
|
|
|
|
$('#allowedApps').select2({
|
|
dropdownParent: $('#addUserModal'),
|
|
placeholder: "Select options, multiple allowed"
|
|
});
|
|
|
|
const optionsMap = {
|
|
district_user: [
|
|
"PPD Head", "Works Head", "MIS", "PPD Staff", "Works Staff",
|
|
"Devt Planning Officer", "MCE", "DCE", "Urban Roads Department Head",
|
|
"District Fire Officer", "District Disaster Prevention Department",
|
|
"Head of District Health Department", "Representative of the Lands Commission",
|
|
"Representative of the Environmental Protection Agency", "Rep from Traditional Council",
|
|
"Chairman of the Works Sub Committee", "Chairman of Development Sub Planning Committee",
|
|
"Nominated Elected Assembly Memebers"
|
|
],
|
|
national_luspa: ["Director", "IT Head", "Staff"],
|
|
regional_luspa: ["Director", "Staff"]
|
|
};
|
|
|
|
function populatePositions(userType, targetDropdown) {
|
|
targetDropdown.empty().append('<option value="">-- Select an option --</option>');
|
|
if (optionsMap[userType]) {
|
|
$.each(optionsMap[userType], function(index, value) {
|
|
targetDropdown.append($("<option></option>").attr("value", value.toLowerCase()).text(value));
|
|
});
|
|
}
|
|
}
|
|
|
|
let initialUserType = $("input[name='user_type']:checked").val();
|
|
if(initialUserType) populatePositions(initialUserType, $("#uaPostionAdd"));
|
|
|
|
// Handle Radio Changes
|
|
$("input[name='user_type']").change(function() {
|
|
let userType = $(this).val();
|
|
|
|
let isDistrict = (userType === 'district_user');
|
|
let isRegional = (userType === 'regional_luspa');
|
|
|
|
$('#regionID, #editRegionID').prop('disabled', !isDistrict && !isRegional);
|
|
$('#districtID, #editdistrictID').prop('disabled', !isDistrict);
|
|
|
|
populatePositions(userType, $("#uaPostionAdd"));
|
|
});
|
|
|
|
|
|
$('.regionIDD').change(function() {
|
|
let region_id = $(this).val();
|
|
let $districtSelect = $('.districtIDD');
|
|
|
|
$districtSelect.empty().append('<option value="">-- Select District --</option>');
|
|
|
|
if(!region_id) return;
|
|
|
|
$.ajax({
|
|
url: base_url + '/admin/districts/' + region_id,
|
|
type: 'GET',
|
|
success: function(data) {
|
|
if(data.districts) {
|
|
$.each(data.districts, function(id, row) {
|
|
$districtSelect.append($("<option />").val(row.districtid).text(row.district_name));
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
let lastTrigger = null;
|
|
|
|
$(document).on('click', '.editUserBtn', function(evnt) {
|
|
evnt.preventDefault();
|
|
lastTrigger = this;
|
|
|
|
const row = $(this).closest('.user-row');
|
|
let selectedUserId = row.data('id');
|
|
|
|
// Ensure phone instance exists before trying to set data into it
|
|
let phoneIti = initPhoneInput("#editPhone");
|
|
|
|
$.ajax({
|
|
url: base_url + '/users/edit/' + selectedUserId,
|
|
type: 'GET',
|
|
beforeSend: function() {
|
|
$('#editSuccessArea').addClass('d-none');
|
|
$('#editErrorArea').removeClass('d-none').text("Please wait ... loading user details!!");
|
|
},
|
|
success: function(response) {
|
|
$('#editErrorArea').addClass('d-none').text('');
|
|
|
|
if (response.success) {
|
|
let user = response.data;
|
|
let allowedAppsArray = user.allowed_apps ? user.allowed_apps.split(",") : [];
|
|
|
|
$('#editFullName').val(user.full_name);
|
|
$('#editEmail').val(user.email);
|
|
$('#editUsername').val(user.username);
|
|
$('#editGender').val(user.gender);
|
|
$('#editTitle').val(user.title);
|
|
$('#editUaPostion').val(user.ua_position);
|
|
$('#editRegionID').val(user.region_id);
|
|
$('#editDistrictId').val(user.district_id);
|
|
$("input[name='user_id']").val(user.user_id);
|
|
|
|
$('#editAllowedApps').val(allowedAppsArray).trigger('change');
|
|
if (user.user_type === 'district_user') {
|
|
$('#editUserTypeDistrict').prop('checked', true);
|
|
}
|
|
else if(user.user_type === 'regional_luspa'){
|
|
$('#editUserTypeLuspaRegion').prop('checked', true);
|
|
}
|
|
else{
|
|
$('#editUserTypeLuspaNational').prop('checked', true);
|
|
}
|
|
|
|
if (phoneIti && user.phone) {
|
|
phoneIti.setNumber(user.phone);
|
|
} else {
|
|
$('#editPhone').val(user.phone);
|
|
}
|
|
// $('#editUserModal').modal('show')
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
$('#editErrorArea').removeClass('d-none').text("Failed to load user: " + error);
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#editUserModal').on('hidden.bs.modal', function(){
|
|
if (lastTrigger && document.contains(lastTrigger)) lastTrigger.focus();
|
|
lastTrigger = null;
|
|
});
|
|
|
|
|
|
function handleFormSubmission(formElement, url, successMessage, phoneInstanceSelector) {
|
|
const $form = $(formElement);
|
|
const isEdit = formElement.id === 'editUserForm';
|
|
const prefix = isEdit ? '#edit' : '#newUser';
|
|
|
|
const $successArea = $(`${prefix}SuccessArea`);
|
|
const $errorArea = $(`${prefix}ErrorArea`);
|
|
const itiInstance = phoneInstances[phoneInstanceSelector];
|
|
|
|
$successArea.addClass('d-none').text("");
|
|
$errorArea.addClass('d-none').text("");
|
|
|
|
const formData = new FormData(formElement);
|
|
let errors = [];
|
|
|
|
// Validate Phone cleanly
|
|
if (itiInstance) {
|
|
if (!itiInstance.isValidNumber()) {
|
|
errors.push("01|Please enter a valid Ghana phone number.");
|
|
} else {
|
|
// Get the clean E.164 database format (e.g. +233241234567)
|
|
formData.set("phone", itiInstance.getNumber());
|
|
}
|
|
}
|
|
|
|
// Validate standard fields
|
|
const fullName = $form.find('input[name="full_name"], [id*="FullName"], [id*="Fullname"]').val().trim();
|
|
const username = $form.find('input[name="username"], [id*="Username"]').val().trim();
|
|
const email = $form.find('input[type="email"], [id*="Email"]').val().trim();
|
|
|
|
if (!fullName) errors.push("Full name is required.");
|
|
if (!username) errors.push("Username is required.");
|
|
if (!email) {
|
|
errors.push("Email is required.");
|
|
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
errors.push("Invalid email format.");
|
|
}
|
|
|
|
if (errors.length > 0) {
|
|
$errorArea.removeClass("d-none").html(errors.join("<br>"));
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: url,
|
|
type: 'POST',
|
|
data: formData,
|
|
processData: false,
|
|
contentType: false,
|
|
beforeSend: function() {
|
|
$successArea.removeClass('d-none').addClass('text-info').text("Processing request, please wait...");
|
|
},
|
|
success: function(data) {
|
|
$successArea.removeClass('text-info');
|
|
if (data.success) {
|
|
$successArea.removeClass('d-none').text(successMessage);
|
|
$.alert({ title: 'Success!', content: successMessage });
|
|
setTimeout(() => location.reload(), 2000);
|
|
} else {
|
|
$successArea.addClass('d-none');
|
|
$errorArea.removeClass('d-none').text(data.msg || "An error occurred.");
|
|
$.alert({ title: 'Error!', content: data.msg || "An error occurred." });
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
$successArea.addClass("d-none");
|
|
if (xhr.status === 422 && xhr.responseJSON && xhr.responseJSON.errors) {
|
|
let messages = [];
|
|
$.each(xhr.responseJSON.errors, function (field, msgs) {
|
|
messages.push(msgs.join("<br>"));
|
|
});
|
|
$errorArea.removeClass("d-none").html(messages.join("<br>"));
|
|
$.alert({ title: "Validation Error", content: messages.join("<br>") });
|
|
} else {
|
|
$errorArea.removeClass("d-none").text("Request failed: " + error);
|
|
$.alert({ title: "Error", content: "Request failed: " + error });
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
$("#editUserForm").on("submit", function (evt) {
|
|
evt.preventDefault();
|
|
handleFormSubmission(this, base_url + '/userupdate', "User details successfully updated!", "#editPhone");
|
|
});
|
|
|
|
$("#newUserForm").on("submit", function (evt) {
|
|
evt.preventDefault();
|
|
handleFormSubmission(this, base_url + '/users', "User successfully created!", "#addUserphone");
|
|
});
|
|
|
|
}); |