Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
c22eebc96b
@ -1032,8 +1032,9 @@ class EmpDataServiceController extends BaseController
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//for cd tranction and cd master data is empty check
|
//for cd tranction and cd master data is empty check
|
||||||
if(!empty($inceptionData) && $inceptionData != null){
|
if(!empty($inceptionData) && $inceptionData != null || !empty($additionData) && $additionData != null || !empty($dependentAdditionData) && $dependentAdditionData != null){
|
||||||
|
|
||||||
$policy_details = $this->clientPolicyModel->where('id', $export_data['client_policy_id'])->first();
|
$policy_details = $this->clientPolicyModel->where('id', $export_data['client_policy_id'])->first();
|
||||||
|
|
||||||
@ -1065,6 +1066,14 @@ class EmpDataServiceController extends BaseController
|
|||||||
$totals = $totals + $item->total;
|
$totals = $totals + $item->total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($additionData as $item) {
|
||||||
|
$totals = $totals + $item->total;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($dependentAdditionData as $item) {
|
||||||
|
$totals = $totals + $item->total;
|
||||||
|
}
|
||||||
|
|
||||||
$totals = round($totals, 2);
|
$totals = round($totals, 2);
|
||||||
|
|
||||||
|
|
||||||
@ -1127,8 +1136,7 @@ class EmpDataServiceController extends BaseController
|
|||||||
AND `insurer_excel_export_template`.`type_name` = :type_name:
|
AND `insurer_excel_export_template`.`type_name` = :type_name:
|
||||||
LIMIT 1";
|
LIMIT 1";
|
||||||
|
|
||||||
$binds = ['client_policy_id' => (int)$export_data['client_policy_id'],
|
$binds = ['client_policy_id' => (int)$export_data['client_policy_id'],'type_name' => $export_data['actions']];
|
||||||
'type_name' => $export_data['actions']];
|
|
||||||
$query = db_connect()->query($sql,$binds);
|
$query = db_connect()->query($sql,$binds);
|
||||||
$template_json = $query->getRowArray();
|
$template_json = $query->getRowArray();
|
||||||
|
|
||||||
|
|||||||
@ -2028,6 +2028,35 @@ private function buildOppAchievement($db, array $sales_manager_ids, $branchId, s
|
|||||||
ORDER BY l.created_at DESC
|
ORDER BY l.created_at DESC
|
||||||
", [$uid, $fyStart, $fyEnd])->getResultArray();
|
", [$uid, $fyStart, $fyEnd])->getResultArray();
|
||||||
|
|
||||||
|
// ── Lost Leads for this user in FY (Opportunities tab — toggle off) ──
|
||||||
|
$lossLeads = $db->query("
|
||||||
|
SELECT
|
||||||
|
l.id AS opportunities_id,
|
||||||
|
l.actual_lead_id,
|
||||||
|
COALESCE(l.lead_form_type, 1) AS lead_form_type_id,
|
||||||
|
l.lead_type AS lead_type_id,
|
||||||
|
sal.company_name AS company,
|
||||||
|
l.client_name AS client_name,
|
||||||
|
CASE WHEN COALESCE(l.lead_form_type, 1) = 1 THEN 'EB' ELSE 'Non-EB' END AS lead_form_type,
|
||||||
|
CASE
|
||||||
|
WHEN l.lead_type = 1 THEN 'Fresh'
|
||||||
|
WHEN l.lead_type = 2 THEN 'Renewal'
|
||||||
|
WHEN l.lead_type = 3 THEN 'Roll Over'
|
||||||
|
ELSE ''
|
||||||
|
END AS lead_type,
|
||||||
|
l.created_at AS created_at,
|
||||||
|
l.status,
|
||||||
|
l.lost_reason AS lost_reason
|
||||||
|
FROM leads l
|
||||||
|
INNER JOIN sales_actual_leads sal
|
||||||
|
ON sal.lead_id = l.actual_lead_id
|
||||||
|
WHERE l.status = 'lost'
|
||||||
|
AND sal.assigned_to = ?
|
||||||
|
AND l.created_at >= ?
|
||||||
|
AND l.created_at <= ?
|
||||||
|
ORDER BY l.created_at DESC
|
||||||
|
", [$uid, $fyStart, $fyEnd])->getResultArray();
|
||||||
|
|
||||||
// -- NOTE: AND TRIM(sal.company_name) = TRIM(l.client_name)
|
// -- NOTE: AND TRIM(sal.company_name) = TRIM(l.client_name)
|
||||||
$result[$uid] = [
|
$result[$uid] = [
|
||||||
'total_policies' => $totalPolicies,
|
'total_policies' => $totalPolicies,
|
||||||
@ -2035,6 +2064,7 @@ private function buildOppAchievement($db, array $sales_manager_ids, $branchId, s
|
|||||||
'target_amt' => $targetAmt,
|
'target_amt' => $targetAmt,
|
||||||
'policies' => $policies,
|
'policies' => $policies,
|
||||||
'won_leads' => $wonLeads, // for Table 2 in modal Tab 2
|
'won_leads' => $wonLeads, // for Table 2 in modal Tab 2
|
||||||
|
'loss_leads' => $lossLeads,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,8 @@
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-hidden-accessible + .select2-container .select2-dropdown {
|
/* Hide dropdown list only for the insurer copy select (search-only UX) */
|
||||||
|
#insurer.select2-hidden-accessible + .select2-container .select2-dropdown {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,6 +54,14 @@
|
|||||||
z-index: 1060;
|
z-index: 1060;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#template_modal .select2-container {
|
||||||
|
z-index: 1061;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template_modal .select2-dropdown {
|
||||||
|
z-index: 1062;
|
||||||
|
}
|
||||||
|
|
||||||
#template_modal.show {
|
#template_modal.show {
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -276,6 +285,44 @@
|
|||||||
<script>
|
<script>
|
||||||
var insurerTemplateDataTable = null;
|
var insurerTemplateDataTable = null;
|
||||||
var templateDebugPrefix = '[InsurerTemplate]';
|
var templateDebugPrefix = '[InsurerTemplate]';
|
||||||
|
var insurerDbColumnOptions = <?= json_encode($db_column_name ?? [], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) ?>;
|
||||||
|
|
||||||
|
function buildDbColumnSelectOptions() {
|
||||||
|
var html = '<option value="" selected>Select</option>';
|
||||||
|
if (!insurerDbColumnOptions || typeof insurerDbColumnOptions !== 'object') {
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
Object.keys(insurerDbColumnOptions).forEach(function (label) {
|
||||||
|
var value = insurerDbColumnOptions[label];
|
||||||
|
html += '<option value="' + String(value).replace(/"/g, '"') + '">' + String(label).replace(/</g, '<') + '</option>';
|
||||||
|
});
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initDbColumnSelect2($select) {
|
||||||
|
if (!$select || !$select.length || typeof $.fn.select2 !== 'function') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($select.hasClass('select2-hidden-accessible')) {
|
||||||
|
$select.select2('destroy');
|
||||||
|
}
|
||||||
|
$select.select2({
|
||||||
|
placeholder: 'Select',
|
||||||
|
allowClear: true,
|
||||||
|
width: '100%',
|
||||||
|
dropdownParent: $('#template_modal')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function destroyDbColumnSelect2InContainer(container) {
|
||||||
|
var $container = container ? $(container) : $('#dynamic-form-container');
|
||||||
|
$container.find('.db-column-name-select').each(function () {
|
||||||
|
var $el = $(this);
|
||||||
|
if ($el.hasClass('select2-hidden-accessible')) {
|
||||||
|
$el.select2('destroy');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showTemplateModal() {
|
function showTemplateModal() {
|
||||||
var $modal = $('#template_modal');
|
var $modal = $('#template_modal');
|
||||||
@ -662,6 +709,7 @@
|
|||||||
input.preventDefault();
|
input.preventDefault();
|
||||||
}
|
}
|
||||||
$('#myCenterModalLabel').text('Create Template');
|
$('#myCenterModalLabel').text('Create Template');
|
||||||
|
destroyDbColumnSelect2InContainer();
|
||||||
$('#dynamic-form-container').empty();
|
$('#dynamic-form-container').empty();
|
||||||
addHTMLInput();
|
addHTMLInput();
|
||||||
showTemplateModal();
|
showTemplateModal();
|
||||||
@ -672,6 +720,10 @@
|
|||||||
const container = document.getElementById('dynamic-form-container');
|
const container = document.getElementById('dynamic-form-container');
|
||||||
const newRow = document.createElement('div');
|
const newRow = document.createElement('div');
|
||||||
newRow.className = 'form-row dynamic-form-row';
|
newRow.className = 'form-row dynamic-form-row';
|
||||||
|
const disableDbSelect = data !== null && data !== undefined && data !== '' && data.default_value != "" && data.default_value != null;
|
||||||
|
const headerValue = data !== null && data !== undefined && data !== '' ? (data.column_name || '') : '';
|
||||||
|
const defaultValue = data != null && data != undefined && data != '' && data.default_value != "" && data.default_value != null ? data.default_value : '';
|
||||||
|
|
||||||
newRow.innerHTML = `
|
newRow.innerHTML = `
|
||||||
<div class="mt-3 p-3" style="width: 100%; background: #F7F7F7;
|
<div class="mt-3 p-3" style="width: 100%; background: #F7F7F7;
|
||||||
border-radius: 30px !important;
|
border-radius: 30px !important;
|
||||||
@ -681,24 +733,19 @@
|
|||||||
">
|
">
|
||||||
<div class="form-group col-md-3">
|
<div class="form-group col-md-3">
|
||||||
<label for="db_column_name">DataBase Column Name<span class="text-danger"></span></label>
|
<label for="db_column_name">DataBase Column Name<span class="text-danger"></span></label>
|
||||||
<select class="form-control db-column-name-select dbColumn" name="db_column_name[]" onchange="checkForDuplicates(this); handleDbColumnChange(this)" ${data !== null && data !== undefined && data !== '' && data.default_value != "" && data.default_value != null ? 'disabled' : ''}>
|
<select class="form-control db-column-name-select" name="db_column_name[]" onchange="checkForDuplicates(this); handleDbColumnChange(this)"${disableDbSelect ? ' disabled' : ''}>
|
||||||
<option value="" selected >Select</option>
|
${buildDbColumnSelectOptions()}
|
||||||
<?php if (!empty($db_column_name)){ ?>
|
|
||||||
<?php foreach ($db_column_name as $key => $value) { ?>
|
|
||||||
<option value="<?= $value ?>"><?= $key ?></option>
|
|
||||||
<?php } ?>
|
|
||||||
<?php } ?>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group col-md-4">
|
<div class="form-group col-md-4">
|
||||||
<label for="excel_column_name">Header Name<span class="text-danger">*</span></label>
|
<label for="excel_column_name">Header Name<span class="text-danger">*</span></label>
|
||||||
<input id="excel_column_name" value="${data !== null && data !== undefined && data !== '' ? data.column_name : ''}" class="form-control" type="text" name="excel_column_name[]" placeholder="Excel Header Column Name">
|
<input id="excel_column_name" value="${headerValue}" class="form-control" type="text" name="excel_column_name[]" placeholder="Excel Header Column Name">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group col-md-3">
|
<div class="form-group col-md-3">
|
||||||
<label for="default_value">Default Value<span class="text-danger"></span></label>
|
<label for="default_value">Default Value<span class="text-danger"></span></label>
|
||||||
<input id="default_value" value="${data != null && data != undefined && data != '' && data.default_value != "" && data.default_value != null ? data.default_value : ''}" class="form-control" type="text" name="default_value[]" placeholder="Excel Default value">
|
<input id="default_value" value="${defaultValue}" class="form-control" type="text" name="default_value[]" placeholder="Excel Default value">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group col-md-2" style="position: relative;left: 28px;">
|
<div class="form-group col-md-2" style="position: relative;left: 28px;">
|
||||||
@ -708,13 +755,14 @@
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
container.appendChild(newRow);
|
container.appendChild(newRow);
|
||||||
|
var $dbSelect = $(newRow).find('.db-column-name-select');
|
||||||
if (data != null && data.db_column_name != undefined) {
|
if (data != null && data.db_column_name != undefined) {
|
||||||
const selectElement = newRow.querySelector('.db-column-name-select');
|
$dbSelect.val(data.db_column_name);
|
||||||
selectElement.value = data.db_column_name;
|
}
|
||||||
$('.dbColumn').select2();
|
initDbColumnSelect2($dbSelect);
|
||||||
|
if (data != null && data.db_column_name != undefined) {
|
||||||
|
$dbSelect.trigger('change');
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.dbColumn').select2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// function removeHTMLInput(element)
|
// function removeHTMLInput(element)
|
||||||
@ -731,6 +779,12 @@
|
|||||||
|
|
||||||
if (rows.length > 1) {
|
if (rows.length > 1) {
|
||||||
const row = element.closest('.dynamic-form-row');
|
const row = element.closest('.dynamic-form-row');
|
||||||
|
$(row).find('.db-column-name-select').each(function () {
|
||||||
|
var $el = $(this);
|
||||||
|
if ($el.hasClass('select2-hidden-accessible')) {
|
||||||
|
$el.select2('destroy');
|
||||||
|
}
|
||||||
|
});
|
||||||
row.remove();
|
row.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -813,6 +867,7 @@
|
|||||||
var data = JSON.parse(res.data.jsoncolumns)
|
var data = JSON.parse(res.data.jsoncolumns)
|
||||||
// console.log(JSON.parse(res.data.jsoncolumns));
|
// console.log(JSON.parse(res.data.jsoncolumns));
|
||||||
|
|
||||||
|
destroyDbColumnSelect2InContainer();
|
||||||
$('#dynamic-form-container').empty();
|
$('#dynamic-form-container').empty();
|
||||||
|
|
||||||
$.each(data, function(index, item) {
|
$.each(data, function(index, item) {
|
||||||
@ -855,6 +910,7 @@
|
|||||||
|
|
||||||
$('.close').click(function()
|
$('.close').click(function()
|
||||||
{
|
{
|
||||||
|
destroyDbColumnSelect2InContainer();
|
||||||
$('#dynamic-form-container').empty();
|
$('#dynamic-form-container').empty();
|
||||||
$('#policy_type').val('');
|
$('#policy_type').val('');
|
||||||
$('#event').val('').change();
|
$('#event').val('').change();
|
||||||
@ -926,9 +982,9 @@
|
|||||||
let $dbSelect = $row.find('select[name="db_column_name[]"]');
|
let $dbSelect = $row.find('select[name="db_column_name[]"]');
|
||||||
|
|
||||||
if ($defaultInput.val().trim() !== '') {
|
if ($defaultInput.val().trim() !== '') {
|
||||||
$dbSelect.val('').trigger('change').prop('disabled', true);
|
$dbSelect.val(null).trigger('change').prop('disabled', true);
|
||||||
} else {
|
} else {
|
||||||
$dbSelect.prop('disabled', false);
|
$dbSelect.prop('disabled', false).trigger('change');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1256,11 +1256,20 @@
|
|||||||
// Start the interval
|
// Start the interval
|
||||||
function startInterval() {
|
function startInterval() {
|
||||||
if (!submitInterval) {
|
if (!submitInterval) {
|
||||||
messageShown = false; // Reset message flag
|
messageShown = false;
|
||||||
|
|
||||||
submitInterval = setInterval(function() {
|
submitInterval = setInterval(function() {
|
||||||
checkCDBalance();
|
checkCDBalance();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
console.log("Checking CD balance started...");
|
console.log("Checking CD balance started...");
|
||||||
|
|
||||||
|
// Stop after 15 seconds
|
||||||
|
setTimeout(function() {
|
||||||
|
clearInterval(submitInterval);
|
||||||
|
submitInterval = null;
|
||||||
|
console.log("Checking CD balance stopped after 15 seconds.");
|
||||||
|
}, 15000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -230,6 +230,17 @@
|
|||||||
.opp-card { background: #f8fafd; border-radius: 12px; padding: 16px; border: 1px solid #e4eaf5; text-align: center; }
|
.opp-card { background: #f8fafd; border-radius: 12px; padding: 16px; border: 1px solid #e4eaf5; text-align: center; }
|
||||||
.opp-card-val { font-size: 22px; font-weight: 800; color: #0f172a; }
|
.opp-card-val { font-size: 22px; font-weight: 800; color: #0f172a; }
|
||||||
.opp-card-lbl { font-size: 11px; color: #7c8db0; font-weight: 700; margin-top: 4px; letter-spacing: .04em; }
|
.opp-card-lbl { font-size: 11px; color: #7c8db0; font-weight: 700; margin-top: 4px; letter-spacing: .04em; }
|
||||||
|
.opp-section-head { display: flex; justify-content: space-between; align-items: center; margin: 24px 0 12px; gap: 12px; flex-wrap: wrap; }
|
||||||
|
.opp-section-head .split-section-title { margin: 0; }
|
||||||
|
.opp-toggle-wrap { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
|
||||||
|
.opp-toggle-lbl { font-size: 12px; font-weight: 700; color: #94a3b8; transition: color .2s; }
|
||||||
|
.opp-toggle-lbl.active { color: #0f172a; }
|
||||||
|
.opp-toggle-switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; }
|
||||||
|
.opp-toggle-switch input { opacity: 0; width: 0; height: 0; }
|
||||||
|
.opp-toggle-slider { position: absolute; cursor: pointer; inset: 0; background: #cbd5e1; border-radius: 99px; transition: background .2s; }
|
||||||
|
.opp-toggle-slider::before { content: ""; position: absolute; height: 18px; width: 18px; left: 3px; bottom: 3px; background: #fff; border-radius: 50%; transition: transform .2s; box-shadow: 0 1px 3px rgba(15,23,42,0.15); }
|
||||||
|
.opp-toggle-switch input:checked + .opp-toggle-slider { background: #4f46e5; }
|
||||||
|
.opp-toggle-switch input:checked + .opp-toggle-slider::before { transform: translateX(20px); }
|
||||||
|
|
||||||
@media(max-width:900px) { .list-col-head,.achieve-row { grid-template-columns: 220px 1fr 110px 110px 110px; } .col-lbl:nth-child(6),.col-lbl:nth-child(7),.achieve-row>*:nth-child(6),.achieve-row>*:nth-child(7) { display: none; } }
|
@media(max-width:900px) { .list-col-head,.achieve-row { grid-template-columns: 220px 1fr 110px 110px 110px; } .col-lbl:nth-child(6),.col-lbl:nth-child(7),.achieve-row>*:nth-child(6),.achieve-row>*:nth-child(7) { display: none; } }
|
||||||
@media(max-width:640px) { .list-col-head { display: none; } .achieve-row { grid-template-columns: 1fr auto; gap: 12px; padding: 14px 16px; } .achieve-row>*:not(:nth-child(1)):not(:nth-child(7)) { display: none; } .section-head { flex-direction: column; align-items: flex-start; gap: 12px; } .modal-summary { grid-template-columns: repeat(2,1fr); } .target-edit-panel { grid-template-columns: 1fr; } .opp-summary-cards { grid-template-columns: 1fr 1fr; } }
|
@media(max-width:640px) { .list-col-head { display: none; } .achieve-row { grid-template-columns: 1fr auto; gap: 12px; padding: 14px 16px; } .achieve-row>*:not(:nth-child(1)):not(:nth-child(7)) { display: none; } .section-head { flex-direction: column; align-items: flex-start; gap: 12px; } .modal-summary { grid-template-columns: repeat(2,1fr); } .target-edit-panel { grid-template-columns: 1fr; } .opp-summary-cards { grid-template-columns: 1fr 1fr; } }
|
||||||
@ -502,7 +513,9 @@ const TEAM = <?php echo json_encode($team_achievement ?? []); ?>;
|
|||||||
const OPP_DATA = <?php echo json_encode($opp_achievement ?? []); ?>;
|
const OPP_DATA = <?php echo json_encode($opp_achievement ?? []); ?>;
|
||||||
/* OPP_DATA shape per userId:
|
/* OPP_DATA shape per userId:
|
||||||
{ total_policies, total_exp_amt, target_amt,
|
{ total_policies, total_exp_amt, target_amt,
|
||||||
policies: [{ policy_no, issue_date, amount, created_at }] } */
|
policies: [{ policy_no, issue_date, amount, created_at }],
|
||||||
|
won_leads: [...], loss_leads: [...] } */
|
||||||
|
let currentModalOppUserId = null;
|
||||||
|
|
||||||
/* ── JS Helpers ── */
|
/* ── JS Helpers ── */
|
||||||
const ACT_ICONS = {Call:'📞',Email:'✉️',Meeting:'📅',Visit:'🚗',Demo:'🖥️','Share Docs':'📄','To Do':'✓'};
|
const ACT_ICONS = {Call:'📞',Email:'✉️',Meeting:'📅',Visit:'🚗',Demo:'🖥️','Share Docs':'📄','To Do':'✓'};
|
||||||
@ -545,6 +558,89 @@ function redirectToOpportunity(leadTypeId, actualLeadId, opportunityId) {
|
|||||||
+ encodeURIComponent(opportunityId);
|
+ encodeURIComponent(opportunityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function escOppCell(text) {
|
||||||
|
return String(text ?? '')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateOppTableHeader(showWon) {
|
||||||
|
const headRow = document.getElementById('oppTableHead');
|
||||||
|
if (!headRow) return;
|
||||||
|
|
||||||
|
if (showWon) {
|
||||||
|
headRow.innerHTML =
|
||||||
|
'<th>Company</th>'
|
||||||
|
+ '<th>Opportunity Type</th>'
|
||||||
|
+ '<th>Date</th>';
|
||||||
|
} else {
|
||||||
|
headRow.innerHTML =
|
||||||
|
'<th>Company</th>'
|
||||||
|
+ '<th>Opportunity Type</th>'
|
||||||
|
+ '<th>Lost Reason</th>'
|
||||||
|
+ '<th>Date</th>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildOpportunityTableRows(leads, showWon) {
|
||||||
|
return (leads || []).map(function(l) {
|
||||||
|
const opportunityType = [
|
||||||
|
l.lead_form_type || '',
|
||||||
|
].filter(Boolean).join('').toUpperCase();
|
||||||
|
const typeBadgeClass = l.lead_form_type === 'EB'
|
||||||
|
? 'style="background:#eff6ff;color:#2563eb;padding:3px 10px;border-radius:99px;font-size:11px;font-weight:700;"'
|
||||||
|
: 'style="background:#f0fdf4;color:#16a34a;padding:3px 10px;border-radius:99px;font-size:11px;font-weight:700;"';
|
||||||
|
const canRedirect = l.lead_form_type_id && l.actual_lead_id && l.opportunities_id;
|
||||||
|
const rowAttrs = canRedirect
|
||||||
|
? ' class="won-opportunity-row" title="Open opportunity" onclick=\'redirectToOpportunity('
|
||||||
|
+ JSON.stringify(String(l.lead_form_type_id)) + ','
|
||||||
|
+ JSON.stringify(String(l.actual_lead_id)) + ','
|
||||||
|
+ JSON.stringify(String(l.opportunities_id)) + ')\''
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const lostReasonCell = showWon ? '' :
|
||||||
|
'<td style="font-size:12px;color:#64748b;max-width:220px;white-space:normal;">'
|
||||||
|
+ escOppCell((l.lost_reason || '').trim() || '—')
|
||||||
|
+ '</td>';
|
||||||
|
|
||||||
|
return '<tr' + rowAttrs + '>'
|
||||||
|
+ '<td style="font-weight:700;color:#0f172a;">' + escOppCell(l.company || '—') + '</td>'
|
||||||
|
+ '<td><span ' + typeBadgeClass + '>' + (opportunityType || '—') + '</span></td>'
|
||||||
|
+ lostReasonCell
|
||||||
|
+ '<td style="font-size:12px;color:#64748b;">' + fmtCreatedAt(l.created_at) + '</td>'
|
||||||
|
+ '</tr>';
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateOppToggleLabels(showWon) {
|
||||||
|
const lostLbl = document.getElementById('oppToggleLblLost');
|
||||||
|
const wonLbl = document.getElementById('oppToggleLblWon');
|
||||||
|
if (lostLbl) lostLbl.classList.toggle('active', !showWon);
|
||||||
|
if (wonLbl) wonLbl.classList.toggle('active', showWon);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderOpportunitiesTable(userId, showWon) {
|
||||||
|
const opp = OPP_DATA[userId];
|
||||||
|
const tbody = document.getElementById('oppTableBody');
|
||||||
|
if (!tbody || !opp) return;
|
||||||
|
|
||||||
|
const leads = showWon ? (opp.won_leads || []) : (opp.loss_leads || []);
|
||||||
|
const colSpan = showWon ? 3 : 4;
|
||||||
|
updateOppTableHeader(showWon);
|
||||||
|
const rows = buildOpportunityTableRows(leads, showWon);
|
||||||
|
const emptyMsg = showWon ? 'No won opportunities found' : 'No lost opportunities found';
|
||||||
|
tbody.innerHTML = rows || '<tr><td colspan="' + colSpan + '" style="text-align:center;color:#aaa;padding:24px;">' + emptyMsg + '</td></tr>';
|
||||||
|
updateOppToggleLabels(showWon);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOppStatusToggle(checked) {
|
||||||
|
if (currentModalOppUserId) {
|
||||||
|
renderOpportunitiesTable(currentModalOppUserId, checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function goSalesPage(page, status, memberId) {
|
function goSalesPage(page, status, memberId) {
|
||||||
const url = new URL(page === 'activities' ? SALES_ACTIVITIES_URL : SALES_LEADS_URL, window.location.origin);
|
const url = new URL(page === 'activities' ? SALES_ACTIVITIES_URL : SALES_LEADS_URL, window.location.origin);
|
||||||
url.searchParams.set('fy', getSelectedDashboardFY());
|
url.searchParams.set('fy', getSelectedDashboardFY());
|
||||||
@ -939,48 +1035,33 @@ function openModal(id) {
|
|||||||
// + '</table>'
|
// + '</table>'
|
||||||
// + '</div>';
|
// + '</div>';
|
||||||
|
|
||||||
/* ── Won Leads Table (Table 2) ── */
|
currentModalOppUserId = id;
|
||||||
const wonLeads = opp.won_leads || [];
|
|
||||||
const wonRows = wonLeads.map(function(l) {
|
|
||||||
// const opportunityType = [
|
|
||||||
// l.lead_form_type || '',
|
|
||||||
// l.lead_type || ''
|
|
||||||
// ].filter(Boolean).join('/').toUpperCase();
|
|
||||||
const opportunityType = [
|
|
||||||
l.lead_form_type || '',
|
|
||||||
].filter(Boolean).join('').toUpperCase();
|
|
||||||
const typeBadgeClass = l.lead_form_type === 'EB'
|
|
||||||
? 'style="background:#eff6ff;color:#2563eb;padding:3px 10px;border-radius:99px;font-size:11px;font-weight:700;"'
|
|
||||||
: 'style="background:#f0fdf4;color:#16a34a;padding:3px 10px;border-radius:99px;font-size:11px;font-weight:700;"';
|
|
||||||
const canRedirect = l.lead_form_type_id && l.actual_lead_id && l.opportunities_id;
|
|
||||||
const rowAttrs = canRedirect
|
|
||||||
? ' class="won-opportunity-row" title="Open opportunity" onclick=\'redirectToOpportunity('
|
|
||||||
+ JSON.stringify(String(l.lead_form_type_id)) + ','
|
|
||||||
+ JSON.stringify(String(l.actual_lead_id)) + ','
|
|
||||||
+ JSON.stringify(String(l.opportunities_id)) + ')\''
|
|
||||||
: '';
|
|
||||||
|
|
||||||
return '<tr' + rowAttrs + '>'
|
|
||||||
+ '<td style="font-weight:700;color:#0f172a;">' + (l.company || '—') + '</td>'
|
|
||||||
+ '<td><span ' + typeBadgeClass + '>' + (opportunityType || '—') + '</span></td>'
|
|
||||||
+ '<td style="font-size:12px;color:#64748b;">' + fmtCreatedAt(l.created_at) + '</td>'
|
|
||||||
+ '</tr>';
|
|
||||||
}).join('');
|
|
||||||
|
|
||||||
tab2Html +=
|
tab2Html +=
|
||||||
'<div class="split-section-title" style="margin-top:24px;"> Opportunities </div>'
|
'<div class="opp-section-head">'
|
||||||
|
+ '<div class="split-section-title">Opportunities</div>'
|
||||||
|
+ '<div class="opp-toggle-wrap">'
|
||||||
|
+ '<span class="opp-toggle-lbl" id="oppToggleLblLost">Lost</span>'
|
||||||
|
+ '<label class="opp-toggle-switch" title="Toggle between won and lost opportunities">'
|
||||||
|
+ '<input type="checkbox" id="oppStatusToggle" checked onchange="onOppStatusToggle(this.checked)">'
|
||||||
|
+ '<span class="opp-toggle-slider"></span>'
|
||||||
|
+ '</label>'
|
||||||
|
+ '<span class="opp-toggle-lbl active" id="oppToggleLblWon">Won</span>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '</div>'
|
||||||
+ '<div style="overflow-x:auto;">'
|
+ '<div style="overflow-x:auto;">'
|
||||||
+ '<table class="split-table">'
|
+ '<table class="split-table">'
|
||||||
+ '<thead><tr>'
|
+ '<thead><tr id="oppTableHead">'
|
||||||
+ '<th>Company</th>'
|
+ '<th>Company</th>'
|
||||||
+ '<th>Opportunity Type</th>'
|
+ '<th>Opportunity Type</th>'
|
||||||
+ '<th>Date</th>'
|
+ '<th>Date</th>'
|
||||||
+ '</tr></thead>'
|
+ '</tr></thead>'
|
||||||
+ '<tbody>' + (wonRows || '<tr><td colspan="3" style="text-align:center;color:#aaa;padding:24px;">No leads found</td></tr>') + '</tbody>'
|
+ '<tbody id="oppTableBody"></tbody>'
|
||||||
+ '</table>'
|
+ '</table>'
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
currentModalOppUserId = null;
|
||||||
tab2Html = '<div class="empty-state"><div class="empty-icon">📋</div>No opportunities data available</div>';
|
tab2Html = '<div class="empty-state"><div class="empty-icon">📋</div>No opportunities data available</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -996,6 +1077,14 @@ function openModal(id) {
|
|||||||
|
|
||||||
document.getElementById('modalOverlay').classList.add('open');
|
document.getElementById('modalOverlay').classList.add('open');
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
|
|
||||||
|
if (currentModalOppUserId && OPP_DATA[currentModalOppUserId]) {
|
||||||
|
const toggle = document.getElementById('oppStatusToggle');
|
||||||
|
if (toggle) toggle.checked = true;
|
||||||
|
renderOpportunitiesTable(currentModalOppUserId, true);
|
||||||
|
} else {
|
||||||
|
currentModalOppUserId = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchTab(idx, btn) {
|
function switchTab(idx, btn) {
|
||||||
@ -1007,6 +1096,7 @@ function switchTab(idx, btn) {
|
|||||||
function closeModal() {
|
function closeModal() {
|
||||||
document.getElementById('modalOverlay').classList.remove('open');
|
document.getElementById('modalOverlay').classList.remove('open');
|
||||||
document.body.style.overflow = '';
|
document.body.style.overflow = '';
|
||||||
|
currentModalOppUserId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('modalOverlay').addEventListener('click', function(e) { if (e.target === e.currentTarget) closeModal(); });
|
document.getElementById('modalOverlay').addEventListener('click', function(e) { if (e.target === e.currentTarget) closeModal(); });
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user