Merge branch 'dev' of bitbucket.org:jubilian/nhance into dev

This commit is contained in:
vadivelJ96 2025-08-29 12:56:48 +05:30
commit bb212d64f0
7 changed files with 239 additions and 53 deletions

View File

@ -369,6 +369,7 @@ $routes->group("/util", ["filter" => "authMVC"], function ($routes) {
$routes->get('getPolicyTypeFields', 'LeadsController::getPolicyTypeFields');
$routes->get('removeMultiFile', 'LeadsController::removeMultiFile');
$routes->get('removeInstallments', 'LeadsController::removeInstallments');
$routes->get('getLeadEmailHistory/(:any)', 'LeadsController::getLeadEmailHistory/$1');
$routes->get('viewHrAccessData', 'ClientController::viewHrAccessData');
$routes->post('saveHrAccessData', 'ClientController::saveHrAccessData');
$routes->get('removeLevelContacts', 'ClientController::removeLevelContacts');

View File

@ -31,6 +31,7 @@ use App\Models\InsurerModel;
use App\Models\OccupancyMasterModel;
use App\Models\LeadFilesModel;
use App\Models\LeadInstallmentPaymentDetails;
use App\Models\GmailSentHistoryModel;
use App\Helpers\MailHelper;
use App\Helpers\ExcelMergeHelper;
@ -70,6 +71,7 @@ class LeadsController extends BaseController
protected $occupancyModel;
protected $leadFilesModel;
protected $leadInstallmentPaymentDetails;
protected $gmailSentHistoryModel;
//variables for storing array
protected $issuer;
@ -102,6 +104,7 @@ class LeadsController extends BaseController
$this->occupancyModel = new OccupancyMasterModel();
$this->leadFilesModel = new LeadFilesModel();
$this->leadInstallmentPaymentDetails = new LeadInstallmentPaymentDetails();
$this->gmailSentHistoryModel = new GmailSentHistoryModel();
$this->issuer = [1 => 'JIBS', 2 => 'Nhance'];
$this->clientType = [1 => 'Group', 2 => 'Individual'];
@ -3668,6 +3671,27 @@ class LeadsController extends BaseController
return $this->loadLayout('leads_form_handler', $data);
}
public function getLeadEmailHistory($id){
if(!empty($id)){
$result = $this->gmailSentHistoryModel
->where('pk', $id)
->where('module',"leads")
->findAll();
if(!empty($result)){
$result = !empty($result) ? $result : [];
return $this->response->setJSON((['status' => 'success', 'data' => $result]))->setStatusCode(200);
}else{
return $this->response->setJSON((['status' => 'error', 'message' => 'No History found']))->setStatusCode(400);
}
}else{
return $this->response->setJSON((['status' => 'error', 'message' => 'ID not found']))->setStatusCode(404);
}
// Select * from gmail_sent_history where pk != "" and module = "leads";
// echo $id;
}
public function getPolicyTypeFields()
{

View File

@ -680,11 +680,10 @@ a.app-badge-secondary:focus, a.app-badge-secondary.focus {
.app-table-body td {
background: #F5FFFF;
padding: 12px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
border-top: 0px solid #fff !important;
border-bottom: 0px solid #fff !important;
}
.app-table-head th:first-child {
border-top-left-radius: 15px !important;
border-bottom-left-radius: 15px !important;
@ -694,7 +693,6 @@ a.app-badge-secondary:focus, a.app-badge-secondary.focus {
border-bottom-right-radius: 15px !important;
}
.app-table-body tr td:first-child {
border-top-left-radius: 15px !important;
border-bottom-left-radius: 15px !important;
@ -704,6 +702,15 @@ a.app-badge-secondary:focus, a.app-badge-secondary.focus {
border-bottom-right-radius: 15px !important;
}
.app-table-body tr:hover td {
background-color: #e0e0e0;
}
.app-datatable {
border-collapse: separate !important;
border-spacing: 0 8px !important; /* space between rows */
width: 100%;
}
</style>

View File

@ -215,6 +215,12 @@ table.dataTable tbody td {
</a>
<?php } ?>
<?php } ?>
<a href="javascript:void(0);"
class="dropdown-item btnHistory app-text-black"
data-id="<?= $row['id']; ?>"
title="Click to view Mail History">
<i class="mdi mdi-history mr-2 text-muted font-18 vertical-middle"></i>Email History
</a>
</div>
</div>
</td>
@ -266,6 +272,22 @@ table.dataTable tbody td {
</div>
</div>
<div class="modal fade app-font-family" id="EmailModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl" style="max-width: 1140px !important;">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Email History</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body history-container" style="padding:11px !important;">
</div>
</div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
@ -442,6 +464,146 @@ document.addEventListener("DOMContentLoaded", function () {
}
</script>
<script>
document.addEventListener("click", function(e) {
if (e.target.closest(".btnHistory")) {
let lead_id = e.target.closest(".btnHistory").dataset.id;
console.log("*********" + lead_id);
let url = '<?= base_url('/util/getLeadEmailHistory/') ?>' + lead_id;
console.log("*********" + url);
fetch('<?= base_url('/util/getLeadEmailHistory/') ?>' + lead_id, {
method: "GET",
headers: {
"Accept": "application/json"
}
})
.then(response => response.json())
.then(response => {
let container = document.querySelector(".history-container");
container.innerHTML = ""; // clear old content
if (response.status === "success" && response.data.length > 0) {
console.log("******** 1" + response.status);
let table = `
<div class="table-responsive">
<table id="historytable" class="table table-striped 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">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>
</tr>
</thead>
<tbody>
`;
response.data.forEach((row, index) => {
let formattedDate = "-";
let statusValue = "-";
if (row.received_message) {
if (row.received_message.toLowerCase().includes("error")) {
statusValue = "Failed";
} else {
statusValue = "Success";
}
}
if (row.created_at) {
let dt = new Date(row.created_at);
let dateStr = dt.toLocaleDateString("en-GB", {
day: "2-digit",
month: "long",
year: "numeric"
});
let timeStr = dt.toLocaleTimeString("en-US", {
hour: "2-digit",
minute: "2-digit",
hour12: true
}).toLowerCase();
formattedDate = `${dateStr} ${timeStr}`;
}
let fromMails = "-";
if (row.from_mail) {
fromMails = row.from_mail
.split(",") // split by comma
.map(m => m.trim().replace(/^"|"$/g, "")) // trim + remove quotes at start/end
.filter(m => m !== "") // remo
.join("<br>"); // join with line break
}
let toMails = "-";
if (row.mail) {
toMails = row.mail
.split(",")
.map(m => m.trim().replace(/^"|"$/g, ""))
.filter(m => m !== "")
.join("<br>");
}
let ccMails = "-";
if (row.cc && row.cc.trim() !== "") {
ccMails = row.cc
.split(",")
.map(m => m.trim().replace(/^"|"$/g, ""))
.filter(m => m !== "")
.join("<br>");
}
let bccMails = "-";
if (row.bcc && row.bcc.trim() !== "") {
bccMails = row.bcc
.split(",")
.map(m => m.trim().replace(/^"|"$/g, ""))
.filter(m => m !== "")
.join("<br>");
}
table += `
<tr>
<td style="white-space: nowrap !important;">${index + 1}</td>
<td style="white-space: nowrap !important;">${fromMails}</td>
<td style="white-space: nowrap !important;">${toMails}</td>
<td style="white-space: nowrap !important;">${bccMails ? bccMails : '-'}</td>
<td style="white-space: nowrap !important;">${ccMails ? ccMails : '-'}</td>
<td style="white-space: nowrap !important;">${row.mail_type ? row.mail_type.toUpperCase() : '-'}</td>
<td style="white-space: nowrap !important;">${statusValue ? statusValue.toUpperCase() : '-'}</td>
<td style="white-space: nowrap !important;">${formattedDate}</td>
</tr>
`;
});
table += `</tbody></table>`;
container.innerHTML = table;
} else {
console.log("******** 2" + response.status);
container.innerHTML = `
<div class="d-flex justify-content-center align-items-center" style="height: 50vh; width:100%;">
<p class="text-center"><i>${response.message ?? 'No history found'}</i></p>
</div>
`;
}
// show modal (if using Bootstrap 5)
let EmailModal = new bootstrap.Modal(document.getElementById("EmailModal"));
EmailModal.show();
})
.catch(error => {
console.log("******** 3" + error);
document.querySelector(".history-container").innerHTML = `
<div class="d-flex justify-content-center align-items-center" style="height: 50vh; width:100%;">
<p class="text-center"><i>No Data Found</i></p>
</div>
`;
let EmailModal = new bootstrap.Modal(document.getElementById("EmailModal"));
EmailModal.show();
console.error(error);
});
}
});
</script>
<script>
function selectOption(element, radioId) {
// Remove selected class from all options
@ -469,4 +631,4 @@ document.addEventListener("DOMContentLoaded", function () {
});
});
</script>
</script>

View File

@ -18,17 +18,11 @@ tbody tr {
/* box-shadow: 0 2px 5px rgba(0,0,0,0.08); */
}
/* Hover effect */
#scroll-horizontal-datatable tbody tr:hover td {
background-color: #e0e0e0;
}
/* Search input with icon */
.dataTables_filter {
position: absolute;
}
.dataTables_filter input {
padding-right: 30px;
background: url('https://cdn.jsdelivr.net/npm/@mdi/svg/svg/magnify.svg') no-repeat right 8px center;
@ -212,7 +206,7 @@ table thead th {
</div>
</div>
<div>
<table id="scroll-horizontal-datatable" class="table w-100 nowrap text-custom-black text-custom app-font-family">
<table id="scroll-horizontal-datatable" class="table w-100 nowrap text-custom-black text-custom app-font-family app-datatable">
<thead class="app-table-head">
<tr>
<th>Ticket ID</th>

View File

@ -1,12 +1,4 @@
<style>
#historytable thead{
background-color: #00999E;
color: #ffffff !important;
}
#historytable tbody tr:hover td {
background-color: #e0e0e0;
}
.notes-box {
display: flex;
@ -413,7 +405,7 @@ hr{
<?php if(!empty($related_tickets)): foreach($related_tickets as $j => $rt): ?>
<div class="card related-ticket-card app-font-family app-text"
style="cursor: pointer;"
onclick="window.location='<?= base_url().'/ticketConversationList?return_type=web&thz_id='.$rt['thz_id']; ?>'">
onclick="window.open('<?= base_url().'/ticketConversationList?return_type=web&thz_id='.$rt['thz_id']; ?>', '_blank')">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center" style="margin-bottom: 10px !important;">
<h5 class="app-font-family app-text"><?php echo '# '.$rt['thz_id']." / ".$rt['ticket_type']; ?></h5>
@ -471,7 +463,8 @@ hr{
</div>
<div class="modal fade app-font-family" id="StatusModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-dialog modal-dialog-centered modal-lg" >
<!-- style="max-width: 775px !important;"> -->
<div class="modal-content" style="border-radius:15px;">
<div class="modal-header" style="border-bottom-width:0;">
@ -618,33 +611,34 @@ function statusHistory(thzId) {
if (response.status === "success" && response.data.length > 0) {
let table = `
<table id="historytable" class="table table-bordered table-sm app-font-family">
<thead>
<div class="table-responsive">
<table class="table w-100 nowrap text-custom-black text-custom app-font-family app-datatable">
<thead class="app-table-head">
<tr>
<th class="app-text-white">S.No</th>
<th class="app-text-white">Old Value</th>
<th class="app-text-white">New Value</th>
<th class="app-text-white">Updated By</th>
<th class="app-text-white">Date/Time</th>
<th class="app-text app-text-white">S.No</th>
<th class="app-text app-text-white">Old Status</th>
<th class="app-text app-text-white">New Status</th>
<th class="app-text app-text-white">Updated By</th>
<th class="app-text app-text-white">Date/Time</th>
</tr>
</thead>
<tbody>
<tbody class="app-table-body">
`;
response.data.forEach((row, index) => {
table += `
<tr>
<td style="text-align:left; vertical-align:middle;">${index + 1}</td>
<td style="text-align:left; vertical-align:middle;">${row.old_value ?? '-'}</td>
<td style="text-align:left; vertical-align:middle;">${row.new_value ?? '-'}</td>
<td style="text-align:left; vertical-align:middle;">${row.created_name ?? '-'}</td>
<td style="text-align:left; vertical-align:middle;">${row.created_at
<td class="app-text" style="text-align:left; vertical-align:middle;">${index + 1}</td>
<td class="app-text" style="text-align:left; vertical-align:middle;">${row.old_value ?? '-'}</td>
<td class="app-text" style="text-align:left; vertical-align:middle;">${row.new_value ?? '-'}</td>
<td class="app-text" style="text-align:left; vertical-align:middle;">${row.created_name ?? '-'}</td>
<td class="app-text" style="text-align:left; vertical-align:middle;">${row.created_at
? (() => {
let dt = new Date(row.created_at);
let dateStr = dt.toLocaleDateString('en-GB', {
day: '2-digit',
month: '2-digit',
month: 'long',
year: 'numeric'
});
@ -654,7 +648,7 @@ function statusHistory(thzId) {
hour12: true
}).toLowerCase();
return `${dateStr}<br>${timeStr}`;
return `${dateStr} ${timeStr}`;
})()
: '-'
}</td>
@ -662,7 +656,7 @@ function statusHistory(thzId) {
`;
});
table += `</tbody></table>`;
table += `</tbody></table></div>`;
container.html(table);
} else {
container.html(`

View File

@ -79,8 +79,8 @@
<label>Employee Data Points</label>
<select name="employee_data_points" id="employee_data_points"
class="form-control">
<option value="mobile">Mobile Number</option>
<option value="emp_code">Employee ID</option>
<option value="mobile">Mobile Number</option>
</select>
</div>
</div>
@ -251,6 +251,20 @@
})
$('#employee_data_points').on('change', function() {
let value = $(this).val();
let $label = $('#employee_data_points_label');
let $input = $('#emp_mobile_number_for_claim');
if (value == "mobile") {
$label.text('Employee Mobile Number');
$input.attr('onkeypress', 'return onlyNumbers(event)').attr('maxlength', '10');
} else {
$label.text('Employee ID');
$input.removeAttr('onkeypress maxlength');
}
});
})
function toggleAccordion(id) {
@ -259,6 +273,9 @@
// Define the other accordion to close
const otherId = id === 'mobileAccordion' ? 'clientBranchAccordion' : 'mobileAccordion';
if(id === 'mobileAccordion'){
$('#employee_data_points').trigger('change');
}
const otherContent = document.getElementById(otherId);
const otherArrow = document.querySelector(`#${id === 'mobileAccordion' ? 'clientBranchArrow' : 'mobileArrow'}`);
@ -905,19 +922,6 @@
// }
// })
$('#employee_data_points').on('change', function() {
let value = $(this).val();
let $label = $('#employee_data_points_label');
let $input = $('#emp_mobile_number_for_claim');
if (value == "mobile") {
$label.text('Employee Mobile Number');
$input.attr('onkeypress', 'return onlyNumbers(event)').attr('maxlength', '10');
} else {
$label.text('Employee ID');
$input.removeAttr('onkeypress maxlength');
}
});
function toResetTheModelFields() {