FIX_UI phase 1
This commit is contained in:
parent
24fe2b79c4
commit
b7e1e01b8a
@ -454,19 +454,44 @@ class LeadsController extends BaseController
|
||||
'errors' => ['required' => 'Entity Type is required'],
|
||||
];
|
||||
|
||||
$clientNameRules = 'required|regex_match[/^[a-zA-Z0-9_ -]+$/]';
|
||||
$clientShortNameRules = 'required|regex_match[/^[a-zA-Z0-9_-]+$/]';
|
||||
|
||||
// Only validate for uniqueness if it's a new client being specified.
|
||||
// If an existing client is selected from the dropdown, `client_id` will be present.
|
||||
if (empty($postData['client_id'])) {
|
||||
$ignoreClientId = null;
|
||||
if ($id) { // This is an update of a lead
|
||||
$lead = $this->leadsModel->find($id);
|
||||
if ($lead && !empty($lead['is_client_created'])) {
|
||||
$ignoreClientId = $lead['is_client_created'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($ignoreClientId) {
|
||||
$clientNameRules .= '|is_unique[clients.client_name,id,' . $ignoreClientId . ']';
|
||||
$clientShortNameRules .= '|is_unique[clients.short_name,id,' . $ignoreClientId . ']';
|
||||
} else {
|
||||
$clientNameRules .= '|is_unique[clients.client_name]';
|
||||
$clientShortNameRules .= '|is_unique[clients.short_name]';
|
||||
}
|
||||
}
|
||||
|
||||
$rules['client_name'] = [
|
||||
'rules' => 'required|regex_match[/^[a-zA-Z0-9_ -]+$/]',
|
||||
'rules' => $clientNameRules,
|
||||
'errors' => [
|
||||
'required' => 'Client Name is required',
|
||||
'regex_match' => 'Client Name only letters, numbers, space, hyphens and underscores are allowed',
|
||||
'is_unique' => 'This Client Name already exists.',
|
||||
],
|
||||
];
|
||||
|
||||
$rules['client_short_name'] = [
|
||||
'rules' => 'required|regex_match[/^[a-zA-Z0-9_-]+$/]',
|
||||
'rules' => $clientShortNameRules,
|
||||
'errors' => [
|
||||
'required' => 'Client Short Name is required',
|
||||
'regex_match' => 'Client Short Name only letters, numbers, hyphens and underscores are allowed'
|
||||
'required' => 'Client Short Name is required',
|
||||
'regex_match' => 'Client Short Name only letters, numbers, hyphens and underscores are allowed',
|
||||
'is_unique' => 'This Client Short Name already exists.',
|
||||
],
|
||||
];
|
||||
}
|
||||
@ -925,6 +950,11 @@ class LeadsController extends BaseController
|
||||
$insertCount[] = $insert;
|
||||
$this->insertLeadStatus($insert, $value['status'], 3);
|
||||
|
||||
if ($value['lead_type'] == 1 && $value['status'] == 'won') {
|
||||
$leadDataForClient = $this->leadsModel->find($insert);
|
||||
$this->createClientWithLeadData($leadDataForClient);
|
||||
}
|
||||
|
||||
if ($value['lead_form_type'] == 1) {
|
||||
//for this push the job to the calculateMembersDemography() function
|
||||
$job_details = new Jobs();
|
||||
@ -950,6 +980,14 @@ class LeadsController extends BaseController
|
||||
|
||||
$this->insertMultiFilesData($data[0]['multi_file_data'], $id, $data[0]['lead_form_type']);
|
||||
$this->insertLeadStatus($id, $data[0]['status'], 3);
|
||||
|
||||
if ($data[0]['lead_type'] == 1 && $data[0]['status'] == 'won') {
|
||||
$leadDataForClient = $this->leadsModel->find($id);
|
||||
if (empty($leadDataForClient['is_client_created'])) {
|
||||
$this->createClientWithLeadData($leadDataForClient);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->respond(['status' => true, 'lead_id' => $id, 'message' => "Opportunity updated successfully", 'data' => $data], 200);
|
||||
}
|
||||
return $this->respond(['status' => false, 'lead_id' => $id, 'message' => "Failed to update Opportunity", 'data' => $data], 200);
|
||||
|
||||
@ -78,13 +78,8 @@ table.dataTable tbody td {
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td {
|
||||
padding: 4px 4px !important;
|
||||
.col-12 {
|
||||
max-width: 98% !important;
|
||||
}
|
||||
|
||||
/* Tooltip Styles */
|
||||
@ -247,9 +242,12 @@ table.dataTable tbody td {
|
||||
border:1px solid rgba(41, 139, 142, 1);
|
||||
}
|
||||
|
||||
.dt-buttons.btn-group{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr .4fr .5fr .2fr;
|
||||
.dt-buttons.btn-group{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
#user-table_filter input{ width:100%; }
|
||||
@ -361,15 +359,15 @@ table.dataTable tbody td {
|
||||
<h4 style="position: relative;">Users</h4>
|
||||
</div>
|
||||
</div> -->
|
||||
<table data-custom-table-css="table" class="table table-sm m-0 table-centered dt-responsive nowrap w-100" cellspacing="a" id="user-table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="user-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium">Name</th>
|
||||
<th class="font-weight-medium">Email</th>
|
||||
<th class="font-weight-medium">Mobile No</th>
|
||||
<th class="font-weight-medium">Role</th>
|
||||
<th class="font-weight-medium">Status</th>
|
||||
<th class="font-weight-medium">Action</th>
|
||||
<th class="font-weight-medium">Name </th>
|
||||
<th class="font-weight-medium">Email </th>
|
||||
<th class="font-weight-medium">Mobile No </th>
|
||||
<th class="font-weight-medium">Role </th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -384,8 +382,8 @@ table.dataTable tbody td {
|
||||
<?php if($row->is_active == 1){ echo 'Active'; }else{ echo 'In-Active'; } ?>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group dropdown" style="position: relative !important;left:0px !important;top:0px !important;">
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right" style="cursor: pointer;">
|
||||
<a class="dropdown-item btnEdit" data-id="<?php echo $row->id; ?>"><i data-id="<?php echo $row->id; ?>" class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle btnEdit"></i>Edit</a>
|
||||
@ -611,7 +609,7 @@ table.dataTable tbody td {
|
||||
<div class="modal-body p-4">
|
||||
<div class="">
|
||||
|
||||
<form role="form" class="parsley-examples" method="post" id="PartnerForm" action="" enctype="multipart/form-data">
|
||||
<form role="form" class="parsley-examples" method="post" id="PartnerForm" action="" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>"/>
|
||||
<input type="hidden" name="PrimaryKey" id="partner_id" name="id"/>
|
||||
<div class="form-group">
|
||||
@ -619,23 +617,22 @@ table.dataTable tbody td {
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="partner_name">Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="partner_name" placeholder="Enter Name" name="name" required>
|
||||
<input type="text" class="form-control" id="partner_name" placeholder="Enter Name" name="name" required data-parsley-pattern="^[a-zA-Z\s\.]+$" data-parsley-trigger="keyup" data-parsley-pattern-message="Please enter a valid name (letters, spaces, dots only).">
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="mobile_no">Mobile Number<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="mobile_no" placeholder="Enter Mobile Number ( starting with 6, 7, 8, or 9 only. )" name="mobile" onkeypress = "return onlyNumbers(event)" maxlength="10" minlength="10" pattern="^[6-9]\d{9}$" data-parsley-type-message="Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9." data-parsley-required-message="Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9." required>
|
||||
<input type="text" class="form-control" id="mobile_no" placeholder="Enter Mobile Number ( starting with 6, 7, 8, or 9 only. )" name="mobile" maxlength="10" minlength="10" pattern="^[6-9]\d{9}$" data-parsley-type-message="Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9." data-parsley-required-message="Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9." required data-parsley-trigger="keyup">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="email_addr">Email<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="email_addr" placeholder="Enter Email" name="email" data-parsley-trigger="change" data-parsley-type="email" required>
|
||||
<input type="email" class="form-control" id="email_addr" placeholder="Enter Email" name="email" data-parsley-trigger="keyup" data-parsley-type="email" required>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="retention_rate">Retention Rate<span class="text-danger">*</span></label>
|
||||
<!-- <input type="text" class="form-control" id="retention_rate" placeholder="Enter Retention Rate" name="retention_rate" required> -->
|
||||
<input type="text" class="form-control" id="retention_rate" name="retention_rate" placeholder="Enter Retention Rate" inputmode="decimal" required>
|
||||
<input type="text" class="form-control" id="retention_rate" name="retention_rate" placeholder="Enter Retention Rate" inputmode="decimal" required data-parsley-type="number" data-parsley-min="0" data-parsley-min-message="Retention rate cannot be negative.">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -662,7 +659,7 @@ table.dataTable tbody td {
|
||||
|
||||
<div class="form-group text-right m-b-0">
|
||||
<button class="btn app-btn-outline-secondary mr-2 " type="button" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||
<button class="btn app-btn-secondary waves-effect waves-light" type="button" id="btnPartnerSubmit" onclick="submitPartner(event)">Submit</button>
|
||||
<button class="btn app-btn-secondary waves-effect waves-light" type="submit" id="btnPartnerSubmit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -1060,11 +1057,15 @@ table.dataTable tbody td {
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
initComplete: function () {
|
||||
$(".dt-buttons").prepend(`
|
||||
<div class="tab-button mr-2" id="toggleButton" style="float:left;">
|
||||
<div class="tab-button mr-2" id="toggleButton" style="margin-right:auto;">
|
||||
<span id="btnUsers" class="highlight-link active">Users</span>
|
||||
<span class="divider-line"> | </span>
|
||||
<span id="btnPartners" class="highlight-link">Nhance Partner</span>
|
||||
@ -1085,6 +1086,26 @@ table.dataTable tbody td {
|
||||
}
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#user-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#user-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
// Mark last two rows on current page to open action menu upward.
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
|
||||
applyBottomRowDropup();
|
||||
$('#user-table').on('draw.dt', applyBottomRowDropup);
|
||||
|
||||
// IMPORTANT — DataTables draw event REF: TTS
|
||||
table.on('draw.dt', function () {
|
||||
|
||||
@ -1243,6 +1264,8 @@ table.dataTable tbody td {
|
||||
});
|
||||
|
||||
$('body').on('click', '.btnPartnerEdit', function () {
|
||||
$('#PartnerForm').parsley().reset();
|
||||
|
||||
let user = JSON.parse($(this).attr('data-obj')); // ✅ convert back to object
|
||||
$('#PartnerForm').attr('action', '<?php echo base_url('/user/partner');?>');
|
||||
$('#partner_id').val(user.id);
|
||||
@ -1328,13 +1351,6 @@ table.dataTable tbody td {
|
||||
|
||||
});
|
||||
|
||||
function onlyNumbers(event){
|
||||
var charcode;
|
||||
charcode = event.which || event.keyCode;
|
||||
if(charcode>= 48 && charcode <= 57)return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
var form = document.getElementById("UserForm");
|
||||
|
||||
form.addEventListener("submit", function(event) {
|
||||
@ -1426,58 +1442,18 @@ form.addEventListener("submit", function(event) {
|
||||
});
|
||||
});
|
||||
|
||||
function submitPartner(event) {
|
||||
event.preventDefault();
|
||||
$('#PartnerForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
var $form = $(this);
|
||||
|
||||
$form.parsley().validate();
|
||||
|
||||
var form = document.getElementById('PartnerForm');
|
||||
if ($form.parsley().isValid()) {
|
||||
var btn = document.getElementById('btnPartnerSubmit');
|
||||
var myModal = new bootstrap.Modal(document.getElementById('nhance-partner-modal'));
|
||||
|
||||
// reset any old error styles
|
||||
form.classList.remove('was-validated');
|
||||
|
||||
var name = document.getElementById('partner_name').value.trim();
|
||||
var mobile = document.getElementById('mobile_no').value.trim();
|
||||
var email = document.getElementById('email_addr').value.trim();
|
||||
// var address = document.getElementById('locn').value.trim();
|
||||
var rate = document.getElementById('retention_rate').value.trim();
|
||||
var nb = document.getElementById('partner_nhance_branch_id').value.trim();
|
||||
|
||||
// Validation checks
|
||||
if (name === "" || mobile === "" || email === "" || rate === "" || nb === "") {
|
||||
// console.log(name);
|
||||
// console.log(mobile);
|
||||
// console.log(email);
|
||||
toastr.warning('Please fill all required fields.', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
|
||||
// if (address.length > 1500) {
|
||||
// toastr.error('Address cannot exceed 1500 characters', 'Warning');
|
||||
// form.classList.add('was-validated');
|
||||
// return;
|
||||
// }
|
||||
|
||||
var mobilePattern = /^[6-9]\d{9}$/; // must start with 6–9 and be 10 digits
|
||||
if (!mobilePattern.test(mobile)) {
|
||||
toastr.warning('Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9.', 'Warning');
|
||||
document.getElementById('mobile').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var emailPattern = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
||||
if (!emailPattern.test(email)) {
|
||||
toastr.warning('Please enter a valid email address.', 'Warning');
|
||||
document.getElementById('email').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable button during submit
|
||||
btn.disabled = true;
|
||||
btn.innerText = "Saving...";
|
||||
|
||||
var formData = new FormData(form);
|
||||
var formData = new FormData(this);
|
||||
|
||||
$.ajax({
|
||||
url: "<?= base_url('user/partner') ?>",
|
||||
@ -1489,8 +1465,9 @@ form.addEventListener("submit", function(event) {
|
||||
success: function(response) {
|
||||
if (response.status === "success") {
|
||||
toastr.success('Partner saved successfully!', 'Success');
|
||||
myModal.hide();
|
||||
form.reset(); // reset form after success
|
||||
$('#nhance-partner-modal').modal('hide');
|
||||
$form[0].reset();
|
||||
$('#partner_nhance_branch_id').val(null).trigger('change.select2');
|
||||
} else {
|
||||
toastr.warning(response.message || 'Something went wrong.', 'Warning');
|
||||
}
|
||||
@ -1498,41 +1475,38 @@ form.addEventListener("submit", function(event) {
|
||||
error: function(xhr) {
|
||||
console.log("Error: " + xhr.statusText);
|
||||
if (xhr.status === 400) {
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
let errorMessages = "";
|
||||
let seenMessages = []; // Array to store unique messages
|
||||
if (response.errors) {
|
||||
$.each(response.errors, function (field, message) {
|
||||
if (!seenMessages.includes(message)) {
|
||||
errorMessages += `• ${message}<br>`;
|
||||
seenMessages.push(message); // Mark this message as "seen"
|
||||
}
|
||||
});
|
||||
toastr.error(errorMessages, 'Validation Error', { "allowHtml": true });
|
||||
} else {
|
||||
toastr.warning(response.message || 'Validation failed', 'Warning');
|
||||
}
|
||||
|
||||
}else if (xhr.status === 403) {
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
toastr.error(response.message, 'Security Policy');
|
||||
} else if (xhr.status === 500) {
|
||||
toastr.error('Something went wrong . Please try again later.', 'Server Error');
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
let errorMessages = "";
|
||||
let seenMessages = [];
|
||||
if (response.errors) {
|
||||
$.each(response.errors, function (field, message) {
|
||||
if (!seenMessages.includes(message)) {
|
||||
errorMessages += `• ${message}<br>`;
|
||||
seenMessages.push(message);
|
||||
}
|
||||
});
|
||||
toastr.error(errorMessages, 'Validation Error', { "allowHtml": true });
|
||||
} else {
|
||||
toastr.error('An unexpected error occurred. Please try again later.', 'Error');
|
||||
toastr.warning(response.message || 'Validation failed', 'Warning');
|
||||
}
|
||||
console.error('Unexpected error:', xhr.responseText);
|
||||
|
||||
} else if (xhr.status === 403) {
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
toastr.error(response.message, 'Security Policy');
|
||||
} else if (xhr.status === 500) {
|
||||
toastr.error('Something went wrong . Please try again later.', 'Server Error');
|
||||
} else {
|
||||
toastr.error('An unexpected error occurred. Please try again later.', 'Error');
|
||||
}
|
||||
console.error('Unexpected error:', xhr.responseText);
|
||||
},
|
||||
complete: function() {
|
||||
btn.disabled = false;
|
||||
btn.innerText = "Submit";
|
||||
$('#nhance-partner-modal').removeClass('show').hide();
|
||||
$('.modal-backdrop').remove();
|
||||
btn.innerText = "Submit";
|
||||
loadPartner();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function submitIncentivePartner(event) {
|
||||
event.preventDefault();
|
||||
@ -1683,7 +1657,8 @@ form.addEventListener("submit", function(event) {
|
||||
];
|
||||
}
|
||||
|
||||
table.row.add(rowData);
|
||||
let newRow = table.row.add(rowData);
|
||||
$(newRow.node()).find('td:last').addClass('text-center table-action-cell');
|
||||
});
|
||||
} else {
|
||||
// Show placeholder if no data
|
||||
@ -2122,6 +2097,8 @@ form.addEventListener("submit", function(event) {
|
||||
// myModal.show(); // open modal
|
||||
// });
|
||||
$(document).on('click', '#btnNhancePartnerAdd', function(){
|
||||
$('#PartnerForm')[0].reset();
|
||||
$('#PartnerForm').parsley().reset();
|
||||
$('#partner_name').val('');
|
||||
$('#email_addr').val('');
|
||||
$('#partner_id').val('');
|
||||
|
||||
@ -1,17 +1,4 @@
|
||||
<style>
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td {
|
||||
padding: 4px 4px !important;
|
||||
}
|
||||
|
||||
table.dataTable thead th {
|
||||
padding: 4px 4px !important;
|
||||
}
|
||||
|
||||
.col-12{
|
||||
|
||||
max-width: 98% !important;
|
||||
@ -35,15 +22,14 @@ table.dataTable thead th {
|
||||
</div> -->
|
||||
<!-- <table data-custom-table-css="table" class="table table-sm table-hover m-0 table-centered dt-responsive nowrap w-100" cellspacing="0"
|
||||
id="tickets-table"> -->
|
||||
<div class="table-responsive">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap w-100 table-centered" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="tickets-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium"><div class="column-header">Advertisement Image Name</div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Client Name</div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Client Short Name</div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Status</div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Action</div></th>
|
||||
<th class="font-weight-medium">Advertisement Image Name </th>
|
||||
<th class="font-weight-medium">Client Name </th>
|
||||
<th class="font-weight-medium">Client Short Name </th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -54,7 +40,7 @@ table.dataTable thead th {
|
||||
<td class="client_info" ><?php echo $row['client_id'] != 0 ? $row['client_name'] : '-' ; ?></td>
|
||||
<td class="client_info" ><?php echo $row['client_id'] != 0 ? $row['short_name'] : '-'; ?></td>
|
||||
<td class="client_info" ><?php echo $row['status']; ?></td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
@ -68,7 +54,6 @@ table.dataTable thead th {
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- end col -->
|
||||
@ -86,7 +71,7 @@ table.dataTable thead th {
|
||||
<h4 id="advertise_add_edit">Add Advertise Image </h4>
|
||||
</div>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<form id="model_form_data" class="px-4" enctype="multipart/form-data">
|
||||
<form id="model_form_data" class="px-4" enctype="multipart/form-data" data-parsley-validate data-parsley-excluded="[disabled]">
|
||||
<input type="hidden" name="add_image_id" id="add_image_id" value="0">
|
||||
|
||||
<!-- old
|
||||
@ -126,15 +111,27 @@ table.dataTable thead th {
|
||||
<div class="form-group">
|
||||
<label for="branchname">Upload Image</label>
|
||||
<div class="input-icon">
|
||||
<input type="file" class="form-control" name="advertise_image" id="advertise_image" accept=".jpg,.jpeg,.png" onchange="PreviewImage();" required>
|
||||
<input type="file" class="form-control" name="advertise_image" id="advertise_image" accept=".jpg,.jpeg,.png" onchange="PreviewImage();" required
|
||||
data-parsley-required-message="Image is required"
|
||||
data-parsley-allowed-ext="true"
|
||||
data-parsley-max-file-size="true"
|
||||
data-parsley-exact-dimensions="true"
|
||||
data-parsley-errors-container="#advertise_image_error">
|
||||
<i class="mdi mdi-upload additional-icon"></i>
|
||||
</div>
|
||||
<div id="advertise_image_error"></div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom section -->
|
||||
<div class="form-group">
|
||||
<label for="client_branch">Client <span class="text-danger">*</span></label>
|
||||
<select class="form-control" id="client_id" name="client_id" required>
|
||||
<select class="form-control" id="client_id" name="client_id" required
|
||||
data-parsley-required-message="Client is required"
|
||||
data-parsley-type="integer"
|
||||
data-parsley-min="0"
|
||||
data-parsley-min-message="Invalid client selected"
|
||||
data-parsley-type-message="Invalid client selected"
|
||||
data-parsley-errors-container="#client_id_error">
|
||||
<option value="">Select Client</option>
|
||||
<option value="0">Default Image</option>
|
||||
<?php
|
||||
@ -145,6 +142,7 @@ table.dataTable thead th {
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<div id="client_id_error"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -175,23 +173,18 @@ table.dataTable thead th {
|
||||
|
||||
|
||||
function submitBranch() {
|
||||
var form = $('#model_form_data');
|
||||
form.parsley().validate();
|
||||
|
||||
if (!form.parsley().isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fileInput = $('#advertise_image')[0].files[0]; // get actual file object
|
||||
const imageId = $('#add_image_id').val();
|
||||
const clientId = $('#client_id').val();
|
||||
|
||||
|
||||
if (!fileInput) {
|
||||
toastr.warning('Please upload an image before submitting', 'Warning');
|
||||
$('#advertise_image').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!clientId){
|
||||
toastr.warning('Please Select Client.', 'Warning');
|
||||
$('#client_id').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var url = '<?= base_url("add_advertise_image") ?>';
|
||||
var formData = new FormData();
|
||||
formData.append('advertise_image', fileInput);
|
||||
@ -267,16 +260,26 @@ table.dataTable thead th {
|
||||
console.log('function called');
|
||||
var fileInput = document.getElementById("advertise_image");
|
||||
var file = fileInput.files[0];
|
||||
var $fileInput = $(fileInput);
|
||||
|
||||
$fileInput.removeAttr('data-dimension-valid');
|
||||
$fileInput.removeAttr('data-size-valid');
|
||||
$fileInput.removeAttr('data-ext-valid');
|
||||
|
||||
if (file) {
|
||||
var allowedExtensions = ["jpg", "jpeg", "png"];
|
||||
var fileExtension = file.name.split('.').pop().toLowerCase();
|
||||
|
||||
if (!allowedExtensions.includes(fileExtension) || file.size > 200 * 1024) {
|
||||
toastr.warning('Maximum file size allowed is 200KB.', 'File size exceeds limit.');
|
||||
fileInput.value = ""; // Clear the file input
|
||||
document.getElementById("uploadPreview").src = "<?= base_url()."public/assets/images/avatar_2x.png" ?>"; // Remove the preview image
|
||||
return;
|
||||
if (!allowedExtensions.includes(fileExtension)) {
|
||||
$fileInput.attr('data-ext-valid', 'false');
|
||||
} else {
|
||||
$fileInput.attr('data-ext-valid', 'true');
|
||||
}
|
||||
|
||||
if (file.size > 200 * 1024) {
|
||||
$fileInput.attr('data-size-valid', 'false');
|
||||
} else {
|
||||
$fileInput.attr('data-size-valid', 'true');
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
@ -288,15 +291,18 @@ table.dataTable thead th {
|
||||
|
||||
img.onload = function () {
|
||||
if (img.width !== 1640 || img.height !== 664) {
|
||||
toastr.warning('Image dimensions must be 1640x664 pixels.', 'Invalid image dimensions.');
|
||||
|
||||
fileInput.value = ""; // Clear the file input
|
||||
$fileInput.attr('data-dimension-valid', 'false');
|
||||
document.getElementById("uploadPreview").src = "<?= base_url()."public/assets/images/avatar_2x.png" ?>"; // Remove the preview image
|
||||
} else {
|
||||
$fileInput.attr('data-dimension-valid', 'true');
|
||||
document.getElementById("uploadPreview").src = img.src;
|
||||
}
|
||||
$fileInput.parsley().validate();
|
||||
};
|
||||
};
|
||||
} else {
|
||||
document.getElementById("uploadPreview").src = "<?= base_url()."public/assets/images/avatar_2x.png" ?>";
|
||||
$fileInput.parsley().validate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +310,31 @@ table.dataTable thead th {
|
||||
var table;
|
||||
|
||||
$(document).ready(function() {
|
||||
window.Parsley.addValidator('allowedExt', {
|
||||
validateString: function(value, requirement, parsleyInstance) {
|
||||
return parsleyInstance.$element.attr('data-ext-valid') !== 'false';
|
||||
},
|
||||
messages: { en: 'Only JPG, JPEG, PNG allowed' }
|
||||
});
|
||||
|
||||
window.Parsley.addValidator('maxFileSize', {
|
||||
validateString: function(value, requirement, parsleyInstance) {
|
||||
return parsleyInstance.$element.attr('data-size-valid') !== 'false';
|
||||
},
|
||||
messages: { en: 'Image size must not exceed 200 KB' }
|
||||
});
|
||||
|
||||
window.Parsley.addValidator('exactDimensions', {
|
||||
validateString: function(value, requirement, parsleyInstance) {
|
||||
return parsleyInstance.$element.attr('data-dimension-valid') !== 'false';
|
||||
},
|
||||
messages: { en: 'Image dimensions must be exactly 1640x664 pixels' }
|
||||
});
|
||||
|
||||
$('#client_id').select2();
|
||||
$('#client_id').on('select2:select select2:clear', function () {
|
||||
$(this).parsley().validate();
|
||||
});
|
||||
$('#add_image_id').val('');
|
||||
$('#client_id').val(null).trigger('change');
|
||||
$('#advertise_image').val('');
|
||||
@ -336,10 +366,33 @@ table.dataTable thead th {
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#tickets-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
|
||||
applyBottomRowDropup();
|
||||
$('#tickets-table').on('draw.dt', applyBottomRowDropup);
|
||||
});
|
||||
|
||||
// ✅ Define your modal function separately
|
||||
@ -348,6 +401,10 @@ table.dataTable thead th {
|
||||
$('#client_id').val(null).trigger('change');
|
||||
$('#advertise_add_edit').html('Add Advertise Image');
|
||||
$('#uploadPreview').attr('src', '<?= base_url()."public/assets/images/avatar_2x.png" ?>');
|
||||
$('#advertise_image').prop('required', true);
|
||||
if ($('#model_form_data').length) {
|
||||
$('#model_form_data').parsley().reset();
|
||||
}
|
||||
$('#bike_model_login-modal').modal('show'); // ✅ this shows the modal
|
||||
var myModal = new bootstrap.Modal(document.getElementById('bike_make_login-modal'));
|
||||
myModal.show();
|
||||
@ -442,6 +499,10 @@ table.dataTable thead th {
|
||||
|
||||
// 5. Clear the file input
|
||||
$('#advertise_image').val('');
|
||||
$('#advertise_image').prop('required', false);
|
||||
if ($('#model_form_data').length) {
|
||||
$('#model_form_data').parsley().reset();
|
||||
}
|
||||
|
||||
// 6. Show the modal
|
||||
var myModal = new bootstrap.Modal(document.getElementById('bike_make_login-modal'));
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<table data-custom-table-css="table" class="table table-hover m-0 table-centered dt-responsive w-100" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" class="table table-hover m-0 table-centered w-100" cellspacing="0" id="tickets-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium">S.No </th>
|
||||
@ -65,7 +65,7 @@
|
||||
<span> <?= $file['status'] ?> </span>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm"
|
||||
data-toggle="dropdown" aria-expanded="false"><i
|
||||
@ -279,7 +279,7 @@
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Add',
|
||||
text: '<i class="mdi mdi-plus" ></i><span class=" btn-custom"> Add </span>',
|
||||
className: 'buttons-html5 addbtnStyle',
|
||||
action: function (e, dt, node, config) {
|
||||
openDumpUploadModal();
|
||||
@ -296,11 +296,33 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true, // Enable pagination
|
||||
pageLength: 15, // Set default number of rows per page (optional)
|
||||
pageLength: 10, // Set default number of rows per page (optional)
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!ticketsTable) return;
|
||||
const currentRows = ticketsTable.DataTable().rows({ page: 'current' }).nodes().toArray();
|
||||
$('#tickets-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
|
||||
applyBottomRowDropup();
|
||||
ticketsTable.on('draw.dt', applyBottomRowDropup);
|
||||
} else {
|
||||
console.error("Table not found.");
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="">
|
||||
<form role="form" class="parsley-examples" id="CDMasterForm" enctype="multipart/form-data">
|
||||
<form role="form" class="parsley-examples" id="CDMasterForm" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" name="PrimaryKey" id="CD_Master_ID" />
|
||||
<div class="form-group">
|
||||
|
||||
@ -67,12 +67,22 @@
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="mobile">CD Account Number<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="cd_ac_no_for_cd_master" name="cd_ac_no" pattern="[a-zA-Z0-9\/_-]+" title="Only letters, numbers, /, -, and _ are allowed" required> <small style="margin-left: 10px;font-size: 10px;"><span class="text-danger" id="cd_ac_no_for_cd_master_errorr"></span></small>
|
||||
<input type="text" class="form-control" id="cd_ac_no_for_cd_master" name="cd_ac_no"
|
||||
required
|
||||
data-parsley-pattern="^[a-zA-Z0-9\/_-]+$"
|
||||
data-parsley-pattern-message="Only letters, numbers, /, -, and _ are allowed."
|
||||
data-parsley-trigger="keyup">
|
||||
<small style="margin-left: 10px;font-size: 10px;"><span class="text-danger" id="cd_ac_no_for_cd_master_errorr"></span></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="mobile">Opening Amount<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="opening_bal" name="opening_bal" onkeypress="return onlyNumbers(event)" required data-parsley-type="digits">
|
||||
<input type="text" class="form-control" id="opening_bal" name="opening_bal"
|
||||
required
|
||||
data-parsley-type="number"
|
||||
data-parsley-min="0"
|
||||
data-parsley-type-message="Opening amount must be numeric."
|
||||
data-parsley-min-message="Opening amount cannot be negative.">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -80,7 +90,7 @@
|
||||
|
||||
<div id="cdButtonWrapper" class="form-group text-right m-b-0">
|
||||
<button class="btn app-btn-outline-secondary mr-2 " type="button" class="close" data-dismiss="modal" aria-hidden="true" onclick="resetCdMasterFormModal()">Cancel</button>
|
||||
<button class="btn btn-primary waves-effect waves-light" id="cd_master_btn_Submit">Submit</button>
|
||||
<button type="submit" class="btn btn-primary waves-effect waves-light" id="cd_master_btn_Submit">Submit</button>
|
||||
<!-- <button type="button" class="btn btn-secondry waves-effect waves-light mr-1" data-dismiss="modal" aria-hidden="true">Close</button> -->
|
||||
</div>
|
||||
</form>
|
||||
@ -235,13 +245,6 @@
|
||||
});
|
||||
});
|
||||
|
||||
function onlyNumbers(event) {
|
||||
var charcode;
|
||||
charcode = event.which || event.keyCode;
|
||||
if (charcode >= 48 && charcode <= 57 || charcode == 46) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function resetCdMasterFormModal(){
|
||||
|
||||
console.log("resetCdMasterFormModal() function called");
|
||||
@ -365,33 +368,4 @@
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Target the input by its ID
|
||||
$('#cd_ac_no_for_cd_master').on('keypress', function(e) {
|
||||
// Get the character code
|
||||
var keyCode = e.which || e.keyCode;
|
||||
var char = String.fromCharCode(keyCode);
|
||||
|
||||
// Regular Expression: allow a-z, A-Z, 0-9, /, -, _
|
||||
// If the character doesn't match, prevent it from being typed
|
||||
var regex = /^[a-zA-Z0-9\/_-]+$/;
|
||||
|
||||
if (!regex.test(char)) {
|
||||
e.preventDefault();
|
||||
// Optional: Show a quick error message in your span
|
||||
$('#cd_ac_no_for_cd_master_errorr').text('Character not allowed').fadeOut(2000, function() {
|
||||
$(this).text('').show();
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Also handle "Paste" to ensure invalid data isn't pasted in
|
||||
$('#cd_ac_no_for_cd_master').on('input', function() {
|
||||
var value = $(this).val();
|
||||
var sanitized = value.replace(/[^a-zA-Z0-9\/_-]/g, '');
|
||||
$(this).val(sanitized);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
@ -1,17 +1,4 @@
|
||||
<style>
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td {
|
||||
padding: 4px 4px !important;
|
||||
}
|
||||
|
||||
table.dataTable thead th {
|
||||
padding: 4px 4px !important;
|
||||
}
|
||||
|
||||
.col-12 {
|
||||
|
||||
max-width: 98% !important;
|
||||
@ -19,38 +6,8 @@ table.dataTable thead th {
|
||||
|
||||
.column-header {margin-right: 10px;}
|
||||
|
||||
.custom-dropdown-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #ffffff !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 0;
|
||||
min-width: 10rem;
|
||||
z-index: 9999;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
padding: 0.5rem 1rem !important;
|
||||
color: #212529 !important;
|
||||
text-decoration: none !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
color: #16181b !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.dataTables_filter {
|
||||
position: absolute;
|
||||
}
|
||||
.dataTables_length label {height: 21px !important;}
|
||||
|
||||
|
||||
@ -71,21 +28,21 @@ table.dataTable thead th {
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<table data-custom-table-css="table" id="scroll-horizontal-datatable" class="table w-100 nowrap text-custom-black text-custom app-datatable">
|
||||
<table data-custom-table-css="table" id="scroll-horizontal-datatable" class="table mb-0 nowrap" cellspacing="0">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium"> <div class="column-header">S.No </div> </th>
|
||||
<th class="font-weight-medium"> <div class="column-header">Client Name </div> </th>
|
||||
<th class="font-weight-medium"> <div class="column-header">Insurer Name </div> </th>
|
||||
<th class="font-weight-medium"> <div class="column-header">Insurer Branch Name </div> </th>
|
||||
<th class="font-weight-medium"> <div class="column-header">Opening Date </div> </th>
|
||||
<th class="font-weight-medium"> <div class="column-header">CD Account No </div> </th>
|
||||
<th class="font-weight-medium"> <div class="column-header">Opening Amount </div> </th>
|
||||
<th class="font-weight-medium"> <div class="column-header">Date/User </div> </th>
|
||||
<th class="font-weight-medium"> <div class="column-header">Action </div> </th>
|
||||
<th class="font-weight-medium">S.No </th>
|
||||
<th class="font-weight-medium">Client Name </th>
|
||||
<th class="font-weight-medium">Insurer Name </th>
|
||||
<th class="font-weight-medium">Insurer Branch Name </th>
|
||||
<th class="font-weight-medium">Opening Date </th>
|
||||
<th class="font-weight-medium">CD Account No </th>
|
||||
<th class="font-weight-medium">Opening Amount </th>
|
||||
<th class="font-weight-medium">Date/User </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="app-table-body">
|
||||
<tbody>
|
||||
<?php foreach($CD_Master_Data as $index => $row){ ?>
|
||||
<tr>
|
||||
<td class="text-center"><?= $index + 1; ?></td>
|
||||
@ -96,7 +53,7 @@ table.dataTable thead th {
|
||||
<td><?php echo $row['cd_ac_no']; ?></td>
|
||||
<td><?php echo $row['opening_bal']; ?></td>
|
||||
<td><?php echo date('d-M-Y h:i A', strtotime($row['created_at'])) ?> <br>by <?php echo $row['user_name']; ?></td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);"class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
@ -107,8 +64,8 @@ table.dataTable thead th {
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -119,105 +76,11 @@ table.dataTable thead th {
|
||||
|
||||
<?php include("cd_master_add_modal.php"); ?>
|
||||
|
||||
<script>
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const table = document.getElementById("scroll-horizontal-datatable");
|
||||
|
||||
// Create custom dropdown
|
||||
function createCustomDropdown(row) {
|
||||
const originalDropdown = row.querySelector('.dropdown-menu');
|
||||
if (!originalDropdown) return null;
|
||||
|
||||
const customDropdown = document.createElement('div');
|
||||
customDropdown.className = 'custom-dropdown-menu';
|
||||
customDropdown.innerHTML = originalDropdown.innerHTML;
|
||||
|
||||
return customDropdown;
|
||||
}
|
||||
|
||||
let activeDropdown = null;
|
||||
|
||||
// Add click event listener to rows
|
||||
table.querySelectorAll("tbody tr").forEach(row => {
|
||||
const customDropdown = createCustomDropdown(row);
|
||||
if (!customDropdown) return;
|
||||
|
||||
row.customDropdown = customDropdown;
|
||||
document.body.appendChild(customDropdown);
|
||||
|
||||
row.addEventListener("click", function(event) {
|
||||
// Ignore clicks on the last column (action column)
|
||||
if (event.target.closest('td') === row.lastElementChild) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide any active dropdown
|
||||
if (activeDropdown && activeDropdown !== customDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
}
|
||||
|
||||
// Toggle the dropdown display
|
||||
const isActive = customDropdown.style.display === 'block';
|
||||
customDropdown.style.display = isActive ? 'none' : 'block';
|
||||
|
||||
// Set the position of the dropdown
|
||||
const rect = event.target.closest('td').getBoundingClientRect();
|
||||
customDropdown.style.position = 'absolute';
|
||||
customDropdown.style.left = `${rect.left}px`;
|
||||
customDropdown.style.top = `${rect.bottom + 5}px`;
|
||||
|
||||
// Set as active dropdown
|
||||
activeDropdown = isActive ? null : customDropdown;
|
||||
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Preserve click handlers for modal actions
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
const isModalAction = this.hasAttribute('data-toggle') && this.getAttribute('data-toggle') === 'modal';
|
||||
if (isModalAction) {
|
||||
return; // Allow modal to function normally
|
||||
}
|
||||
|
||||
// Close the dropdown if it's not related to modal
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
|
||||
const onclickAttr = this.getAttribute('onclick');
|
||||
if (onclickAttr) {
|
||||
eval(onclickAttr);
|
||||
}
|
||||
|
||||
const href = this.getAttribute('href');
|
||||
if (href && href !== '#') {
|
||||
window.location.href = href;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
document.addEventListener("click", function() {
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#scroll-horizontal-datatable').DataTable({
|
||||
var table = $('#scroll-horizontal-datatable').DataTable({
|
||||
scrollX: true,
|
||||
// dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" +
|
||||
// "<'row'<'col-sm-12'tr>>" +
|
||||
@ -270,7 +133,11 @@ table.dataTable thead th {
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true,
|
||||
pageLength: 10,
|
||||
@ -303,6 +170,23 @@ table.dataTable thead th {
|
||||
// },
|
||||
// paging: true,
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#scroll-horizontal-datatable tbody tr').removeClass('nh-force-dropup');
|
||||
$('#scroll-horizontal-datatable tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
$('#scroll-horizontal-datatable').on('draw.dt', applyBottomRowDropup);
|
||||
})
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
@ -131,7 +131,7 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<table data-custom-table-css="table" class="table table-hover m-0 table-centered dt-responsive w-100" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" class="table table-hover m-0 table-centered w-100" cellspacing="0" id="tickets-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium">S.No </th>
|
||||
@ -174,7 +174,7 @@
|
||||
<span style="color : #34A853 ;"> <?= $file['status'] ?> </span>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm"
|
||||
data-toggle="dropdown" aria-expanded="false"><i
|
||||
@ -486,7 +486,7 @@
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Add',
|
||||
text: '<i class="mdi mdi-plus" ></i><span class=" btn-custom"> Add </span>',
|
||||
className: 'buttons-html5 addbtnStyle',
|
||||
action: function (e, dt, node, config) {
|
||||
openDumpUploadModal();
|
||||
@ -503,11 +503,33 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true, // Enable pagination
|
||||
pageLength: 15, // Set default number of rows per page (optional)
|
||||
pageLength: 10, // Set default number of rows per page (optional)
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!ticketsTable) return;
|
||||
const currentRows = ticketsTable.DataTable().rows({ page: 'current' }).nodes().toArray();
|
||||
$('#tickets-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
|
||||
applyBottomRowDropup();
|
||||
ticketsTable.on('draw.dt', applyBottomRowDropup);
|
||||
} else {
|
||||
console.error("Table not found.");
|
||||
}
|
||||
|
||||
@ -308,7 +308,7 @@
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Add',
|
||||
text: '<i class="mdi mdi-plus"></i><span class="btn-custom"> Add </span>',
|
||||
className: 'buttons-html5 addbtnStyle',
|
||||
action: function (e, dt, node, config) {
|
||||
openDumpUploadModal();
|
||||
|
||||
@ -126,6 +126,9 @@ input:checked + .slider-branch-contact:before {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="branch_list">
|
||||
<tr id="branch_no_data_row">
|
||||
<td colspan="3" class="text-center">No data available</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -306,6 +309,16 @@ var branch_form_action = '';
|
||||
var contactCount = 1;
|
||||
var branch_PrimaryKey = $('#client_id_for_client_branch').val();
|
||||
|
||||
function ensureBranchNoDataRow() {
|
||||
const branchList = $('#branch_list');
|
||||
const hasDataRows = branchList.find('tr').not('#branch_no_data_row').length > 0;
|
||||
if (hasDataRows) {
|
||||
$('#branch_no_data_row').remove();
|
||||
} else if ($('#branch_no_data_row').length === 0) {
|
||||
branchList.append('<tr id="branch_no_data_row"><td colspan="3" class="text-center">No data available</td></tr>');
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
branch_PrimaryKey = $('#client_id_branch').val();
|
||||
@ -350,8 +363,11 @@ $(document).ready(function() {
|
||||
|
||||
});
|
||||
$('#branch_list').append(branchTable);
|
||||
ensureBranchNoDataRow();
|
||||
}
|
||||
|
||||
ensureBranchNoDataRow();
|
||||
|
||||
});
|
||||
|
||||
$('#btnBranchAdd').click(function() {
|
||||
@ -550,6 +566,7 @@ $("#branch_form").submit(function(event) {
|
||||
|
||||
});
|
||||
$('#branch_list').append(branchTableInsert);
|
||||
ensureBranchNoDataRow();
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error(xhr.responseText);
|
||||
|
||||
@ -46,6 +46,11 @@
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.switch-label .slider,
|
||||
.switch-label .slider_blue {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.slider,
|
||||
.slider_blue {
|
||||
position: relative;
|
||||
@ -89,14 +94,45 @@ input:checked + .slider_blue::before {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#table-client-policy_wrapper .row>.col-sm-12.col-md-6:first-child{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#table-client-policy_filter{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#table-client-policy{
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
#table-client-policy_wrapper .datatable-search-wrapper{
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
#table-client-policy thead th{
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#table-client-policy_filter input{
|
||||
padding-right: 34px !important;
|
||||
width: 220px !important;
|
||||
}
|
||||
|
||||
#table-client-policy tbody td.dataTables_empty{
|
||||
text-align: center !important;
|
||||
padding: 18px 12px !important;
|
||||
color: #6c757d !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#table-client-policy_wrapper .row.align-items-center{
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
#table-client-policy_wrapper .dataTables_info,
|
||||
#table-client-policy_wrapper .dataTables_length,
|
||||
#table-client-policy_wrapper .dataTables_paginate{
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="save-indicator" id="saveIndicator">Saved</div>
|
||||
@ -119,7 +155,7 @@ input:checked + .slider_blue::before {
|
||||
</div>
|
||||
|
||||
<div class="table-responsive" id="table_list">
|
||||
<table data-custom-table-css="table" class="table table-borderless table mb-0" id="table-client-policy">
|
||||
<table data-custom-table-css="table" class="table table-borderless table mb-0 w-100 nowrap" id="table-client-policy">
|
||||
<thead class="">
|
||||
<tr style="color:black !important;">
|
||||
<th>Insurer</th>
|
||||
@ -569,23 +605,32 @@ input:checked + .slider_blue::before {
|
||||
paging: true,
|
||||
searching: true,
|
||||
autoWidth: false,
|
||||
responsive: true,
|
||||
scrollX: true,
|
||||
responsive: false,
|
||||
dom: "<'row'<'col-12 d-flex justify-content-between align-items-center'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'>>>" +
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
|
||||
language: {
|
||||
search: `
|
||||
<div class="datatable-search-wrapper" style="position:relative; display:inline-block; width:100%;">
|
||||
<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">
|
||||
_INPUT_
|
||||
<i class="mdi mdi-magnify datatable-search-icon"
|
||||
style="position:absolute; right:122px !important; top:50%; transform:translateY(-50%); color:#666;"></i>
|
||||
style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666;"></i>
|
||||
|
||||
<i class="mdi mdi-close-circle datatable-clear-icon"
|
||||
style="position:absolute; right:122px !important; top:50%; transform:translateY(-50%); color:#666; display:none; cursor:pointer;"></i>
|
||||
style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666; display:none;"></i>
|
||||
</div>
|
||||
`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No data available</div>',
|
||||
zeroRecords: '<div class="text-center text-muted">No data available</div>'
|
||||
},
|
||||
|
||||
});
|
||||
setTimeout(function () {
|
||||
const dt = $('#table-client-policy').DataTable();
|
||||
dt.columns.adjust().draw(false);
|
||||
}, 0);
|
||||
|
||||
|
||||
|
||||
@ -2664,7 +2709,7 @@ input:checked + .slider_blue::before {
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('#chk-show-expired').on('change', function () {
|
||||
$(document).on('change', '#chk-show-expired', function () {
|
||||
|
||||
const showExpired = $(this).is(':checked');
|
||||
|
||||
@ -2795,35 +2840,59 @@ $(document).ready(function () {
|
||||
|
||||
});
|
||||
|
||||
const table = $('#table-client-policy').DataTable();
|
||||
table.clear().destroy();
|
||||
if ($.fn.DataTable.isDataTable('#table-client-policy')) {
|
||||
$('#table-client-policy').DataTable().clear().destroy();
|
||||
}
|
||||
|
||||
$('#table-client-policy tbody').html(policyTable); // replace tbody content
|
||||
|
||||
$('#table-client-policy').DataTable({
|
||||
const policyTableInstance = $('#table-client-policy').DataTable({
|
||||
paging: true,
|
||||
searching: true,
|
||||
autoWidth: false,
|
||||
responsive: true,
|
||||
// language: {
|
||||
// search: `
|
||||
// <div class="datatable-search-wrapper" style="position:relative; display:inline-block; width:100%;">
|
||||
// _INPUT_
|
||||
// <i class="mdi mdi-magnify datatable-search-icon"
|
||||
// style="position:absolute; right:122px !important; top:50%; transform:translateY(-50%); color:#666;"></i>
|
||||
scrollX: true,
|
||||
responsive: false,
|
||||
dom: "<'row'<'col-12 d-flex justify-content-between align-items-center'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'>>>" +
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
|
||||
language: {
|
||||
search: `
|
||||
<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">
|
||||
_INPUT_
|
||||
<i class="mdi mdi-magnify datatable-search-icon"
|
||||
style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666;"></i>
|
||||
|
||||
// <i class="mdi mdi-close-circle datatable-clear-icon"
|
||||
// style="position:absolute; right:122px !important; top:50%; transform:translateY(-50%); color:#666; display:none; cursor:pointer;"></i>
|
||||
// </div>
|
||||
// `,
|
||||
// searchPlaceholder: "Search",
|
||||
// emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
// },
|
||||
<i class="mdi mdi-close-circle datatable-clear-icon"
|
||||
style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666; display:none;"></i>
|
||||
</div>
|
||||
`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No data available</div>',
|
||||
zeroRecords: '<div class="text-center text-muted">No data available</div>'
|
||||
},
|
||||
});
|
||||
setTimeout(function () {
|
||||
policyTableInstance.columns.adjust().draw(false);
|
||||
}, 0);
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Fix header/body alignment when tab becomes visible
|
||||
$(document).on('shown.bs.tab', 'a[data-toggle="tab"], a[data-bs-toggle="tab"]', function () {
|
||||
const target = $(this).attr('href') || $(this).data('target');
|
||||
if (target === '#police-tab' && $.fn.DataTable.isDataTable('#table-client-policy')) {
|
||||
const dt = $('#table-client-policy').DataTable();
|
||||
dt.columns.adjust().draw(false);
|
||||
}
|
||||
});
|
||||
|
||||
$(window).on('resize', function () {
|
||||
if ($.fn.DataTable.isDataTable('#table-client-policy')) {
|
||||
$('#table-client-policy').DataTable().columns.adjust();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
<style>
|
||||
.dataTables_filter {
|
||||
position: absolute;
|
||||
.col-12 {
|
||||
max-width: 98% !important;
|
||||
}
|
||||
.dataTables_length label {height: 21px !important;}
|
||||
|
||||
.custom-dropdown-menu {
|
||||
display: none;
|
||||
@ -30,6 +29,9 @@
|
||||
color: #16181b !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.dataTables_length label {height: 21px !important;}
|
||||
|
||||
</style>
|
||||
|
||||
<!-- End ADD and EDIT Page HTML -->
|
||||
@ -37,15 +39,15 @@
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<table data-custom-table-css="table" class="table table-sm m-0 table-centered dt-responsive nowrap w-100" cellspacing="a" id="user-table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="user-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium">S.No.</th>
|
||||
<th class="font-weight-medium">Category</th>
|
||||
<th class="font-weight-medium">Question</th>
|
||||
<th class="font-weight-medium">S.No. </th>
|
||||
<th class="font-weight-medium">Category </th>
|
||||
<th class="font-weight-medium">Question </th>
|
||||
<!-- <th class="font-weight-medium">Answer</th> -->
|
||||
<th class="font-weight-medium">Status</th>
|
||||
<th class="font-weight-medium">Action</th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -76,8 +78,8 @@
|
||||
<?php if($row['is_active'] == 1){ echo 'Active'; }else{ echo 'In-Active'; } ?>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group dropdown" style="position: relative !important;left:0px !important;top:0px !important;">
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right" style="cursor: pointer;">
|
||||
<a class="dropdown-item" data-id="<?= $row['id']; ?>" onclick="handleSaveEditAndDelete('edit', this)">
|
||||
@ -116,7 +118,12 @@
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="category">Category<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="category" name="category" placeholder="Enter Category" required>
|
||||
<input type="text" class="form-control" id="category" name="category" placeholder="Enter Category" required
|
||||
data-parsley-pattern="^[a-zA-Z0-9 \/\-\.\,"\']+$"
|
||||
data-parsley-pattern-message="Category can contain only letters, numbers, spaces, and these characters: / - . , " '"
|
||||
data-parsley-maxlength="100"
|
||||
data-parsley-maxlength-message="Category cannot exceed 100 characters"
|
||||
data-parsley-trigger="keyup input">
|
||||
<small class="form-text text-muted text-end text-right">
|
||||
Please enter the sub-category separated by '/'. For Example: Category / Category-1 / Category-2
|
||||
</small>
|
||||
@ -126,18 +133,26 @@
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="question">Question<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="question" name="question" placeholder="Enter Question" required>
|
||||
<input type="text" class="form-control" id="question" name="question" placeholder="Enter Question" required
|
||||
data-parsley-pattern="^[a-zA-Z0-9 _\-\.,;:!?()&\/]+$"
|
||||
data-parsley-pattern-message="Question can contain only letters, numbers, spaces, and these characters: . , ; : ! ? ( ) & / -"
|
||||
data-parsley-maxlength="1000"
|
||||
data-parsley-maxlength-message="Question cannot exceed 1000 characters"
|
||||
data-parsley-trigger="keyup input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="answer">Answer<span class="text-danger">*</span></label>
|
||||
<!-- <textarea id="answer" name="answer" class="form-control" required></textarea> -->
|
||||
<textarea id="answer" name="answer" class="form-control answer" rows="7">
|
||||
<textarea id="answer" name="answer" class="form-control answer" rows="7" required
|
||||
data-parsley-maxlength="5000"
|
||||
data-parsley-maxlength-message="Answer cannot exceed 5000 characters">
|
||||
<!-- <h5>Hello {USER_NAME}, </h5>
|
||||
<p>We create simple, flat & responsive custom mail template.</p>
|
||||
<p>Please, write text here!</p> -->
|
||||
</textarea>
|
||||
<div id="answer-errors"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -155,10 +170,6 @@
|
||||
// let faqEditor;
|
||||
let editor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ClassicEditor
|
||||
// .create(document.querySelector('#answer'))
|
||||
// .then(editor => {
|
||||
@ -207,9 +218,13 @@
|
||||
|
||||
// 2. Initialize
|
||||
editor = Jodit.make("#answer", editorConfig);
|
||||
editor.events.on('change keyup', function () {
|
||||
$('#answer').val(editor.value);
|
||||
$('#answer').parsley().validate();
|
||||
});
|
||||
|
||||
var ticketsTable = $('#user-table');
|
||||
ticketsTable.DataTable({
|
||||
var table = ticketsTable.DataTable({
|
||||
scrollX: true,
|
||||
// dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right
|
||||
// "<'row'<'col-sm-12'tr>>" +
|
||||
@ -220,8 +235,7 @@
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Add',
|
||||
className: 'btn app-btn-primary mr-2',
|
||||
text: '<i class="mdi mdi-plus"></i><span class="btn-custom"> Add </span>',
|
||||
action: function(e, dt, node, config) {
|
||||
resetValues();openModal();
|
||||
}
|
||||
@ -253,12 +267,59 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true, // Enable pagination
|
||||
pageLength: 10, // Set default number of rows per page (optional)
|
||||
// ordering: false,
|
||||
});
|
||||
|
||||
function placeActionDropdown($toggle) {
|
||||
const $group = $toggle.closest('.btn-group.dropdown');
|
||||
const $menu = $group.find('.dropdown-menu');
|
||||
if (!$group.length || !$menu.length) return;
|
||||
|
||||
// Reset previous state before recalculating placement.
|
||||
$group.removeClass('dropup');
|
||||
|
||||
const toggleRect = $toggle[0].getBoundingClientRect();
|
||||
const menuHeight = $menu.outerHeight() || 120;
|
||||
const spaceBelow = window.innerHeight - toggleRect.bottom;
|
||||
const spaceAbove = toggleRect.top;
|
||||
|
||||
// Open upward only when bottom space is insufficient.
|
||||
if (spaceBelow < menuHeight + 12 && spaceAbove > menuHeight) {
|
||||
$group.addClass('dropup');
|
||||
}
|
||||
}
|
||||
|
||||
$('#user-table').on('show.bs.dropdown', '.table-action-cell .dropdown-toggle', function () {
|
||||
const $toggle = $(this);
|
||||
const $scrollBody = $toggle.closest('.dataTables_scrollBody');
|
||||
|
||||
if ($scrollBody.length) {
|
||||
$scrollBody.data('prev-overflow-y', $scrollBody.css('overflow-y'));
|
||||
$scrollBody.css('overflow-y', 'visible');
|
||||
}
|
||||
|
||||
placeActionDropdown($toggle);
|
||||
});
|
||||
|
||||
$('#user-table').on('hide.bs.dropdown', '.table-action-cell .dropdown-toggle', function () {
|
||||
const $scrollBody = $(this).closest('.dataTables_scrollBody');
|
||||
const prevOverflowY = $scrollBody.data('prev-overflow-y');
|
||||
if ($scrollBody.length) {
|
||||
$scrollBody.css('overflow-y', prevOverflowY || 'auto');
|
||||
}
|
||||
});
|
||||
|
||||
ticketsTable.on('draw.dt', function () {
|
||||
$('#user-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
});
|
||||
});
|
||||
|
||||
$('.close').click(function(){ resetValues(); })
|
||||
@ -404,115 +465,23 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof editor !== 'undefined') {
|
||||
// Strip HTML tags and trim whitespace to see if there is actual text
|
||||
const plainText = editor.value.replace(/<[^>]*>/g, '').trim();
|
||||
|
||||
// Check if it's truly empty or just contains empty tags like <p><br></p>
|
||||
if (editor.value === '' || plainText === '') {
|
||||
toastr.warning("Answer is required", 'Warning');
|
||||
return; // Stop the function here
|
||||
}
|
||||
var isValid = $(this).parsley({
|
||||
excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]'
|
||||
}).validate();
|
||||
|
||||
// Block unsafe HTML/JS patterns
|
||||
if (hasUnsafeHtml(editor.value)) {
|
||||
toastr.error("Answer contains restricted tags or attributes. Script tags, iframes and event handlers (like onclick, onerror, onmouseover) are not allowed.", "Validation Error");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!isValid) return;
|
||||
|
||||
// If valid, submit via AJAX
|
||||
handleSaveEditAndDelete('submit');
|
||||
});
|
||||
|
||||
</script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.getElementById("user-table");
|
||||
|
||||
// Create custom dropdown
|
||||
function createCustomDropdown(row) {
|
||||
// Get the original dropdown items
|
||||
const originalDropdown = row.querySelector('.dropdown-menu');
|
||||
if (!originalDropdown) return null;
|
||||
|
||||
// Create new dropdown with proper background and spacing
|
||||
const customDropdown = document.createElement('div');
|
||||
customDropdown.className = 'custom-dropdown-menu';
|
||||
|
||||
// Copy inner content while maintaining icon alignment
|
||||
customDropdown.innerHTML = originalDropdown.innerHTML;
|
||||
|
||||
return customDropdown;
|
||||
}
|
||||
|
||||
let activeDropdown = null;
|
||||
|
||||
// Add click event listener to rows
|
||||
table.querySelectorAll("tbody tr").forEach(row => {
|
||||
const customDropdown = createCustomDropdown(row);
|
||||
if (!customDropdown) return;
|
||||
|
||||
// Append the custom dropdown to the body
|
||||
document.body.appendChild(customDropdown);
|
||||
|
||||
row.addEventListener("click", function(event) {
|
||||
// Ignore clicks on the action column
|
||||
if (event.target.closest('td:last-child')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide any active dropdown
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
}
|
||||
|
||||
// Get click position
|
||||
const rect = event.target.getBoundingClientRect();
|
||||
|
||||
// Position the dropdown with some offset
|
||||
customDropdown.style.display = 'block';
|
||||
customDropdown.style.position = 'fixed';
|
||||
customDropdown.style.left = `${rect.left}px`;
|
||||
customDropdown.style.top = `${rect.bottom + 5}px`; // Add 5px gap
|
||||
|
||||
// Set as active dropdown
|
||||
activeDropdown = customDropdown;
|
||||
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Preserve click handlers and add auto-close
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
const onclickAttr = this.getAttribute('onclick');
|
||||
if (onclickAttr) {
|
||||
eval(onclickAttr);
|
||||
}
|
||||
|
||||
const href = this.getAttribute('href');
|
||||
if (href && href !== '#') {
|
||||
window.location.href = href;
|
||||
}
|
||||
|
||||
// Close the dropdown after handling the click
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
document.addEventListener("click", function() {
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
});
|
||||
// Restrict user typing to allow Regex only characters
|
||||
$('#category').on('input', function() {
|
||||
this.value = this.value.replace(/[^a-zA-Z0-9 \/\-.,"']/g, '');
|
||||
});
|
||||
</script>
|
||||
|
||||
$('#question').on('input', function() {
|
||||
this.value = this.value.replace(/[^a-zA-Z0-9 _\-.,;:!?()&\/]/g, '');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@ -39,6 +39,39 @@
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#tickets-table{
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
#tickets-table thead th{
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#tickets-table_wrapper .datatable-search-wrapper{
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
#tickets-table_wrapper .dataTables_filter input{
|
||||
padding-right: 34px !important;
|
||||
width: 220px !important;
|
||||
}
|
||||
|
||||
#tickets-table_wrapper .row.align-items-center{
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
#tickets-table_wrapper .dataTables_info,
|
||||
#tickets-table_wrapper .dataTables_length,
|
||||
#tickets-table_wrapper .dataTables_paginate{
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#tickets-table_wrapper .datatable-search-icon,
|
||||
#tickets-table_wrapper .datatable-clear-icon{
|
||||
right: 11px !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="col-12">
|
||||
@ -542,6 +575,17 @@
|
||||
paging: true,
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
const dt = $('#tickets-table').DataTable();
|
||||
dt.columns.adjust().draw(false);
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
$(window).on('resize', function () {
|
||||
if ($.fn.DataTable.isDataTable('#tickets-table')) {
|
||||
$('#tickets-table').DataTable().columns.adjust();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
@ -1,34 +1,8 @@
|
||||
<style>
|
||||
.dataTables_filter {
|
||||
position: absolute;
|
||||
.col-12 {
|
||||
max-width: 98% !important;
|
||||
}
|
||||
.dataTables_length label {height: 21px !important;}
|
||||
.custom-dropdown-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #ffffff !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 0;
|
||||
min-width: 10rem;
|
||||
z-index: 9999;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
padding: 0.5rem 1rem !important;
|
||||
color: #212529 !important;
|
||||
text-decoration: none !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
color: #16181b !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- End ADD and EDIT Page HTML -->
|
||||
@ -36,16 +10,16 @@
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<table data-custom-table-css="table" class="table table-sm m-0 table-centered dt-responsive nowrap w-100" cellspacing="a" id="user-table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="user-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<!-- `content` `notes` -->
|
||||
<th class="font-weight-medium">S.No.</th>
|
||||
<th class="font-weight-medium">Type</th>
|
||||
<th class="font-weight-medium">Content Section</th>
|
||||
<th class="font-weight-medium">Heading</th>
|
||||
<th class="font-weight-medium">Status</th>
|
||||
<th class="font-weight-medium">Action</th>
|
||||
<th class="font-weight-medium">S.No. </th>
|
||||
<th class="font-weight-medium">Type </th>
|
||||
<th class="font-weight-medium">Content Section </th>
|
||||
<th class="font-weight-medium">Heading </th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -61,10 +35,10 @@
|
||||
<?php if($row['is_active'] == 1){ echo 'Active'; }else{ echo 'In-Active'; } ?>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group dropdown" style="position: relative !important;left:0px !important;top:0px !important;">
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right" style="cursor: pointer;">
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item" data-status="<?= $row['is_active']; ?>" data-id="<?= $row['id']; ?>" onclick="handleSaveEditAndDelete('edit', this)">
|
||||
<i class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle"></i>Edit
|
||||
</a>
|
||||
@ -101,15 +75,30 @@
|
||||
<div class="form-row">
|
||||
<div class="col-md-4">
|
||||
<label for="type">Type<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="type" name="type" placeholder="Enter Type" required>
|
||||
<input type="text" class="form-control" id="type" name="type" placeholder="Enter Type" required
|
||||
data-parsley-pattern="^[a-zA-Z0-9_ \-]+$"
|
||||
data-parsley-pattern-message="Type can contain only letters, numbers, spaces, _ and -"
|
||||
data-parsley-maxlength="255"
|
||||
data-parsley-maxlength-message="Type cannot exceed 255 characters"
|
||||
data-parsley-trigger="keyup input">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="content_section">Content Section<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="content_section" name="content_section" placeholder="Enter Content Section" required>
|
||||
<input type="text" class="form-control" id="content_section" name="content_section" placeholder="Enter Content Section" required
|
||||
data-parsley-pattern="^[a-zA-Z0-9_ \-]+$"
|
||||
data-parsley-pattern-message="Content Section can contain only letters, numbers, spaces, _ and -"
|
||||
data-parsley-maxlength="255"
|
||||
data-parsley-maxlength-message="Content Section cannot exceed 255 characters"
|
||||
data-parsley-trigger="keyup input">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="branch_name">Heading<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="heading" name="heading" placeholder="Enter Heading" required>
|
||||
<input type="text" class="form-control" id="heading" name="heading" placeholder="Enter Heading" required
|
||||
data-parsley-pattern="^[a-zA-Z0-9 _\-\.,;:!?()&\/]+$"
|
||||
data-parsley-pattern-message="Heading can contain only letters, numbers, spaces, and these characters: . , ; : ! ? ( ) & / -"
|
||||
data-parsley-maxlength="255"
|
||||
data-parsley-maxlength-message="Heading cannot exceed 255 characters"
|
||||
data-parsley-trigger="keyup input">
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
@ -117,21 +106,30 @@
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="content">Content<span class="text-danger">*</span></label>
|
||||
<textarea id="content" name="content" class="form-control content" rows="5">
|
||||
<textarea id="content" name="content" class="form-control content" rows="5" required
|
||||
data-parsley-maxlength="5000"
|
||||
data-parsley-maxlength-message="Content cannot exceed 5000 characters"
|
||||
data-parsley-errors-container="#content-errors">
|
||||
<!-- <h5>Hello {USER_NAME}, </h5>
|
||||
<p>We create simple, flat & responsive custom mail template.</p>
|
||||
<p>Please, write text here!</p> -->
|
||||
</textarea>
|
||||
<div id="content-errors"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="notes">Notes<span class="text-danger">*</span></label>
|
||||
<textarea id="notes" name="notes" class="form-control notes" rows="5">
|
||||
<textarea id="notes" name="notes" class="form-control notes" rows="5" required
|
||||
data-parsley-maxlength="1500"
|
||||
data-parsley-maxlength-message="Notes cannot exceed 1500 characters"
|
||||
data-parsley-errors-container="#notes-errors">
|
||||
<!-- <h5>Hello {USER_NAME}, </h5>
|
||||
<p>We create simple, flat & responsive custom mail template.</p>
|
||||
<p>Please, write text here!</p> -->
|
||||
</textarea>
|
||||
<div id="notes-errors"></div>
|
||||
<small id="notes_error" class="text-danger d-none"></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -259,10 +257,19 @@
|
||||
// placeholder: "Start typing here...",
|
||||
// };
|
||||
content_editor = Jodit.make("#content", editorConfig);
|
||||
content_editor.events.on('change keyup', function () {
|
||||
$('#content').val(content_editor.value);
|
||||
$('#content').parsley().validate();
|
||||
});
|
||||
|
||||
notes_editor = Jodit.make("#notes", editorConfig);
|
||||
notes_editor.events.on('change keyup', function () {
|
||||
$('#notes').val(notes_editor.value);
|
||||
$('#notes').parsley().validate();
|
||||
});
|
||||
|
||||
var ticketsTable = $('#user-table');
|
||||
ticketsTable.DataTable({
|
||||
table = ticketsTable.DataTable({
|
||||
scrollX: true,
|
||||
// dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right
|
||||
// "<'row'<'col-sm-12'tr>>" +
|
||||
@ -273,7 +280,7 @@
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Add',
|
||||
text: '<i class="mdi mdi-plus"></i><span class="btn-custom"> Add </span>',
|
||||
className: 'btn app-btn-primary mr-2',
|
||||
action: function(e, dt, node, config) {
|
||||
resetValues();openModal();// $('#btnSubmit').removeClass('d-none');
|
||||
@ -306,12 +313,34 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true, // Enable pagination
|
||||
pageLength: 10, // Set default number of rows per page (optional)
|
||||
// ordering: false,
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#user-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#user-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
$('#user-table').on('draw.dt', applyBottomRowDropup);
|
||||
});
|
||||
|
||||
$('.close').click(function(){ resetValues(); })
|
||||
@ -560,6 +589,20 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Sync jodit value back to textarea before parsely validation
|
||||
if (typeof content_editor !== 'undefined') {
|
||||
$('#content').val(content_editor.value);
|
||||
}
|
||||
if (typeof notes_editor !== 'undefined') {
|
||||
$('#notes').val(notes_editor.value);
|
||||
}
|
||||
|
||||
var isValid = $(this).parsley({
|
||||
excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]'
|
||||
}).validate();
|
||||
|
||||
if (!isValid) return;
|
||||
|
||||
// Content validation
|
||||
if (typeof content_editor !== 'undefined') {
|
||||
if (isEditorEmpty(content_editor.value)) {
|
||||
@ -629,9 +672,24 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Restrict user typing to allow Regex only characters
|
||||
$('#type').on('input', function() {
|
||||
this.value = this.value.replace(/[^a-zA-Z0-9_ \-]/g, '');
|
||||
});
|
||||
|
||||
$('#content_section').on('input', function() {
|
||||
this.value = this.value.replace(/[^a-zA-Z0-9_ \-]/g, '');
|
||||
});
|
||||
|
||||
$('#heading').on('input', function() {
|
||||
this.value = this.value.replace(/[^a-zA-Z0-9 _\-.,;:!?()&\/]/g, '');
|
||||
});
|
||||
|
||||
// $('#type').on('input blur', function () { fieldTouched.type = true; validateTypeField(false); });
|
||||
// $('#heading').on('input blur', function () { fieldTouched.heading = true; validateHeadingField(false); });
|
||||
|
||||
</script>
|
||||
<script>
|
||||
<!-- <script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.getElementById("user-table");
|
||||
|
||||
@ -720,4 +778,4 @@
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
-->
|
||||
|
||||
@ -49,6 +49,20 @@ table.dataTable tbody td {
|
||||
}
|
||||
.dataTables_length label {height: 21px !important;}
|
||||
|
||||
#scroll-horizontal-datatable_wrapper .datatable-search-wrapper{
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
#scroll-horizontal-datatable_wrapper .dataTables_filter input{
|
||||
width: 220px !important;
|
||||
padding-right: 34px !important;
|
||||
}
|
||||
|
||||
#scroll-horizontal-datatable_wrapper .datatable-search-icon,
|
||||
#scroll-horizontal-datatable_wrapper .datatable-clear-icon{
|
||||
right: 11px !important;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@ -109,13 +123,13 @@ $(document).ready(function () {
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
language: {
|
||||
search: `
|
||||
<div class="datatable-search-wrapper" style="position:relative; display:inline-block; width:100%;">
|
||||
<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">
|
||||
_INPUT_
|
||||
<i class="mdi mdi-magnify datatable-search-icon"
|
||||
style="position:absolute; right:122px !important; top:50%; transform:translateY(-50%); color:#666;"></i>
|
||||
style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666;"></i>
|
||||
|
||||
<i class="mdi mdi-close-circle datatable-clear-icon"
|
||||
style="position:absolute; right:122px !important; top:50%; transform:translateY(-50%); color:#666; display:none; cursor:pointer;"></i>
|
||||
style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666; display:none; cursor:pointer;"></i>
|
||||
</div>
|
||||
`,
|
||||
searchPlaceholder: "Search",
|
||||
@ -146,10 +160,8 @@ $('.dataTables_filter input').css({
|
||||
'background': '#F0F0F0',
|
||||
'border': 'none',
|
||||
'border-radius': '8px',
|
||||
'padding-right': '35px'
|
||||
}).wrap('<div style="position:relative; display:inline-block;"></div>')
|
||||
.after('<i class="mdi mdi-magnify" ' +
|
||||
'style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666;"></i>');
|
||||
'padding-right': '34px'
|
||||
});
|
||||
|
||||
|
||||
// Attach submit handler separately so it works
|
||||
|
||||
@ -12,9 +12,7 @@ table.dataTable thead th {
|
||||
padding: 4px 4px !important;
|
||||
}
|
||||
|
||||
.dataTables_filter {
|
||||
position: absolute;
|
||||
}
|
||||
/* .dataTables_filter: global listing layout (nhance-datatables-uniform.css) */
|
||||
|
||||
.filter-sidebar {
|
||||
height: 100%;
|
||||
|
||||
@ -69,7 +69,7 @@ input:checked + .slider:before {
|
||||
<div class="col-12">
|
||||
<div class="card-body">
|
||||
<div class="custom-form">
|
||||
<form role="form" class="parsley-examples" method="post" id="insurer_general_form" enctype="multipart/form-data">
|
||||
<form role="form" class="parsley-examples" method="post" id="insurer_general_form" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>" />
|
||||
<input type="hidden" name="PrimaryKey" id="insurer_General_PrimaryKey" value="<?= isset($insurer['id']) ? $insurer['id'] : '' ?>" />
|
||||
<input type="hidden" name="insurer_id" id="insurer_id" />
|
||||
@ -78,8 +78,12 @@ input:checked + .slider:before {
|
||||
<div class="form-group row">
|
||||
<label for="insurer_name" class="col-md-4 col-form-label">Insurer Name<span class="text-danger">*</span></label>
|
||||
<div class="col-md-5">
|
||||
<input type="text" class="form-control" id="insurer_name" placeholder="Enter Insurer Name"
|
||||
value="<?= isset($insurer['name']) ? $insurer['name'] : '' ?>" name="name" required>
|
||||
<input type="text" class="form-control" id="insurer_name" placeholder="Enter Insurer Name"
|
||||
value="<?= isset($insurer['name']) ? $insurer['name'] : '' ?>" name="name"
|
||||
required
|
||||
data-parsley-pattern="/^[a-zA-Z0-9\s\-_]+$/"
|
||||
data-parsley-pattern-message="Insurer Name can only contain letters, numbers, spaces, hyphens, and underscores."
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -87,8 +91,12 @@ input:checked + .slider:before {
|
||||
<div class="form-group row">
|
||||
<label for="short_name" class="col-md-4 col-form-label">Insurer Short Name<span class="text-danger">*</span></label>
|
||||
<div class="col-md-5">
|
||||
<input type="text" class="form-control" id="short_name" placeholder="Enter Short Name"
|
||||
value="<?= isset($insurer['short_name']) ? $insurer['short_name'] : '' ?>" name="short_name" required minlength="3" maxlength="8">
|
||||
<input type="text" class="form-control" id="short_name" placeholder="Enter Short Name"
|
||||
value="<?= isset($insurer['short_name']) ? $insurer['short_name'] : '' ?>" name="short_name"
|
||||
required data-parsley-minlength="3" data-parsley-maxlength="8"
|
||||
data-parsley-pattern="/^[a-zA-Z0-9\-_]+$/"
|
||||
data-parsley-pattern-message="Short Name can only contain letters, numbers, hyphens, and underscores (no spaces)."
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -160,10 +168,15 @@ input:checked + .slider:before {
|
||||
<label for="insurer_logo" class="col-md-4 col-form-label">Insurer Logo</label>
|
||||
<div class="col-md-5">
|
||||
<div class="input-icon">
|
||||
<input type="file" class="form-control" id="insurer_logo" name="insurer_logo"
|
||||
accept="image/jpeg, image/jpg, image/png" onchange="PreviewImage();">
|
||||
<input type="file" class="form-control" id="insurer_logo" name="insurer_logo"
|
||||
accept="image/jpeg, image/jpg, image/png" onchange="PreviewImage();"
|
||||
data-parsley-max-file-size="200"
|
||||
data-parsley-file-extension="jpg,jpeg,png"
|
||||
data-parsley-errors-container="#logo_error_container">
|
||||
<i class="mdi mdi-upload additional-icon"></i>
|
||||
</div>
|
||||
<div id="logo_error_container"></div>
|
||||
<small class="text-muted">Allowed: JPG, JPEG, PNG. Max size: 200KB.</small>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<img src="<?= isset($insurer['insurer_logo']) && !empty($insurer['insurer_logo']) ? base_url() . "public/uploads/logo/" . $insurer['insurer_logo'] : base_url() . "public/assets/images/avatar_2x.png" ?>"
|
||||
@ -191,6 +204,40 @@ input:checked + .slider:before {
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
// Custom Parsley validator for file size
|
||||
window.Parsley.addValidator('maxFileSize', {
|
||||
validateString: function(value, maxSize, parsleyInstance) {
|
||||
if (!window.FileReader) {
|
||||
alert('Your browser does not support FileReader API, please upgrade.');
|
||||
return true;
|
||||
}
|
||||
var files = parsleyInstance.$element[0].files;
|
||||
if (files.length == 0) {
|
||||
return true; // No file, so validation passes (unless required)
|
||||
}
|
||||
return files[0].size <= maxSize * 1024;
|
||||
},
|
||||
requirementType: 'integer',
|
||||
messages: {
|
||||
en: 'This file should not be larger than %s KB.'
|
||||
}
|
||||
});
|
||||
|
||||
// Custom Parsley validator for file extension
|
||||
window.Parsley.addValidator('fileExtension', {
|
||||
validateString: function(value, requirement, parsleyInstance) {
|
||||
var file = parsleyInstance.$element[0].files[0];
|
||||
if (!file) { return true; } // No file, so validation passes
|
||||
var extensions = requirement.split(',').map(function(ext) { return ext.trim().toLowerCase(); });
|
||||
var fileExtension = file.name.split('.').pop().toLowerCase();
|
||||
return extensions.indexOf(fileExtension) !== -1;
|
||||
},
|
||||
requirementType: 'string',
|
||||
messages: {
|
||||
en: 'Allowed extensions are: %s.'
|
||||
}
|
||||
});
|
||||
|
||||
$('#insurer_logo').on('change', function() {
|
||||
PreviewImage();
|
||||
});
|
||||
@ -293,34 +340,6 @@ input:checked + .slider:before {
|
||||
}
|
||||
});
|
||||
|
||||
function validateForm() {
|
||||
var isValid = true;
|
||||
|
||||
// Perform validation for each field
|
||||
$('#insurer_general_form input, #insurer_general_form select').each(function() {
|
||||
// Check for empty text inputs and selects
|
||||
if ($(this).is('input[type="text"]') || $(this).is('select')) {
|
||||
if ($.trim($(this).val()) == '') {
|
||||
alert('Please fill in all fields');
|
||||
isValid = false;
|
||||
return false; // Exit the loop early
|
||||
}
|
||||
}
|
||||
|
||||
// Check for file inputs (assuming image files)
|
||||
if ($(this).is('input[type="file"]')) {
|
||||
var fileInput = $(this)[0];
|
||||
if (fileInput.files.length === 0) {
|
||||
alert('Please select an image file');
|
||||
isValid = false;
|
||||
return false; // Exit the loop early
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -28,17 +28,31 @@
|
||||
overflow-y: auto;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
#insurerBranchModal {
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
#insurerBranchModal.show {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#insurerBranchModal {
|
||||
z-index: 1060;
|
||||
}
|
||||
|
||||
.modal-backdrop {
|
||||
z-index: 1050;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="tab-pane fade" id="branch-tab" style="padding-left: 25px;">
|
||||
|
||||
<div class="row float-right" style="padding-bottom: 10px;position: relative;">
|
||||
<a href="#" id="btnBranchAdd" class="btn app-btn-primary mr-2"><span class="mdi mdi-plus" aria-hidden="true" style="padding: 5px 10px;"></span>Add Branch</a>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive" id="branch_table" >
|
||||
<div class="table-responsive nh-listing-table-scope" id="branch_table" >
|
||||
|
||||
<table data-custom-table-css="table" class="table table-borderless table-nowrap mb-0" id="branch-datatable">
|
||||
<table data-custom-table-css="table" class="table table-borderless table-nowrap mb-0 w-100 nowrap" id="branch-datatable">
|
||||
<thead class="">
|
||||
|
||||
<tr>
|
||||
@ -52,137 +66,22 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- <div class="row" id="add_branch">
|
||||
<div class="col-12">
|
||||
<div class="card-body">
|
||||
<div class="row float-right" style="position: relative; bottom: 20px; right: 13px;">
|
||||
<button type="button" id="btnBranchBack" class="btn btn-primary waves-effect waves-light btn-sm btnBack"><span class="mdi mdi-format-list-bulleted" aria-hidden="true" style="padding: 5px 10px;"></span>Back To List</button>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<form role="form" class="parsley-examples" method="post" id="insurer_branch_form"
|
||||
enctype="multipart/form-data">
|
||||
<input type="hidden" class="form-control" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>" />
|
||||
<input type="hidden" name="PrimaryKey" id="insurer_Branch_PrimaryKey" />
|
||||
<input type="hidden" name="insurer_id" id="insurer_id_branch" value="<?= isset($insurer['id']) ? $insurer['id'] : '' ?>"/>
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="branch_name">Branch Name<span
|
||||
class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="branch_name"
|
||||
placeholder="Enter Branch Name" name="branch_name" required>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="branch_code">Branch Code<span
|
||||
class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="branch_code"
|
||||
placeholder="Enter Branch Code" name="branch_code" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="address1">Address Line 1<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="address1" name="address1" placeholder="Enter Address 1" required>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="address2">Address Line 2<span class="text-danger"></span></label>
|
||||
<input type="text" class="form-control" id="address2" placeholder="Enter Address 2" name="address2">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-3">
|
||||
<label for="state">State<span
|
||||
class="text-danger">*</span></label>
|
||||
<select class="form-control" id="state" name="state" required>
|
||||
<option value="">Select State</option>
|
||||
<?php foreach($state as $value) { ?>
|
||||
<option value="<?= $value['id'] ?>"><?= $value['state'] ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="district">District<span
|
||||
class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="district"
|
||||
placeholder="Enter District" name="district" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="city">City<span
|
||||
class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="branch_city"
|
||||
placeholder="Enter City" name="city" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-3">
|
||||
<label for="gst">Pincode<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="pincode" placeholder="Enter Pincode" name="pincode" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<h6 class="header-title">Contact 1</h6>
|
||||
<br>
|
||||
|
||||
<div class="form-row">
|
||||
<input type="hidden" name="primarykey[]" id="contact_id_1" value=""/>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="first_name">Name<span class="text-danger">*</span></label>
|
||||
<input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="designation">Designation<span class="text-danger">*</span></label>
|
||||
<input value="" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" id="designation" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="last_name">Email<span class="text-danger">*</span></label>
|
||||
<input value="" type="email" data-parsley-type="email" class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="mobile">Mobile<span class="text-danger">*</span></label>
|
||||
<input name="mobile[]" pattern="[0-9]{10}" value="" type="tel" data-parsley-type="number" data-parsley-length="[10,10]" class="form-control" placeholder="Enter Contact Mobile" id="mobile" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" style="display: flex;">
|
||||
<button style="margin-right: 10px;" type="button" class="btn btn-primary btn-sm ac" onclick="appendContactHtml()" id="add">Add Contact</button>
|
||||
<button type="button" class="btn btn-danger btn-sm" onclick="removeContact(this)" id="${uniqueId}_remove">Remove</button>
|
||||
</div>
|
||||
|
||||
<div id="container"></div>
|
||||
|
||||
</div>
|
||||
<div class="form-group text-right m-b-0">
|
||||
<button type="submit" class="btn btn-primary waves-effect waves-light mr-1"
|
||||
id="btnSubmit">Submit</button>
|
||||
<button type="button" class="btn btn-secondary waves-effect btnBack"
|
||||
id="btnBack">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div> !-- end col-- -->
|
||||
</div>
|
||||
<!-- end -->
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="insurerBranchModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-xl" style="max-width: 1140px !important;">
|
||||
<div class="modal-dialog modal-dialog-centered modal-xl">
|
||||
<div class="modal-content">
|
||||
<!-- Modal Header -->
|
||||
<div class="modal-header flex-column">
|
||||
<div class="d-flex w-100 justify-content-between align-items-center">
|
||||
<h4 class="modal-title mb-0" id="modalLabel">New Branch</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<button type="button" class="close js-branch-modal-close" data-dismiss="modal" data-bs-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Body -->
|
||||
<div class="modal-body" style="overflow-y:auto; max-height:80vh;">
|
||||
<div class="modal-body">
|
||||
<form id="insurer_branch_form" role="form" class="parsley-examples" method="post" action="" enctype="multipart/form-data">
|
||||
<input type="hidden" class="form-control" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>" />
|
||||
<input type="hidden" name="PrimaryKey" id="insurer_Branch_PrimaryKey" />
|
||||
@ -253,7 +152,7 @@
|
||||
<!-- <div class="form-group col-md-12 mt-2"> -->
|
||||
<div style="margin-top: 85px;">
|
||||
<button type="submit" class="btn btn-primary mr-2" id="btnSubmit">Submit</button>
|
||||
<button type="button" class="btn app-btn-outline-secondary btnBack" id="btnBack" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||
<button type="button" class="btn app-btn-outline-secondary btnBack" id="btnBack" data-dismiss="modal" data-bs-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
@ -323,113 +222,296 @@
|
||||
var contactCount = 1;
|
||||
var insurer_branch_form_action = '';
|
||||
var insurer_Branch_PrimaryKey = $('#insurer_id_branch').val();
|
||||
var branchDataTable = null;
|
||||
var branchDebugPrefix = '[InsurerBranch]';
|
||||
|
||||
window.addEventListener('error', function (event) {
|
||||
try {
|
||||
console.error(branchDebugPrefix + ' window.error:', event.message, 'at', event.filename + ':' + event.lineno + ':' + event.colno, event.error || '');
|
||||
} catch (e) {}
|
||||
});
|
||||
|
||||
window.addEventListener('unhandledrejection', function (event) {
|
||||
try {
|
||||
console.error(branchDebugPrefix + ' unhandledrejection:', event.reason);
|
||||
} catch (e) {}
|
||||
});
|
||||
/**
|
||||
* This app loads Bootstrap 3/4 jQuery plugins (see footer) and may also expose
|
||||
* a partial window.bootstrap.Modal. Prefer $.fn.modal when present so the modal
|
||||
* actually opens; native bootstrap.Modal is only a fallback.
|
||||
*/
|
||||
function showBranchModal() {
|
||||
var $m = $('#insurerBranchModal');
|
||||
console.log(branchDebugPrefix + ' modal function');
|
||||
if (typeof jQuery !== 'undefined' && jQuery.fn && typeof jQuery.fn.modal === 'function') {
|
||||
try {
|
||||
$m.modal('show');
|
||||
console.log(branchDebugPrefix + ' opened with jQuery.modal');
|
||||
setTimeout(function () {
|
||||
if (!$m.hasClass('show') || !$m.is(':visible')) {
|
||||
console.warn(branchDebugPrefix + ' jQuery modal did not render, applying force-open fallback');
|
||||
forceShowBranchModal();
|
||||
}
|
||||
}, 120);
|
||||
} catch (err) {
|
||||
console.error(branchDebugPrefix + ' jQuery.modal show failed:', err);
|
||||
forceShowBranchModal();
|
||||
}
|
||||
return;
|
||||
}
|
||||
var modalEl = document.getElementById('insurerBranchModal');
|
||||
if (!modalEl) {
|
||||
console.error(branchDebugPrefix + ' modal element #insurerBranchModal not found');
|
||||
return;
|
||||
}
|
||||
if (window.bootstrap && bootstrap.Modal) {
|
||||
if (typeof bootstrap.Modal.getOrCreateInstance === 'function') {
|
||||
try {
|
||||
bootstrap.Modal.getOrCreateInstance(modalEl).show();
|
||||
console.log(branchDebugPrefix + ' opened with bootstrap.Modal.getOrCreateInstance');
|
||||
} catch (err) {
|
||||
console.error(branchDebugPrefix + ' bootstrap getOrCreateInstance failed:', err);
|
||||
forceShowBranchModal();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (typeof bootstrap.Modal.getInstance === 'function') {
|
||||
var existing = bootstrap.Modal.getInstance(modalEl);
|
||||
if (existing) {
|
||||
try {
|
||||
existing.show();
|
||||
console.log(branchDebugPrefix + ' opened with existing bootstrap modal instance');
|
||||
} catch (err) {
|
||||
console.error(branchDebugPrefix + ' existing bootstrap modal show failed:', err);
|
||||
forceShowBranchModal();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
(new bootstrap.Modal(modalEl)).show();
|
||||
console.log(branchDebugPrefix + ' opened with new bootstrap.Modal');
|
||||
} catch (e) {
|
||||
console.error(branchDebugPrefix + ' bootstrap.Modal constructor show failed:', e);
|
||||
forceShowBranchModal();
|
||||
}
|
||||
return;
|
||||
}
|
||||
console.error(branchDebugPrefix + ' no modal library available (jQuery modal/bootstrap modal missing)');
|
||||
forceShowBranchModal();
|
||||
}
|
||||
|
||||
function forceShowBranchModal() {
|
||||
var modalEl = document.getElementById('insurerBranchModal');
|
||||
if (!modalEl) {
|
||||
console.error(branchDebugPrefix + ' forceShow failed: modal element missing');
|
||||
return;
|
||||
}
|
||||
|
||||
modalEl.style.display = 'block';
|
||||
modalEl.classList.add('show');
|
||||
modalEl.removeAttribute('aria-hidden');
|
||||
modalEl.setAttribute('aria-modal', 'true');
|
||||
document.body.classList.add('modal-open');
|
||||
|
||||
if (!document.querySelector('.modal-backdrop')) {
|
||||
var backdrop = document.createElement('div');
|
||||
backdrop.className = 'modal-backdrop fade show';
|
||||
document.body.appendChild(backdrop);
|
||||
}
|
||||
|
||||
console.log(branchDebugPrefix + ' force-open fallback applied');
|
||||
}
|
||||
|
||||
function hideBranchModal() {
|
||||
var $m = $('#insurerBranchModal');
|
||||
if (typeof jQuery !== 'undefined' && jQuery.fn && typeof jQuery.fn.modal === 'function') {
|
||||
$m.modal('hide');
|
||||
return;
|
||||
}
|
||||
var modalEl = document.getElementById('insurerBranchModal');
|
||||
if (window.bootstrap && bootstrap.Modal) {
|
||||
if (typeof bootstrap.Modal.getOrCreateInstance === 'function') {
|
||||
bootstrap.Modal.getOrCreateInstance(modalEl).hide();
|
||||
return;
|
||||
}
|
||||
if (typeof bootstrap.Modal.getInstance === 'function') {
|
||||
var existing = bootstrap.Modal.getInstance(modalEl);
|
||||
if (existing) {
|
||||
existing.hide();
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
(new bootstrap.Modal(modalEl)).hide();
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function resetInsurerBranchFormState() {
|
||||
var $form = $('#insurer_branch_form');
|
||||
if ($form.length && $form[0] && typeof $form[0].reset === 'function') {
|
||||
$form[0].reset();
|
||||
}
|
||||
|
||||
if ($form.length && typeof $form.parsley === 'function') {
|
||||
try {
|
||||
$form.parsley().reset();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
contactCount = 1;
|
||||
$('#container').empty();
|
||||
$('#contact_1_wrapper input').val('');
|
||||
$('#insurer_Branch_PrimaryKey').val('');
|
||||
toggleAddButton();
|
||||
}
|
||||
|
||||
function renderBranchRows(rows) {
|
||||
var html = '';
|
||||
$.each(rows || [], function(index, item) {
|
||||
html += `
|
||||
<tr>
|
||||
<td>${item.branch_name || ''}</td>
|
||||
<td>${item.branch_code || ''}</td>
|
||||
<td>
|
||||
<a class="mdi mdi-lead-pencil btnBranchEdit" href="#" data-id="${item.id}" style="font-size:18px;"></a>
|
||||
<a style="color:#02a8b5" data-id="${item.id}" onclick="removeInsurerBranch(this)"><i data-id="${item.id}" class="mdi mdi-delete" style="font-size:18px;"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
$('#insurer_branch_list').html(html);
|
||||
}
|
||||
|
||||
function initBranchDataTable() {
|
||||
if ($.fn.DataTable.isDataTable('#branch-datatable')) {
|
||||
$('#branch-datatable').DataTable().destroy();
|
||||
}
|
||||
|
||||
branchDataTable = $('#branch-datatable').DataTable({
|
||||
paging: true,
|
||||
searching: true,
|
||||
autoWidth: false,
|
||||
scrollX: false,
|
||||
responsive: false,
|
||||
dom: "<'row'<'col-12 d-flex justify-content-between align-items-center'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'B>>>" +
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
language: {
|
||||
search: `
|
||||
<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">
|
||||
_INPUT_
|
||||
<i class="mdi mdi-magnify datatable-search-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666;"></i>
|
||||
<i class="mdi mdi-close-circle datatable-clear-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No data available</div>'
|
||||
},
|
||||
buttons: [
|
||||
{
|
||||
text: '<i class="mdi mdi-plus" ></i><span class=" btn-custom"> Add Branch </span>',
|
||||
className: 'btn app-btn-primary mr-2 js-insurer-branch-add',
|
||||
action: function(e, dt, node, config) {
|
||||
openCreateBranchModal(e);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
function openCreateBranchModal(e) {
|
||||
try {
|
||||
console.log(branchDebugPrefix + ' add button click captured');
|
||||
if (e && typeof e.preventDefault === 'function') {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
insurer_branch_form_action = '<?= base_url("master/insurer/branch/create"); ?>';
|
||||
contactCount = 1;
|
||||
|
||||
showBranchModal();
|
||||
|
||||
var $form = $('#insurer_branch_form');
|
||||
if ($form.length && $form[0] && typeof $form[0].reset === 'function') {
|
||||
$form[0].reset();
|
||||
}
|
||||
|
||||
$('#branch_name').val('');
|
||||
$('#branch_code').val('');
|
||||
$('#state').val('');
|
||||
$('#district').val('');
|
||||
$('#branch_city').val('');
|
||||
|
||||
$('#name').val('');
|
||||
$('#email').val('');
|
||||
$('#mobile').val('');
|
||||
$('#designation').val('');
|
||||
|
||||
var addButton = document.getElementById('add');
|
||||
if (addButton && addButton.style.display === 'none') {
|
||||
addButton.style.display = 'block';
|
||||
}
|
||||
|
||||
var buttonIds = JSON.parse(localStorage.getItem('buttonIds')) || [];
|
||||
for (var i = 0; i < buttonIds.length; i++) {
|
||||
var firstElement = buttonIds[i].split('_')[0];
|
||||
var elementToRemove = document.getElementById(firstElement);
|
||||
if (elementToRemove) {
|
||||
elementToRemove.parentNode.removeChild(elementToRemove);
|
||||
}
|
||||
localStorage.removeItem('buttonIds');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(branchDebugPrefix + ' openCreateBranchModal failed:', err);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
insurer_Branch_PrimaryKey = $('#insurer_id_branch').val();
|
||||
var myModal = new bootstrap.Modal(document.getElementById('insurerBranchModal'));
|
||||
myModal.hide();
|
||||
|
||||
// $('#add_branch').hide();
|
||||
// $('.btnBack').hide();
|
||||
var data = <?= isset($insuer_branch) ? json_encode($insuer_branch) : '[]' ?>;
|
||||
|
||||
if(insurer_Branch_PrimaryKey !== ''){
|
||||
|
||||
var branchTable = '';
|
||||
var data = <?= isset($insuer_branch) ? json_encode($insuer_branch) : '[]' ?>;
|
||||
console.log("insurer branch data", data);
|
||||
$.each(data, function(index, item) {
|
||||
branchTable += `
|
||||
<tr>
|
||||
<td>${item.branch_name}</td>
|
||||
<td>${item.branch_code}</td>
|
||||
<td>
|
||||
<a class="mdi mdi-lead-pencil btnBranchEdit" href="#" data-id="${item.id}" style="font-size:18px;"></a>
|
||||
<a style="color:#02a8b5" data-id="${item.id}" onclick="removeInsurerBranch(this)"><i data-id="${item.id}" class="mdi mdi-delete" style="font-size:18px;"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
$('#insurer_branch_list').append(branchTable);
|
||||
}
|
||||
renderBranchRows(data);
|
||||
initBranchDataTable();
|
||||
|
||||
$('#branch-datatable').DataTable({
|
||||
paging: true ,
|
||||
searching: true
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$('#btnBranchAdd').click(function(){
|
||||
|
||||
$("#insurer_branch_form")[0].reset();
|
||||
contactCount = 1
|
||||
insurer_branch_form_action = '<?= base_url("master/insurer/branch/create"); ?>';
|
||||
var myModal = new bootstrap.Modal(document.getElementById('insurerBranchModal'));
|
||||
myModal.show();
|
||||
// $('#add_branch').show();
|
||||
// $('#branch_table').hide();
|
||||
// $('.btnBack').show();
|
||||
// $('#btnBranchAdd').hide();
|
||||
|
||||
$('#branch_name').val('');
|
||||
$('#branch_code').val('');
|
||||
$('#state').val('');
|
||||
$('#district').val('');
|
||||
$('#branch_city').val('');
|
||||
|
||||
$('#name').val('');
|
||||
$('#email').val('');
|
||||
$('#mobile').val('');
|
||||
$('#designation').val('');
|
||||
contactCount = 1
|
||||
|
||||
var addButton = document.getElementById('add');
|
||||
if (addButton.style.display === 'none') {
|
||||
addButton.style.display = 'block';
|
||||
}
|
||||
|
||||
var buttonIds = JSON.parse(localStorage.getItem('buttonIds')) || [];
|
||||
for (var i = 0; i < buttonIds.length; i++) {
|
||||
var firstElement = buttonIds[i].split('_')[0];
|
||||
console.log(firstElement);
|
||||
|
||||
// Find the element by its ID
|
||||
var elementToRemove = document.getElementById(firstElement);
|
||||
console.log(elementToRemove);
|
||||
|
||||
if (elementToRemove) {
|
||||
console.log(elementToRemove);
|
||||
elementToRemove.parentNode.removeChild(elementToRemove);
|
||||
$('a[data-toggle="tab"], a[data-bs-toggle="tab"]').on('shown.bs.tab', function () {
|
||||
if ($.fn.DataTable.isDataTable('#branch-datatable')) {
|
||||
$('#branch-datatable').DataTable().columns.adjust();
|
||||
}
|
||||
localStorage.removeItem('buttonIds')
|
||||
});
|
||||
|
||||
$(document).on('click', '.js-insurer-branch-add', function(e){
|
||||
console.log(branchDebugPrefix + ' delegated click fired for .js-insurer-branch-add/#btnBranchAdd');
|
||||
// DataTable button already calls openCreateBranchModal in its action.
|
||||
// Avoid double invocation when both handlers fire.
|
||||
if (!$(this).hasClass('dt-button')) {
|
||||
openCreateBranchModal(e);
|
||||
}
|
||||
});
|
||||
|
||||
$('#insurerBranchModal').on('hidden.bs.modal', function () {
|
||||
resetInsurerBranchFormState();
|
||||
});
|
||||
});
|
||||
|
||||
$('.btnBack').click(function(e){
|
||||
if (e && typeof e.preventDefault === 'function') {
|
||||
e.preventDefault();
|
||||
}
|
||||
})
|
||||
hideBranchModal();
|
||||
});
|
||||
|
||||
$('.btnBack').click(function(){
|
||||
|
||||
$("#insurer_branch_form")[0].reset();
|
||||
|
||||
contactCount = 1
|
||||
$('.close').click();
|
||||
// $('#add_branch').hide();
|
||||
// $('#branch_table').show();
|
||||
// $('.btnBack').hide();
|
||||
// $('#btnBranchAdd').show();
|
||||
|
||||
$('#branch_name').val('');
|
||||
$('#branch_code').val('');
|
||||
$('#state').val('');
|
||||
$('#district').val('');
|
||||
$('#branch_city').val('');
|
||||
|
||||
$('#name').val('');
|
||||
$('#email').val('');
|
||||
$('#mobile').val('');
|
||||
$('#designation').val('');
|
||||
$('#container').empty(); $('#contact_1_wrapper input').val('');
|
||||
|
||||
})
|
||||
$(document).on('click', '.js-branch-modal-close', function(e){
|
||||
if (e && typeof e.preventDefault === 'function') {
|
||||
e.preventDefault();
|
||||
}
|
||||
hideBranchModal();
|
||||
});
|
||||
|
||||
|
||||
$("#insurer_branch_form").submit(function(events) {
|
||||
@ -457,23 +539,10 @@
|
||||
$("#insurer_branch_form")[0].reset();
|
||||
console.log(res);
|
||||
$('#insurer_branch_list tr').remove();
|
||||
var insurerBranchTableInsert = ''
|
||||
$.each(res.data, function(index, item) {
|
||||
insurerBranchTableInsert += `
|
||||
<tr>
|
||||
<td>${item.branch_name}</td>
|
||||
<td>${item.branch_code}</td>
|
||||
<td>
|
||||
<a class="mdi mdi-lead-pencil btnBranchEdit" href="#" data-id="${item.id}" style="font-size:18px;"></a>
|
||||
<a style="color:#02a8b5" data-id="${item.id}" onclick="removeInsurerBranch(this)"><i data-id="${item.id}" class="mdi mdi-delete" style="font-size:18px;"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
|
||||
$('#insurer_branch_list').append(insurerBranchTableInsert);
|
||||
renderBranchRows(res.data || []);
|
||||
initBranchDataTable();
|
||||
$('#container').empty(); $('#contact_1_wrapper input').val('');
|
||||
$('.close').click();
|
||||
hideBranchModal();
|
||||
// window.location.reload();
|
||||
// $('#add_branch').hide();
|
||||
// $('#branch_table').show();
|
||||
@ -496,7 +565,7 @@
|
||||
$('.loader').fadeOut();
|
||||
$('.loader-mask').delay(350).fadeOut('slow');
|
||||
}, 1000);
|
||||
$('.close').click();
|
||||
hideBranchModal();
|
||||
}
|
||||
});
|
||||
|
||||
@ -527,8 +596,7 @@
|
||||
$('.loader').fadeOut();
|
||||
$('.loader-mask').delay(350).fadeOut('slow');
|
||||
}, 1000);
|
||||
var myModal = new bootstrap.Modal(document.getElementById('insurerBranchModal'));
|
||||
myModal.show();
|
||||
showBranchModal();
|
||||
// $('#add_branch').show();
|
||||
// $('#branch_table').show();
|
||||
// $('.btnBack').show();
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
<style>
|
||||
#insurer_datatable {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
overflow-x: auto;
|
||||
}
|
||||
@ -62,13 +66,13 @@
|
||||
|
||||
<div class="form-group col-md-6" style="position: relative;top: 28px;">
|
||||
<label for="email"><span class="text-danger"></span></label>
|
||||
<a href="#" class="btn app-btn-secondary mr-2" onclick="checkInsurerTemplete(this)">Copy</a>
|
||||
<a href="javascript:void(0);" class="btn app-btn-secondary mr-2" onclick="checkInsurerTemplete(this)">Copy</a>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-2" style="position: relative;top: 28px;">
|
||||
<div class="float-right">
|
||||
<label for="email"><span class="text-danger"></span></label>
|
||||
<a href="#" class="btn app-btn-primary " onclick="addNewJsonExportTemplate(this)"><i class="mdi mdi-plus"></i> Add </a>
|
||||
<a href="javascript:void(0);" class="btn app-btn-primary" onclick="addNewJsonExportTemplate(this)"><i class="mdi mdi-plus"></i> Add </a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -76,7 +80,7 @@
|
||||
|
||||
<div class="table-responsive" id="branch_table" >
|
||||
|
||||
<table data-custom-table-css="table" class="table table-borderless table-nowrap mb-0" id="insurer_datatable">
|
||||
<table data-custom-table-css="table" class="table table-borderless table-nowrap mb-0 w-100" id="insurer_datatable">
|
||||
<thead class="">
|
||||
|
||||
<tr>
|
||||
@ -102,7 +106,7 @@
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item" href="#" onclick="editJSONExportTemplate(this, '<?= $value['id']; ?>')"><i class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle"></i>Edit</a>
|
||||
<a class="dropdown-item" id="template_id_for_duplicate" data-id="<?= $value['id']; ?>" data-toggle="modal" data-target="#centermodal"><i class="mdi mdi-content-duplicate mr-2 text-muted font-18 vertical-middle"></i>Duplicate</a>
|
||||
<a class="dropdown-item template_id_for_duplicate" data-id="<?= $value['id']; ?>" data-toggle="modal" data-target="#centermodal"><i class="mdi mdi-content-duplicate mr-2 text-muted font-18 vertical-middle"></i>Duplicate</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@ -213,6 +217,7 @@
|
||||
<div class="modal-body">
|
||||
|
||||
<input type="hidden" id="insurer_id_for_dub_temp" value="<?= isset($insurer['id']) ? $insurer['id'] : '' ?>">
|
||||
<input type="hidden" id="duplicate_template_id" value="">
|
||||
|
||||
<div class="form-row">
|
||||
|
||||
@ -254,18 +259,59 @@
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<script>
|
||||
var insurerTemplateDataTable = null;
|
||||
|
||||
function showTemplateModal() {
|
||||
var modalEl = document.getElementById('template_modal');
|
||||
if (window.bootstrap && bootstrap.Modal) {
|
||||
if (typeof bootstrap.Modal.getOrCreateInstance === 'function') {
|
||||
bootstrap.Modal.getOrCreateInstance(modalEl).show();
|
||||
return;
|
||||
}
|
||||
if (typeof bootstrap.Modal.getInstance === 'function') {
|
||||
var existing = bootstrap.Modal.getInstance(modalEl);
|
||||
if (existing) {
|
||||
existing.show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
(new bootstrap.Modal(modalEl)).show();
|
||||
return;
|
||||
} catch (e) {}
|
||||
}
|
||||
$('#template_modal').modal('show');
|
||||
}
|
||||
|
||||
function initInsurerTemplateDataTable() {
|
||||
if ($.fn.DataTable.isDataTable('#insurer_datatable')) {
|
||||
$('#insurer_datatable').DataTable().destroy();
|
||||
}
|
||||
insurerTemplateDataTable = $('#insurer_datatable').DataTable({
|
||||
paging: true,
|
||||
searching: true,
|
||||
autoWidth: false,
|
||||
scrollX: false,
|
||||
responsive: false,
|
||||
language: {
|
||||
emptyTable: "No template data available"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#insurer').select2();
|
||||
// $('#event').select2();
|
||||
featchInsurerList();
|
||||
|
||||
setTimeout(() => {
|
||||
$('#insurer_datatable').DataTable({
|
||||
paging: true ,
|
||||
searching: true
|
||||
});
|
||||
}, 2000);
|
||||
initInsurerTemplateDataTable();
|
||||
$('a[data-toggle="tab"], a[data-bs-toggle="tab"]').on('shown.bs.tab', function () {
|
||||
if ($.fn.DataTable.isDataTable('#insurer_datatable')) {
|
||||
$('#insurer_datatable').DataTable().columns.adjust();
|
||||
}
|
||||
});
|
||||
$(document).on('click', '.template_id_for_duplicate', function() {
|
||||
$('#duplicate_template_id').val($(this).data('id'));
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
@ -488,11 +534,13 @@
|
||||
|
||||
function addNewJsonExportTemplate(input)
|
||||
{
|
||||
if (input && input.preventDefault) {
|
||||
input.preventDefault();
|
||||
}
|
||||
$('#myCenterModalLabel').text('Create Template');
|
||||
$('#dynamic-form-container').empty();
|
||||
addHTMLInput();
|
||||
var myModal = new bootstrap.Modal(document.getElementById('template_modal'));
|
||||
myModal.show();
|
||||
showTemplateModal();
|
||||
}
|
||||
|
||||
function addHTMLInput(element = null, data = null)
|
||||
@ -658,8 +706,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
var myModal = new bootstrap.Modal(document.getElementById('template_modal'));
|
||||
myModal.show();
|
||||
showTemplateModal();
|
||||
}
|
||||
|
||||
function checkForDuplicates(selectElement)
|
||||
@ -693,10 +740,15 @@
|
||||
|
||||
function dublicateTemplate()
|
||||
{
|
||||
var template_id = $('#template_id_for_duplicate').attr('data-id');
|
||||
var template_id = $('#duplicate_template_id').val();
|
||||
var event_name = $('#event_name_for_duplicate').val();
|
||||
var insurer_id = $('#insurer_id_for_dub_temp').val();
|
||||
|
||||
if (template_id === "") {
|
||||
toastr.warning('Please select a template to duplicate.', 'Warning');
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('template_id_for_duplicate', template_id)
|
||||
console.log('event_name_for_duplicate', event_name)
|
||||
console.log('insurer_id', insurer_id)
|
||||
|
||||
@ -1,31 +1,4 @@
|
||||
<style>
|
||||
.custom-dropdown-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #ffffff !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 0;
|
||||
min-width: 10rem;
|
||||
z-index: 9999;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
padding: 0.5rem 1rem !important;
|
||||
color: #212529 !important;
|
||||
text-decoration: none !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
color: #16181b !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.btn-color {
|
||||
background-color: rgba(52, 174, 178, 1);
|
||||
color: white;
|
||||
@ -40,6 +13,10 @@
|
||||
|
||||
.dataTables_length label {height: 21px !important;}
|
||||
|
||||
.col-12 {
|
||||
max-width: 98% !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container-fluid-min">
|
||||
@ -52,13 +29,13 @@
|
||||
<h4 style="position: relative;">Insurers</h4>
|
||||
</div>
|
||||
</div> -->
|
||||
<table data-custom-table-css="table" class="table table-sm table-hover m-0 table-centered dt-responsive nowrap w-100" cellspacing="0"
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0"
|
||||
id="tickets-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium">Name</th>
|
||||
<th class="font-weight-medium">Type</th>
|
||||
<th class="font-weight-medium">Action</th>
|
||||
<th class="font-weight-medium">Name </th>
|
||||
<th class="font-weight-medium">Type </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -68,7 +45,7 @@
|
||||
<tr>
|
||||
<td><?php echo $row['name']; ?> ( <?php echo $row['short_name']; ?> ) </td>
|
||||
<td><?php echo $row['type']; ?></td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
@ -91,100 +68,10 @@
|
||||
|
||||
<!-- end row -->
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.getElementById("tickets-table");
|
||||
|
||||
// Create custom dropdown
|
||||
function createCustomDropdown(row) {
|
||||
// Get the original dropdown items
|
||||
const originalDropdown = row.querySelector('.dropdown-menu');
|
||||
if (!originalDropdown) return null;
|
||||
|
||||
// Create new dropdown with proper background and spacing
|
||||
const customDropdown = document.createElement('div');
|
||||
customDropdown.className = 'custom-dropdown-menu';
|
||||
|
||||
// Copy inner content while maintaining icon alignment
|
||||
customDropdown.innerHTML = originalDropdown.innerHTML;
|
||||
|
||||
return customDropdown;
|
||||
}
|
||||
|
||||
let activeDropdown = null;
|
||||
|
||||
// Add click event listener to rows
|
||||
table.querySelectorAll("tbody tr").forEach(row => {
|
||||
const customDropdown = createCustomDropdown(row);
|
||||
if (!customDropdown) return;
|
||||
|
||||
document.body.appendChild(customDropdown);
|
||||
|
||||
row.addEventListener("click", function(event) {
|
||||
// Ignore clicks on the action column
|
||||
if (event.target.closest('td:last-child')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide any active dropdown
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
}
|
||||
|
||||
// Get click position
|
||||
const rect = event.target.getBoundingClientRect();
|
||||
|
||||
// Position the dropdown with some offset
|
||||
customDropdown.style.display = 'block';
|
||||
customDropdown.style.position = 'fixed';
|
||||
customDropdown.style.left = `${rect.left}px`;
|
||||
customDropdown.style.top = `${rect.bottom + 5}px`; // Add 5px gap
|
||||
|
||||
// Set as active dropdown
|
||||
activeDropdown = customDropdown;
|
||||
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Preserve click handlers and add auto-close
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
event.preventDefault(e);
|
||||
const onclickAttr = this.getAttribute('onclick');
|
||||
if (onclickAttr) {
|
||||
eval(onclickAttr);
|
||||
}
|
||||
|
||||
const href = this.getAttribute('href');
|
||||
if (href && href !== '#') {
|
||||
window.location.href = href;
|
||||
}
|
||||
|
||||
// Close the dropdown after handling the click
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
document.addEventListener("click", function() {
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#tickets-table').DataTable({
|
||||
var table = $('#tickets-table').DataTable({
|
||||
// dom: "<'row'<'col-12 d-flex justify-content-between align-items-center'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'B>>>" +
|
||||
// "<'row'<'col-sm-12'tr>>" +
|
||||
// "<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
@ -227,72 +114,34 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true,
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
const btnExport = document.querySelector("#btnExport");
|
||||
const tableElement = document.querySelector("#tickets-table");
|
||||
|
||||
btnExport.addEventListener("click", () => {
|
||||
const obj = new csvExport(tableElement);
|
||||
const csvData = obj.exportCsv();
|
||||
const blob = new Blob([csvData], {
|
||||
type: "text/csv"
|
||||
});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "UserList.csv";
|
||||
a.click();
|
||||
|
||||
setTimeout(() => {
|
||||
URL.revokeObjectURL(url);
|
||||
}, 500);
|
||||
});
|
||||
|
||||
|
||||
class csvExport {
|
||||
constructor(table, header = true) {
|
||||
this.table = table;
|
||||
this.rows = Array.from(table.querySelectorAll("tr"));
|
||||
if (!header && this.rows[0].querySelectorAll("th").length) {
|
||||
this.rows.shift();
|
||||
}
|
||||
}
|
||||
|
||||
exportCsv() {
|
||||
const lines = [];
|
||||
const ncols = this._longestRow();
|
||||
for (const row of this.rows) {
|
||||
let line = "";
|
||||
for (let i = 0; i < ncols - 1; i++) { // Exclude the last column
|
||||
if (row.children[i] !== undefined) {
|
||||
line += csvExport.safeData(row.children[i]);
|
||||
}
|
||||
line += i !== ncols - 2 ? "," : ""; // Adjusted for the last column exclusion
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#tickets-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
lines.push(line);
|
||||
}
|
||||
return lines.join("\n");
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
$('#tickets-table').on('draw.dt', applyBottomRowDropup);
|
||||
|
||||
_longestRow() {
|
||||
return this.rows.reduce((length, row) => (row.childElementCount > length ? row.childElementCount : length), 0);
|
||||
}
|
||||
|
||||
static safeData(td) {
|
||||
let data = td.textContent;
|
||||
//Replace all double quote to two double quotes
|
||||
data = data.replace(/"/g, `""`);
|
||||
//Replace , and \n to double quotes
|
||||
data = /[",\n"]/.test(data) ? `"${data}"` : data;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
function removeInsurer(element) {
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
<style>
|
||||
/* ---- CSS cleaned/optimized ---- */
|
||||
.table th, .table td { padding: 8px; }
|
||||
table.dataTable tbody td { padding: 4px 4px !important; }
|
||||
.col-12 { max-width: 98% !important; }
|
||||
.dataTables_filter { position: absolute; }
|
||||
.column-header { margin-right: 10px; }
|
||||
.dataTables_length label {height: 21px !important;}
|
||||
.filter-inline { display: flex; align-items: center; gap: 10px; }
|
||||
.filter-inline input[type="date"] { padding: 8px 12px; border:1px solid #ddd; border-radius:4px; font-size:13px; background:white; cursor:pointer; }
|
||||
.filter-inline input[type="date"]:focus { outline:none; border-color:#00a9a3; }
|
||||
@ -205,19 +203,19 @@ table.dataTable tbody td { padding: 4px 4px !important; }
|
||||
|
||||
<div class="card-body" style="padding-top: unset !important; border: white !important; background: unset !important;">
|
||||
<div>
|
||||
<table data-custom-table-css="table" class="table table-striped mb-0 nowrap" cellspacing="0" id="policy_table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="policy_table">
|
||||
|
||||
<!-- <table data-custom-table-css="table" class="table table-borderless mb-0 nowrap" id="policy_table"> -->
|
||||
<thead>
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th style="text-align:center;"><input type="checkbox" class="CB" id="selectAll" onchange="toggleSelectAll(this)"></th>
|
||||
<th><div class="column-header">Policy No</div></th><!-- 2 -->
|
||||
<th><div class="column-header">Customer</div></th> <!-- 3 -->
|
||||
<th><div class="column-header">Premium</div></th> <!-- 4 -->
|
||||
<th><div class="column-header">Policy Issues Date</div></th> <!-- 5 -->
|
||||
<th><div class="column-header">Commission Amount</div></th> <!-- 6 -->
|
||||
<th class="font-weight-medium" style="text-align:center;"><input type="checkbox" class="CB" id="selectAll" onchange="toggleSelectAll(this)"></th>
|
||||
<th class="font-weight-medium">Policy No </th><!-- 2 -->
|
||||
<th class="font-weight-medium">Customer </th> <!-- 3 -->
|
||||
<th class="font-weight-medium">Premium </th> <!-- 4 -->
|
||||
<th class="font-weight-medium">Policy Issues Date </th> <!-- 5 -->
|
||||
<th class="font-weight-medium">Commission Amount </th> <!-- 6 -->
|
||||
<?php if(isset($type) && $type === 'adjustment'): ?>
|
||||
<th><div class="column-header">Paid Amount</div></th> <!-- 7 -->
|
||||
<th class="font-weight-medium">Paid Amount </th> <!-- 7 -->
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -424,7 +422,11 @@ table.dataTable tbody td { padding: 4px 4px !important; }
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -947,7 +949,7 @@ function auditingHistory() {
|
||||
let table = `
|
||||
<div class="table-responsive">
|
||||
<table data-custom-table-css="table"
|
||||
class="table w-100 nowrap text-custom-black text-custom app-datatable">
|
||||
class="table mb-0 nowrap" cellspacing="0">
|
||||
|
||||
<thead class="bg-light">
|
||||
<!-- MAIN TITLE
|
||||
@ -968,16 +970,16 @@ function auditingHistory() {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>S.No</th>
|
||||
<th>Field Name</th>
|
||||
<th>Old Value</th>
|
||||
<th>New Value</th>
|
||||
<th>Updated By</th>
|
||||
<th>Date/Time</th>
|
||||
<th class="font-weight-medium">S.No </th>
|
||||
<th class="font-weight-medium">Field Name </th>
|
||||
<th class="font-weight-medium">Old Value </th>
|
||||
<th class="font-weight-medium">New Value </th>
|
||||
<th class="font-weight-medium">Updated By </th>
|
||||
<th class="font-weight-medium">Date/Time </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="app-table-body">`;
|
||||
<tbody>`;
|
||||
|
||||
// ============= MAIN INVOICE HISTORY =============
|
||||
invoiceArray.forEach((row, index) => {
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
<style>
|
||||
#table-kyc-docs_wrapper .datatable-search-wrapper{
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
#table-kyc-docs_wrapper .dataTables_filter input{
|
||||
width: 220px !important;
|
||||
padding-right: 34px !important;
|
||||
}
|
||||
|
||||
#table-kyc-docs_wrapper .datatable-search-icon,
|
||||
#table-kyc-docs_wrapper .datatable-clear-icon{
|
||||
right: 11px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="tab-pane fade" id="branch-tab">
|
||||
|
||||
<div class="row float-right" style="padding-bottom: 10px;position: relative;right: 13px;">
|
||||
@ -108,8 +124,9 @@
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
var kyc_Docs_PrimaryKey = $('#kyc_General_PrimaryKey').val();
|
||||
var kyc_Docs_PrimaryKey = $('#kyc_type_id').val();
|
||||
var kyc_docs_form_action = '';
|
||||
var kycDocsTable = null;
|
||||
var myModal = new bootstrap.Modal(document.getElementById('kycdocsModal'));
|
||||
myModal.hide();
|
||||
// $('#add_branch').hide();
|
||||
@ -118,7 +135,10 @@ $(document).ready(function () {
|
||||
loadKYCDocsList();
|
||||
|
||||
|
||||
$('#btnBranchAdd').click(function(){
|
||||
$('#btnBranchAdd').click(function(e){
|
||||
if (e && typeof e.preventDefault === 'function') {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
kyc_docs_form_action = '<?= base_url("master/kyc/kycdocs/createpost"); ?>';
|
||||
var myModal = new bootstrap.Modal(document.getElementById('kycdocsModal'));
|
||||
@ -149,7 +169,10 @@ $(document).ready(function () {
|
||||
$('#designation2').val('');
|
||||
})
|
||||
|
||||
$('.btnBack').click(function(){
|
||||
$('.btnBack').click(function(e){
|
||||
if (e && typeof e.preventDefault === 'function') {
|
||||
e.preventDefault();
|
||||
}
|
||||
var myModal = new bootstrap.Modal(document.getElementById('kycdocsModal'));
|
||||
myModal.hide();
|
||||
// $('#add_branch').hide();
|
||||
@ -183,7 +206,7 @@ $(document).ready(function () {
|
||||
if(kyc_Docs_PrimaryKey !== ''){
|
||||
|
||||
var branchTable = '';
|
||||
var data = <?= isset($insurer_branch) ? json_encode($insurer_branch) : '[]' ?>;
|
||||
var data = <?= isset($kyc_docs) ? json_encode($kyc_docs) : '[]' ?>;
|
||||
$.each(data, function(index, item) {
|
||||
branchTable += `
|
||||
<tr>
|
||||
@ -195,7 +218,7 @@ $(document).ready(function () {
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
$('#insurer_branch_list').append(branchTable);
|
||||
$('#kyc_docs_list').append(branchTable);
|
||||
}
|
||||
|
||||
|
||||
@ -356,7 +379,7 @@ $(document).ready(function () {
|
||||
function loadKYCDocsList() {
|
||||
var base_url = '<?= base_url("master/kyc/kycdocs/list/"); ?>';
|
||||
|
||||
var kyc_Docs_PrimaryKey_1 = $('#kyc_General_PrimaryKey').val();
|
||||
var kyc_Docs_PrimaryKey_1 = $('#kyc_type_id').val();
|
||||
|
||||
// console.log("kyc_Docs_PrimaryKey_1");
|
||||
// console.log(kyc_Docs_PrimaryKey_1);
|
||||
@ -409,10 +432,50 @@ $(document).ready(function () {
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
$('#table-kyc-docs').DataTable({
|
||||
paging: true ,
|
||||
searching: true
|
||||
kycDocsTable = $('#table-kyc-docs').DataTable({
|
||||
paging: true,
|
||||
searching: true,
|
||||
autoWidth: false,
|
||||
scrollX: false,
|
||||
responsive: false,
|
||||
columnDefs: [
|
||||
{ targets: 0, width: '50%' },
|
||||
{ targets: 1, width: '50%' }
|
||||
],
|
||||
initComplete: function () {
|
||||
var $wrapper = $('#table-kyc-docs_wrapper');
|
||||
$wrapper.find('.dataTables_scrollHeadInner').css({
|
||||
'box-sizing': 'content-box',
|
||||
'padding-right': '0px',
|
||||
'width': '100%'
|
||||
});
|
||||
this.api().columns.adjust();
|
||||
},
|
||||
dom: "<'datatable-top-section'f>" +
|
||||
"tr" +
|
||||
"<'datatable-bottom-section d-flex justify-content-between align-items-center mt-2'<'datatable-info'i><'datatable-controls d-flex align-items-center'<'me-2'l>p>>",
|
||||
language: {
|
||||
search: `
|
||||
<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">
|
||||
_INPUT_
|
||||
<i class="mdi mdi-magnify datatable-search-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666;"></i>
|
||||
<i class="mdi mdi-close-circle datatable-clear-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No data available</div>'
|
||||
}
|
||||
});
|
||||
|
||||
// Table is inside a tab-pane; adjust once visible to keep th/td aligned.
|
||||
$('a[data-toggle="tab"][href="#branch-tab"], a[data-bs-toggle="tab"][href="#branch-tab"]').on('shown.bs.tab', function () {
|
||||
if (kycDocsTable) {
|
||||
kycDocsTable.columns.adjust().draw(false);
|
||||
}
|
||||
});
|
||||
|
||||
if ($('#branch-tab').hasClass('active') || $('#branch-tab').hasClass('show')) {
|
||||
kycDocsTable.columns.adjust().draw(false);
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
|
||||
@ -3,17 +3,20 @@
|
||||
<div class="col-12">
|
||||
<div class="card-body subcard">
|
||||
<div class="custom-form">
|
||||
<form role="form" class="parsley-examples" method="post" id="kyc_general_form" enctype="multipart/form-data">
|
||||
<form role="form" class="parsley-examples" method="post" id="kyc_general_form" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>" />
|
||||
<input type="hidden" name="PrimaryKey" id="kyc_General_PrimaryKey" value="<?= isset($kyc['id']) ? $kyc['id'] : '' ?>"/>
|
||||
<input type="hidden" name="kyc_type_id" id="kyc_type_id" value="<?= isset($kyc['id']) ? $kyc['id'] : '' ?>"/>
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="kyc_name">KYC Entity Type Name<span
|
||||
class="text-danger">*</span></label>
|
||||
<label for="kyc_name">KYC Entity Type Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="name"
|
||||
placeholder="Enter Kyc Entity Type Name" value="<?= isset($kyc['name']) ? $kyc['name'] : '' ?>" name="name" required>
|
||||
placeholder="Enter Kyc Entity Type Name" value="<?= isset($kyc['name']) ? $kyc['name'] : '' ?>" name="name"
|
||||
required
|
||||
data-parsley-pattern="^[a-zA-Z0-9\s/_-]+$"
|
||||
data-parsley-pattern-message="This field may only contain letters, numbers, spaces, and the characters / - _"
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -119,35 +122,6 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
function validateForm() {
|
||||
var isValid = true;
|
||||
|
||||
// Perform validation for each field
|
||||
$('#kyc_general_form input, #kyc_general_form select').each(function() {
|
||||
// Check for empty text inputs and selects
|
||||
if ($(this).is('input[type="text"]') || $(this).is('select')) {
|
||||
if ($.trim($(this).val()) == '') {
|
||||
alert('Please fill in all fields');
|
||||
isValid = false;
|
||||
return false; // Exit the loop early
|
||||
}
|
||||
}
|
||||
|
||||
// Check for file inputs (assuming image files)
|
||||
if ($(this).is('input[type="file"]')) {
|
||||
var fileInput = $(this)[0];
|
||||
if (fileInput.files.length === 0) {
|
||||
alert('Please select an image file');
|
||||
isValid = false;
|
||||
return false; // Exit the loop early
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@ -49,7 +49,7 @@
|
||||
<h4 style="position: relative;">KYC Entity Type</h4>
|
||||
</div>
|
||||
<div class="col-6" style="text-align: right;">
|
||||
<a href="<?= base_url("master/kyc/list"); ?>" ><i class="mdi mdi-arrow-left" style="font-size: 17px;"></i> </a>
|
||||
<a href="<?= base_url("master/kyc/list"); ?>" ><i class="ri-arrow-left-circle-line" style="font-size: 17px;"></i> </a>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="tab-wrapper position-relative">
|
||||
|
||||
@ -92,6 +92,94 @@
|
||||
<!-- <script src="<?= base_url() . "public"; ?>/assets/libs/pdfmake/build/pdfmake.min.js"></script>
|
||||
<script src="<?= base_url() . "public"; ?>/assets/libs/pdfmake/build/vfs_fonts.js"></script> -->
|
||||
<!-- third party js ends -->
|
||||
<script>
|
||||
(function () {
|
||||
if (typeof jQuery === 'undefined' || !jQuery.fn || !jQuery.fn.dataTable) {
|
||||
return;
|
||||
}
|
||||
var $ = jQuery;
|
||||
|
||||
// Global defaults for all list pages unless overridden in a specific view.
|
||||
// Use horizontal scroll (scrollX) instead of Responsive (+/- child rows).
|
||||
$.extend(true, $.fn.dataTable.defaults, {
|
||||
scrollX: true,
|
||||
scrollY: '55vh',
|
||||
scrollCollapse: true,
|
||||
autoWidth: false,
|
||||
pageLength: 10,
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
responsive: false,
|
||||
language: {
|
||||
search: '<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">_INPUT_<i class="mdi mdi-magnify datatable-search-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666;"></i><i class="mdi mdi-close-circle datatable-clear-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666; display:none;"></i></div>',
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
}
|
||||
});
|
||||
|
||||
// Per-table init can still pass responsive: true; force off so every list uses scrollX, not +/- rows.
|
||||
$(document).on('preInit.dt', function (e, settings) {
|
||||
if (settings && settings.oInit) {
|
||||
settings.oInit.responsive = false;
|
||||
}
|
||||
});
|
||||
|
||||
function normalizeAddButtonLabel(buttonApi) {
|
||||
if (!buttonApi || !buttonApi.length) {
|
||||
return;
|
||||
}
|
||||
buttonApi.each(function () {
|
||||
var node = this.node ? this.node() : null;
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
var $btn = $(node);
|
||||
var rawText = ($btn.text() || '').trim().toLowerCase();
|
||||
if (rawText !== 'add') {
|
||||
return;
|
||||
}
|
||||
if ($btn.find('.mdi-plus').length) {
|
||||
return;
|
||||
}
|
||||
$btn.html('<i class="mdi mdi-plus"></i><span class="btn-custom"> Add </span>');
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeExportButtonLabel(buttonApi) {
|
||||
if (!buttonApi || !buttonApi.length) {
|
||||
return;
|
||||
}
|
||||
buttonApi.each(function () {
|
||||
var node = this.node ? this.node() : null;
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
var $btn = $(node);
|
||||
var rawText = ($btn.text() || '').trim().toLowerCase();
|
||||
if (rawText !== 'export') {
|
||||
return;
|
||||
}
|
||||
if ($btn.find('.mdi-menu-down').length) {
|
||||
return;
|
||||
}
|
||||
$btn.html('<span class="btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>');
|
||||
});
|
||||
}
|
||||
|
||||
// Keep Add CTA visual consistent across all DataTables pages.
|
||||
$(document).on('init.dt', function (e, settings) {
|
||||
if (!settings || !settings.nTable) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var dt = $(settings.nTable).DataTable();
|
||||
normalizeAddButtonLabel(dt.buttons());
|
||||
normalizeExportButtonLabel(dt.buttons());
|
||||
} catch (err) {
|
||||
// Do not block table render if a specific page has non-standard buttons.
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script src="<?= base_url() . "public"; ?>/assets/libs/bootstrap-datepicker/js/bootstrap-datepicker.min.js"></script>
|
||||
<script src="<?= base_url() . "public"; ?>/assets/libs/moment/min/moment.min.js"></script>
|
||||
@ -134,6 +222,26 @@
|
||||
<!-- bootstrap datepicker -->
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.10.0/js/bootstrap-datepicker.min.js"></script> -->
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Bootstrap popover compatibility shim for x-editable/bootstrap-editable.
|
||||
* Some builds expect `$.fn.popover.defaults` (BS3 style) which is missing
|
||||
* in newer Bootstrap plugin wrappers. Mirror Constructor defaults to keep
|
||||
* old plugins working and avoid:
|
||||
* "a.fn.popover.defaults is undefined".
|
||||
*/
|
||||
(function (window) {
|
||||
if (!window.jQuery || !window.jQuery.fn || !window.jQuery.fn.popover) {
|
||||
return;
|
||||
}
|
||||
var $ = window.jQuery;
|
||||
var ctor = $.fn.popover.Constructor;
|
||||
if (!$.fn.popover.defaults) {
|
||||
$.fn.popover.defaults = (ctor && (ctor.Default || ctor.DEFAULT)) ? (ctor.Default || ctor.DEFAULT) : {};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
<script src="<?= base_url() . "public"; ?>/assets/js/pages/jquery.xeditable.js"></script>
|
||||
<script src="<?= base_url() . "public"; ?>/assets/js/form-xeditable.init.js"></script>
|
||||
<script src="<?= base_url() . "public"; ?>/assets/js/bootstrap-editable.min.js"></script>
|
||||
@ -1287,6 +1395,379 @@ $(function(){
|
||||
table.search('').draw();
|
||||
});
|
||||
|
||||
/**
|
||||
* NHance — DataTables row action menus (tbody .dropdown)
|
||||
*
|
||||
* Moving the menu to body broke Bootstrap: clicks on Edit/Delete are no longer inside
|
||||
* the .btn-group parent, so the menu closes before the link receives the click.
|
||||
*
|
||||
* Keep the menu in the DOM under the ⋯: data-display="static" (no Popper transforms),
|
||||
* data-boundary="scrollParent" (no position-static parent). While open, set overflow
|
||||
* visible on .table-responsive / scroll body so the menu is not clipped. If there is
|
||||
* more room above the button than below, add Bootstrap’s .dropup so the menu opens
|
||||
* upward (last rows / short viewport).
|
||||
*/
|
||||
(function () {
|
||||
if (typeof jQuery === 'undefined') {
|
||||
return;
|
||||
}
|
||||
var $ = jQuery;
|
||||
var syncNs = '.nhDtRowToolbarDd';
|
||||
|
||||
function nhRowDropdownScrollHost($dd) {
|
||||
var $body = $dd.closest('.dataTables_scrollBody');
|
||||
if ($body.length) {
|
||||
return $body;
|
||||
}
|
||||
return $dd.closest('.table-responsive');
|
||||
}
|
||||
|
||||
function nhScheduleDropdownPopper($dd) {
|
||||
var $toggle = $dd.children('[data-toggle="dropdown"]').first();
|
||||
if (!$toggle.length) {
|
||||
return;
|
||||
}
|
||||
var inst = $toggle.data('bs.dropdown');
|
||||
if (inst && inst._popper) {
|
||||
inst._popper.scheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
function nhRowActionDropdownOpts() {
|
||||
$('.dataTables_wrapper table.dataTable tbody [data-toggle="dropdown"]').attr({
|
||||
'data-boundary': 'scrollParent',
|
||||
'data-display': 'static',
|
||||
'data-flip': 'false'
|
||||
});
|
||||
}
|
||||
|
||||
function nhNormalizeActionCells(tableApi) {
|
||||
if (!tableApi) {
|
||||
return;
|
||||
}
|
||||
var $table = $(tableApi.table().node());
|
||||
$table.find('tbody tr').each(function () {
|
||||
var $row = $(this);
|
||||
var $actionCell = $row.find('td').filter(function () {
|
||||
return $(this).find('.btn-group.dropdown, .dropdown-menu').length > 0;
|
||||
}).last();
|
||||
if ($actionCell.length) {
|
||||
$actionCell.addClass('table-action-cell');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function nhApplyBottomRowDropup(tableApi) {
|
||||
if (!tableApi) {
|
||||
return;
|
||||
}
|
||||
var $table = $(tableApi.table().node());
|
||||
var rows = tableApi.rows({ page: 'current' }).nodes().toArray();
|
||||
$table.find('tbody tr').removeClass('nh-force-dropup');
|
||||
$table.find('tbody td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
var target = 0;
|
||||
for (var i = rows.length - 1; i >= 0 && target < 2; i--) {
|
||||
var $row = $(rows[i]);
|
||||
var $group = $row.find('td.table-action-cell .btn-group.dropdown').first();
|
||||
if (!$group.length) {
|
||||
continue;
|
||||
}
|
||||
$row.addClass('nh-force-dropup');
|
||||
$group.addClass('dropup');
|
||||
target++;
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
var D = $.fn.dropdown && $.fn.dropdown.Constructor && $.fn.dropdown.Constructor.Default;
|
||||
if (D) {
|
||||
D.boundary = 'window';
|
||||
}
|
||||
nhRowActionDropdownOpts();
|
||||
});
|
||||
|
||||
$(document).on('draw.dt', 'table.dataTable', function () {
|
||||
nhRowActionDropdownOpts();
|
||||
var dt = $(this).DataTable();
|
||||
nhNormalizeActionCells(dt);
|
||||
nhApplyBottomRowDropup(dt);
|
||||
});
|
||||
|
||||
$(document).on('show.bs.dropdown', '.dataTables_wrapper table.dataTable tbody .dropdown', function () {
|
||||
var $dd = $(this);
|
||||
var $toggle = $dd.children('[data-toggle="dropdown"]').first();
|
||||
var $menu = $dd.children('.dropdown-menu').first();
|
||||
var el = $toggle[0];
|
||||
var $row = $dd.closest('tr');
|
||||
var isForcedDropup = $row.hasClass('nh-force-dropup');
|
||||
if (!isForcedDropup) {
|
||||
// Fallback: if row marker is missing, still force dropup on the last 2 visible rows.
|
||||
var $tbodyRows = $row.closest('tbody').children('tr:visible');
|
||||
if ($tbodyRows.length) {
|
||||
var rowIdx = $tbodyRows.index($row);
|
||||
isForcedDropup = rowIdx >= ($tbodyRows.length - 2);
|
||||
}
|
||||
}
|
||||
var $scroll = $dd.closest('.dataTables_scrollBody');
|
||||
if ($scroll.length) {
|
||||
$scroll.data('nh-prev-overflow', $scroll.css('overflow'));
|
||||
$scroll.css('overflow', 'visible');
|
||||
}
|
||||
var $resp = $dd.closest('.table-responsive');
|
||||
if ($resp.length) {
|
||||
$resp.data('nh-prev-overflow-tr', $resp.css('overflow'));
|
||||
$resp.css('overflow', 'visible');
|
||||
}
|
||||
var $cardBody = $dd.closest('.card-body');
|
||||
if ($cardBody.length) {
|
||||
$cardBody.data('nh-prev-overflow-cb', $cardBody.css('overflow'));
|
||||
$cardBody.css('overflow', 'visible');
|
||||
}
|
||||
if (!el || !el.getClientRects().length) {
|
||||
return;
|
||||
}
|
||||
var rect = el.getBoundingClientRect();
|
||||
var vh = window.innerHeight;
|
||||
var below = Math.max(0, vh - rect.bottom - 8);
|
||||
var above = Math.max(0, rect.top - 8);
|
||||
var menuHeight = 0;
|
||||
if ($menu.length) {
|
||||
// Measure true menu height even while hidden.
|
||||
var prevStyle = $menu.attr('style');
|
||||
$menu.css({ display: 'block', visibility: 'hidden', maxHeight: '', overflowY: '' });
|
||||
menuHeight = $menu.outerHeight() || 0;
|
||||
if (prevStyle !== undefined) {
|
||||
$menu.attr('style', prevStyle);
|
||||
} else {
|
||||
$menu.removeAttr('style');
|
||||
}
|
||||
}
|
||||
|
||||
// Pick direction by space; prefer the side that can fit the full menu.
|
||||
var openUp = false;
|
||||
if (isForcedDropup) {
|
||||
openUp = true;
|
||||
} else if (menuHeight > 0) {
|
||||
if (below >= menuHeight) {
|
||||
openUp = false;
|
||||
} else if (above >= menuHeight) {
|
||||
openUp = true;
|
||||
} else {
|
||||
openUp = above > below;
|
||||
}
|
||||
} else {
|
||||
openUp = below < 150 && above > below;
|
||||
}
|
||||
|
||||
// Keep explicit per-row dropup (set by nhApplyBottomRowDropup / page scripts).
|
||||
if (!isForcedDropup) {
|
||||
$dd.removeClass('dropup');
|
||||
}
|
||||
$dd.removeData('nh-auto-dropup');
|
||||
|
||||
if (openUp) {
|
||||
$dd.addClass('dropup');
|
||||
if (!isForcedDropup) {
|
||||
$dd.data('nh-auto-dropup', 1);
|
||||
}
|
||||
}
|
||||
|
||||
// If there still isn't enough room, keep all actions reachable via scroll.
|
||||
if ($menu.length && menuHeight > 0) {
|
||||
var usableSpace = openUp ? above : below;
|
||||
var maxVisible = Math.max(140, usableSpace - 12);
|
||||
if (menuHeight > maxVisible) {
|
||||
$menu.css({
|
||||
maxHeight: maxVisible + 'px',
|
||||
overflowY: 'auto'
|
||||
});
|
||||
} else {
|
||||
$menu.css({
|
||||
maxHeight: '',
|
||||
overflowY: ''
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('hidden.bs.dropdown', '.dataTables_wrapper table.dataTable tbody .dropdown', function () {
|
||||
var $dd = $(this);
|
||||
var $scroll = $dd.closest('.dataTables_scrollBody');
|
||||
if ($scroll.length) {
|
||||
var o = $scroll.data('nh-prev-overflow');
|
||||
if (o !== undefined) {
|
||||
$scroll.css('overflow', o);
|
||||
}
|
||||
$scroll.removeData('nh-prev-overflow');
|
||||
}
|
||||
var $resp = $dd.closest('.table-responsive');
|
||||
if ($resp.length) {
|
||||
var o2 = $resp.data('nh-prev-overflow-tr');
|
||||
if (o2 !== undefined) {
|
||||
$resp.css('overflow', o2);
|
||||
}
|
||||
$resp.removeData('nh-prev-overflow-tr');
|
||||
}
|
||||
var $cardBody = $dd.closest('.card-body');
|
||||
if ($cardBody.length) {
|
||||
var o3 = $cardBody.data('nh-prev-overflow-cb');
|
||||
if (o3 !== undefined) {
|
||||
$cardBody.css('overflow', o3);
|
||||
}
|
||||
$cardBody.removeData('nh-prev-overflow-cb');
|
||||
}
|
||||
if ($dd.data('nh-auto-dropup')) {
|
||||
$dd.removeClass('dropup');
|
||||
$dd.removeData('nh-auto-dropup');
|
||||
}
|
||||
$dd.children('.dropdown-menu').css({
|
||||
maxHeight: '',
|
||||
overflowY: ''
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('shown.bs.dropdown', '.dataTables_wrapper .dropdown', function () {
|
||||
var $dd = $(this);
|
||||
if ($dd.closest('table.dataTable tbody').length) {
|
||||
return;
|
||||
}
|
||||
var sync = function () {
|
||||
nhScheduleDropdownPopper($dd);
|
||||
};
|
||||
nhScheduleDropdownPopper($dd);
|
||||
nhRowDropdownScrollHost($dd).off(syncNs).on('scroll' + syncNs, sync);
|
||||
$(window).off(syncNs).on('scroll' + syncNs, sync);
|
||||
var $contentPage = $dd.closest('.content-page');
|
||||
if ($contentPage.length) {
|
||||
$contentPage.off(syncNs).on('scroll' + syncNs, sync);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('hidden.bs.dropdown', '.dataTables_wrapper .dropdown', function () {
|
||||
var $dd = $(this);
|
||||
if ($dd.closest('table.dataTable tbody').length) {
|
||||
return;
|
||||
}
|
||||
nhRowDropdownScrollHost($dd).off(syncNs);
|
||||
$(window).off(syncNs);
|
||||
$dd.closest('.content-page').off(syncNs);
|
||||
});
|
||||
|
||||
/**
|
||||
* NHance — standardize DataTables control layout for pages still using
|
||||
* default DataTables DOM:
|
||||
* top: length + search, bottom: info + paginate
|
||||
*
|
||||
* Requirement format:
|
||||
* - top row: search (left), buttons (right if present)
|
||||
* - bottom row: info (left), show-length + pagination (right)
|
||||
*
|
||||
* For wrappers without custom dom, move top `.dataTables_length` to
|
||||
* bottom row before `.dataTables_paginate`.
|
||||
*/
|
||||
function normalizeDataTableLayout(wrapper) {
|
||||
if (!wrapper || !wrapper.length) {
|
||||
return;
|
||||
}
|
||||
var $rows = wrapper.children('div.row');
|
||||
if ($rows.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $top = $rows.first();
|
||||
var $bottom = $rows.last();
|
||||
|
||||
var $topLength = $top.find('div.dataTables_length').first();
|
||||
var $bottomPaginate = $bottom.find('div.dataTables_paginate').first();
|
||||
|
||||
if (!$topLength.length || !$bottomPaginate.length) {
|
||||
applyBottomSlotClasses($bottom);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($bottom.find('div.dataTables_length').length) {
|
||||
applyBottomSlotClasses($bottom);
|
||||
return; // already normalized/customized
|
||||
}
|
||||
|
||||
$bottomPaginate.before($topLength);
|
||||
applyBottomSlotClasses($bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark bottom row containers so CSS can enforce exact requirement layout:
|
||||
* info left; length + pagination grouped right.
|
||||
*/
|
||||
function applyBottomSlotClasses($bottomRow) {
|
||||
if (!$bottomRow || !$bottomRow.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bottomRow.children('div').removeClass('nh-dt-bottom-info nh-dt-bottom-length nh-dt-bottom-paginate');
|
||||
|
||||
var $info = $bottomRow.find('div.dataTables_info').first().closest('div');
|
||||
var $len = $bottomRow.find('div.dataTables_length').first().closest('div');
|
||||
var $pag = $bottomRow.find('div.dataTables_paginate').first().closest('div');
|
||||
|
||||
if ($info.length) {
|
||||
$info.addClass('nh-dt-bottom-info');
|
||||
}
|
||||
if ($len.length) {
|
||||
$len.addClass('nh-dt-bottom-length');
|
||||
}
|
||||
if ($pag.length) {
|
||||
$pag.addClass('nh-dt-bottom-paginate');
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('init.dt', function (e, settings) {
|
||||
if (!settings || !settings.nTableWrapper) {
|
||||
return;
|
||||
}
|
||||
var wrapper = $(settings.nTableWrapper);
|
||||
normalizeDataTableLayout(wrapper);
|
||||
/* Stops Bootstrap `.table-responsive` from adding a second horizontal scrollbar under pagination */
|
||||
wrapper.closest('.table-responsive').addClass('nh-dt-no-outer-scroll');
|
||||
try {
|
||||
var dt = $(settings.nTable).DataTable();
|
||||
nhNormalizeActionCells(dt);
|
||||
nhApplyBottomRowDropup(dt);
|
||||
} catch (err) {
|
||||
// keep page running if a table has non-standard setup
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Prev/next disabled state (first page, last page, single page): DataTables
|
||||
* normally sets `li.page-item.disabled`; re-sync from page.info() after each
|
||||
* draw so grey-arrow styles in custom.css / header always match behaviour.
|
||||
*/
|
||||
$(document).on('draw.dt', function (e, settings) {
|
||||
if (!settings || !settings.nTableWrapper || !settings.oFeatures || !settings.oFeatures.bPaginate) {
|
||||
return;
|
||||
}
|
||||
var api;
|
||||
try {
|
||||
api = new $.fn.dataTable.Api(settings);
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
var info = api.page.info();
|
||||
var $pag = $(settings.nTableWrapper).find('.dataTables_paginate');
|
||||
if (!$pag.length) {
|
||||
return;
|
||||
}
|
||||
var pages = info.pages;
|
||||
var atFirst = info.page <= 0;
|
||||
var atLast = pages <= 0 || info.page >= pages - 1;
|
||||
$pag.find('li.paginate_button.page-item.previous, li.page-item.previous').toggleClass('disabled', atFirst);
|
||||
$pag.find('li.paginate_button.page-item.next, li.page-item.next').toggleClass('disabled', atLast);
|
||||
$pag.find('a.paginate_button.previous').toggleClass('disabled', atFirst);
|
||||
$pag.find('a.paginate_button.next').toggleClass('disabled', atLast);
|
||||
});
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
<link href="<?= base_url() . "public"; ?>/assets/css/bootstrap-creative-dark.min.css" rel="stylesheet" type="text/css" id="bs-dark-stylesheet" />
|
||||
<link href="<?= base_url() . "public"; ?>/assets/css/app-creative-dark.min.css" rel="stylesheet" type="text/css" id="app-dark-stylesheet" />
|
||||
<link href="<?= base_url() . "public"; ?>/assets/css/custom.css" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!-- icons -->
|
||||
<link href="<?= base_url() . "public"; ?>/assets/css/icons.min.css" rel="stylesheet" type="text/css" />
|
||||
@ -828,43 +829,164 @@
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
/* Previous / Next buttons */
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous .page-link,
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.next .page-link {
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous,
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.next {
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
align-self: center !important;
|
||||
}
|
||||
|
||||
/* Previous / Next — white background; box matches page number height; arrow via ::before */
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous:not(.disabled) .page-link,
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.next:not(.disabled) .page-link {
|
||||
border-radius: 13px !important;
|
||||
background-color: #F5FFFF;
|
||||
background-color: #ffffff !important;
|
||||
border: none !important;
|
||||
box-shadow: 0 0 0 0.15rem #F5FFFF;
|
||||
font-size: 0;
|
||||
/* hide default text */
|
||||
position: relative;
|
||||
box-shadow: none !important;
|
||||
outline: none !important;
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
color: transparent !important;
|
||||
position: relative !important;
|
||||
overflow: hidden !important;
|
||||
min-width: 32px !important;
|
||||
width: 32px !important;
|
||||
min-height: 2.25rem !important;
|
||||
padding: 0 !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
/* Custom arrows */
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous .page-link::before {
|
||||
content: "◄";
|
||||
font-size: 14px;
|
||||
/* Previous / Next — disabled (first page, last page, or single page): white btn, grey arrows */
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous.disabled .page-link,
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.next.disabled .page-link {
|
||||
border-radius: 13px !important;
|
||||
background-color: #ffffff !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
outline: none !important;
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
color: transparent !important;
|
||||
position: relative !important;
|
||||
overflow: hidden !important;
|
||||
min-width: 32px !important;
|
||||
width: 32px !important;
|
||||
min-height: 2.25rem !important;
|
||||
padding: 0 !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous.disabled .page-link::before,
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.next.disabled .page-link::before {
|
||||
color: #adb5bd !important;
|
||||
}
|
||||
|
||||
/* DataTables variant without .page-item/.page-link markup */
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button.previous:not(.disabled),
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button.next:not(.disabled) {
|
||||
border-radius: 13px !important;
|
||||
background-color: #ffffff !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
outline: none !important;
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
color: transparent !important;
|
||||
position: relative !important;
|
||||
overflow: hidden !important;
|
||||
min-width: 32px !important;
|
||||
width: 32px !important;
|
||||
min-height: 2.25rem !important;
|
||||
padding: 0 !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button.previous.disabled,
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button.next.disabled {
|
||||
border-radius: 13px !important;
|
||||
background-color: #ffffff !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
outline: none !important;
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
min-width: 32px !important;
|
||||
width: 32px !important;
|
||||
min-height: 2.25rem !important;
|
||||
padding: 0 !important;
|
||||
position: relative !important;
|
||||
overflow: hidden !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button.previous.disabled::before,
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button.next.disabled::before {
|
||||
color: #adb5bd !important;
|
||||
}
|
||||
|
||||
/* Arrows: dead-center in the hit box (Unicode glyphs have uneven metrics otherwise) */
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous .page-link::before,
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.next .page-link::before {
|
||||
content: "►";
|
||||
font-size: 14px;
|
||||
content: "";
|
||||
position: absolute !important;
|
||||
left: 50% !important;
|
||||
top: 50% !important;
|
||||
transform: translate(-50%, -50%) !important;
|
||||
line-height: 1 !important;
|
||||
font-size: 12px !important;
|
||||
display: block !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous:not(.disabled) .page-link::before {
|
||||
content: "◄";
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.next:not(.disabled) .page-link::before {
|
||||
content: "►";
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.previous.disabled .page-link::before {
|
||||
content: "◄";
|
||||
}
|
||||
|
||||
/* Active / Inactive pages */
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.next.disabled .page-link::before {
|
||||
content: "►";
|
||||
}
|
||||
|
||||
/* Avoid double arrows when Bootstrap markup nests .paginate_button + .page-link */
|
||||
.dataTables_wrapper .dataTables_paginate li.paginate_button.previous::before,
|
||||
.dataTables_wrapper .dataTables_paginate li.paginate_button.next::before {
|
||||
content: none !important;
|
||||
}
|
||||
|
||||
/* Active / Inactive page numbers only (not prev/next arrows) */
|
||||
.dataTables_wrapper .dataTables_paginate .page-item.active .page-link {
|
||||
color: #fff !important;
|
||||
border-radius: 13px !important;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .page-item:not(.active) .page-link {
|
||||
.dataTables_wrapper .dataTables_paginate .page-item:not(.active):not(.previous):not(.next) .page-link {
|
||||
border: 1px solid #fff !important;
|
||||
border-radius: 13px !important;
|
||||
}
|
||||
|
||||
|
||||
/* Info text */
|
||||
.dataTables_info {
|
||||
font-size: 12px;
|
||||
@ -959,8 +1081,7 @@
|
||||
.card-body .card-body .dt-buttons,
|
||||
.card-body .card-body .datatable-buttons {
|
||||
margin-right: 0 !important;
|
||||
padding-right: 2.25rem !important;
|
||||
/* match card-body padding */
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
/* Applies only to tables with data-custom-table-css="table" */
|
||||
@ -1424,7 +1545,7 @@
|
||||
}
|
||||
|
||||
|
||||
.dropdown {
|
||||
.topbar-actions .dropdown {
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
|
||||
@ -2389,6 +2510,20 @@ body[data-sidebar-size="condensed"] .footer {
|
||||
$default = base_url('public/assets/images/avatar_2x.png');
|
||||
$firstName = isset(get_session_userdata()->first_name) ? get_session_userdata()->first_name : 'A';
|
||||
$initial = strtoupper(substr($firstName, 0, 1));
|
||||
$roleId = get_role_id();
|
||||
$roleName = 'User';
|
||||
if ($roleId == ADMIN_ROLE_ID) {
|
||||
$roleName = 'Admin';
|
||||
} elseif ($roleId == HEAD_ROLE_ID) {
|
||||
$roleName = 'Head';
|
||||
} elseif ($roleId == MANAGER_ROLE_ID) {
|
||||
$roleName = 'Manager';
|
||||
} elseif ($roleId == ACCOUNT_MANAGER_ROLE_ID) {
|
||||
$roleName = 'Account Manager';
|
||||
} elseif ($roleId == STAFF_ROLE_ID) {
|
||||
$roleName = 'Staff';
|
||||
}
|
||||
$userTitle = $firstName . ' ( ' . $roleName . ' )';
|
||||
?>
|
||||
|
||||
<?php if (!empty($profile)) : ?>
|
||||
@ -2397,18 +2532,19 @@ body[data-sidebar-size="condensed"] .footer {
|
||||
src="<?= $profile ?>"
|
||||
onerror="this.onerror=null; this.src='<?= $default ?>'; this.style.display='none'; document.getElementById('avatar-fallback').style.display='flex';"
|
||||
alt="user-image"
|
||||
title="<?= $userTitle ?>"
|
||||
height="38" width="38"
|
||||
class="rounded-circle"
|
||||
style="object-fit:cover; border: 2px solid var(--primary-light); cursor:pointer;"
|
||||
>
|
||||
<!-- Fallback avatar (hidden by default, shown if image fails) -->
|
||||
<div class="avatar-btn" id="avatar-fallback" title="<?= $firstName ?>" style="display:none;">
|
||||
<div class="avatar-btn" id="avatar-fallback" title="<?= $userTitle ?>" style="display:none;">
|
||||
<?= $initial ?>
|
||||
</div>
|
||||
|
||||
<?php else : ?>
|
||||
<!-- No profile image — show initial avatar -->
|
||||
<div class="avatar-btn" title="<?= $firstName ?>">
|
||||
<div class="avatar-btn" title="<?= $userTitle ?>">
|
||||
<?= $initial ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
@ -1,19 +1,6 @@
|
||||
<style>
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td {
|
||||
padding: 4px 4px !important;
|
||||
}
|
||||
|
||||
.col-12 {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.dataTables_filter {
|
||||
position: absolute;
|
||||
max-width: 98% !important;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
@ -49,32 +36,6 @@ table.dataTable tbody td {
|
||||
}
|
||||
|
||||
|
||||
.custom-dropdown-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #ffffff !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 0;
|
||||
min-width: 10rem;
|
||||
z-index: 9999;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
padding: 0.5rem 1rem !important;
|
||||
color: #212529 !important;
|
||||
text-decoration: none !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
color: #16181b !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.addbtnStyle{
|
||||
margin-left: 20px !important;
|
||||
@ -173,23 +134,23 @@ table.dataTable tbody td {
|
||||
</div>
|
||||
<div>
|
||||
<div class="table-responsive">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap w-100 table-centered" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="tickets-table">
|
||||
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th><div class="column-header">S.No </div></th>
|
||||
<th><div class="column-header">Opportunity Type </div></th>
|
||||
<th><div class="column-header">Issuer </div></th>
|
||||
<th><div class="column-header">Client Type </div></th>
|
||||
<th><div class="column-header">Client / Branch </div></th>
|
||||
<th><div class="column-header">Entity Type </div></th>
|
||||
<th><div class="column-header">Branch Name </div></th>
|
||||
<th><div class="column-header">Branch Code </div></th>
|
||||
<th><div class="column-header">Contact Person Name </div></th>
|
||||
<th><div class="column-header">Contact Person Mobile </div></th>
|
||||
<th><div class="column-header">Policy Type </div></th>
|
||||
<th><div class="column-header">Status </div></th>
|
||||
<th><div class="column-header">Action </div></th>
|
||||
<th class="font-weight-medium">S.No </th>
|
||||
<th class="font-weight-medium">Opportunity Type </th>
|
||||
<th class="font-weight-medium">Issuer </th>
|
||||
<th class="font-weight-medium">Client Type </th>
|
||||
<th class="font-weight-medium">Client / Branch </th>
|
||||
<th class="font-weight-medium">Entity Type </th>
|
||||
<th class="font-weight-medium">Branch Name </th>
|
||||
<th class="font-weight-medium">Branch Code </th>
|
||||
<th class="font-weight-medium">Contact Person Name </th>
|
||||
<th class="font-weight-medium">Contact Person Mobile </th>
|
||||
<th class="font-weight-medium">Policy Type </th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -220,12 +181,11 @@ table.dataTable tbody td {
|
||||
<td><?php echo $row['contact_person_mobile'] ?? '-'; ?></td>
|
||||
<td><?php echo $row['policy_type'] ?? '-'; ?></td>
|
||||
<td><?php echo $lead_status[$row['status']] ?? '-'; ?></td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript:void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm"
|
||||
data-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
data-boundary="window"> <i class="mdi mdi-dots-horizontal"></i>
|
||||
aria-expanded="false"> <i class="mdi mdi-dots-horizontal"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<?php $isNonEb = isset($row['lead_form_type']) && (int) $row['lead_form_type'] === 2; ?>
|
||||
@ -751,186 +711,7 @@ table.dataTable tbody td {
|
||||
};
|
||||
|
||||
// New menu
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const table = document.getElementById("tickets-table");
|
||||
// RFQ_or_QCR: 1 = RFQ (insurer/internal), 2 = QCR (client)
|
||||
window.RFQ_or_QCR = 1;
|
||||
// Logged-in user role id (used in mail modal rendering)
|
||||
window.user_role_id = <?php echo get_role_id(); ?>;
|
||||
|
||||
function createCustomDropdown(row) {
|
||||
const originalDropdown = row.querySelector('.dropdown-menu');
|
||||
if (!originalDropdown) return null;
|
||||
|
||||
const customDropdown = document.createElement('div');
|
||||
customDropdown.className = 'custom-dropdown-menu';
|
||||
|
||||
// Clone the items but remove their original click handlers
|
||||
const items = originalDropdown.querySelectorAll('.dropdown-item');
|
||||
items.forEach(item => {
|
||||
const newItem = item.cloneNode(true);
|
||||
// Preserve the attributes but remove the onclick
|
||||
newItem.removeAttribute('onclick');
|
||||
customDropdown.appendChild(newItem);
|
||||
});
|
||||
|
||||
return customDropdown;
|
||||
}
|
||||
|
||||
let activeDropdown = null;
|
||||
|
||||
table.querySelectorAll("tbody tr").forEach(row => {
|
||||
const customDropdown = createCustomDropdown(row);
|
||||
if (!customDropdown) return;
|
||||
|
||||
document.body.appendChild(customDropdown);
|
||||
|
||||
row.addEventListener("click", function(event) {
|
||||
if (event.target.closest('.dropdown-toggle')) {
|
||||
event.stopPropagation();
|
||||
const originalDropdown = event.target.closest('.btn-group').querySelector('.dropdown-menu');
|
||||
if (originalDropdown) {
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
}
|
||||
const rect = event.target.getBoundingClientRect();
|
||||
customDropdown.style.display = 'block';
|
||||
customDropdown.style.position = 'fixed';
|
||||
customDropdown.style.left = `${rect.left}px`;
|
||||
customDropdown.style.top = `${rect.bottom + 5}px`;
|
||||
activeDropdown = customDropdown;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target.closest('td:last-child')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
}
|
||||
|
||||
const rect = event.target.getBoundingClientRect();
|
||||
|
||||
customDropdown.style.display = 'block';
|
||||
customDropdown.style.position = 'fixed';
|
||||
customDropdown.style.left = `${rect.left}px`;
|
||||
customDropdown.style.top = `${rect.bottom + 5}px`;
|
||||
|
||||
activeDropdown = customDropdown;
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
console.log("##############");
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Get the data-id and other attributes from the original button
|
||||
const originalItem = row.querySelector(`.dropdown-item[data-id="${this.getAttribute('data-id')}"]`);
|
||||
|
||||
// For edit functionality
|
||||
if (this.classList.contains('btnEdit')) {
|
||||
const id = this.getAttribute('data-id');
|
||||
const lead_form_type = this.getAttribute('data-ft');
|
||||
console.log('second drop lead_form_type', lead_form_type)
|
||||
if (id) {
|
||||
getLeadsDataForEdit(id, lead_form_type);
|
||||
}
|
||||
}else if (this.classList.contains('btnHistory')) {
|
||||
let lead_id = this.getAttribute('data-id');
|
||||
if(lead_id){ console.log("******** Clicked from td lead_id-", lead_id); getLeadsDataForMailHistory(lead_id); }
|
||||
else{ console.log("******** Clicked from td but i don`t have lead_id"); }
|
||||
|
||||
}else if (this.classList.contains('btnRfqSheetList')) {
|
||||
const leadId = this.getAttribute('data-id');
|
||||
if (leadId) {
|
||||
createRfqSheetFromList(leadId);
|
||||
}
|
||||
|
||||
}else if (this.classList.contains('btnQcrSheetList')) {
|
||||
const leadId = this.getAttribute('data-id');
|
||||
if (leadId) {
|
||||
createQcrSheetFromList(leadId);
|
||||
}
|
||||
|
||||
}else if (this.classList.contains('btnInternalMailList')) {
|
||||
const leadId = this.getAttribute('data-id');
|
||||
if (leadId) {
|
||||
openInternalMailFromList(leadId);
|
||||
}
|
||||
|
||||
}else if (this.classList.contains('btnInsurerMailList')) {
|
||||
const leadId = this.getAttribute('data-id');
|
||||
if (leadId) {
|
||||
openInsurerMailFromList(leadId);
|
||||
}
|
||||
|
||||
}else if (this.classList.contains('btnClientMailList')) {
|
||||
const leadId = this.getAttribute('data-id');
|
||||
if (leadId) {
|
||||
openClientMailFromList(leadId);
|
||||
}
|
||||
|
||||
}else if (this.classList.contains('btnPlacementList')) {
|
||||
const leadId = this.getAttribute('data-id');
|
||||
if (leadId) {
|
||||
openPlacementFromList(leadId);
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
const onclickAttr = this.getAttribute('onclick');
|
||||
if (onclickAttr) {
|
||||
eval(onclickAttr);
|
||||
}
|
||||
}
|
||||
|
||||
// For RFQ links
|
||||
const href = this.getAttribute('href');
|
||||
if (
|
||||
href &&
|
||||
href !== '#' &&
|
||||
!this.classList.contains('btnEdit') &&
|
||||
!this.classList.contains('btnRfqSheetList') &&
|
||||
!this.classList.contains('btnQcrSheetList') &&
|
||||
!this.classList.contains('btnInternalMailList') &&
|
||||
!this.classList.contains('btnInsurerMailList') &&
|
||||
!this.classList.contains('btnClientMailList') &&
|
||||
!this.classList.contains('btnPlacementList')
|
||||
) {
|
||||
window.location.href = href;
|
||||
}
|
||||
|
||||
// Close the dropdown
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
document.addEventListener("click", function() {
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("click", function(e) {
|
||||
const historyBtn = e.target.closest(".btnHistory");
|
||||
if (historyBtn && historyBtn.dataset.id) {
|
||||
let lead_id = historyBtn.dataset.id;
|
||||
console.log("******** in triple dot id available - " + lead_id);
|
||||
getLeadsDataForMailHistory(lead_id);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
var table;
|
||||
|
||||
// Datatable document ready
|
||||
$(document).ready(function() {
|
||||
@ -938,8 +719,7 @@ table.dataTable tbody td {
|
||||
var ticketsTable = $('#tickets-table');
|
||||
|
||||
if (ticketsTable.length) {
|
||||
ticketsTable.DataTable({
|
||||
scrollX: true,
|
||||
table = ticketsTable.DataTable({
|
||||
// dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right
|
||||
// "<'row'<'col-sm-12'tr>>" +
|
||||
// "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector
|
||||
@ -989,12 +769,34 @@ table.dataTable tbody td {
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true, // Enable pagination
|
||||
pageLength: 10, // Set default number of rows per page (optional)
|
||||
// ordering: false,
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#tickets-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
ticketsTable.on('draw.dt', applyBottomRowDropup);
|
||||
} else {
|
||||
console.error("Table not found.");
|
||||
}
|
||||
@ -1050,18 +852,18 @@ table.dataTable tbody td {
|
||||
console.log("******** 1" + response.status);
|
||||
let table = `
|
||||
<div class="table-responsive">
|
||||
<table data-custom-table-css="table" id="historytable" class="table table-striped mb-0 nowrap" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" id="historytable" class="table mb-0 nowrap" cellspacing="0">
|
||||
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th><div class="column-header">S.No </div></th>
|
||||
<th><div class="column-header">From Mail </div></th>
|
||||
<th><div class="column-header">To Mail </div></th>
|
||||
<th><div class="column-header">BCC </div></th>
|
||||
<th><div class="column-header">CC </div></th>
|
||||
<th><div class="column-header">Type </div></th>
|
||||
<th><div class="column-header">Status </div></th>
|
||||
<th><div class="column-header">Date/Time </div></th>
|
||||
<th class="font-weight-medium">S.No </th>
|
||||
<th class="font-weight-medium">From Mail </th>
|
||||
<th class="font-weight-medium">To Mail </th>
|
||||
<th class="font-weight-medium">BCC </th>
|
||||
<th class="font-weight-medium">CC </th>
|
||||
<th class="font-weight-medium">Type </th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium">Date/Time </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -2350,4 +2152,5 @@ table.dataTable tbody td {
|
||||
console.log('Developer Notice: The file lead_filter.php must be loaded by the controller for the filters to work, not leads_list.php.');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@ -70,18 +70,22 @@
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<!-- <form class="parsley-examples" id="nhanceBranchForm" enctype="multipart/form-data"> -->
|
||||
<form id="nhanceBranchForm" enctype="multipart/form-data">
|
||||
<form id="nhanceBranchForm" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" name="pk" id="nhance_branch_id"/>
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="branch_name">Branch Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="branch_name" name="branch_name" placeholder="Enter Branch Name" required>
|
||||
<input type="text" class="form-control" id="branch_name" name="branch_name" placeholder="Enter Branch Name"
|
||||
required
|
||||
data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
|
||||
data-parsley-pattern-message="Branch name may only contain alphanumeric, space, underscore, and dash characters."
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-right m-b-0">
|
||||
<button type="button" class="btn app-btn-secondary waves-effect waves-light" id="btnSubmit" onclick="handleSaveEditAndDelete('submit')">Submit</button>
|
||||
<button type="submit" class="btn app-btn-secondary waves-effect waves-light" id="btnSubmit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -104,7 +108,7 @@
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Add',
|
||||
text: '<i class="mdi mdi-plus" ></i><span class=" btn-custom"> Add </span>',
|
||||
className: 'btn app-btn-primary mr-2',
|
||||
action: function(e, dt, node, config) {
|
||||
resetValues();openModal();
|
||||
@ -146,7 +150,10 @@
|
||||
});
|
||||
|
||||
$('.close').click(function(){
|
||||
resetValues()
|
||||
resetValues();
|
||||
if ($('#nhanceBranchForm').parsley()) {
|
||||
$('#nhanceBranchForm').parsley().reset();
|
||||
}
|
||||
})
|
||||
|
||||
function openModal(){
|
||||
@ -324,6 +331,9 @@
|
||||
function resetValues(){
|
||||
$('#modalLabel').text('Add Branch');
|
||||
$('#nhanceBranchForm')[0].reset();
|
||||
if ($('#nhanceBranchForm').parsley()) {
|
||||
$('#nhanceBranchForm').parsley().reset();
|
||||
}
|
||||
}
|
||||
|
||||
function appendEditData(data){
|
||||
@ -331,5 +341,13 @@
|
||||
$('#branch_name').val(data[0]['branch_name']);
|
||||
openModal()
|
||||
}
|
||||
</script>
|
||||
|
||||
$('#nhanceBranchForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
var $form = $(this);
|
||||
$form.parsley().validate();
|
||||
if ($form.parsley().isValid()) {
|
||||
handleSaveEditAndDelete('submit');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -211,7 +211,7 @@
|
||||
<th class="font-weight-medium">Status</th>
|
||||
<!-- <th class="font-weight-medium">Agent</th> -->
|
||||
<th class="font-weight-medium">POS</th>
|
||||
<th class="font-weight-medium">Action</th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -227,7 +227,7 @@
|
||||
<td> <?= $row['status_text'] ?> </td>
|
||||
<!-- <td> <?= $row['agent_name'] ?? " - " ?> </td> -->
|
||||
<td> <?= $row['pos_name'] ?? " - " ?> </td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
@ -304,7 +304,6 @@
|
||||
if (tableEl.length) {
|
||||
|
||||
var ticketsTable = tableEl.DataTable({
|
||||
scrollX: true,
|
||||
// dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // Filter left, buttons right
|
||||
// "<'row'<'col-sm-12'tr>>" +
|
||||
// "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector
|
||||
@ -320,13 +319,13 @@
|
||||
openPayoutFilterNav();
|
||||
}
|
||||
},
|
||||
// {
|
||||
// text: 'Add',
|
||||
// className: 'btn app-btn-primary mr-2',
|
||||
// action: function (e, dt, node, config) {
|
||||
// window.location.href = "<?= base_url('payout/invoices?type=add') ?>";
|
||||
// }
|
||||
// },
|
||||
{
|
||||
text: '<i class="mdi mdi-plus" ></i><span class=" btn-custom"> Add </span>',
|
||||
className: 'btn app-btn-primary mr-2',
|
||||
action: function (e, dt, node, config) {
|
||||
window.location.href = "<?= base_url('payout/invoices?type=add') ?>";
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'collection',
|
||||
text: '<span class=" btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>',
|
||||
@ -363,12 +362,33 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true, // Enable pagination
|
||||
pageLength: 10, // Set default number of rows per page (optional)
|
||||
ordering: false
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!ticketsTable) return;
|
||||
const currentRows = ticketsTable.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#scroll-horizontal-datatable tbody tr').removeClass('nh-force-dropup');
|
||||
$('#scroll-horizontal-datatable tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
ticketsTable.on('draw.dt', applyBottomRowDropup);
|
||||
|
||||
// IMPORTANT — DataTables draw event REF: TTS
|
||||
ticketsTable.on('draw.dt', function () {
|
||||
|
||||
@ -1,15 +1,6 @@
|
||||
<style>
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td {
|
||||
padding: 4px 4px !important;
|
||||
}
|
||||
|
||||
.dataTables_filter {
|
||||
position: absolute;
|
||||
.col-12 {
|
||||
max-width: 98% !important;
|
||||
}
|
||||
|
||||
.column-header {
|
||||
@ -28,38 +19,6 @@
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu {
|
||||
display: none;
|
||||
position: fixed;
|
||||
background-color: #ffffff !important;
|
||||
border: 1px solid rgba(0, 0, 0, .15);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 0;
|
||||
min-width: 10rem;
|
||||
z-index: 9999;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
padding: 0.5rem 1rem !important;
|
||||
clear: both !important;
|
||||
font-weight: 400 !important;
|
||||
color: #212529 !important;
|
||||
text-align: inherit !important;
|
||||
white-space: nowrap !important;
|
||||
background-color: transparent !important;
|
||||
border: 0 !important;
|
||||
text-decoration: none !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
color: #16181b !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item i {
|
||||
margin-right: 8px !important;
|
||||
@ -315,23 +274,23 @@
|
||||
<div class="col-12" id="endorsement_list">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<table data-custom-table-css="table" class="table table-striped mb-0 nowrap" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="tickets-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th>Sno</th>
|
||||
<th>Issuer</th>
|
||||
<th>Client</th>
|
||||
<th>Branch</th>
|
||||
<th>Insurer</th>
|
||||
<th>Policy</th>
|
||||
<th>Endorsement Type</th>
|
||||
<th>Endorsement No</th>
|
||||
<th>Data Recived Date</th>
|
||||
<th>No of Insured</th>
|
||||
<th>No of Dependence</th>
|
||||
<th>Policy Issue Date</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
<th class="font-weight-medium">Sno </th>
|
||||
<th class="font-weight-medium">Issuer </th>
|
||||
<th class="font-weight-medium">Client </th>
|
||||
<th class="font-weight-medium">Branch </th>
|
||||
<th class="font-weight-medium">Insurer </th>
|
||||
<th class="font-weight-medium">Policy </th>
|
||||
<th class="font-weight-medium">Endorsement Type </th>
|
||||
<th class="font-weight-medium">Endorsement No </th>
|
||||
<th class="font-weight-medium">Data Recived Date </th>
|
||||
<th class="font-weight-medium">No of Insured </th>
|
||||
<th class="font-weight-medium">No of Dependence </th>
|
||||
<th class="font-weight-medium">Policy Issue Date </th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -350,7 +309,7 @@
|
||||
<td class="right-align-input"><?php echo $row['dependent_count'] ?: '0'; ?></td>
|
||||
<td><?php echo empty($row['policy_issue_date']) ? 'N/A' : date('d/m/Y', strtotime($row['policy_issue_date'])); ?></td>
|
||||
<td><?php echo $policy_status[$row['status']] ?: 'N/A'; ?></td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
@ -378,95 +337,13 @@
|
||||
<?php include('pt_endorsement_form_file_upload_tab.php'); ?>
|
||||
|
||||
<script>
|
||||
/* Modified by Gemini Code Assist */
|
||||
function openEndorsementFilterNav() {
|
||||
document.getElementById("filter-sidebar").style.width = "350px";
|
||||
}
|
||||
|
||||
/* Modified by Gemini Code Assist */
|
||||
function closeFilterNav() {
|
||||
document.getElementById("filter-sidebar").style.width = "0";
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.getElementById("tickets-table");
|
||||
|
||||
// Create custom dropdown
|
||||
function createCustomDropdown(row) {
|
||||
const originalDropdown = row.querySelector('.dropdown-menu');
|
||||
if (!originalDropdown) return null;
|
||||
|
||||
const customDropdown = document.createElement('div');
|
||||
customDropdown.className = 'custom-dropdown-menu';
|
||||
customDropdown.innerHTML = originalDropdown.innerHTML;
|
||||
|
||||
// Remove inline onclick handlers and store them in data attributes
|
||||
const originalItems = originalDropdown.querySelectorAll('.dropdown-item');
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach((item, index) => {
|
||||
const originalOnclick = originalItems[index].getAttribute('onclick');
|
||||
item.removeAttribute('onclick'); // Remove the inline handler
|
||||
item.setAttribute('data-onclick', originalOnclick); // Store in data attribute
|
||||
});
|
||||
|
||||
return customDropdown;
|
||||
}
|
||||
|
||||
let activeDropdown = null;
|
||||
|
||||
// Add click event listener to rows
|
||||
table.querySelectorAll("tbody tr").forEach(row => {
|
||||
const customDropdown = createCustomDropdown(row);
|
||||
if (!customDropdown) return;
|
||||
|
||||
document.body.appendChild(customDropdown);
|
||||
|
||||
row.addEventListener("click", function(event) {
|
||||
// Ignore clicks on the first column
|
||||
if (event.target.closest('td:first-child')) return;
|
||||
|
||||
if (activeDropdown) activeDropdown.style.display = 'none';
|
||||
|
||||
const rect = event.target.getBoundingClientRect();
|
||||
customDropdown.style.display = 'block';
|
||||
customDropdown.style.position = 'fixed';
|
||||
customDropdown.style.left = `${rect.left}px`;
|
||||
customDropdown.style.top = `${rect.bottom + 5}px`;
|
||||
activeDropdown = customDropdown;
|
||||
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Handle custom dropdown clicks
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Execute the original onclick from data attribute
|
||||
const onclickAttr = this.getAttribute('data-onclick');
|
||||
if (onclickAttr) eval(onclickAttr);
|
||||
|
||||
// Handle href navigation
|
||||
const href = this.getAttribute('href');
|
||||
if (href && href !== '#') window.location.href = href;
|
||||
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Close dropdown on outside click
|
||||
document.addEventListener("click", function() {
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
@ -516,7 +393,7 @@
|
||||
var ticketsTable = $('#tickets-table');
|
||||
|
||||
if (ticketsTable.length) {
|
||||
ticketsTable.DataTable({
|
||||
var table = ticketsTable.DataTable({
|
||||
scrollX: true,
|
||||
dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
@ -566,12 +443,34 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true, // Enable pagination
|
||||
pageLength: 10, // Set default number of rows per page (optional)
|
||||
ordering: false,
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#tickets-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
ticketsTable.on('draw.dt', applyBottomRowDropup);
|
||||
} else {
|
||||
console.error("Table not found.");
|
||||
}
|
||||
|
||||
@ -3,70 +3,66 @@
|
||||
<div class="col-12">
|
||||
<div class="card-body subcard">
|
||||
<div class="custom-form">
|
||||
<form role="form" class="parsley-examples" method="post" id="policytype_general_form" enctype="multipart/form-data">
|
||||
<form role="form" class="parsley-examples" method="post" id="policytype_general_form" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>" />
|
||||
<input type="hidden" name="PrimaryKey" id="policytype_General_PrimaryKey" value="<?= isset($policytype['id']) ? $policytype['id'] : '' ?>"/>
|
||||
<input type="hidden" name="policy_id" id="policy_id" />
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="kyc_name">Policy Type Name<span
|
||||
class="text-danger">*</span></label>
|
||||
<label for="policy_type">Policy Type Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="policy_type"
|
||||
placeholder="Enter Policy Type Name" value="<?= isset($policytype['policy_type']) ? $policytype['policy_type'] : '' ?>" name="policy_type" required>
|
||||
placeholder="Enter Policy Type Name" value="<?= isset($policytype['policy_type']) ? $policytype['policy_type'] : '' ?>" name="policy_type" required data-parsley-minlength="2">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="kyc_name">Policy Type Long Name</label>
|
||||
<label for="long_name">Policy Type Long Name</label>
|
||||
<input type="text" class="form-control" id="long_name"
|
||||
placeholder="Enter Policy Type Long Name" value="<?= isset($policytype['long_name']) ? $policytype['long_name'] : '' ?>" name="long_name">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="bap">BAP<span
|
||||
class="text-danger">*</span></label>
|
||||
<label for="bap">BAP<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="bap"
|
||||
placeholder="Enter Bap" value="<?= isset($policytype['bap']) ? $policytype['bap'] : '' ?>" name="bap" required>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="allocg">Category<span
|
||||
class="text-danger">*</span></label>
|
||||
<label for="allocg">Category<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="allocg"
|
||||
placeholder="Enter Allocg" value="<?= isset($policytype['allocg']) ? $policytype['allocg'] : '' ?>" name="allocg" required>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="alloci">BAP Category<span
|
||||
class="text-danger">*</span></label>
|
||||
<label for="alloci">BAP Category<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="alloci"
|
||||
placeholder="Enter Alloci" value="<?= isset($policytype['alloci']) ? $policytype['alloci'] : '' ?>" name="alloci" required>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="ebp">Group Base Premium<span class="text-muted"> (STD %)</span></label>
|
||||
<input type="number" class="form-control" id="ebp"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['ebp']) ? $policytype['ebp'] : '' ?>" name="ebp">
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['ebp']) ? $policytype['ebp'] : '' ?>" name="ebp" data-parsley-type="number" data-parsley-min="0" data-parsley-min-message="Value cannot be negative">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="etp">Group Third Party Premium<span
|
||||
class="text-muted"> (STD %)</span></label> <input type="number" class="form-control" id="etp"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['etp']) ? $policytype['etp'] : '' ?>" name="etp">
|
||||
<label for="etp">Group Third Party Premium<span class="text-muted"> (STD %)</span></label>
|
||||
<input type="number" class="form-control" id="etp"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['etp']) ? $policytype['etp'] : '' ?>" name="etp" data-parsley-type="number" data-parsley-min="0" data-parsley-min-message="Value cannot be negative">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="etep">Group Terrorism Premium<span
|
||||
class="text-muted"> (STD %)</span></label> <input type="number" class="form-control" id="etep"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['etep']) ? $policytype['etep'] : '' ?>" name="etep">
|
||||
<label for="etep">Group Terrorism Premium<span class="text-muted"> (STD %)</span></label>
|
||||
<input type="number" class="form-control" id="etep"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['etep']) ? $policytype['etep'] : '' ?>" name="etep" data-parsley-type="number" data-parsley-min="0" data-parsley-min-message="Value cannot be negative">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="iep">Individual Base Premium<span
|
||||
class="text-muted"> (STD %)</span></label> <input type="number" class="form-control" id="iep"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['iep']) ? $policytype['iep'] : '' ?>" name="iep">
|
||||
<label for="iep">Individual Base Premium<span class="text-muted"> (STD %)</span></label>
|
||||
<input type="number" class="form-control" id="iep"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['iep']) ? $policytype['iep'] : '' ?>" name="iep" data-parsley-type="number" data-parsley-min="0" data-parsley-min-message="Value cannot be negative">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="itp">Individual Third-Party Premium<span
|
||||
class="text-muted"> (STD %)</span></label> <input type="number" class="form-control" id="itp"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['itp']) ? $policytype['itp'] : '' ?>" name="itp">
|
||||
<label for="itp">Individual Third-Party Premium<span class="text-muted"> (STD %)</span></label>
|
||||
<input type="number" class="form-control" id="itp"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['itp']) ? $policytype['itp'] : '' ?>" name="itp" data-parsley-type="number" data-parsley-min="0" data-parsley-min-message="Value cannot be negative">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="itep">Individual Terrorism Premium<span
|
||||
class="text-muted"> (STD %)</span></label> <input type="number" class="form-control" id="itep"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['itep']) ? $policytype['itep'] : '' ?>" name="itep">
|
||||
<label for="itep">Individual Terrorism Premium<span class="text-muted"> (STD %)</span></label>
|
||||
<input type="number" class="form-control" id="itep"
|
||||
placeholder="Enter Group Base Premium" value="<?= isset($policytype['itep']) ? $policytype['itep'] : '' ?>" name="itep" data-parsley-type="number" data-parsley-min="0" data-parsley-min-message="Value cannot be negative">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -148,35 +144,6 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
function validateForm() {
|
||||
var isValid = true;
|
||||
|
||||
// Perform validation for each field
|
||||
$('#policytype_general_form input, #policytype_general_form select').each(function() {
|
||||
// Check for empty text inputs and selects
|
||||
if ($(this).is('input[type="text"]') || $(this).is('select')) {
|
||||
if ($.trim($(this).val()) == '') {
|
||||
alert('Please fill in all fields');
|
||||
isValid = false;
|
||||
return false; // Exit the loop early
|
||||
}
|
||||
}
|
||||
|
||||
// Check for file inputs (assuming image files)
|
||||
if ($(this).is('input[type="file"]')) {
|
||||
var fileInput = $(this)[0];
|
||||
if (fileInput.files.length === 0) {
|
||||
alert('Please select an image file');
|
||||
isValid = false;
|
||||
return false; // Exit the loop early
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@ -98,14 +98,13 @@
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<!-- <form class="parsley-examples" id="partnerPOSForm" enctype="multipart/form-data"> -->
|
||||
<form id="partnerPOSForm" enctype="multipart/form-data">
|
||||
<form id="partnerPOSForm" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" name="pk" id="pos_id"/>
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="manager_id">Manager<span class="text-danger">*</span></label>
|
||||
<select class="form-control" id="manager_id" name="manager_id" required>
|
||||
<select class="form-control" id="manager_id" name="manager_id" required>
|
||||
<option value="" selected>Select Manager</option>
|
||||
<?php if (!empty($data['manager_list'])): ?>
|
||||
<?php foreach ($data['manager_list'] as $value): ?>
|
||||
@ -120,21 +119,19 @@
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-3">
|
||||
<label for="name">Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="name" name="name" placeholder="Enter Name" required>
|
||||
<input type="text" class="form-control" id="name" name="name" placeholder="Enter Name" required data-parsley-pattern="^[a-zA-Z\s\.]+$" data-parsley-trigger="keyup" data-parsley-pattern-message="Please enter a valid name (letters, spaces, dots only).">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="pos_code">POS Code<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="pos_code" name="pos_code" placeholder="Enter Code" required>
|
||||
<input type="text" class="form-control" id="pos_code" name="pos_code" placeholder="Enter Code" required data-parsley-pattern="^[a-zA-Z0-9_-]+$" data-parsley-trigger="keyup" data-parsley-pattern-message="Please enter a valid code (alphanumeric, underscore, hyphen).">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="email">Email<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="email" name="email" placeholder="Enter Email" required>
|
||||
<small id="email_error" class="text-danger d-none"></small>
|
||||
<input type="email" class="form-control" id="email" name="email" placeholder="Enter Email" required data-parsley-type="email" data-parsley-trigger="keyup">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="mobile">Mobile<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="mobile" name="mobile" placeholder="Enter Mobile" maxlength="10" inputmode="numeric" pattern="[0-9]{10}" required>
|
||||
<small id="mobile_error" class="text-danger d-none"></small>
|
||||
<input type="text" class="form-control" id="mobile" name="mobile" placeholder="Enter Mobile" required data-parsley-pattern="^[6-9]\d{9}$" data-parsley-trigger="keyup" data-parsley-length="[10,10]" data-parsley-validation-threshold="10" data-parsley-length-message="Mobile number must be 10 digits." data-parsley-pattern-message="Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9.">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
@ -152,44 +149,42 @@
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="pincode">Pincode<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="pincode" name="pincode" placeholder="Enter Pincode" required>
|
||||
<input type="text" class="form-control" id="pincode" name="pincode" placeholder="Enter Pincode" required data-parsley-type="digits" data-parsley-length="[6,6]" data-parsley-trigger="keyup" data-parsley-validation-threshold="6" data-parsley-length-message="Pincode must be 6 digits.">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="aadhar">Aadhaar Number<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="aadhar" name="aadhar" placeholder="Enter Aadhaar Number" maxlength="12" inputmode="numeric" pattern="[0-9]{12}" required>
|
||||
<small id="aadhar_error" class="text-danger d-none"></small>
|
||||
<input type="text" class="form-control" id="aadhar" name="aadhar" placeholder="Enter Aadhaar Number" required data-parsley-type="digits" data-parsley-length="[12,12]" data-parsley-length-message="Aadhaar number must be 12 digits." data-parsley-trigger="keyup">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="pan">PAN Number<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="pan" name="pan" placeholder="Enter PAN Number" maxlength="10" style="text-transform:uppercase" pattern="[A-Z]{5}[0-9]{4}[A-Z]{1}" required>
|
||||
<small id="pan_error" class="text-danger d-none"></small>
|
||||
<input type="text" class="form-control" id="pan" name="pan" placeholder="Enter PAN Number" style="text-transform:uppercase" required data-parsley-pattern="[A-Z]{5}[0-9]{4}[A-Z]{1}" data-parsley-maxlength="10" data-parsley-maxlength-message="PAN number cannot exceed 10 characters." data-parsley-pattern-message="Invalid PAN format (e.g., ABCDE1234F)." data-parsley-trigger="keyup">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="gst">GST Number</label>
|
||||
<input type="text" class="form-control" id="gst" name="gst" placeholder="Enter GST Number">
|
||||
<input type="text" class="form-control" id="gst" name="gst" placeholder="Enter GST Number" data-parsley-pattern="/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$/" data-parsley-maxlength="15" data-parsley-maxlength-message="GST number cannot exceed 15 characters." data-parsley-pattern-message="Invalid GST format." data-parsley-trigger="keyup">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="aadhar_file_name">Aadhar</label>
|
||||
<div class="input-icon">
|
||||
<input type="file" class="form-control" name="aadhar_file_name" id="aadhar_file_name" accept=".pdf,.jpg,.jpeg,.png">
|
||||
<input type="file" class="form-control" name="aadhar_file_name" id="aadhar_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation>
|
||||
<i class="mdi mdi-upload additional-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="pan_file_name">PAN</label>
|
||||
<div class="input-icon">
|
||||
<input type="file" class="form-control" name="pan_file_name" id="pan_file_name" accept=".pdf,.jpg,.jpeg,.png">
|
||||
<input type="file" class="form-control" name="pan_file_name" id="pan_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation>
|
||||
<i class="mdi mdi-upload additional-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="certificate_file_name">Certificate</label>
|
||||
<div class="input-icon">
|
||||
<input type="file" class="form-control" name="certificate_file_name" id="certificate_file_name" accept=".pdf,.jpg,.jpeg,.png">
|
||||
<input type="file" class="form-control" name="certificate_file_name" id="certificate_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation>
|
||||
<i class="mdi mdi-upload additional-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
@ -229,6 +224,41 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Parsley custom validator for file type and size
|
||||
window.Parsley.addValidator('fileValidation', {
|
||||
requirementType: 'string',
|
||||
validateString: function(value, requirement, parsleyInstance) {
|
||||
const file = parsleyInstance.$element[0].files[0];
|
||||
if (!file) {
|
||||
return true; // Skip validation if no file is selected (unless 'required' is also present)
|
||||
}
|
||||
|
||||
const maxImageSize = 500 * 1024; // 500KB
|
||||
const maxPdfSize = 25 * 1024 * 1024; // 25MB
|
||||
const imageTypes = ['image/jpeg', 'image/png', 'image/jpg'];
|
||||
const pdfType = 'application/pdf';
|
||||
|
||||
if (imageTypes.includes(file.type)) {
|
||||
if (file.size > maxImageSize) {
|
||||
this.errorMessage = 'Image size cannot exceed 500KB.';
|
||||
return false;
|
||||
}
|
||||
} else if (file.type === pdfType) {
|
||||
if (file.size > maxPdfSize) {
|
||||
this.errorMessage = 'PDF size cannot exceed 25MB.';
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
this.errorMessage = 'Allowed file types are JPG, JPEG, PNG, and PDF.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
messages: {
|
||||
en: 'File is invalid.' // Default fallback message
|
||||
}
|
||||
});
|
||||
var table;
|
||||
$(document).ready(function () {
|
||||
$('#manager_id').select2();
|
||||
@ -285,7 +315,12 @@
|
||||
});
|
||||
});
|
||||
|
||||
$('.close').click(function(){ resetValues(); })
|
||||
$('.close').click(function(){
|
||||
resetValues();
|
||||
if ($('#partnerPOSForm').parsley()) {
|
||||
$('#partnerPOSForm').parsley().reset();
|
||||
}
|
||||
})
|
||||
|
||||
function openModal(){
|
||||
var myModal = new bootstrap.Modal(document.getElementById('con-close-modal'));
|
||||
@ -396,6 +431,9 @@
|
||||
function resetValues(){
|
||||
$('#modalLabel').text('Add POS Details');
|
||||
$('#partnerPOSForm')[0].reset();
|
||||
if ($('#partnerPOSForm').parsley()) {
|
||||
$('#partnerPOSForm').parsley().reset();
|
||||
}
|
||||
$('#manager_id').val(null).trigger('change');
|
||||
|
||||
}
|
||||
@ -452,81 +490,18 @@
|
||||
|
||||
$('#partnerPOSForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const form = this;
|
||||
var $form = $(this);
|
||||
|
||||
// Validate the form using Parsley
|
||||
$form.parsley().validate();
|
||||
|
||||
// HTML5 built-in validation
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity(); // shows required/pattern tooltips
|
||||
return;
|
||||
// Check if the form is valid
|
||||
if ($form.parsley().isValid()) {
|
||||
// If valid, submit via AJAX
|
||||
handleSaveEditAndDelete('submit');
|
||||
}
|
||||
|
||||
// Custom validation
|
||||
if (!validateForm()) return;
|
||||
|
||||
// If valid, submit via AJAX
|
||||
handleSaveEditAndDelete('submit');
|
||||
});
|
||||
|
||||
|
||||
function validateForm() {
|
||||
let isValid = true;
|
||||
|
||||
// Clear old errors
|
||||
$('.text-danger').addClass('d-none').text('');
|
||||
|
||||
// Regex patterns
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
const mobileRegex = /^[6-9]\d{9}$/;
|
||||
const aadharRegex = /^\d{12}$/;
|
||||
const panRegex = /^[A-Z]{5}[0-9]{4}[A-Z]$/;
|
||||
|
||||
// EMAIL
|
||||
const email = $('#email').val().trim();
|
||||
if (email === '') {
|
||||
$('#email_error').text('Email is required').removeClass('d-none');
|
||||
isValid = false;
|
||||
} else if (!emailRegex.test(email)) {
|
||||
$('#email_error').text('Enter a valid email').removeClass('d-none');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// MOBILE
|
||||
const mobile = $('#mobile').val().trim();
|
||||
if (mobile === '') {
|
||||
$('#mobile_error').text('Mobile number is required').removeClass('d-none');
|
||||
isValid = false;
|
||||
} else if (!mobileRegex.test(mobile)) {
|
||||
$('#mobile_error').text('Enter a valid 10-digit mobile number').removeClass('d-none');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// AADHAAR
|
||||
const aadhar = $('#aadhar').val().trim();
|
||||
if (aadhar === '') {
|
||||
$('#aadhar_error').text('Aadhaar is required').removeClass('d-none');
|
||||
isValid = false;
|
||||
} else if (!aadharRegex.test(aadhar)) {
|
||||
$('#aadhar_error').text('Aadhaar must be 12 digits').removeClass('d-none');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// PAN
|
||||
const pan = $('#pan').val().trim();
|
||||
if (pan === '') {
|
||||
$('#pan_error').text('PAN is required').removeClass('d-none');
|
||||
isValid = false;
|
||||
} else if (!panRegex.test(pan)) {
|
||||
$('#pan_error').text('Invalid PAN format (AAAPA1234A)').removeClass('d-none');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
@ -616,5 +591,5 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</script>
|
||||
|
||||
@ -138,7 +138,7 @@
|
||||
<h4 style="position: relative;">Endorsement</h4>
|
||||
</div>
|
||||
</div> -->
|
||||
<table data-custom-table-css="table" class="table table-hover m-0 table-centered dt-responsive w-100" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" class="table table-hover m-0 table-centered w-100" cellspacing="0" id="tickets-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium">S.No </th>
|
||||
@ -151,7 +151,7 @@
|
||||
<th class="font-weight-medium">Mananger </th>
|
||||
<th class="font-weight-medium">Created At </th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium">Action </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -182,8 +182,15 @@
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="text-center"><a href="#" data-id="<?php echo $employee['id'] ?>" data-eno="<?php echo $employee['endorsement_no'] ?>" data-status="<?php echo $employee['status'] ?>"
|
||||
class="mdi mdi-pencil text-muted vertical-middle emp_data_model" aria-hidden="true" data-toggle="modal" data-target="#centermodal"></a>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item emp_data_model" href="#" data-id="<?php echo $employee['id'] ?>" data-eno="<?php echo $employee['endorsement_no'] ?>" data-status="<?php echo $employee['status'] ?>" data-toggle="modal" data-target="#centermodal">
|
||||
<i class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle"></i>Edit
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php }
|
||||
@ -398,7 +405,8 @@
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#tickets-table').DataTable({
|
||||
var table = $('#tickets-table').DataTable({
|
||||
scrollX: true,
|
||||
dom: "<'row'<'col-12 d-flex justify-content-between align-items-center'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'B>>>" +
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
|
||||
@ -453,7 +461,11 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true,
|
||||
// pagingType: 'full_numbers'
|
||||
@ -464,6 +476,25 @@
|
||||
],
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#tickets-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
// Mark last two rows on current page to open action menu upward.
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
|
||||
applyBottomRowDropup();
|
||||
$('#tickets-table').on('draw.dt', applyBottomRowDropup);
|
||||
|
||||
|
||||
});
|
||||
|
||||
@ -72,37 +72,53 @@
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<!-- <form class="parsley-examples" id="RTOForm" enctype="multipart/form-data"> -->
|
||||
<form id="RTOForm" enctype="multipart/form-data">
|
||||
<form id="RTOForm" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" name="pk" id="rto_id"/>
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="rto_name">RTO Office Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="rto_name" name="rto_name" placeholder="Enter RTO Office Name" required>
|
||||
<input type="text" class="form-control" id="rto_name" name="rto_name" placeholder="Enter RTO Office Name"
|
||||
required
|
||||
data-parsley-required-message="RTO Office Name is required"
|
||||
data-parsley-minlength="3"
|
||||
data-parsley-minlength-message="RTO Office Name must be at least 3 characters"
|
||||
data-parsley-maxlength="100"
|
||||
data-parsley-maxlength-message="RTO Office Name maximum 100 characters"
|
||||
data-parsley-pattern="^[a-zA-Z0-9\s]+$"
|
||||
data-parsley-pattern-message="RTO Office Name may only contain alphanumeric and space characters"
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label for="rto_code">RTO Code<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="rto_code" name="rto_code"
|
||||
placeholder="Enter RTO Code" required
|
||||
maxlength="2"
|
||||
inputmode="numeric"
|
||||
pattern="[0-9]{2}"
|
||||
oninput="this.value = this.value.replace(/[^0-9]/g, '').slice(0,2);">
|
||||
placeholder="Enter RTO Code"
|
||||
required
|
||||
data-parsley-required-message="RTO Code is required"
|
||||
data-parsley-type="digits"
|
||||
data-parsley-type-message="RTO Code must contain only numbers"
|
||||
data-parsley-length="[2,2]"
|
||||
data-parsley-length-message="RTO Code must be exactly 2 digits"
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="rto_state">RTO State<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="rto_state" name="rto_state"
|
||||
placeholder="Enter RTO State" required
|
||||
maxlength="2"
|
||||
pattern="[A-Z]{2}"
|
||||
oninput="this.value = this.value.replace(/[^A-Za-z]/g, '').toUpperCase().slice(0,2);">
|
||||
placeholder="Enter RTO State" style="text-transform:uppercase"
|
||||
required
|
||||
data-parsley-required-message="RTO State is required"
|
||||
data-parsley-type="alpha"
|
||||
data-parsley-type-message="RTO State must contain only alphabets"
|
||||
data-parsley-length="[2,2]"
|
||||
data-parsley-length-message="RTO State must be exactly 2 letters"
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-right m-b-0">
|
||||
<button type="button" class="btn app-btn-secondary waves-effect waves-light" id="btnSubmit" onclick="handleSaveEditAndDelete('submit')">Submit</button>
|
||||
<button type="submit" class="btn app-btn-secondary waves-effect waves-light" id="btnSubmit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -167,7 +183,10 @@
|
||||
});
|
||||
|
||||
$('.close').click(function(){
|
||||
resetValues()
|
||||
resetValues();
|
||||
if ($('#RTOForm').parsley()) {
|
||||
$('#RTOForm').parsley().reset();
|
||||
}
|
||||
})
|
||||
|
||||
function openModal(){
|
||||
@ -273,6 +292,9 @@
|
||||
function resetValues(){
|
||||
$('#modalLabel').text('Add RTO Details');
|
||||
$('#RTOForm')[0].reset();
|
||||
if ($('#RTOForm').parsley()) {
|
||||
$('#RTOForm').parsley().reset();
|
||||
}
|
||||
}
|
||||
|
||||
function appendEditData(data){
|
||||
@ -282,5 +304,16 @@
|
||||
$('#rto_state').val(data[0]['rto_state']);
|
||||
openModal()
|
||||
}
|
||||
</script>
|
||||
|
||||
$('#RTOForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
var $form = $(this);
|
||||
|
||||
// Validate the form using Parsley
|
||||
$form.parsley().validate();
|
||||
|
||||
if ($form.parsley().isValid()) {
|
||||
handleSaveEditAndDelete('submit');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,8 @@
|
||||
<style>
|
||||
.col-12 {
|
||||
max-width: 98% !important;
|
||||
}
|
||||
|
||||
.badge2 {
|
||||
box-shadow: none;
|
||||
}
|
||||
@ -31,7 +35,7 @@
|
||||
}
|
||||
|
||||
.dataTables_filter{
|
||||
position: absolute;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.right-align-input {
|
||||
@ -60,38 +64,6 @@
|
||||
#map_emp_modal .modal-backdrop.show {
|
||||
opacity: 0.5; /* Darken backdrop for better focus */
|
||||
}
|
||||
|
||||
.custom-dropdown-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #ffffff !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 0;
|
||||
min-width: 10rem;
|
||||
z-index: 9999;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
padding: 0.5rem 1rem !important;
|
||||
color: #212529 !important;
|
||||
text-decoration: none !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
color: #16181b !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
th, td {
|
||||
text-align: center; /* Or left/right depending on your preference */
|
||||
vertical-align: middle; /* Ensures content is vertically centered */
|
||||
}
|
||||
|
||||
th:first-child, td:first-child {
|
||||
width: 50px; /* Adjust width as needed */
|
||||
}
|
||||
@ -99,8 +71,22 @@ th:first-child, td:first-child {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
/* Allow header text and sort icons to keep proper spacing. */
|
||||
.table {
|
||||
table-layout: fixed; /* Prevent columns from resizing dynamically */
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
/* Keep this long header readable and prevent sort icon overlap. */
|
||||
#tickets-table th.existing-policy-col,
|
||||
#tickets-table td.existing-policy-col {
|
||||
min-width: 170px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Action column aligned center in both head and body. */
|
||||
#tickets-table th.action-col {
|
||||
min-width: 90px;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.unmapEmployees{
|
||||
@ -135,7 +121,7 @@ th:first-child, td:first-child {
|
||||
<h3 style="position: relative;">Employees</h3>
|
||||
</div>
|
||||
</div> -->
|
||||
<table data-custom-table-css="table" class="table table-striped mb-0 nowrap" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="tickets-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th><input type="checkbox" id="selectAll" onclick="toggleAll(this)"> </th>
|
||||
@ -153,7 +139,7 @@ th:first-child, td:first-child {
|
||||
<th class="font-weight-medium">Relationship </th>
|
||||
<th class="font-weight-medium">Gender </th>
|
||||
<th class="font-weight-medium">Date of Birth </th>
|
||||
<th class="font-weight-medium">Existing Policy Count </th>
|
||||
<th class="font-weight-medium existing-policy-col">Existing Policy Count </th>
|
||||
<!-- <th class="font-weight-medium">Policy name</th>
|
||||
<th class="font-weight-medium">Insurer name</th>
|
||||
<th class="font-weight-medium">TPA ID</th>
|
||||
@ -163,7 +149,7 @@ th:first-child, td:first-child {
|
||||
<th class="font-weight-medium">(₹)Premium</th>
|
||||
<th class="font-weight-medium" id="rata_premium" data-toggle="tooltip" data-placement="top">(₹)Pro Rata <br> Premium</th>
|
||||
<th class="font-weight-medium" id="gst" data-toggle="tooltip" data-placement="top">(₹)GST</th> -->
|
||||
<th class="font-weight-medium" > Action </th>
|
||||
<th class="font-weight-medium text-center action-col">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -228,8 +214,8 @@ th:first-child, td:first-child {
|
||||
<td><?php // if(isset($employee['gst'])){$gst_total += $employee['gst']; echo format_indian_number($employee['gst']); }?></td> -->
|
||||
*/
|
||||
?>
|
||||
<td><?= $employee['policy_count'] ?></td>
|
||||
<td>
|
||||
<td class="existing-policy-col"><?= $employee['policy_count'] ?></td>
|
||||
<td class="table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
@ -428,88 +414,6 @@ th:first-child, td:first-child {
|
||||
</div>
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const table = document.getElementById("tickets-table");
|
||||
|
||||
// Create custom dropdown
|
||||
function createCustomDropdown(row) {
|
||||
const originalDropdown = row.querySelector('.dropdown-menu');
|
||||
if (!originalDropdown) return null;
|
||||
|
||||
const customDropdown = document.createElement('div');
|
||||
customDropdown.className = 'custom-dropdown-menu';
|
||||
customDropdown.innerHTML = originalDropdown.innerHTML;
|
||||
|
||||
// Remove inline onclick handlers and store them in data attributes
|
||||
const originalItems = originalDropdown.querySelectorAll('.dropdown-item');
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach((item, index) => {
|
||||
const originalOnclick = originalItems[index].getAttribute('onclick');
|
||||
item.removeAttribute('onclick'); // Remove the inline handler
|
||||
item.setAttribute('data-onclick', originalOnclick); // Store in data attribute
|
||||
});
|
||||
|
||||
return customDropdown;
|
||||
}
|
||||
|
||||
let activeDropdown = null;
|
||||
|
||||
// Add click event listener to rows
|
||||
table.querySelectorAll("tbody tr").forEach(row => {
|
||||
const customDropdown = createCustomDropdown(row);
|
||||
if (!customDropdown) return;
|
||||
|
||||
document.body.appendChild(customDropdown);
|
||||
|
||||
row.addEventListener("click", function(event) {
|
||||
// Ignore clicks on the first column
|
||||
if (event.target.closest('td:first-child')) return;
|
||||
|
||||
if (activeDropdown) activeDropdown.style.display = 'none';
|
||||
|
||||
const rect = event.target.getBoundingClientRect();
|
||||
customDropdown.style.display = 'block';
|
||||
customDropdown.style.position = 'fixed';
|
||||
customDropdown.style.left = `${rect.left}px`;
|
||||
customDropdown.style.top = `${rect.bottom + 5}px`;
|
||||
activeDropdown = customDropdown;
|
||||
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Handle custom dropdown clicks
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Execute the original onclick from data attribute
|
||||
const onclickAttr = this.getAttribute('data-onclick');
|
||||
if (onclickAttr) eval(onclickAttr);
|
||||
|
||||
// Handle href navigation
|
||||
const href = this.getAttribute('href');
|
||||
if (href && href !== '#') window.location.href = href;
|
||||
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Close dropdown on outside click
|
||||
document.addEventListener("click", function() {
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function toggleAll(selectAllCheckbox) {
|
||||
const rowCheckboxes = document.querySelectorAll('.rowCheckbox');
|
||||
@ -538,7 +442,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
var ticketsTable = $('#tickets-table');
|
||||
|
||||
if (ticketsTable.length) {
|
||||
ticketsTable.DataTable({
|
||||
var table = ticketsTable.DataTable({
|
||||
scrollX: true,
|
||||
// dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // Filter left, buttons right
|
||||
// "<'row'<'col-sm-12'tr>>" +
|
||||
@ -552,14 +456,14 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
action: function(e, dt, node, config) {
|
||||
mapEmployees();
|
||||
},
|
||||
className:"mapEmployees"
|
||||
className:"btn app-btn-primary mr-2 mapEmployees"
|
||||
},
|
||||
{
|
||||
text:'Unmap Employees',
|
||||
action: function(e, dt, node, config) {
|
||||
unmapEmployees();
|
||||
},
|
||||
className:"unmapEmployees"
|
||||
className:"btn app-btn-primary unmapEmployees"
|
||||
}],
|
||||
language: {
|
||||
search: `
|
||||
@ -571,11 +475,34 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
paging: true, // Enable pagination
|
||||
pageLength: 25 // Set default number of rows per page (optional)
|
||||
pageLength: 10 // Set default number of rows per page (optional)
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#tickets-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
// Mark last two rows on current page to open action menu upward.
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
$('#tickets-table').on('draw.dt', applyBottomRowDropup);
|
||||
} else {
|
||||
console.error("Table not found.");
|
||||
}
|
||||
|
||||
@ -167,6 +167,7 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
required pattern="[0-9]{10}" maxlength="10" inputmode="numeric"
|
||||
oninput="this.value=this.value.replace(/[^0-9]/g,'');"
|
||||
title="Please enter a valid 10-digit mobile number">
|
||||
<small class="text-danger d-block mt-1 field-error" id="mobile_error"></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-1" style="padding:32.5px 0 0 18px;">
|
||||
@ -186,6 +187,7 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
<div class="form-group col-md-4 ">
|
||||
<label for="name">Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="name" name="name" placeholder="Enter Name" required>
|
||||
<small class="text-danger d-block mt-1 field-error" id="name_error"></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-4 ">
|
||||
@ -194,11 +196,13 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
name="email" placeholder="Enter Email"
|
||||
required
|
||||
title="Please enter a valid email address">
|
||||
<small class="text-danger d-block mt-1 field-error" id="email_error"></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-4 ">
|
||||
<label for="empcode">Employee code</label>
|
||||
<input type="text" class="form-control" id="empcode" name="empcode" placeholder="Enter Employee code">
|
||||
<small class="text-danger d-block mt-1 field-error" id="empcode_error"></small>
|
||||
</div>
|
||||
|
||||
|
||||
@ -218,6 +222,7 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
<small class="text-danger d-block mt-1 field-error" id="ticket_type_error"></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-4 " id="policy_container">
|
||||
@ -254,6 +259,7 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
<small class="text-danger d-block mt-1 field-error" id="assign_to_error"></small>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<input type="hidden" id="hide_assign_to" name="assign_to" value="<?= esc(get_session_userid()); ?>">
|
||||
@ -269,6 +275,7 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
<small id="subjectCounter" class="form-text text-muted">0/150</small>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="subject" name="subject" placeholder="Enter Subject" required maxlength="150">
|
||||
<small class="text-danger d-block mt-1 field-error" id="subject_error"></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12 ">
|
||||
@ -278,6 +285,7 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
</div>
|
||||
<!-- <input type="text" class="form-control" id="message" name="message" placeholder="Enter Message"> -->
|
||||
<textarea class="form-control" id="message" name="message" placeholder="Enter Message" rows="3" required maxlength="1500"></textarea>
|
||||
<small class="text-danger d-block mt-1 field-error" id="message_error"></small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -406,6 +414,7 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
form.reset();
|
||||
$("#client_id").select2();
|
||||
$("#ticket_type").select2();
|
||||
clearAllFieldErrors();
|
||||
document.getElementById('thz_id').value = '';
|
||||
document.getElementById('modalLabel').innerText = "New Ticket";
|
||||
document.getElementById('return_type').innerText = "Web";
|
||||
@ -418,6 +427,125 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
form.reset();
|
||||
$("#client_id").select2();
|
||||
$("#ticket_type").select2();
|
||||
clearAllFieldErrors();
|
||||
}
|
||||
|
||||
function showFieldError(fieldId, message) {
|
||||
var field = document.getElementById(fieldId);
|
||||
var error = document.getElementById(fieldId + "_error");
|
||||
if (!field || !error) return;
|
||||
error.textContent = message || "";
|
||||
if (message) {
|
||||
field.classList.add("is-invalid");
|
||||
} else {
|
||||
field.classList.remove("is-invalid");
|
||||
}
|
||||
}
|
||||
|
||||
function clearAllFieldErrors() {
|
||||
document.querySelectorAll(".field-error").forEach(function (el) {
|
||||
el.textContent = "";
|
||||
});
|
||||
["mobile", "name", "email", "empcode", "ticket_type", "assign_to", "subject", "message"].forEach(function (id) {
|
||||
var field = document.getElementById(id);
|
||||
if (field) field.classList.remove("is-invalid");
|
||||
});
|
||||
}
|
||||
|
||||
function validateMobile(value) {
|
||||
if (!value) return "Mobile number is required";
|
||||
if (!/^[0-9]{10}$/.test(value)) return "Mobile number must be exactly 10 digits";
|
||||
return "";
|
||||
}
|
||||
|
||||
function validateName(value) {
|
||||
if (!value) return "Name is required";
|
||||
if (value.length < 3) return "Name must be at least 3 characters";
|
||||
if (value.length > 100) return "Name must be at most 100 characters";
|
||||
if (!/^[A-Za-z ]+$/.test(value)) return "Name can contain only letters and spaces";
|
||||
return "";
|
||||
}
|
||||
|
||||
function validateEmail(value) {
|
||||
if (!value) return "Email address is required.";
|
||||
if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
|
||||
return "Please enter a valid email format (e.g., name@domain.com).";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function validateEmpcode(value) {
|
||||
if (!value) return "";
|
||||
if (value.length > 50) return "Employee code is too long";
|
||||
if (!/^[A-Za-z0-9 ~!#\$%\^&\*\(\)_\+\-\=\{\}\[\]\|:;\"'<>,\.\/\?`]+$/.test(value)) {
|
||||
return "Employee code contains invalid characters.";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function validateTicketType(value) {
|
||||
if (!value) return "Ticket Type is required";
|
||||
return "";
|
||||
}
|
||||
|
||||
function validateAssignTo(value) {
|
||||
if (!value) return "";
|
||||
if (!/^\d+$/.test(value)) return "Invalid assignee selected";
|
||||
return "";
|
||||
}
|
||||
|
||||
function validateSubject(value) {
|
||||
if (!value) return "Subject is required.";
|
||||
if (value.length < 3) return "Subject must be at least 3 characters long.";
|
||||
if (value.length > 150) return "Subject cannot exceed 150 characters";
|
||||
if (!/^[a-zA-Z0-9 .,\-_()&\/\?]+$/.test(value)) {
|
||||
return "Subject contains invalid characters (Avoid quotes and special symbols).";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function validateMessage(value) {
|
||||
if (!value) return "Message is required";
|
||||
if (value.length < 10) return "Message must be at least 10 characters";
|
||||
if (value.length > 1500) return "Message cannot exceed 1500 characters";
|
||||
return "";
|
||||
}
|
||||
|
||||
function validateField(fieldId) {
|
||||
var field = document.getElementById(fieldId);
|
||||
if (!field) return true;
|
||||
var value = (field.value || "").trim();
|
||||
var error = "";
|
||||
switch (fieldId) {
|
||||
case "mobile": error = validateMobile(value); break;
|
||||
case "name": error = validateName(value); break;
|
||||
case "email": error = validateEmail(value); break;
|
||||
case "empcode": error = validateEmpcode(value); break;
|
||||
case "ticket_type": error = validateTicketType(value); break;
|
||||
case "assign_to": error = validateAssignTo(value); break;
|
||||
case "subject": error = validateSubject(value); break;
|
||||
case "message": error = validateMessage(value); break;
|
||||
}
|
||||
showFieldError(fieldId, error);
|
||||
return !error;
|
||||
}
|
||||
|
||||
function validateTicketForm() {
|
||||
var fields = ["mobile", "name", "email", "empcode", "ticket_type", "subject", "message"];
|
||||
if (document.getElementById("assign_to")) {
|
||||
fields.push("assign_to");
|
||||
}
|
||||
|
||||
var firstInvalid = null;
|
||||
var isValid = true;
|
||||
fields.forEach(function (fieldId) {
|
||||
var ok = validateField(fieldId);
|
||||
if (!ok && !firstInvalid) firstInvalid = document.getElementById(fieldId);
|
||||
if (!ok) isValid = false;
|
||||
});
|
||||
|
||||
if (!isValid && firstInvalid) firstInvalid.focus();
|
||||
return isValid;
|
||||
}
|
||||
|
||||
function submitTicket(event) {
|
||||
@ -425,59 +553,8 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
event.preventDefault();
|
||||
|
||||
var form = document.getElementById('ticketForm');
|
||||
|
||||
// reset any old error styles
|
||||
form.classList.remove('was-validated');
|
||||
|
||||
var name = document.getElementById('name').value.trim();
|
||||
var mobile = document.getElementById('mobile').value.trim();
|
||||
var email = document.getElementById('email').value.trim();
|
||||
var message = document.getElementById('message').value.trim();
|
||||
var subject = document.getElementById('subject').value.trim();
|
||||
var ticketType = document.getElementById('ticket_type').value.trim();
|
||||
|
||||
// Validation checks
|
||||
if (message.length === 0) {
|
||||
toastr.warning('Message cannot be empty', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.length > 1500) {
|
||||
toastr.warning('Message cannot exceed 1500 characters', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
|
||||
if (subject.length === 0) {
|
||||
toastr.warning('Subject cannot be empty', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
|
||||
if (subject.length > 150) {
|
||||
toastr.warning('Subject cannot exceed 150 characters', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
|
||||
var mobilePattern = /^[0-9]{10}$/;
|
||||
if (!mobilePattern.test(mobile)) {
|
||||
toastr.warning('Please enter a valid 10-digit mobile number.', 'Warning');
|
||||
document.getElementById('mobile').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var emailPattern = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
||||
if (!emailPattern.test(email)) {
|
||||
toastr.warning('Please enter a valid email address.', 'Warning');
|
||||
document.getElementById('email').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (name === "" || mobile === "" || email === "" || ticketType === "" || subject === "" || message === "") {
|
||||
toastr.warning('Please fill all required fields.', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
if (!validateTicketForm()) {
|
||||
toastr.warning('Please correct highlighted fields.', 'Warning');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -509,10 +586,12 @@ beccause = dataTables_length and dataTables_paginate need in same line thats why
|
||||
console.error(xhr.responseText);
|
||||
if (xhr.status === 400) {
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
clearAllFieldErrors();
|
||||
let errorMessages = "";
|
||||
let seenMessages = []; // Array to store unique messages
|
||||
if (response.errors) {
|
||||
$.each(response.errors, function (field, message) {
|
||||
showFieldError(field, message);
|
||||
if (!seenMessages.includes(message)) {
|
||||
errorMessages += `• ${message}<br>`;
|
||||
seenMessages.push(message); // Mark this message as "seen"
|
||||
@ -719,11 +798,11 @@ $(document).ready(function() {
|
||||
subjectCounter.textContent = `${subjectLength}/150`;
|
||||
|
||||
if (subjectLength > 150) {
|
||||
toastr.warning('Subject cannot exceed 150 characters', 'Warning');
|
||||
subjectInput.classList.add('is-invalid');
|
||||
} else {
|
||||
subjectInput.classList.remove('is-invalid');
|
||||
}
|
||||
validateField("subject");
|
||||
});
|
||||
|
||||
|
||||
@ -735,11 +814,27 @@ $(document).ready(function() {
|
||||
messageCounter.textContent = `${messageLength}/1500`;
|
||||
|
||||
if (messageLength > 1500) {
|
||||
toastr.warning('Message cannot exceed 1500 characters', 'Warning');
|
||||
messageInput.classList.add('is-invalid');
|
||||
} else {
|
||||
messageInput.classList.remove('is-invalid');
|
||||
}
|
||||
validateField("message");
|
||||
});
|
||||
|
||||
[
|
||||
{ id: "mobile", event: "input" },
|
||||
{ id: "name", event: "input" },
|
||||
{ id: "email", event: "input" },
|
||||
{ id: "empcode", event: "input" },
|
||||
{ id: "ticket_type", event: "change" },
|
||||
{ id: "assign_to", event: "change" }
|
||||
].forEach(function (cfg) {
|
||||
var el = document.getElementById(cfg.id);
|
||||
if (el) {
|
||||
el.addEventListener(cfg.event, function () {
|
||||
validateField(cfg.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
@ -169,19 +169,19 @@ hr{
|
||||
</div>
|
||||
<div class="card-body card-scroll " style="padding:0 27px !important; background:#F5FFFF; border-radius: 15px !important;">
|
||||
<div class="row mb-2 ml-o">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Ticket ID</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Ticket ID</div>
|
||||
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['thz_id'];?></div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Name</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Name</div>
|
||||
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['name'];?></div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Mobile</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Mobile</div>
|
||||
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['mobile'];?></div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Policy Number</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Policy Number</div>
|
||||
<div class="col-8 text-end font-color-black" style="font-weight: 500 !important;">
|
||||
<?= (!empty($master[0]['policy_no']) && strtolower($master[0]['policy_no']) !== 'null')
|
||||
? '<u class="font-color-black">
|
||||
@ -198,11 +198,11 @@ hr{
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Assigned To</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Assigned To</div>
|
||||
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['assignee_name'];?></div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Status</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Status</div>
|
||||
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;">
|
||||
<?= (!empty($master[0]['status']) && strtolower($master[0]['status']) !== 'null')
|
||||
? '<u class="font-color-black">
|
||||
@ -219,19 +219,19 @@ hr{
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Ticket Type</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Ticket Type</div>
|
||||
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['ticket_type'];?></div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Subject</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Subject</div>
|
||||
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important; text-align: justify;"><?= $master[0]['subject'];?></div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Message</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Message</div>
|
||||
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important; text-align: justify;"><?= $master[0]['message'];?></div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4 app-subtitle app-text-grey ">Related Tickets</div>
|
||||
<div class="col-4 app-text-grey " style="font-size: 14px;">Related Tickets</div>
|
||||
<div class="col-8 text-end " style="font-weight: 500 !important;">
|
||||
<u class="text-warning">
|
||||
<a href="javascript:void(0);"
|
||||
@ -310,6 +310,7 @@ hr{
|
||||
</div>
|
||||
</div>
|
||||
<small id="messageCounter" class="form-text text-muted text-end text-right">0/1500</small>
|
||||
<small id="notes_error" class="text-danger d-block mt-1 field-error" role="alert"></small>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -482,6 +483,38 @@ data-backdrop="static"
|
||||
|
||||
<script>
|
||||
|
||||
function showNotesFieldError(message) {
|
||||
var field = document.getElementById("notes");
|
||||
var error = document.getElementById("notes_error");
|
||||
if (!field || !error) return;
|
||||
error.textContent = message || "";
|
||||
if (message) {
|
||||
field.classList.add("is-invalid");
|
||||
} else {
|
||||
field.classList.remove("is-invalid");
|
||||
}
|
||||
}
|
||||
|
||||
function clearNotesFieldError() {
|
||||
showNotesFieldError("");
|
||||
}
|
||||
|
||||
/** Mirrors ticketConversationSave rules for `notes` */
|
||||
function validateNotesValue(raw) {
|
||||
var v = raw == null ? "" : String(raw);
|
||||
if (v.length > 1500) {
|
||||
return "Notes cannot exceed 1500 characters";
|
||||
}
|
||||
var t = v.trim();
|
||||
if (v.length === 0) {
|
||||
return "Notes is required";
|
||||
}
|
||||
if (t.length === 0) {
|
||||
return "Notes cannot be empty";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Initialize select2
|
||||
$("#ticket_type, #status, #assign_to").select2();
|
||||
@ -493,12 +526,8 @@ data-backdrop="static"
|
||||
const messageLength = messageInput.value.length;
|
||||
messageCounter.textContent = `${messageLength}/1500`;
|
||||
|
||||
if (messageLength > 1500) {
|
||||
toastr.warning('Message cannot exceed 1500 characters', 'Warning');
|
||||
messageInput.classList.add('is-invalid');
|
||||
} else {
|
||||
messageInput.classList.remove('is-invalid');
|
||||
}
|
||||
var err = validateNotesValue(messageInput.value);
|
||||
showNotesFieldError(err);
|
||||
});
|
||||
|
||||
const btn = document.querySelector("button[onclick='submitTicket()']");
|
||||
@ -608,8 +637,6 @@ data-backdrop="static"
|
||||
}
|
||||
|
||||
function submitConverstionTicket(notetype,btn) {
|
||||
btn.disabled = true;
|
||||
|
||||
document.getElementById("notes_type").value = notetype;
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
document.getElementById("thz_id").value = urlParams.get('thz_id');
|
||||
@ -618,14 +645,16 @@ data-backdrop="static"
|
||||
// reset any old error styles
|
||||
form.classList.remove('was-validated');
|
||||
|
||||
var notes = document.getElementById('notes').value.trim();
|
||||
|
||||
if (notes === "") {
|
||||
toastr.warning('Please enter notes', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
var notesEl = document.getElementById('notes');
|
||||
var notesErr = validateNotesValue(notesEl.value);
|
||||
showNotesFieldError(notesErr);
|
||||
if (notesErr) {
|
||||
notesEl.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
btn.disabled = true;
|
||||
|
||||
var formData = new FormData(form);
|
||||
|
||||
$.ajax({
|
||||
@ -639,6 +668,9 @@ data-backdrop="static"
|
||||
if (response.status === "success") {
|
||||
toastr.success(response.message, 'Success');
|
||||
form.reset();
|
||||
clearNotesFieldError();
|
||||
var mc = document.getElementById("messageCounter");
|
||||
if (mc) mc.textContent = "0/1500";
|
||||
window.location.href = "<?= base_url('ticketConversationList?return_type=web&thz_id=') ?>" + id;
|
||||
} else {
|
||||
toastr.error(response.message, 'Error');
|
||||
@ -648,16 +680,10 @@ data-backdrop="static"
|
||||
console.error(xhr.responseText);
|
||||
if (xhr.status === 400) {
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
let errorMessages = "";
|
||||
let seenMessages = []; // Array to store unique messages
|
||||
if (response.errors) {
|
||||
$.each(response.errors, function (field, message) {
|
||||
if (!seenMessages.includes(message)) {
|
||||
errorMessages += `• ${message}<br>`;
|
||||
seenMessages.push(message); // Mark this message as "seen"
|
||||
}
|
||||
});
|
||||
toastr.error(errorMessages, 'Validation Error', { "allowHtml": true });
|
||||
if (response.errors.notes) {
|
||||
showNotesFieldError(response.errors.notes);
|
||||
}
|
||||
} else {
|
||||
toastr.warning(response.message || 'Validation failed', 'Warning');
|
||||
}
|
||||
@ -689,7 +715,7 @@ function statusHistory(thzId) {
|
||||
if (response.status === "success" && response.data.length > 0) {
|
||||
let table = `
|
||||
<div class="table-responsive">
|
||||
<table data-custom-table-css="table" class="table w-100 nowrap text-custom-black text-custom app-datatable">
|
||||
<table data-custom-table-css="table" class="table app-table-card w-100 nowrap text-custom-black text-custom app-datatable">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="app-text-white">S.No</th>
|
||||
|
||||
@ -262,7 +262,7 @@
|
||||
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
buttons: [{
|
||||
text: 'Add Template',
|
||||
text: '<i class="mdi mdi-plus"></i><span class="btn-custom"> Add Template </span>',
|
||||
className: 'buttons-html5 addbtnStyle',
|
||||
action: function(e, dt, node, config) {
|
||||
openModal('new_mail_template')
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
<div class="col-12">
|
||||
<div class="card-body subcard">
|
||||
<div class="custom-form">
|
||||
<form role="form" class="parsley-examples" method="post" id="tpa_general_form" enctype="multipart/form-data">
|
||||
<form role="form" class="parsley-examples" method="post" id="tpa_general_form" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>" />
|
||||
<input type="hidden" name="PrimaryKey" id="tpa_General_PrimaryKey" value="<?= isset($tpa['id']) ? $tpa['id'] : '' ?>" />
|
||||
<input type="hidden" name="tpa_id" id="tpa_id" />
|
||||
@ -68,11 +68,11 @@
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="tpa_name">TPA Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="tpa_name" placeholder="Enter TPA Name" value="<?= isset($tpa['name']) ? $tpa['name'] : '' ?>" name="name" required>
|
||||
<input type="text" class="form-control" id="tpa_name" placeholder="Enter TPA Name" value="<?= isset($tpa['name']) ? $tpa['name'] : '' ?>" name="name" required data-parsley-minlength="2">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="tpa_short_name">TPA Short Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="short_name" placeholder="Enter Short Name" value="<?= isset($tpa['short_name']) ? $tpa['short_name'] : '' ?>" name="short_name" required>
|
||||
<input type="text" class="form-control" id="short_name" placeholder="Enter Short Name" value="<?= isset($tpa['short_name']) ? $tpa['short_name'] : '' ?>" name="short_name" required data-parsley-minlength="3">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label for="tpa_network_hospitals">Network Hospitals<span class="text-danger">*</span></label>
|
||||
@ -151,12 +151,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="tpa_logo_error_container"></div>
|
||||
|
||||
<!-- Hidden File Input -->
|
||||
<input type="file" class="hidden-input"
|
||||
id="tpa_logo" name="tpa_logo"
|
||||
accept="image/jpeg, image/jpg, image/png"
|
||||
onchange="PreviewImage0(event);" />
|
||||
onchange="PreviewImage0(event);"
|
||||
data-parsley-max-file-size="200"
|
||||
data-parsley-file-extension="jpg,jpeg,png"
|
||||
data-parsley-errors-container="#tpa_logo_error_container"
|
||||
/>
|
||||
</div>
|
||||
<!-- TPA Logo Ends -->
|
||||
<!-- Front Image -->
|
||||
@ -184,12 +189,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="fc_error_container"></div>
|
||||
|
||||
<!-- Hidden File Input -->
|
||||
<input type="file" class="hidden-input"
|
||||
id="fc" name="fc"
|
||||
accept="image/jpeg, image/jpg, image/png"
|
||||
onchange="PreviewImage1(event);" />
|
||||
onchange="PreviewImage1(event);"
|
||||
data-parsley-max-file-size="500"
|
||||
data-parsley-file-extension="jpg,jpeg,png"
|
||||
data-parsley-errors-container="#fc_error_container"
|
||||
/>
|
||||
</div>
|
||||
<!-- Front Image Ends -->
|
||||
<!-- Back Image -->
|
||||
@ -217,12 +227,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bc_error_container"></div>
|
||||
|
||||
<!-- Hidden File Input -->
|
||||
<input type="file" class="hidden-input"
|
||||
id="bc" name="bc"
|
||||
accept="image/jpeg, image/jpg, image/png"
|
||||
onchange="PreviewImage4(event);" />
|
||||
onchange="PreviewImage4(event);"
|
||||
data-parsley-max-file-size="500"
|
||||
data-parsley-file-extension="jpg,jpeg,png"
|
||||
data-parsley-errors-container="#bc_error_container"
|
||||
/>
|
||||
</div>
|
||||
<!-- Back Image Ends -->
|
||||
</div>
|
||||
@ -264,6 +279,42 @@
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
// Custom Parsley validator for file size
|
||||
window.Parsley.addValidator('maxFileSize', {
|
||||
validateString: function(value, maxSize, parsleyInstance) {
|
||||
if (!window.FileReader) {
|
||||
alert('You browser does not support FileReader API, please upgrade.');
|
||||
return true;
|
||||
}
|
||||
var files = parsleyInstance.$element[0].files;
|
||||
if (files.length == 0) {
|
||||
return true; // No file, so validation passes (unless required)
|
||||
}
|
||||
return files[0].size <= maxSize * 1024;
|
||||
},
|
||||
requirementType: 'integer',
|
||||
messages: {
|
||||
en: 'This file should not be larger than %s KB.'
|
||||
}
|
||||
});
|
||||
|
||||
// Custom Parsley validator for file extension
|
||||
window.Parsley.addValidator('fileExtension', {
|
||||
validateString: function(value, requirement, parsleyInstance) {
|
||||
var file = parsleyInstance.$element[0].files[0];
|
||||
if (!file) {
|
||||
return true; // No file, so validation passes
|
||||
}
|
||||
var extensions = requirement.split(',').map(function(ext) { return ext.trim().toLowerCase(); });
|
||||
var fileExtension = file.name.split('.').pop().toLowerCase();
|
||||
return extensions.indexOf(fileExtension) !== -1;
|
||||
},
|
||||
requirementType: 'string',
|
||||
messages: {
|
||||
en: 'Allowed extensions are: %s.'
|
||||
}
|
||||
});
|
||||
|
||||
if($('#tpa_General_PrimaryKey').val() != ""){
|
||||
|
||||
$('#view_pre_btn').show()
|
||||
|
||||
@ -28,6 +28,36 @@
|
||||
overflow-y: auto;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
#tpa-branch-datatable{
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
#tpa-branch-datatable_wrapper .datatable-search-wrapper{
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
#tpa-branch-datatable_wrapper .dataTables_filter input{
|
||||
width: 220px !important;
|
||||
padding-right: 34px !important;
|
||||
}
|
||||
|
||||
#tpa-branch-datatable_wrapper .datatable-search-icon,
|
||||
#tpa-branch-datatable_wrapper .datatable-clear-icon{
|
||||
right: 11px !important;
|
||||
}
|
||||
|
||||
/* Fix DataTables scroll header and body alignment */
|
||||
#tpa-branch-datatable_wrapper .dataTables_scrollHeadInner{
|
||||
box-sizing: content-box !important;
|
||||
padding-right: 0px !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
#tpa-branch-datatable_wrapper .dataTables_scrollHeadInner table,
|
||||
#tpa-branch-datatable_wrapper .dataTables_scrollBody table{
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
<div class="tab-pane fade" id="branch-tab">
|
||||
|
||||
@ -37,7 +67,7 @@
|
||||
|
||||
<div class="table-responsive" id="branch_table" >
|
||||
|
||||
<table data-custom-table-css="table" class="table table-borderless table-nowrap mb-0" id="tpa-branch-datatable">
|
||||
<table data-custom-table-css="table" class="table table-borderless table-nowrap mb-0 w-100 nowrap" id="tpa-branch-datatable">
|
||||
<thead class="">
|
||||
|
||||
<tr>
|
||||
@ -315,12 +345,56 @@
|
||||
|
||||
var contactCount = 1;
|
||||
|
||||
function resetTPABranchFormState() {
|
||||
var $form = $('#tpa_branch_form');
|
||||
if ($form.length && $form[0] && typeof $form[0].reset === 'function') {
|
||||
$form[0].reset();
|
||||
}
|
||||
|
||||
if ($form.length && typeof $form.parsley === 'function') {
|
||||
try {
|
||||
$form.parsley().reset();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
contactCount = 1;
|
||||
$('#container').empty();
|
||||
$('#contact_1_wrapper input').val('');
|
||||
$('#tpa_Branch_PrimaryKey').val('');
|
||||
toggleAddButton();
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
$('#tpa-branch-datatable').DataTable({
|
||||
paging: true ,
|
||||
searching: true
|
||||
});
|
||||
paging: true,
|
||||
searching: true,
|
||||
autoWidth: false,
|
||||
scrollX: false,
|
||||
responsive: false,
|
||||
initComplete: function () {
|
||||
var $wrapper = $('#tpa-branch-datatable_wrapper');
|
||||
$wrapper.find('.dataTables_scrollHeadInner').css({
|
||||
'box-sizing': 'content-box',
|
||||
'padding-right': '0px',
|
||||
'width': '100%'
|
||||
});
|
||||
this.api().columns.adjust();
|
||||
},
|
||||
dom: "<'datatable-top-section'f>" +
|
||||
"tr" +
|
||||
"<'datatable-bottom-section d-flex justify-content-between align-items-center mt-2'<'datatable-info'i><'datatable-controls d-flex align-items-center'<'me-2'l>p>>",
|
||||
language: {
|
||||
search: `
|
||||
<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">
|
||||
_INPUT_
|
||||
<i class="mdi mdi-magnify datatable-search-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666;"></i>
|
||||
<i class="mdi mdi-close-circle datatable-clear-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No data available</div>'
|
||||
}
|
||||
});
|
||||
|
||||
var tpa_Branch_PrimaryKey = $('#tpa_id_branch').val();
|
||||
var tpa_branch_form_action = '';
|
||||
@ -331,7 +405,10 @@ $(document).ready(function () {
|
||||
|
||||
loadBranchList();
|
||||
|
||||
$('#btnBranchAdd').click(function(){
|
||||
$('#btnBranchAdd').click(function(e){
|
||||
if (e && typeof e.preventDefault === 'function') {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
tpa_branch_form_action = '<?= base_url("master/tpa/branch/create"); ?>';
|
||||
var myModal = new bootstrap.Modal(document.getElementById('tpaBranchModal'));
|
||||
@ -375,31 +452,20 @@ $(document).ready(function () {
|
||||
}
|
||||
localStorage.removeItem('buttonIds')
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$('.btnBack').click(function(){
|
||||
$('.btnBack').click(function(e){
|
||||
if (e && typeof e.preventDefault === 'function') {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
var myModal = new bootstrap.Modal(document.getElementById('tpaBranchModal'));
|
||||
myModal.hide();
|
||||
// $('#add_branch').hide();
|
||||
// $('#branch_table').show();
|
||||
// $('.btnBack').hide();
|
||||
// $('#btnBranchAdd').show();
|
||||
});
|
||||
|
||||
$('#branch_name').val('');
|
||||
$('#branch_code').val('');
|
||||
$('#state').val('');
|
||||
$('#district').val('');
|
||||
$('#branch_city').val('');
|
||||
|
||||
$('#name').val('');
|
||||
$('#email').val('');
|
||||
$('#mobile').val('');
|
||||
$('#designation').val('');
|
||||
$('#container').empty(); $('#contact_1_wrapper input').val('');
|
||||
|
||||
|
||||
})
|
||||
$('#tpaBranchModal').on('hidden.bs.modal', function () {
|
||||
resetTPABranchFormState();
|
||||
});
|
||||
|
||||
|
||||
if(tpa_Branch_PrimaryKey !== ''){
|
||||
@ -466,7 +532,7 @@ $(document).ready(function () {
|
||||
}
|
||||
$('#tpa_branch_list').append(tpaBranchTableInsert);
|
||||
$('#container').empty(); $('#contact_1_wrapper input').val('');
|
||||
$('.close').click();
|
||||
$('#tpaBranchModal .close').trigger('click');
|
||||
// $('#add_branch').hide();
|
||||
// $('#branch_table').show();
|
||||
// $('.btnBack').hide();
|
||||
@ -509,7 +575,7 @@ $(document).ready(function () {
|
||||
$('.loader').fadeOut();
|
||||
$('.loader-mask').delay(350).fadeOut('slow');
|
||||
}, 1000);
|
||||
$('.close').click();
|
||||
$('#tpaBranchModal .close').trigger('click');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
<h4 style="position: relative;">TPA</h4>
|
||||
</div>
|
||||
<div class="col-6" style="text-align: right;">
|
||||
<a href="<?= base_url("master/tpa/list"); ?>"><i class="mdi mdi-arrow-left" style="font-size: 17px;"></i> </a>
|
||||
<a href="<?= base_url("master/tpa/list"); ?>"><i class="ri-arrow-left-circle-line" style="font-size: 17px;"></i> </a>
|
||||
</div> -->
|
||||
<!-- </div> -->
|
||||
<div class="tab-wrapper position-relative">
|
||||
|
||||
@ -1,17 +1,4 @@
|
||||
<style>
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td {
|
||||
padding: 4px 4px !important;
|
||||
}
|
||||
|
||||
/* table.dataTable thead th {
|
||||
padding: 4px 4px !important;
|
||||
} */
|
||||
|
||||
.col-12 {
|
||||
max-width: 98% !important;
|
||||
}
|
||||
@ -22,26 +9,6 @@ table.dataTable tbody td {
|
||||
background-color: #f0f0f0;
|
||||
color: #666;
|
||||
}
|
||||
.custom-dropdown-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #ffffff !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 0;
|
||||
min-width: 10rem;
|
||||
z-index: 9999;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
padding: 0.5rem 1rem !important;
|
||||
color: #212529 !important;
|
||||
text-decoration: none !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.custom-dropdown-menu .dropdown-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
@ -73,17 +40,17 @@ table.dataTable tbody td {
|
||||
<h4 style="position: relative;">Vehicle Master</h4>
|
||||
</div>
|
||||
</div> -->
|
||||
<table data-custom-table-css="table" id="scroll-horizontal-datatable" class="table w-100 nowrap">
|
||||
<table data-custom-table-css="table" id="scroll-horizontal-datatable" class="table mb-0 nowrap" cellspacing="0">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium"><div class="column-header">S.No </div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Owner Type </div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Owner Name </div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">RC Book No </div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Vehicle No </div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Vehicle type </div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Description </div></th>
|
||||
<th class="font-weight-medium"><div class="column-header">Action </div></th>
|
||||
<th class="font-weight-medium">S.No </th>
|
||||
<th class="font-weight-medium">Owner Type </th>
|
||||
<th class="font-weight-medium">Owner Name </th>
|
||||
<th class="font-weight-medium">RC Book No </th>
|
||||
<th class="font-weight-medium">Vehicle No </th>
|
||||
<th class="font-weight-medium">Vehicle type </th>
|
||||
<th class="font-weight-medium">Description </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -97,7 +64,7 @@ table.dataTable tbody td {
|
||||
<td><?php echo $row['vehicle_no'] ?: 'N/A'; ?></td>
|
||||
<td><?php echo $row['vehicle_type'] ?: 'N/A'; ?></td>
|
||||
<td><?php echo $vehicle_des[$row['description']] ?? "N/A"; ?></td>
|
||||
<td>
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);"
|
||||
class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown"
|
||||
@ -135,7 +102,7 @@ table.dataTable tbody td {
|
||||
aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="parsley-examples" method="post" id="vehicle_form" enctype="multipart/form-data">
|
||||
<form class="parsley-examples" method="post" id="vehicle_form" enctype="multipart/form-data" data-parsley-validate>
|
||||
<div class="form-group">
|
||||
|
||||
<input type="hidden" id="vehicle_primary_key" name="vehicle_primary_key">
|
||||
@ -155,16 +122,15 @@ table.dataTable tbody td {
|
||||
<div class="form-group col-md-6">
|
||||
<label for="cost_center">Vehicle No<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="vehicle_no" placeholder="Enter Vehicle No"
|
||||
name="vehicle_no"
|
||||
name="vehicle_no" required
|
||||
data-parsley-pattern="^[A-Z]{2}[0-9]{1,2}[A-Z]{1,2}[0-9]{4}$"
|
||||
data-parsley-error-message="Invalid Vehicle Number. Example: TN22AB1234"
|
||||
data-parsley-trigger="change"
|
||||
data-parsley-pattern="^[A-Z]{2}[0-9]{2}[A-Z]{1,2}[0-9]{4}$" required>
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="rc">RC Book <span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="rc" placeholder="Enter RC Book No" name="rc"
|
||||
required>
|
||||
<input type="text" class="form-control" id="rc" placeholder="Enter RC Book No" name="rc" required data-parsley-trigger="keyup">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
@ -197,8 +163,7 @@ table.dataTable tbody td {
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="rc"> Old Owner Name <span class="text-danger">(if exist)</span></label>
|
||||
<input type="text" class="form-control" id="old_onwer" name="old_onwer"
|
||||
placeholder="Enter Old Owner Name">
|
||||
<input type="text" class="form-control" id="old_onwer" name="old_onwer" placeholder="Enter Old Owner Name" data-parsley-pattern="^[a-zA-Z0-9\s\.]+$" data-parsley-trigger="keyup">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
@ -220,7 +185,7 @@ table.dataTable tbody td {
|
||||
|
||||
</div>
|
||||
<div class="form-group text-right m-b-0" id="hide_smbt_btn">
|
||||
<button class="btn app-btn-outline-secondary mr-2 colse" type="button" id="close_btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||
<button class="btn app-btn-outline-secondary mr-2 close" type="button" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||
<button type="submit" id="btnSubmit" class="btn app-btn-secondary waves-effect waves-light" id="cd_master_btn_Submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
@ -243,7 +208,7 @@ table.dataTable tbody td {
|
||||
<button type="button" id="close_btn" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="parsley-examples" method="post" id="client_form" enctype="multipart/form-data">
|
||||
<form class="parsley-examples" method="post" id="client_form" enctype="multipart/form-data" data-parsley-validate>
|
||||
<div class="form-group">
|
||||
|
||||
<div class="form-row">
|
||||
@ -258,16 +223,16 @@ table.dataTable tbody td {
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label for="client_name">Client Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="client_name" name="client_name" required>
|
||||
<input type="text" class="form-control" id="client_name" name="client_name" required data-parsley-pattern="^[a-zA-Z0-9\s\.,\-_'&\(\)]+$" data-parsley-trigger="keyup">
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label for="short_name">Client Short name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="short_name" name="short_name" required>
|
||||
<input type="text" class="form-control" id="short_name" name="short_name" required data-parsley-pattern="^[a-zA-Z0-9_\-]+$" data-parsley-trigger="keyup">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="cost_center">PAN<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="pan" placeholder="Enter PAN No" name="pan">
|
||||
<input type="text" class="form-control" id="pan" placeholder="Enter PAN No" name="pan" required data-parsley-pattern="^[A-Z]{5}[0-9]{4}[A-Z]$" data-parsley-trigger="keyup">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -278,25 +243,22 @@ table.dataTable tbody td {
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="dob">Date of Birth<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="dob" placeholder="DD/MM/YYYY" name="dob">
|
||||
<input type="text" class="form-control" id="dob" placeholder="DD/MM/YYYY" name="dob" data-parsley-pattern="^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/(19|20)\d\d$" data-parsley-pattern-message="Please enter a valid date in DD/MM/YYYY format.">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="cost_center">Mobile<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="phone" placeholder="Enter Mobile Number"
|
||||
maxlength="10" name="phone" onkeypress="return onlyNumbers(event)">
|
||||
<input type="text" class="form-control" id="phone" placeholder="Enter Mobile Number" name="phone" data-parsley-type="digits" data-parsley-length="[10,10]">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="cost_center">Email<span class="text-danger">*</span></label>
|
||||
<input type="email" class="form-control" id="email" placeholder="Enter Email"
|
||||
name="email">
|
||||
<input type="email" class="form-control" id="email" placeholder="Enter Email" name="email">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="aadhar">Aadhar<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="aadhar" placeholder="Enter PAN No"
|
||||
name="aadhar">
|
||||
<input type="text" class="form-control" id="aadhar" placeholder="Enter Aadhaar No" name="aadhar" data-parsley-type="digits" data-parsley-length="[12,12]">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -320,23 +282,22 @@ table.dataTable tbody td {
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="client_name">Branch Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="branch_name" name="branch_name">
|
||||
<input type="text" class="form-control" id="branch_name" name="branch_name" data-parsley-pattern="^[a-zA-Z0-9\s\.,\-_'&\(\)]+$">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="branch_code">Branch Code<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="branch_code" name="branch_code">
|
||||
<input type="text" class="form-control" id="branch_code" name="branch_code" data-parsley-pattern="^[a-zA-Z0-9_\-]+$">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="branch_code">Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="name" name="name">
|
||||
<input type="text" class="form-control" id="name" name="name" data-parsley-pattern="^[a-zA-Z\s\.]+$">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<label for="branch_code">Mobile<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="mobile" maxlength="10" name="mobile"
|
||||
onkeypress="return onlyNumbers(event)">
|
||||
<input type="text" class="form-control" id="mobile" name="mobile" data-parsley-type="digits" data-parsley-length="[10,10]">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
@ -361,98 +322,6 @@ table.dataTable tbody td {
|
||||
</div>
|
||||
|
||||
<!-- end of Client form content modal -->
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const table = document.getElementById("scroll-horizontal-datatable");
|
||||
|
||||
// Create custom dropdown
|
||||
function createCustomDropdown(row) {
|
||||
// Get the original dropdown menu
|
||||
const originalDropdown = row.querySelector('.dropdown-menu');
|
||||
if (!originalDropdown) return null;
|
||||
|
||||
// Create new dropdown menu with the same content
|
||||
const customDropdown = document.createElement('div');
|
||||
customDropdown.className = 'custom-dropdown-menu';
|
||||
|
||||
// Copy content of the original dropdown
|
||||
customDropdown.innerHTML = originalDropdown.innerHTML;
|
||||
|
||||
return customDropdown;
|
||||
}
|
||||
|
||||
let activeDropdown = null;
|
||||
|
||||
// Add click event listener to rows
|
||||
table.querySelectorAll("tbody tr").forEach(row => {
|
||||
const customDropdown = createCustomDropdown(row);
|
||||
if (!customDropdown) return;
|
||||
|
||||
// Append custom dropdown to the body
|
||||
document.body.appendChild(customDropdown);
|
||||
|
||||
row.addEventListener("click", function(event) {
|
||||
// Prevent opening dropdown if clicking on the action column (button)
|
||||
if (event.target.closest('td:last-child') || event.target.closest('.dropdown-toggle')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Close any existing active dropdown
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
}
|
||||
|
||||
// Get the position of the clicked cell
|
||||
const rect = event.target.getBoundingClientRect();
|
||||
|
||||
// Position the dropdown based on where you click in the row (excluding action column)
|
||||
customDropdown.style.display = 'block';
|
||||
customDropdown.style.position = 'absolute';
|
||||
customDropdown.style.left = `${rect.left + window.scrollX}px`; // Align with the clicked position
|
||||
customDropdown.style.top = `${rect.bottom + window.scrollY + 5}px`; // 5px gap below the row
|
||||
|
||||
// Set this dropdown as the active one
|
||||
activeDropdown = customDropdown;
|
||||
|
||||
event.stopPropagation(); // Prevent event from bubbling up
|
||||
});
|
||||
|
||||
// Add click event to handle dropdown item actions
|
||||
customDropdown.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
const onclickAttr = this.getAttribute('onclick');
|
||||
if (onclickAttr) {
|
||||
eval(onclickAttr);
|
||||
}
|
||||
|
||||
const href = this.getAttribute('href');
|
||||
if (href && href !== '#') {
|
||||
window.location.href = href;
|
||||
}
|
||||
|
||||
// Close the dropdown after handling the click
|
||||
if (activeDropdown) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
|
||||
e.stopPropagation(); // Prevent event from bubbling up
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
document.addEventListener("click", function(event) {
|
||||
if (activeDropdown && !event.target.closest('.custom-dropdown-menu')) {
|
||||
activeDropdown.style.display = 'none';
|
||||
activeDropdown = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
var client_list = ''; // local variable for storing the client list
|
||||
@ -467,9 +336,9 @@ $(document).ready(function() {
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
var ticketsTable = $('#scroll-horizontal-datatable');
|
||||
if (ticketsTable.length) {
|
||||
ticketsTable.DataTable({
|
||||
var table = $('#scroll-horizontal-datatable');
|
||||
if (table.length) {
|
||||
var dataTable = table.DataTable({
|
||||
scrollX: true,
|
||||
// dom: "<'row'<'col-12 d-flex justify-content-between align-items-center'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'B>>>" +
|
||||
// "<'row'<'col-sm-12'tr>>" +
|
||||
@ -533,6 +402,25 @@ $(document).ready(function() {
|
||||
pageLength: 10,
|
||||
order: [[0, 'desc']]
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!dataTable) return;
|
||||
|
||||
const currentRows = dataTable.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#scroll-horizontal-datatable tbody tr').removeClass('nh-force-dropup');
|
||||
$('#scroll-horizontal-datatable tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
$('#scroll-horizontal-datatable').on('draw.dt', applyBottomRowDropup);
|
||||
|
||||
} else {
|
||||
console.error("Table atet found.");
|
||||
}
|
||||
@ -596,8 +484,13 @@ function getEditVehicleDetailsData(input) {
|
||||
function showModal(type) {
|
||||
|
||||
if (type == 'add') {
|
||||
|
||||
$('#vehicle_form')[0].reset();
|
||||
if ($('#vehicle_form').parsley()) {
|
||||
$('#vehicle_form').parsley().reset();
|
||||
}
|
||||
$('#myCenterModalLabel').text('Add New Vehicle');
|
||||
$('#owner').removeClass('readonly-select');
|
||||
$('#owner_branch').removeClass('readonly-select');
|
||||
$('#Owner_type').val('');
|
||||
$('#vehicle_no').val('');
|
||||
$('#rc').val('');
|
||||
@ -662,10 +555,10 @@ function ownerTypeBasedShowAndHideOwnerBranch(input) {
|
||||
|
||||
if (owner_type_id == 2) {
|
||||
$('.ownerbranchdiv').hide();
|
||||
// $('#owner_branch').prop('required', false);
|
||||
$('#owner_branch').prop('required', false);
|
||||
} else {
|
||||
$('.ownerbranchdiv').show();
|
||||
// $('#owner_branch').prop('required', true);
|
||||
$('#owner_branch').prop('required', true);
|
||||
}
|
||||
|
||||
// Clear and add default options for client
|
||||
|
||||
@ -40,13 +40,8 @@
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td {
|
||||
padding: 4px 4px !important;
|
||||
.col-12 {
|
||||
max-width: 98% !important;
|
||||
}
|
||||
|
||||
/* Tooltip Styles */
|
||||
@ -316,15 +311,15 @@
|
||||
<h4 style="position: relative;">Users</h4>
|
||||
</div>
|
||||
</div> -->
|
||||
<table data-custom-table-css="table" class="table table-sm m-0 table-centered dt-responsive nowrap w-100" cellspacing="a" id="user-table">
|
||||
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="user-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium">S.No.</th>
|
||||
<th class="font-weight-medium"></th>
|
||||
<th class="font-weight-medium">Mobile No</th>
|
||||
<th class="font-weight-medium">Role</th>
|
||||
<th class="font-weight-medium">Status</th>
|
||||
<th class="font-weight-medium">Action</th>
|
||||
<th class="font-weight-medium">S.No. </th>
|
||||
<th class="font-weight-medium"> </th>
|
||||
<th class="font-weight-medium">Mobile No </th>
|
||||
<th class="font-weight-medium">Role </th>
|
||||
<th class="font-weight-medium">Status </th>
|
||||
<th class="font-weight-medium text-center">Action </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -339,8 +334,8 @@
|
||||
<?php if($row->is_active == 1){ echo 'Active'; }else{ echo 'In-Active'; } ?>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group dropdown" style="position: relative !important;left:0px !important;top:0px !important;">
|
||||
<td class="text-center table-action-cell">
|
||||
<div class="btn-group dropdown">
|
||||
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
|
||||
<div class="dropdown-menu dropdown-menu-right" style="cursor: pointer;">
|
||||
<a data-toggle="modal" data-target="#con-close-modal" class="dropdown-item btnEdit" data-id="<?php echo $row->id; ?>"><i data-id="<?php echo $row->id; ?>" class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle btnEdit"></i>Edit</a>
|
||||
@ -870,7 +865,11 @@
|
||||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||||
</div>`,
|
||||
searchPlaceholder: "Search",
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||||
emptyTable: '<div class="text-center text-muted">No Data found</div>',
|
||||
paginate: {
|
||||
previous: '◄',
|
||||
next: '►'
|
||||
}
|
||||
},
|
||||
initComplete: function () {
|
||||
$(".dt-buttons").prepend(`
|
||||
@ -895,6 +894,24 @@
|
||||
}
|
||||
});
|
||||
|
||||
function applyBottomRowDropup() {
|
||||
if (!table) return;
|
||||
|
||||
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
|
||||
$('#user-table tbody tr').removeClass('nh-force-dropup');
|
||||
$('#user-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
|
||||
|
||||
// Mark last two rows on current page to open action menu upward.
|
||||
const targetCount = Math.min(2, currentRows.length);
|
||||
for (let i = 0; i < targetCount; i++) {
|
||||
const row = currentRows[currentRows.length - 1 - i];
|
||||
if (!row) continue;
|
||||
$(row).addClass('nh-force-dropup');
|
||||
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
|
||||
}
|
||||
}
|
||||
applyBottomRowDropup();
|
||||
$('#user-table').on('draw.dt', applyBottomRowDropup);
|
||||
|
||||
|
||||
$('#team').multiselect({
|
||||
|
||||
@ -69,18 +69,22 @@
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<!-- <form class="parsley-examples" id="vehicleTypeForm" enctype="multipart/form-data"> -->
|
||||
<form id="vehicleTypeForm" enctype="multipart/form-data">
|
||||
<form id="vehicleTypeForm" enctype="multipart/form-data" data-parsley-validate>
|
||||
<input type="hidden" name="pk" id="vehicle_type_id"/>
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="vehicle_type">Vehicle Type<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="vehicle_type" name="vehicle_type" placeholder="Enter Vehicle Type" required>
|
||||
<input type="text" class="form-control" id="vehicle_type" name="vehicle_type" placeholder="Enter Vehicle Type"
|
||||
required
|
||||
data-parsley-pattern="^[a-zA-Z0-9\s_.-]+$"
|
||||
data-parsley-pattern-message="Vehicle type may only contain alphanumeric, space, underscore, dot, and dash characters."
|
||||
data-parsley-trigger="keyup">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-right m-b-0">
|
||||
<button type="button" class="btn app-btn-secondary waves-effect waves-light" id="btnSubmit" onclick="handleSaveEditAndDelete('submit')">Submit</button>
|
||||
<button type="submit" class="btn app-btn-secondary waves-effect waves-light" id="btnSubmit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -103,7 +107,7 @@
|
||||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Add',
|
||||
text: '<i class="mdi mdi-plus"></i><span class="btn-custom"> Add </span>',
|
||||
className: 'btn app-btn-primary mr-2',
|
||||
action: function(e, dt, node, config) {
|
||||
openModal()
|
||||
@ -145,7 +149,10 @@
|
||||
});
|
||||
|
||||
$('.close').click(function(){
|
||||
resetValues()
|
||||
resetValues();
|
||||
if ($('#vehicleTypeForm').parsley()) {
|
||||
$('#vehicleTypeForm').parsley().reset();
|
||||
}
|
||||
})
|
||||
|
||||
function openModal(){
|
||||
@ -252,6 +259,9 @@
|
||||
function resetValues(){
|
||||
$('#modalLabel').text('Add Vehicle Type');
|
||||
$('#vehicleTypeForm')[0].reset();
|
||||
if ($('#vehicleTypeForm').parsley()) {
|
||||
$('#vehicleTypeForm').parsley().reset();
|
||||
}
|
||||
}
|
||||
|
||||
function appendEditData(data){
|
||||
@ -259,5 +269,13 @@
|
||||
$('#vehicle_type').val(data[0]['vehicle_type']);
|
||||
openModal()
|
||||
}
|
||||
</script>
|
||||
|
||||
$('#vehicleTypeForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
var $form = $(this);
|
||||
$form.parsley().validate();
|
||||
if ($form.parsley().isValid()) {
|
||||
handleSaveEditAndDelete('submit');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
821
public/assets/css/custom.css
Normal file
821
public/assets/css/custom.css
Normal file
@ -0,0 +1,821 @@
|
||||
/**
|
||||
* =============================================================================
|
||||
* NHance — custom.css (listing tables / DataTables)
|
||||
* =============================================================================
|
||||
* Purpose:
|
||||
* Shared look for DataTables-based listing pages: toolbar, footer, sort
|
||||
* arrows, last-column spacing, card-style rows (.app-table-card +
|
||||
* tbody.app-table-body), and
|
||||
* safer row action dropdowns.
|
||||
*
|
||||
* Load order:
|
||||
* Include this file in the layout <head> after app-creative and DataTables
|
||||
* Bootstrap CSS so these rules can override theme defaults.
|
||||
*
|
||||
* Related layout:
|
||||
* app/Views/layout/header.php — <link> to this file
|
||||
*
|
||||
* Behaviour notes (why some issues happened):
|
||||
* - Toolbar: pages that used position:absolute on .dataTables_filter broke the
|
||||
* flex row; we keep the filter in normal flow (see rules below).
|
||||
* - Sort icons: theme used fixed vertical offsets; we use stacked triangles
|
||||
* with top:50% for alignment with header text.
|
||||
* - Action dropdowns: DataTables scrollX wraps the table in .dataTables_scrollBody
|
||||
* with overflow:auto. Bootstrap’s dropdown (Popper) then uses a scroll
|
||||
* boundary that can mis-place menus (often worse on the last row). Global
|
||||
* JS in layout/footer.php sets Popper boundary and temporarily relaxes
|
||||
* overflow while the menu is open — see comments there.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SECTION: DataTables toolbar (first row inside .dataTables_wrapper)
|
||||
* Search/filter left, export/buttons right, vertically centered.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
div.dataTables_wrapper > div.row:first-of-type {
|
||||
display: flex !important;
|
||||
flex-wrap: wrap;
|
||||
align-items: center !important;
|
||||
justify-content: space-between !important;
|
||||
gap: 0.15rem 0.25rem;
|
||||
/* margin-left: 0 !important; */
|
||||
/* margin-right: 0 !important; */
|
||||
/* margin-bottom: 0.25rem !important; */
|
||||
}
|
||||
|
||||
/* Match horizontal padding with Bootstrap columns */
|
||||
div.dataTables_wrapper > div.row:first-of-type > [class*="col-"] {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
/* Keep filter in document flow (overrides stray position:absolute in old views) */
|
||||
div.dataTables_wrapper div.dataTables_filter {
|
||||
position: relative !important;
|
||||
float: none !important;
|
||||
text-align: left !important;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dt-buttons {
|
||||
text-align: right !important;
|
||||
float: none !important;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .datatable-search,
|
||||
div.dataTables_wrapper .datatable-buttons {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
/* Keep top controls on one line for desktop/tablet list pages */
|
||||
@media (min-width: 768px) {
|
||||
div.dataTables_wrapper > div.row:first-of-type {
|
||||
flex-wrap: nowrap !important;
|
||||
}
|
||||
|
||||
/* Legacy view-level CSS sets .dt-buttons.btn-group to grid; normalize */
|
||||
div.dataTables_wrapper .dt-buttons.btn-group,
|
||||
div.dataTables_wrapper .datatable-buttons.dt-buttons {
|
||||
display: inline-flex !important;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
/* Prevent search area from consuming full row width */
|
||||
div.dataTables_wrapper div.dataTables_filter {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper div.dataTables_filter label {
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
margin-bottom: 0 !important;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .datatable-search-wrapper {
|
||||
width: min(320px, 100%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Custom dom: d-flex justify-content-between (e.g. client_list, tpa_list) */
|
||||
div.dataTables_wrapper .row .d-flex.justify-content-between {
|
||||
width: 100%;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SECTION: DataTables footer (last row — info, length, pagination)
|
||||
* “Showing X to Y” left; “Show n entries” + pager right.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
div.dataTables_wrapper > div.row:last-of-type {
|
||||
display: flex !important;
|
||||
flex-wrap: wrap;
|
||||
align-items: center !important;
|
||||
justify-content: space-between !important;
|
||||
margin-top: 0.35rem !important;
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default Bootstrap/DataTables bottom row often puts length + paginate in the last
|
||||
* grid column using floats; wide pagination then overlaps the word “entries”.
|
||||
* Flex + gap keeps both visible on all listing pages.
|
||||
*/
|
||||
div.dataTables_wrapper > div.row:last-of-type > div[class*="col-"]:last-child:has(.dataTables_paginate),
|
||||
div.dataTables_wrapper > div.row:last-child > div[class*="col-"]:last-child:has(.dataTables_paginate) {
|
||||
display: flex !important;
|
||||
flex-wrap: wrap;
|
||||
align-items: center !important;
|
||||
justify-content: flex-end !important;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper div.dataTables_info {
|
||||
padding-top: 0.5rem !important;
|
||||
color: #333 !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper div.dataTables_length {
|
||||
padding-top: 0 !important;
|
||||
/* Keep “Show … entries” fully visible when pagination is wide (flex row must not shrink this) */
|
||||
flex-shrink: 0 !important;
|
||||
margin-right: 0.65rem !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper div.dataTables_length label {
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
gap: 0.35rem;
|
||||
margin-bottom: 0 !important;
|
||||
overflow: visible !important;
|
||||
/* Views set height: 21px which can clip label text */
|
||||
height: auto !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
/* Length “entries” dropdown — light panel */
|
||||
div.dataTables_wrapper div.dataTables_length select {
|
||||
/* background-color: #e0f7fa !important; */
|
||||
border: 1px solid #b2ebf2 !important;
|
||||
border-radius: 8px !important;
|
||||
padding: 0.2rem 1.75rem 0.2rem 0.5rem !important;
|
||||
font-weight: 500 !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper div.dataTables_paginate {
|
||||
text-align: right !important;
|
||||
padding-top: 0 !important;
|
||||
flex-shrink: 1 !important;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate ul.pagination {
|
||||
justify-content: flex-end !important;
|
||||
align-items: center !important;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
/* Extra gap between “entries” and pager when both sit in a flex row (custom dom: …<'me-2'l>p…) */
|
||||
div.dataTables_wrapper > div.row:last-of-type .d-flex.align-items-center,
|
||||
div.dataTables_wrapper > div.row:last-child .d-flex.align-items-center {
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* Length is often wrapped in .me-2 — that wrapper was shrinking and clipping “entries” */
|
||||
div.dataTables_wrapper > div.row:last-of-type .d-flex > .me-2,
|
||||
div.dataTables_wrapper > div.row:last-child .d-flex > .me-2 {
|
||||
flex-shrink: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
/* Inactive numbered links */
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item:not(.active):not(.previous):not(.next) .page-link {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
/* Previous / Next — shared box; arrows centered via ::before (absolute + translate) */
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.previous,
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.next {
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
align-self: center !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.previous .page-link,
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.next .page-link {
|
||||
border-radius: 13px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
outline: none !important;
|
||||
position: relative !important;
|
||||
/* Hide DataTables “Previous/Next” text; icon is ::before only */
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
color: transparent !important;
|
||||
overflow: hidden !important;
|
||||
min-width: 32px !important;
|
||||
width: 32px !important;
|
||||
min-height: 2.25rem !important;
|
||||
padding: 0 !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.previous:not(.disabled) .page-link,
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.next:not(.disabled) .page-link {
|
||||
background-color: #ffffff !important;
|
||||
cursor: pointer !important;
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
|
||||
/* First page / last page / single page: Bootstrap + DataTables add .disabled on the <li> */
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.previous.disabled .page-link,
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.next.disabled .page-link {
|
||||
background-color: #ffffff !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.previous .page-link::before,
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.next .page-link::before {
|
||||
content: "";
|
||||
position: absolute !important;
|
||||
left: 50% !important;
|
||||
top: 50% !important;
|
||||
transform: translate(-50%, -50%) !important;
|
||||
text-indent: 0 !important;
|
||||
line-height: 1 !important;
|
||||
font-size: 12px !important;
|
||||
font-family: inherit !important;
|
||||
display: block !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.previous:not(.disabled) .page-link::before {
|
||||
content: "◄";
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.next:not(.disabled) .page-link::before {
|
||||
content: "►";
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.previous.disabled .page-link::before {
|
||||
content: "◄";
|
||||
color: #adb5bd !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .page-item.next.disabled .page-link::before {
|
||||
content: "►";
|
||||
color: #adb5bd !important;
|
||||
}
|
||||
|
||||
/* DataTables markup variant without .page-item/.page-link */
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.previous,
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.next {
|
||||
border-radius: 13px !important;
|
||||
background-color: #F5FFFF !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
outline: none !important;
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
color: transparent !important;
|
||||
position: relative !important;
|
||||
overflow: hidden !important;
|
||||
min-width: 32px !important;
|
||||
width: 32px !important;
|
||||
min-height: 2.25rem !important;
|
||||
padding: 0 !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.previous:not(.disabled),
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.next:not(.disabled) {
|
||||
background-color: #ffffff !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.previous.disabled,
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.next.disabled {
|
||||
background-color: #ffffff !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.previous::before,
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.next::before {
|
||||
position: absolute !important;
|
||||
left: 50% !important;
|
||||
top: 50% !important;
|
||||
transform: translate(-50%, -50%) !important;
|
||||
line-height: 1 !important;
|
||||
font-size: 12px !important;
|
||||
display: block !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.previous:not(.disabled)::before {
|
||||
content: "◄";
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.next:not(.disabled)::before {
|
||||
content: "►";
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.previous.disabled::before {
|
||||
content: "◄";
|
||||
color: #adb5bd !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_paginate .paginate_button.next.disabled::before {
|
||||
content: "►";
|
||||
color: #adb5bd !important;
|
||||
}
|
||||
|
||||
/* Bootstrap nested markup: show arrow only on .page-link (avoid duplicate icon) */
|
||||
div.dataTables_wrapper .dataTables_paginate li.paginate_button.previous::before,
|
||||
div.dataTables_wrapper .dataTables_paginate li.paginate_button.next::before {
|
||||
content: none !important;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SECTION: Header cells — vertical alignment for label + sort icons
|
||||
* ----------------------------------------------------------------------------- */
|
||||
table.dataTable thead > tr > th {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
/* Optional wrapper used in some views — keep label from colliding with sort */
|
||||
table.dataTable thead th .column-header {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: 0;
|
||||
max-width: calc(100% - 40px);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SECTION: Last column — extra right inset (header sort + row actions)
|
||||
* Rounded teal header and “…” buttons were flush to the edge; this adds
|
||||
* breathing room on all listing tables using .dataTable.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
table.dataTable thead > tr > th:last-child,
|
||||
table.dataTable tbody > tr > td:last-child {
|
||||
padding-right: 1.35rem !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Action cells: only when the last column contains a Bootstrap dropdown (avoids
|
||||
* right-aligning numeric/text-only last columns on other listings).
|
||||
*/
|
||||
table.dataTable tbody > tr > td:last-child:has(.dropdown) {
|
||||
position: relative;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
table.dataTable tbody > tr > td:last-child:has(.dropdown) .btn-group.dropdown {
|
||||
display: inline-flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Action column — centered “…” / dropdown (opt-in per row)
|
||||
* Add class="table-action-cell" on the <td> that wraps .btn-group.dropdown
|
||||
* (any column position; overrides last-column right-align above).
|
||||
* ----------------------------------------------------------------------------- */
|
||||
table.dataTable tbody > tr > td.table-action-cell {
|
||||
text-align: center !important;
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
table.dataTable tbody > tr > td.table-action-cell .btn-group.dropdown {
|
||||
display: inline-flex !important;
|
||||
justify-content: center !important;
|
||||
float: none !important;
|
||||
margin-right: 0 !important; /* Prevent global dropdown margin shifting anchor */
|
||||
}
|
||||
|
||||
table.dataTable tbody > tr > td:last-child.table-action-cell:has(.dropdown),
|
||||
table.dataTable tbody > tr > td.table-action-cell:has(.dropdown) {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
table.dataTable tbody > tr > td:last-child.table-action-cell:has(.dropdown) .btn-group.dropdown {
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
/* Dropdown menu stacks above row borders / scroll quirks */
|
||||
div.dataTables_wrapper .dropdown-menu {
|
||||
z-index: 1050;
|
||||
}
|
||||
|
||||
/* Tbody row actions: static + optional .dropup from footer.js — menu stays inside .btn-group */
|
||||
div.dataTables_wrapper table.dataTable tbody .btn-group.dropdown {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper table.dataTable tbody .btn-group.dropdown .dropdown-menu {
|
||||
z-index: 1060;
|
||||
}
|
||||
|
||||
/* If global boundary=window ever added .position-static to a row dropdown parent, the menu
|
||||
loses its anchor; tbody row toggles use data-boundary="scrollParent" — this is a safety net. */
|
||||
div.dataTables_wrapper table.dataTable tbody .btn-group.dropdown.position-static {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SECTION: Sort arrows — stacked triangles (neutral / asc / desc)
|
||||
* ----------------------------------------------------------------------------- */
|
||||
table.dataTable thead > tr > th.sorting,
|
||||
table.dataTable thead > tr > th.sorting_asc,
|
||||
table.dataTable thead > tr > th.sorting_desc,
|
||||
table.dataTable thead > tr > th.sorting_asc_disabled,
|
||||
table.dataTable thead > tr > th.sorting_desc_disabled {
|
||||
position: relative !important;
|
||||
/* Room for stacked sort triangles + gap before cell edge */
|
||||
padding-right: 2.35rem !important;
|
||||
}
|
||||
|
||||
/* Reset theme font icons to CSS triangles */
|
||||
table.dataTable thead .sorting:before,
|
||||
table.dataTable thead .sorting_asc:before,
|
||||
table.dataTable thead .sorting_desc:before,
|
||||
table.dataTable thead .sorting_asc_disabled:before,
|
||||
table.dataTable thead .sorting_desc_disabled:before,
|
||||
table.dataTable thead .sorting:after,
|
||||
table.dataTable thead .sorting_asc:after,
|
||||
table.dataTable thead .sorting_desc:after,
|
||||
table.dataTable thead .sorting_asc_disabled:after,
|
||||
table.dataTable thead .sorting_desc_disabled:after {
|
||||
font-family: inherit !important;
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
border: none !important;
|
||||
bottom: auto !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* Up triangle */
|
||||
table.dataTable thead .sorting:before,
|
||||
table.dataTable thead .sorting_asc:before,
|
||||
table.dataTable thead .sorting_desc:before,
|
||||
table.dataTable thead .sorting_asc_disabled:before,
|
||||
table.dataTable thead .sorting_desc_disabled:before {
|
||||
content: "" !important;
|
||||
position: absolute;
|
||||
right: 0.85rem !important;
|
||||
left: auto !important;
|
||||
top: 50% !important;
|
||||
margin-top: -7px !important;
|
||||
border-left: 4px solid transparent !important;
|
||||
border-right: 4px solid transparent !important;
|
||||
border-bottom: 5px solid rgba(178, 235, 242, 0.95) !important;
|
||||
}
|
||||
|
||||
/* Down triangle */
|
||||
table.dataTable thead .sorting:after,
|
||||
table.dataTable thead .sorting_asc:after,
|
||||
table.dataTable thead .sorting_desc:after,
|
||||
table.dataTable thead .sorting_asc_disabled:after,
|
||||
table.dataTable thead .sorting_desc_disabled:after {
|
||||
content: "" !important;
|
||||
position: absolute;
|
||||
right: 0.85rem !important;
|
||||
left: auto !important;
|
||||
top: 50% !important;
|
||||
margin-top: 0 !important;
|
||||
border-left: 4px solid transparent !important;
|
||||
border-right: 4px solid transparent !important;
|
||||
border-top: 5px solid rgba(178, 235, 242, 0.95) !important;
|
||||
}
|
||||
|
||||
/* Active: ascending — strong up arrow */
|
||||
table.dataTable thead .sorting_asc:before {
|
||||
border-bottom-color: #ffffff !important;
|
||||
}
|
||||
table.dataTable thead .sorting_asc:after {
|
||||
border-top-color: rgba(255, 255, 255, 0.35) !important;
|
||||
}
|
||||
|
||||
/* Active: descending — strong down arrow */
|
||||
table.dataTable thead .sorting_desc:before {
|
||||
border-bottom-color: rgba(255, 255, 255, 0.35) !important;
|
||||
}
|
||||
table.dataTable thead .sorting_desc:after {
|
||||
border-top-color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* Sortable but not active */
|
||||
table.dataTable thead .sorting:before,
|
||||
table.dataTable thead .sorting:after {
|
||||
border-bottom-color: rgba(178, 235, 242, 0.95) !important;
|
||||
border-top-color: rgba(178, 235, 242, 0.95) !important;
|
||||
}
|
||||
|
||||
/* Compact table variant */
|
||||
table.dataTable.table-sm > thead > tr > th.sorting:before,
|
||||
table.dataTable.table-sm > thead > tr > th.sorting_asc:before,
|
||||
table.dataTable.table-sm > thead > tr > th.sorting_desc:before {
|
||||
margin-top: -7px !important;
|
||||
}
|
||||
|
||||
table.dataTable.table-sm > thead > tr > th.sorting:after,
|
||||
table.dataTable.table-sm > thead > tr > th.sorting_asc:after,
|
||||
table.dataTable.table-sm > thead > tr > th.sorting_desc:after {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Last header column only: sort triangles sit 2px from the inner right edge of
|
||||
* the <th> (all listing pages). Matches product ask: fixed 2px gap vs. rounded edge.
|
||||
*/
|
||||
table.dataTable thead > tr > th:last-child.sorting:before,
|
||||
table.dataTable thead > tr > th:last-child.sorting_asc:before,
|
||||
table.dataTable thead > tr > th:last-child.sorting_desc:before,
|
||||
table.dataTable thead > tr > th:last-child.sorting_asc_disabled:before,
|
||||
table.dataTable thead > tr > th:last-child.sorting_desc_disabled:before,
|
||||
table.dataTable thead > tr > th:last-child.sorting:after,
|
||||
table.dataTable thead > tr > th:last-child.sorting_asc:after,
|
||||
table.dataTable thead > tr > th:last-child.sorting_desc:after,
|
||||
table.dataTable thead > tr > th:last-child.sorting_asc_disabled:after,
|
||||
table.dataTable thead > tr > th:last-child.sorting_desc_disabled:after {
|
||||
right: 0.65rem !important;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SECTION: Compact spacing mode for all listing tables
|
||||
* Reduce extra white space around search/buttons/header/rows.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
/* Search input compact height */
|
||||
div.dataTables_wrapper .dataTables_filter input[type="search"] {
|
||||
height: 34px !important;
|
||||
min-height: 34px !important;
|
||||
padding-top: 0.28rem !important;
|
||||
padding-bottom: 0.28rem !important;
|
||||
}
|
||||
|
||||
/* DataTables buttons compact */
|
||||
div.dataTables_wrapper .dt-buttons .btn {
|
||||
padding-top: 0.34rem !important;
|
||||
padding-bottom: 0.34rem !important;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SECTION: Card-style listing rows
|
||||
* Markup: <table class="app-table-card" data-custom-table-css="table">
|
||||
* <tbody class="app-table-body">…</tbody>
|
||||
*
|
||||
* Why .app-table-card (not :has()):
|
||||
* - :has() is unsupported in some environments; when invalid, the whole rule
|
||||
* is dropped, so row gaps never apply.
|
||||
* - dataTables.bootstrap4 sets table.dataTable { border-spacing: 0 }; we need
|
||||
* a selector at least as specific as table.table.dataTable with !important.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
table[data-custom-table-css="table"].app-table-card.table.dataTable,
|
||||
table[data-custom-table-css="table"].app-table-card.table,
|
||||
table[data-custom-table-css="second-table"].app-table-card.table.dataTable,
|
||||
table[data-custom-table-css="second-table"].app-table-card.table {
|
||||
border-collapse: separate !important;
|
||||
border-spacing: 0 6px !important;
|
||||
}
|
||||
|
||||
table[data-custom-table-css="table"].app-table-card thead tr th:first-child,
|
||||
table[data-custom-table-css="second-table"].app-table-card thead tr th:first-child {
|
||||
border-top-left-radius: 12px !important;
|
||||
border-bottom-left-radius: 12px !important;
|
||||
}
|
||||
|
||||
table[data-custom-table-css="table"].app-table-card thead tr th:last-child,
|
||||
table[data-custom-table-css="second-table"].app-table-card thead tr th:last-child {
|
||||
border-top-right-radius: 12px !important;
|
||||
border-bottom-right-radius: 12px !important;
|
||||
}
|
||||
|
||||
table[data-custom-table-css="table"].app-table-card tbody.app-table-body > tr > td,
|
||||
table[data-custom-table-css="second-table"].app-table-card tbody.app-table-body > tr > td {
|
||||
background-color: #ffffff !important;
|
||||
border-style: solid !important;
|
||||
border-color: #e8ecef !important;
|
||||
border-width: 1px 0 !important;
|
||||
vertical-align: middle !important;
|
||||
transition: background-color 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
table[data-custom-table-css="table"].app-table-card tbody.app-table-body > tr > td:first-child,
|
||||
table[data-custom-table-css="second-table"].app-table-card tbody.app-table-body > tr > td:first-child {
|
||||
border-left-width: 1px !important;
|
||||
border-top-left-radius: 12px !important;
|
||||
border-bottom-left-radius: 12px !important;
|
||||
}
|
||||
|
||||
table[data-custom-table-css="table"].app-table-card tbody.app-table-body > tr > td:last-child,
|
||||
table[data-custom-table-css="second-table"].app-table-card tbody.app-table-body > tr > td:last-child {
|
||||
border-right-width: 1px !important;
|
||||
border-top-right-radius: 12px !important;
|
||||
border-bottom-right-radius: 12px !important;
|
||||
}
|
||||
|
||||
table[data-custom-table-css="table"].app-table-card tbody.app-table-body > tr:hover > td,
|
||||
table[data-custom-table-css="second-table"].app-table-card tbody.app-table-body > tr:hover > td {
|
||||
background-color: #f0fafb !important;
|
||||
border-color: #c5e6e8 !important;
|
||||
}
|
||||
|
||||
/* Reduce header/body padding globally for listing tables */
|
||||
table[data-custom-table-css="table"].dataTable thead th,
|
||||
table[data-custom-table-css="second-table"].dataTable thead th {
|
||||
padding-top: 10px !important;
|
||||
padding-bottom: 10px !important;
|
||||
/* Match body cell horizontal inset so header labels line up with td text */
|
||||
padding-left: 0.75rem !important;
|
||||
padding-right: 0.75rem !important;
|
||||
}
|
||||
|
||||
table[data-custom-table-css="table"] tbody td,
|
||||
table[data-custom-table-css="second-table"] tbody td {
|
||||
padding-top: 8px !important;
|
||||
padding-bottom: 8px !important;
|
||||
padding-left: 0.75rem !important;
|
||||
padding-right: 0.75rem !important;
|
||||
}
|
||||
|
||||
/* Keep listing text in single line (requested no-wrap). */
|
||||
div.dataTables_wrapper table.dataTable th,
|
||||
div.dataTables_wrapper table.dataTable td {
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
/* Keep horizontal + vertical scrolling behavior consistent across list pages. */
|
||||
div.dataTables_wrapper .dataTables_scrollHead,
|
||||
div.dataTables_wrapper .dataTables_scrollBody {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper .dataTables_scrollBody {
|
||||
overflow-x: auto !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bootstrap `.table-responsive` uses overflow-x: auto. Listing pages wrap the whole
|
||||
* `.dataTables_wrapper` (toolbar + scrollX area + pagination) in it, so the same div
|
||||
* gets a second horizontal scrollbar under the footer. Only `.dataTables_scrollBody`
|
||||
* should scroll horizontally — turn off outer overflow when a DT wrapper is inside.
|
||||
* Class is set from layout/footer.php on `init.dt`; `:has()` covers edge cases without JS.
|
||||
*/
|
||||
.table-responsive.nh-dt-no-outer-scroll,
|
||||
.table-responsive:has(.dataTables_wrapper) {
|
||||
overflow-x: visible !important;
|
||||
-webkit-overflow-scrolling: auto;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper {
|
||||
overflow-x: visible !important;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Let the middle row shrink inside flex layouts so the wrapper doesn’t widen the page */
|
||||
div.dataTables_wrapper > .row .dataTables_scroll {
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Reusable listing-table dropdown + footer spacing helpers */
|
||||
div.dataTables_wrapper .dataTables_scroll {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper > .row:last-child {
|
||||
clear: both;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper table.dataTable tbody tr.nh-force-dropup td.table-action-cell .btn-group.dropdown .dropdown-menu {
|
||||
top: auto !important;
|
||||
bottom: 100% !important;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0.15rem !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper table.dataTable tbody td.table-action-cell .dropdown-menu {
|
||||
background-color: #ffffff !important;
|
||||
opacity: 1 !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.12) !important;
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12) !important;
|
||||
z-index: 1080 !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper table.dataTable tbody td.table-action-cell .dropdown-menu .dropdown-item {
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper table.dataTable tbody td.table-action-cell .dropdown-menu .dropdown-item:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
|
||||
/* Row action menu: reusable click-to-open menu for list pages */
|
||||
table.nh-row-action-table tbody td.table-action-cell .action-menu-toggle {
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
padding: 2px 8px !important;
|
||||
color: #7a7a7a !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
table.nh-row-action-table tbody td.table-action-cell .action-menu-toggle:hover,
|
||||
table.nh-row-action-table tbody td.table-action-cell .action-menu-toggle:focus {
|
||||
background: #f3f6f9 !important;
|
||||
color: #495057 !important;
|
||||
}
|
||||
|
||||
table.nh-row-action-table tbody td.table-action-cell .action-menu-toggle i {
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
table.nh-row-action-table tbody .nh-row-action-menu {
|
||||
position: fixed !important;
|
||||
min-width: 190px;
|
||||
display: none;
|
||||
z-index: 1085 !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
table.nh-row-action-table tbody .nh-row-action-menu.show {
|
||||
display: block !important;
|
||||
bottom: auto !important;
|
||||
}
|
||||
|
||||
/* Force downward opening for custom row-action menu, even if legacy dropup classes exist */
|
||||
div.dataTables_wrapper table.nh-row-action-table tbody tr.nh-force-dropup td.table-action-cell .btn-group.dropdown .nh-row-action-menu,
|
||||
div.dataTables_wrapper table.nh-row-action-table tbody td.table-action-cell .btn-group.dropdown.dropup .nh-row-action-menu,
|
||||
div.dataTables_wrapper table.nh-row-action-table tbody td.table-action-cell .dropup .nh-row-action-menu {
|
||||
bottom: auto !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SECTION: Small screens — stack/center DataTables controls
|
||||
* ----------------------------------------------------------------------------- */
|
||||
@media (max-width: 767.98px) {
|
||||
div.dataTables_wrapper div.dataTables_filter,
|
||||
div.dataTables_wrapper div.dataTables_length,
|
||||
div.dataTables_wrapper div.dataTables_info,
|
||||
div.dataTables_wrapper div.dataTables_paginate {
|
||||
text-align: center !important;
|
||||
}
|
||||
div.dataTables_wrapper .dataTables_paginate ul.pagination {
|
||||
justify-content: center !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Last column sort: enough right padding so triangles are not flush to edge
|
||||
* (still respects th:last-child extra inset from “last column” section above).
|
||||
* ============================================================================ */
|
||||
table.dataTable thead > tr > th.sorting:last-child,
|
||||
table.dataTable thead > tr > th.sorting_asc:last-child,
|
||||
table.dataTable thead > tr > th.sorting_desc:last-child,
|
||||
table.dataTable thead > tr > th.sorting_asc_disabled:last-child,
|
||||
table.dataTable thead > tr > th.sorting_desc_disabled:last-child {
|
||||
padding-right: 2.35rem !important;
|
||||
}
|
||||
|
||||
table.dataTable thead > tr > th.sorting:last-child:before,
|
||||
table.dataTable thead > tr > th.sorting_asc:last-child:before,
|
||||
table.dataTable thead > tr > th.sorting_desc:last-child:before,
|
||||
table.dataTable thead > tr > th.sorting_asc_disabled:last-child:before,
|
||||
table.dataTable thead > tr > th.sorting_desc_disabled:last-child:before,
|
||||
table.dataTable thead > tr > th.sorting:last-child:after,
|
||||
table.dataTable thead > tr > th.sorting_asc:last-child:after,
|
||||
table.dataTable thead > tr > th.sorting_desc:last-child:after,
|
||||
table.dataTable thead > tr > th.sorting_asc_disabled:last-child:after,
|
||||
table.dataTable thead > tr > th.sorting_desc_disabled:last-child:after {
|
||||
right: 0.65rem !important;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user