completed clients and MNO module

This commit is contained in:
Kwesi Banson Jnr
2026-08-12 20:25:43 +00:00
parent cab4591777
commit 65245e5bc9
27 changed files with 1607 additions and 471 deletions

View File

@@ -249,5 +249,134 @@ document.addEventListener("DOMContentLoaded", function() {
</div>
`);
});
// 1. Populate Edit Client Modal when opened
$(document).on('click', '[data-bs-target="#editClientModal"]', function() {
let clientId = $(this).data('client-id');
let $form = $('#editClientForm');
$form.attr('action', base_url + '/clients/' + clientId);
// Fetch Services first, then Client data
$.ajax({
url: base_url + '/api/services',
type: 'GET',
success: function(services) {
let $servicesSelect = $('#edit_services');
$servicesSelect.empty();
services.forEach(function(s) {
$servicesSelect.append(new Option(s.name, s.id));
});
// Now fetch client details
$.ajax({
url: base_url + '/clients/' + clientId + '/json',
type: 'GET',
success: function(client) {
$('#edit_name').val(client.name);
$('#edit_email').val(client.email);
$('#edit_phone').val(client.phone);
$('#edit_contact_person').val(client.contact_person);
$('#edit_company_type').val(client.company_type);
$('#edit_contract_type').val(client.contract_type);
$('#edit_industry').val(client.industry);
$('#edit_status').val(client.status);
$('#edit_currency').val(client.currency);
$('#edit_country').val(client.country);
// Helper function to set values for Select2 multi-select tags fields
function setSelect2Values(selector, values) {
let $el = $(selector);
$el.val(null).trigger('change');
if (values && Array.isArray(values)) {
values.forEach(function(val) {
if ($el.find("option[value='" + val + "']").length === 0) {
$el.append(new Option(val, val, true, true));
}
});
$el.val(values).trigger('change');
}
}
setSelect2Values('#edit_services', client.services);
setSelect2Values('#edit_message_types', client.message_types);
setSelect2Values('#edit_connections', client.connections);
setSelect2Values('#edit_support_phones', client.support_phones);
setSelect2Values('#edit_support_emails', client.support_emails);
setSelect2Values('#edit_rate_emails', client.rate_emails);
setSelect2Values('#edit_support_skype', client.support_skype);
}
});
}
});
});
// Initialize Select2 with tags option enabled for all multi-select fields inside edit modal
$('#editClientModal').on('shown.bs.modal', function () {
$('#editClientModal .select2-tags').each(function() {
if (!$(this).hasClass("select2-hidden-accessible")) {
$(this).select2({
theme: 'bootstrap-5',
dropdownParent: $('#editClientModal'),
tags: true, // Allows typing custom entries for emails, phones, etc.
tokenSeparators: [',', ' '],
placeholder: 'Select or type and hit enter...'
});
}
});
});
// Clean up Select2 when modal closes
$('#editClientModal').on('hidden.bs.modal', function () {
$('#editClientModal .select2-tags').val(null).trigger('change');
});
// Submit Edit Client Form via AJAX
$(document).on('submit', '#editClientForm', function(e) {
e.preventDefault(); // Hard stop on native form post
let $form = $(this);
let $submitBtn = $form.find('button[type="submit"]');
let originalBtnText = $submitBtn.text();
$submitBtn.prop('disabled', true).text('Updating...');
$.ajax({
url: $form.attr('action'),
type: 'POST', // Spoofed as PUT via hidden input
data: $form.serialize(),
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
success: function(response) {
$('#editClientModal').modal('hide');
Swal.fire({
icon: 'success',
title: 'Updated!',
text: response.message || 'Client updated successfully.',
confirmButtonColor: '#0d6efd'
}).then(() => {
location.reload();
});
},
error: function(xhr) {
let errors = xhr.responseJSON?.errors;
let errorMsg = 'Something went wrong. Please check your inputs.';
if (errors) {
errorMsg = Object.values(errors).flat().join('\n');
}
Swal.fire({
icon: 'error',
title: 'Validation Error',
text: errorMsg,
confirmButtonColor: '#dc3545'
});
$submitBtn.prop('disabled', false).text(originalBtnText);
}
});
});
});
});

View File

@@ -0,0 +1,183 @@
$(document).ready(function() {
const mnoModal = new bootstrap.Modal(document.getElementById('mnoModal'));
const $form = $('#mnoForm');
function loadServicesAndOpen(callback) {
$.ajax({
url: base_url + '/api/services',
type: 'GET',
success: function(services) {
let $servicesSelect = $('#mnoServices');
$servicesSelect.empty();
services.forEach(function(s) {
$servicesSelect.append(new Option(s.name, s.id));
});
if (typeof callback === 'function') callback();
}
});
}
function setSelect2Values(selector, values) {
let $el = $(selector);
$el.val(null).trigger('change');
if (values && Array.isArray(values)) {
values.forEach(function(val) {
if ($el.find("option[value='" + val + "']").length === 0) {
// If it's a free-form tag not in the base options, append it
$el.append(new Option(val, val, true, true));
}
});
$el.val(values).trigger('change');
}
}
// --- OPEN MODAL FOR CREATE ---
$('#btnOpenMnoModal').on('click', function(e) {
e.preventDefault(); // Prevent any default anchor/button jump
$form[0].reset();
$('#mnoId').val('');
$('#methodField').html('');
$form.attr('action', "{{ route('mnos.store') }}");
$('#mnoModalTitle').text('Add New MNO');
$('#btnSubmitMno').html('<i class="bi bi-save me-2"></i>Save Gateway Profile');
// Clear all multi-selects first
$('#mnoServices, #mnoSupportEmails, #mnoFinanceEmails').val(null).trigger('change');
// Fetch services and then open the modal directly
$.ajax({
url: base_url + '/api/services',
type: 'GET',
success: function(services) {
let $servicesSelect = $('#mnoServices');
$servicesSelect.empty();
services.forEach(function(s) {
$servicesSelect.append(new Option(s.name, s.id));
});
$servicesSelect.trigger('change');
// Open modal safely once data is ready
mnoModal.show();
},
error: function() {
// Fallback: open modal even if service fetch fails
mnoModal.show();
}
});
});
// --- OPEN MODAL FOR EDIT ---
$(document).on('click', '.btn-edit-mno', function() {
const mnoId = $(this).data('id');
$form[0].reset();
$('#methodField').html('<input type="hidden" name="_method" value="PUT">');
$form.attr('action', base_url + '/mnos/' + mnoId);
$('#mnoModalTitle').text('Modify MNO Profile');
$('#btnSubmitMno').html('<i class="bi bi-check-circle me-2"></i>Apply Changes');
loadServicesAndOpen(function() {
$.ajax({
url: base_url + '/mnos/' + mnoId + '/json',
type: 'GET',
success: function(mno) {
$('#mnoId').val(mno.id);
$('#mnoName').val(mno.name);
$('#mnoCountry').val(mno.country);
$('#mnoConnectionStatus').val(mno.connection_status);
$('#mnoContactPerson').val(mno.contact_person);
$('#mnoContactPhone').val(mno.contact_person_phone);
$('#mnoContactEmail').val(mno.contact_person_email);
$('#mnoTechSupport').val(mno.technical_support_person);
$('#mnoSupportSkype').val(mno.support_skype);
$('#mnoAccountManager').val(mno.mno_account_manager);
$('#mnoBuyingRate').val(mno.buying_rate);
$('#mnoRateType').val(mno.rate_type);
$('#mnoPaymentTerms').val(mno.payment_terms);
$('#mnoConnectionType').val(mno.connection_type);
// Populate Select2 fields with existing records
setSelect2Values('#mnoServices', mno.services);
setSelect2Values('#mnoSupportEmails', mno.support_emails);
setSelect2Values('#mnoFinanceEmails', mno.finance_emails);
mnoModal.show();
},
error: function() {
Swal.fire('Error', 'Could not fetch MNO details.', 'error');
}
});
});
});
// --- INITIALIZE SELECT2 TAGS ON MODAL SHOWN ---
$('#mnoModal').on('shown.bs.modal', function () {
// Initialize Database-driven services multi-select (no custom tags allowed)
if (!$('#mnoServices').hasClass("select2-hidden-accessible")) {
$('#mnoServices').select2({
theme: 'bootstrap-5',
dropdownParent: $('#mnoModal'),
placeholder: 'Select services...'
});
}
// Initialize Email fields with custom tagging enabled (allows typing custom emails)
$('#mnoModal .select2-tags').each(function() {
if (!$(this).hasClass("select2-hidden-accessible")) {
$(this).select2({
theme: 'bootstrap-5',
dropdownParent: $('#mnoModal'),
tags: true,
tokenSeparators: [',', ' '],
placeholder: 'Type email and press enter...'
});
}
});
});
// --- AJAX FORM SUBMISSION ---
$form.on('submit', function(e) {
e.preventDefault();
const $btn = $('#btnSubmitMno');
const originalText = $btn.html();
$btn.html('<span class="spinner-border spinner-border-sm me-2"></span> Saving...');
$btn.prop('disabled', true);
$.ajax({
url: $form.attr('action'),
type: 'POST',
data: $form.serialize(),
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
success: function(response) {
mnoModal.hide();
Swal.fire({
icon: 'success',
title: 'Success!',
text: response.message || 'Saved successfully.',
confirmButtonColor: '#5c4df0'
}).then(() => {
location.reload();
});
},
error: function(xhr) {
let errors = xhr.responseJSON?.errors;
let errorMsg = 'Validation failed. Please check inputs.';
if (errors) {
errorMsg = Object.values(errors).flat().join('\n');
}
Swal.fire({
icon: 'error',
title: 'Error',
text: errorMsg,
confirmButtonColor: '#dc3545'
});
$btn.html(originalText).prop('disabled', false);
}
});
});
});