1092 lines
42 KiB
PHP
1092 lines
42 KiB
PHP
<style>
|
|
.table th,
|
|
.table td {
|
|
padding: 8px;
|
|
}
|
|
|
|
table.dataTable tbody td {
|
|
padding: 4px 4px !important;
|
|
}
|
|
|
|
#retail_policy_list {
|
|
margin-top: 18px;
|
|
}
|
|
|
|
#retail_policy_list .card-body {
|
|
padding: 12px 16px 8px;
|
|
}
|
|
|
|
#retail-policy-table_wrapper > .row:first-child {
|
|
margin-top: 4px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
#retail-policy-table .renewal-status-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: 72px;
|
|
height: 22px;
|
|
padding: 0 8px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
border-radius: 12px;
|
|
line-height: 1;
|
|
}
|
|
|
|
#retail-policy-table_wrapper .row {
|
|
margin-left: 0;
|
|
margin-right: 0;
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
#retail-policy-table_wrapper .row:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
#retail-policy-table_wrapper .dataTables_filter,
|
|
#retail-policy-table_wrapper .dt-buttons {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
#retail-policy-table_wrapper .dataTables_filter label {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
#retail-policy-table_wrapper .dataTables_info,
|
|
#retail-policy-table_wrapper .dataTables_length label,
|
|
#retail-policy-table_wrapper .dataTables_paginate {
|
|
margin-bottom: 0;
|
|
padding-top: 0;
|
|
font-size: 13px;
|
|
}
|
|
|
|
#retail-policy-table_wrapper .dataTables_length select {
|
|
margin: 0 6px;
|
|
padding: 2px 6px;
|
|
height: auto;
|
|
}
|
|
|
|
#retail_reminder_config_modal .modal-dialog {
|
|
width: 90%;
|
|
max-width: 980px;
|
|
}
|
|
|
|
#retail_reminder_template_modal .modal-dialog {
|
|
width: 95%;
|
|
max-width: 1200px;
|
|
}
|
|
|
|
#retail_reminder_config_modal .modal-header,
|
|
#retail_reminder_template_modal .modal-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
#retail_reminder_config_modal .modal-title,
|
|
#retail_reminder_template_modal .modal-title {
|
|
margin: 0;
|
|
}
|
|
|
|
#retail_reminder_template_editor_container {
|
|
height: calc(100vh - 340px);
|
|
max-height: 460px;
|
|
min-height: 280px;
|
|
border: 1px solid #e9ecef;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
background: #fff;
|
|
}
|
|
|
|
.retail-unlayer-editor-wrap {
|
|
position: relative;
|
|
}
|
|
|
|
.retail-unlayer-branding-mask {
|
|
position: absolute;
|
|
right: 1px;
|
|
bottom: 1px;
|
|
width: 230px;
|
|
height: 36px;
|
|
background: #f5f5f5;
|
|
z-index: 25;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.retail-template-placeholder-select {
|
|
width: 100%;
|
|
max-width: none;
|
|
}
|
|
|
|
#retail_reminder_template_modal .retail-template-top-row {
|
|
align-items: flex-start;
|
|
margin-bottom: 0.35rem;
|
|
}
|
|
|
|
#retail_reminder_template_modal .retail-template-top-row .form-group {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
#retail_reminder_template_modal .retail-template-top-row .form-group > label {
|
|
display: block;
|
|
margin-bottom: 0.55rem;
|
|
font-weight: 500;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
#retail_reminder_template_modal .retail-template-top-row .form-control {
|
|
height: calc(1.5em + 0.75rem + 2px);
|
|
}
|
|
|
|
.retail-placeholder-hint {
|
|
font-size: 12px;
|
|
color: #6c757d;
|
|
margin-top: 6px;
|
|
}
|
|
|
|
.retail-date-field-options {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.75rem 1rem;
|
|
padding-top: 0.35rem;
|
|
}
|
|
|
|
.retail-date-field-options .custom-control {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.retail-date-field-options .custom-control-label {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.retail-config-switch-row .form-group {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
#retail_reminder_config_modal .modal-body {
|
|
padding: 1.5rem 1.75rem !important;
|
|
}
|
|
|
|
#retail_reminder_config_modal .modal-body > .form-row {
|
|
margin-left: 0;
|
|
margin-right: 0;
|
|
margin-bottom: 1.35rem;
|
|
}
|
|
|
|
#retail_reminder_config_modal .modal-body > .form-row:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
#retail_reminder_config_modal .form-group {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
#retail_reminder_config_modal .form-group > label {
|
|
display: block;
|
|
margin-bottom: 0.55rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
#retail_reminder_config_modal .retail-config-switch-row {
|
|
margin-bottom: 1.5rem !important;
|
|
padding-bottom: 0.35rem;
|
|
}
|
|
|
|
#retail_reminder_config_modal .custom-control.custom-switch {
|
|
min-height: 1.75rem;
|
|
padding-top: 0.15rem;
|
|
}
|
|
|
|
#retail_reminder_config_modal .modal-footer,
|
|
#retail_reminder_template_modal .modal-footer {
|
|
padding: 1rem 1.75rem !important;
|
|
}
|
|
</style>
|
|
|
|
<div class="row" id="retail_policy_list">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table data-custom-table-css="table" class="table table-hover mb-0 nowrap w-100 table-centered m-0" cellspacing="0" id="retail-policy-table">
|
|
<thead class="bg-light">
|
|
<tr>
|
|
<th class="font-weight-medium">S.No </th>
|
|
<th class="font-weight-medium">Policy No </th>
|
|
<th class="font-weight-medium">Policy Type </th>
|
|
<th class="font-weight-medium">Client Name </th>
|
|
<th class="font-weight-medium">Mobile </th>
|
|
<th class="font-weight-medium">Email </th>
|
|
<th class="font-weight-medium">Renewal Date </th>
|
|
<th class="font-weight-medium">Policy Period </th>
|
|
<th class="font-weight-medium">Renewal Status </th>
|
|
<th class="font-weight-medium">Action </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="font-12"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mail Config Modal -->
|
|
<div class="modal fade" id="retail_reminder_config_modal" tabindex="-1" role="dialog" aria-labelledby="retailReminderConfigLabel" aria-hidden="true" aria-modal="true" data-backdrop="static">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header d-flex align-items-center justify-content-between">
|
|
<h4 class="modal-title" id="retailReminderConfigLabel">Retail Reminder Mail Config</h4>
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
</div>
|
|
<form id="retail_reminder_config_form">
|
|
<div class="modal-body">
|
|
<div class="form-row retail-config-switch-row">
|
|
<div class="form-group col-md-3 col-sm-6">
|
|
<div class="custom-control custom-switch">
|
|
<input type="checkbox" class="custom-control-input" id="cfg_enabled" name="enabled" value="1">
|
|
<label class="custom-control-label" for="cfg_enabled">Enabled</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group col-md-3 col-sm-6">
|
|
<div class="custom-control custom-switch">
|
|
<input type="checkbox" class="custom-control-input" id="cfg_daily" name="daily" value="1">
|
|
<label class="custom-control-label" for="cfg_daily">Run Daily</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group col-md-3 col-sm-6">
|
|
<div class="custom-control custom-switch">
|
|
<input type="checkbox" class="custom-control-input" id="cfg_includeClientEmail" name="includeClientEmail" value="1">
|
|
<label class="custom-control-label" for="cfg_includeClientEmail">Include Client Email</label>
|
|
</div>
|
|
</div>
|
|
<!--
|
|
<div class="form-group col-md-3 col-sm-6">
|
|
<div class="custom-control custom-switch">
|
|
<input type="checkbox" class="custom-control-input" id="cfg_includeOverdue" name="includeOverdue" value="1">
|
|
<label class="custom-control-label" for="cfg_includeOverdue">Include Overdue</label>
|
|
</div>
|
|
</div>
|
|
-->
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group col-md-4">
|
|
<label>Date Field</label>
|
|
<div class="retail-date-field-options">
|
|
<div class="custom-control custom-radio">
|
|
<input type="radio" class="custom-control-input" id="cfg_dateField_renewal" name="dateField" value="renewal_date" checked>
|
|
<label class="custom-control-label" for="cfg_dateField_renewal">Renewal Date</label>
|
|
</div>
|
|
<div class="custom-control custom-radio">
|
|
<input type="radio" class="custom-control-input" id="cfg_dateField_policy_end" name="dateField" value="policy_end_date">
|
|
<label class="custom-control-label" for="cfg_dateField_policy_end">Policy End Date</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group col-md-8">
|
|
<label for="cfg_daysBefore">Days Before</label>
|
|
<input type="text" class="form-control" id="cfg_daysBefore" name="daysBefore" value="30" placeholder="30, 15, 7, 1, -2, -5, -10">
|
|
<small class="form-text text-muted">Comma-separated offsets. Positive = days before due, negative = days after due.</small>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group col-md-12">
|
|
<label for="cfg_days">Weekdays (used when daily is off)</label>
|
|
<input type="text" class="form-control" id="cfg_days" name="days" placeholder="mon,tue,wed,thu,fri">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group col-md-12">
|
|
<label for="cfg_toEmails">TO Emails</label>
|
|
<input type="text" class="form-control" id="cfg_toEmails" name="toEmails" placeholder="mail1@example.com,mail2@example.com">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group col-md-6">
|
|
<label for="cfg_ccEmails">CC Emails</label>
|
|
<input type="text" class="form-control" id="cfg_ccEmails" name="ccEmails">
|
|
</div>
|
|
<div class="form-group col-md-6">
|
|
<label for="cfg_bccEmails">BCC Emails</label>
|
|
<input type="text" class="form-control" id="cfg_bccEmails" name="bccEmails">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group col-md-12">
|
|
<label for="cfg_fromMail">From Mail</label>
|
|
<input type="email" class="form-control" id="cfg_fromMail" name="fromMail" value="<?= esc($retail_default_from_mail ?? '') ?>" placeholder="sender@example.com">
|
|
</div>
|
|
</div>
|
|
<input type="hidden" name="clientTypes" value="2">
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-light waves-effect waves-light" data-dismiss="modal">Close</button>
|
|
<button type="submit" class="btn btn-primary waves-effect waves-light">Save Config</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Email Template Modal -->
|
|
<div class="modal fade" id="retail_reminder_template_modal" tabindex="-1" role="dialog" aria-labelledby="retailReminderTemplateLabel" aria-hidden="true" aria-modal="true" data-backdrop="static">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header d-flex align-items-center justify-content-between">
|
|
<h4 class="modal-title" id="retailReminderTemplateLabel">Retail Reminder Email Template</h4>
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
</div>
|
|
<form id="retail_reminder_template_form">
|
|
<input type="hidden" name="template_name" value="retail_reminder_mail">
|
|
<div class="modal-body">
|
|
<div class="form-row retail-template-top-row">
|
|
<div class="form-group col-md-8">
|
|
<label for="tpl_subject">Subject</label>
|
|
<input type="text" class="form-control" id="tpl_subject" name="subject" placeholder="Subject">
|
|
</div>
|
|
<div class="form-group col-md-4">
|
|
<label for="tpl_placeholder">Placeholders</label>
|
|
<select id="tpl_placeholder" class="form-control retail-template-placeholder-select">
|
|
<option value="">Insert placeholder</option>
|
|
<option value="{{client_name}}">Client Name</option>
|
|
<option value="{{client_short_name}}">Client Short Name</option>
|
|
<option value="{{policy_no}}">Policy No</option>
|
|
<option value="{{policy_type}}">Policy Type</option>
|
|
<option value="{{insurer_name}}">Insurer Name</option>
|
|
<option value="{{policy_period}}">Policy Period</option>
|
|
<option value="{{reminder_date}}">Reminder Date</option>
|
|
<option value="{{days_before}}">Days Before</option>
|
|
<option value="{{client_type}}">Client Type</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="retail-placeholder-hint">
|
|
Select a placeholder to copy it, then paste into subject or email body.
|
|
</div>
|
|
<div class="form-group mb-0 mt-3">
|
|
<label>Mail Content</label>
|
|
<div class="retail-unlayer-editor-wrap">
|
|
<div id="retail_reminder_template_editor_container"></div>
|
|
<div class="retail-unlayer-branding-mask" aria-hidden="true"></div>
|
|
</div>
|
|
</div>
|
|
<div class="form-row mt-3 mb-0 retail-test-mail-row">
|
|
<div class="form-group col-md-8 mb-0">
|
|
<label for="tpl_test_email">Test Email</label>
|
|
<input type="email" class="form-control" id="tpl_test_email" name="test_email" placeholder="Enter email to send test mail" autocomplete="off">
|
|
<small id="tpl_test_email_error" class="text-danger d-none">Please enter a valid email address.</small>
|
|
</div>
|
|
<div class="form-group col-md-4 mb-0 d-flex align-items-end">
|
|
<button type="button" class="btn btn-info waves-effect waves-light w-100" id="btn_send_test_mail">
|
|
<i class="mdi mdi-email-send-outline"></i> Send Test Mail
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-light waves-effect waves-light" data-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-primary waves-effect waves-light">Submit</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
var listDataUrl = '<?= base_url('policy_tranction/retail-policy/list-data') ?>';
|
|
var configUrl = '<?= base_url('policy_tranction/retail-policy/config') ?>';
|
|
var templateUrl = '<?= base_url('policy_tranction/retail-policy/template') ?>';
|
|
var markRenewedUrl = '<?= base_url('policy_tranction/retail-policy/mark-renewed') ?>';
|
|
var testMailUrl = '<?= base_url('policy_tranction/retail-policy/send-test-mail') ?>';
|
|
var retailUnlayerEditor = null;
|
|
var retailPolicyTable = null;
|
|
var retailUnlayerProjectId = <?= json_encode(getenv('unlayer.projectID')) ?>;
|
|
var retailDefaultFromMail = <?= json_encode($retail_default_from_mail ?? '') ?>;
|
|
|
|
function resolveRetailFromMail(value) {
|
|
var mail = (value != null ? String(value) : '').trim();
|
|
return mail || (retailDefaultFromMail || '');
|
|
}
|
|
|
|
function boolVal(v) {
|
|
return v === true || v === 1 || v === '1' || v === 'true';
|
|
}
|
|
|
|
function listVal(v) {
|
|
if (Array.isArray(v)) {
|
|
return v.join(',');
|
|
}
|
|
return v != null ? String(v) : '';
|
|
}
|
|
|
|
function showRetailModal(modalId) {
|
|
var modalEl = document.getElementById(modalId);
|
|
if (!modalEl) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Same open pattern as policy_transaction_inception_form.php (moreInfoModal)
|
|
var myModal = new bootstrap.Modal(modalEl);
|
|
myModal.show();
|
|
return;
|
|
} catch (e) {
|
|
console.error('bootstrap.Modal open failed, falling back to jQuery modal:', e);
|
|
}
|
|
|
|
$('#' + modalId).modal('show');
|
|
}
|
|
|
|
function hideRetailModal(modalId) {
|
|
var modalEl = document.getElementById(modalId);
|
|
if (!modalEl) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
if (typeof bootstrap !== 'undefined' && bootstrap.Modal && typeof bootstrap.Modal.getInstance === 'function') {
|
|
var instance = bootstrap.Modal.getInstance(modalEl);
|
|
if (instance) {
|
|
instance.hide();
|
|
return;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// fall through to jQuery hide
|
|
}
|
|
|
|
$('#' + modalId).modal('hide');
|
|
}
|
|
|
|
function hideRetailLoader() {
|
|
$('.loader').fadeOut();
|
|
$('.loader-mask').delay(200).fadeOut('slow');
|
|
}
|
|
|
|
function setRetailDateField(value) {
|
|
var normalized = value === 'policy_end_date' ? 'policy_end_date' : 'renewal_date';
|
|
$('input[name="dateField"][value="' + normalized + '"]').prop('checked', true);
|
|
}
|
|
|
|
function getRetailDateField() {
|
|
var selected = $('input[name="dateField"]:checked').val();
|
|
return selected === 'policy_end_date' ? 'policy_end_date' : 'renewal_date';
|
|
}
|
|
|
|
function populateRetailConfigForm(data) {
|
|
data = data || {};
|
|
$('#cfg_enabled').prop('checked', boolVal(data.enabled));
|
|
$('#cfg_daily').prop('checked', boolVal(data.daily));
|
|
$('#cfg_includeClientEmail').prop('checked', boolVal(data.includeClientEmail));
|
|
$('#cfg_includeOverdue').prop('checked', boolVal(data.includeOverdue));
|
|
$('#cfg_daysBefore').val(listVal(data.daysBefore) || '30');
|
|
setRetailDateField(data.dateField || 'renewal_date');
|
|
$('#cfg_days').val(listVal(data.days) || 'mon,tue,wed,thu,fri');
|
|
$('#cfg_toEmails').val(listVal(data.toEmails));
|
|
$('#cfg_ccEmails').val(listVal(data.ccEmails));
|
|
$('#cfg_bccEmails').val(listVal(data.bccEmails));
|
|
$('#cfg_fromMail').val(resolveRetailFromMail(data.fromMail));
|
|
}
|
|
|
|
function openMailConfigModal() {
|
|
$('.loader, .loader-mask').fadeIn();
|
|
$.ajax({
|
|
url: configUrl,
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
success: function (res) {
|
|
try {
|
|
populateRetailConfigForm((res && res.data) ? res.data : {});
|
|
showRetailModal('retail_reminder_config_modal');
|
|
} catch (e) {
|
|
console.error('Failed to open mail config modal:', e);
|
|
toastr.error('Failed to open mail config');
|
|
}
|
|
},
|
|
error: function () {
|
|
toastr.error('Failed to load mail config');
|
|
},
|
|
complete: function () {
|
|
hideRetailLoader();
|
|
}
|
|
});
|
|
}
|
|
|
|
function isRetailUnlayerLoaded() {
|
|
return typeof unlayer !== 'undefined' && unlayer !== null;
|
|
}
|
|
|
|
function waitForRetailUnlayer(callback, maxAttempts) {
|
|
var attempts = 0;
|
|
maxAttempts = maxAttempts || 20;
|
|
|
|
var timer = setInterval(function () {
|
|
attempts++;
|
|
if (isRetailUnlayerLoaded()) {
|
|
clearInterval(timer);
|
|
callback(true);
|
|
return;
|
|
}
|
|
if (attempts >= maxAttempts) {
|
|
clearInterval(timer);
|
|
callback(false);
|
|
}
|
|
}, 500);
|
|
}
|
|
|
|
function destroyRetailTemplateEditor() {
|
|
if (retailUnlayerEditor && typeof retailUnlayerEditor.destroy === 'function') {
|
|
retailUnlayerEditor.destroy();
|
|
}
|
|
retailUnlayerEditor = null;
|
|
|
|
var container = document.getElementById('retail_reminder_template_editor_container');
|
|
if (container) {
|
|
container.innerHTML = '';
|
|
}
|
|
}
|
|
|
|
function initRetailTemplateEditor(templateData, callback) {
|
|
templateData = templateData || {};
|
|
var container = document.getElementById('retail_reminder_template_editor_container');
|
|
|
|
if (!container) {
|
|
if (callback) {
|
|
callback(null);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!document.querySelector('script[src*="unlayer"]')) {
|
|
toastr.error('Unlayer editor is not available on this page');
|
|
if (callback) {
|
|
callback(null);
|
|
}
|
|
return;
|
|
}
|
|
|
|
waitForRetailUnlayer(function (loaded) {
|
|
if (!loaded) {
|
|
toastr.error('Failed to load Unlayer editor');
|
|
if (callback) {
|
|
callback(null);
|
|
}
|
|
return;
|
|
}
|
|
|
|
try {
|
|
destroyRetailTemplateEditor();
|
|
|
|
retailUnlayerEditor = unlayer.createEditor({
|
|
id: 'retail_reminder_template_editor_container',
|
|
projectId: retailUnlayerProjectId,
|
|
displayMode: 'email',
|
|
features: {
|
|
textEditor: {
|
|
tables: true
|
|
},
|
|
preview: {
|
|
enabled: true,
|
|
deviceOptions: ['desktop', 'mobile']
|
|
},
|
|
imageEditor: {
|
|
enabled: true
|
|
}
|
|
},
|
|
appearance: {
|
|
theme: 'light',
|
|
panels: {
|
|
tools: {
|
|
dock: 'right'
|
|
}
|
|
}
|
|
},
|
|
branding: false,
|
|
tools: {
|
|
text: { enabled: true },
|
|
image: { enabled: true }
|
|
}
|
|
});
|
|
|
|
if (templateData.mail_content_json) {
|
|
try {
|
|
retailUnlayerEditor.loadDesign(JSON.parse(templateData.mail_content_json));
|
|
} catch (error) {
|
|
console.error('Failed to load saved Unlayer design', error);
|
|
}
|
|
}
|
|
|
|
if (callback) {
|
|
callback(retailUnlayerEditor);
|
|
}
|
|
|
|
setTimeout(hideRetailUnlayerBranding, 400);
|
|
} catch (error) {
|
|
console.error('Retail Unlayer init failed', error);
|
|
if (callback) {
|
|
callback(null);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function hideRetailUnlayerBranding() {
|
|
$('#retail_reminder_template_editor_container iframe').off('load.retailUnlayerBranding').on('load.retailUnlayerBranding', function () {
|
|
var $iframe = $(this);
|
|
var $parent = $iframe.parent();
|
|
|
|
if ($parent.css('position') === 'static') {
|
|
$parent.css('position', 'relative');
|
|
}
|
|
|
|
$parent.find('.retail-unlayer-branding-overlay').remove();
|
|
$parent.append(
|
|
$('<div>', {
|
|
class: 'retail-unlayer-branding-overlay',
|
|
css: {
|
|
position: 'absolute',
|
|
right: 0,
|
|
bottom: 0,
|
|
width: $iframe.outerWidth(),
|
|
height: '36px',
|
|
backgroundColor: '#f5f5f5',
|
|
zIndex: 9999,
|
|
pointerEvents: 'none'
|
|
}
|
|
})
|
|
);
|
|
});
|
|
}
|
|
|
|
function openEmailTemplateModal() {
|
|
$('.loader, .loader-mask').fadeIn();
|
|
$.ajax({
|
|
url: templateUrl,
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
success: function (res) {
|
|
try {
|
|
var data = (res && res.data) ? res.data : {};
|
|
$('#tpl_subject').val(data.subject || '');
|
|
showRetailModal('retail_reminder_template_modal');
|
|
|
|
var retryCount = 0;
|
|
var initWithRetry = function () {
|
|
initRetailTemplateEditor(data, function (editorInstance) {
|
|
if (!editorInstance && retryCount < 3) {
|
|
retryCount++;
|
|
setTimeout(initWithRetry, 800);
|
|
return;
|
|
}
|
|
if (!editorInstance) {
|
|
toastr.error('Editor initialization failed. Please refresh the page.');
|
|
}
|
|
});
|
|
};
|
|
|
|
setTimeout(initWithRetry, 300);
|
|
} catch (e) {
|
|
console.error('Failed to open email template modal:', e);
|
|
toastr.error('Failed to open email template');
|
|
}
|
|
},
|
|
error: function () {
|
|
toastr.error('Failed to load email template');
|
|
},
|
|
complete: function () {
|
|
hideRetailLoader();
|
|
}
|
|
});
|
|
}
|
|
|
|
function exportRetailPolicyData(e, dt, button, config, buttonType) {
|
|
var self = this;
|
|
var oldStart = dt.page.info().start;
|
|
var oldSearch = (dt.search() || '').trim();
|
|
|
|
dt.one('preXhr', function (x, s, data) {
|
|
data.start = 0;
|
|
data.length = -1;
|
|
data.search = { value: oldSearch, regex: false };
|
|
});
|
|
|
|
dt.one('draw', function () {
|
|
$.fn.dataTable.ext.buttons[buttonType].action.call(self, e, dt, button, config);
|
|
|
|
dt.one('preXhr', function (x, s, data) {
|
|
data.start = oldStart;
|
|
data.length = dt.page.len();
|
|
data.search = { value: oldSearch, regex: false };
|
|
});
|
|
|
|
setTimeout(function () {
|
|
dt.ajax.reload(null, false);
|
|
}, 0);
|
|
});
|
|
|
|
dt.ajax.reload();
|
|
}
|
|
|
|
function initRetailPolicyDataTable() {
|
|
if (!$.fn.DataTable) {
|
|
return;
|
|
}
|
|
|
|
var $table = $('#retail-policy-table');
|
|
if (!$table.length) {
|
|
return;
|
|
}
|
|
|
|
if ($.fn.DataTable.isDataTable('#retail-policy-table')) {
|
|
$table.DataTable().destroy();
|
|
}
|
|
|
|
if (typeof nhanceListDataTableBeforeInit === 'function') {
|
|
nhanceListDataTableBeforeInit();
|
|
}
|
|
|
|
var dtOptions = {
|
|
processing: true,
|
|
serverSide: true,
|
|
ordering: false,
|
|
pageLength: 10,
|
|
lengthMenu: [[10, 25, 50, 100], [10, 25, 50, 100]],
|
|
dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'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>>",
|
|
ajax: {
|
|
url: listDataUrl,
|
|
type: 'POST'
|
|
},
|
|
columns: [
|
|
{ data: 0 },
|
|
{ data: 1 },
|
|
{ data: 2 },
|
|
{ data: 3 },
|
|
{ data: 4 },
|
|
{ data: 5 },
|
|
{ data: 6 },
|
|
{ data: 7 },
|
|
{ data: 8 },
|
|
{ data: 9, orderable: false }
|
|
],
|
|
buttons: [
|
|
{
|
|
text: '<i class="mdi mdi-cog-outline"></i><span class="btn-custom"> Mail Config </span>',
|
|
className: 'btn app-btn-primary mr-2',
|
|
action: function () {
|
|
openMailConfigModal();
|
|
}
|
|
},
|
|
{
|
|
text: '<i class="mdi mdi-email-edit-outline"></i><span class="btn-custom"> Email Template </span>',
|
|
className: 'btn app-btn-secondary mr-2',
|
|
action: function () {
|
|
openEmailTemplateModal();
|
|
}
|
|
},
|
|
{
|
|
extend: 'excel',
|
|
text: '<i class="mdi mdi-file-excel"></i><span class="btn-custom"> EXCEL </span>',
|
|
className: 'btn app-btn-secondary',
|
|
title: 'Retail Policy',
|
|
sheetName: 'Retail Policy',
|
|
action: function (e, dt, button, config) {
|
|
exportRetailPolicyData.call(this, e, dt, button, config, 'excelHtml5');
|
|
},
|
|
exportOptions: {
|
|
modifier: {
|
|
search: 'applied',
|
|
page: 'all'
|
|
},
|
|
columns: [0, 1, 2, 3, 4, 5, 6, 7, 8],
|
|
format: {
|
|
body: function (data, row, column, node) {
|
|
return $(node).text().replace(/\s+/g, ' ').trim();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
],
|
|
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:10px; top:50%; transform:translateY(-50%); color:#666;"></i>
|
|
</div>`,
|
|
searchPlaceholder: 'Search policy no, type, name, mobile, email',
|
|
emptyTable: '<div class="text-center text-muted">No retail policies found</div>',
|
|
zeroRecords: '<div class="text-center text-muted">No matching retail policies</div>'
|
|
}
|
|
};
|
|
|
|
retailPolicyTable = typeof nhanceMergeListDataTableOptions === 'function'
|
|
? $table.DataTable(nhanceMergeListDataTableOptions(dtOptions))
|
|
: $table.DataTable(dtOptions);
|
|
|
|
if (typeof nhanceListDataTableAfterInit === 'function') {
|
|
nhanceListDataTableAfterInit();
|
|
}
|
|
|
|
if (typeof nhanceListDataTableBindAdjust === 'function') {
|
|
nhanceListDataTableBindAdjust(retailPolicyTable);
|
|
}
|
|
}
|
|
|
|
$(document).ready(function () {
|
|
initRetailPolicyDataTable();
|
|
|
|
$(document).on('click', '.btn-mark-renewed', function () {
|
|
var ptId = $(this).data('id');
|
|
if (!ptId) {
|
|
return;
|
|
}
|
|
|
|
var doMarkRenewed = function () {
|
|
$('.loader, .loader-mask').fadeIn();
|
|
$.ajax({
|
|
url: markRenewedUrl,
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: { id: ptId },
|
|
success: function (res) {
|
|
if (res && res.status) {
|
|
toastr.success(res.message || 'Policy marked as renewed');
|
|
if (retailPolicyTable) {
|
|
retailPolicyTable.ajax.reload(null, false);
|
|
}
|
|
} else {
|
|
toastr.error((res && res.message) || 'Failed to update status');
|
|
}
|
|
},
|
|
error: function () {
|
|
toastr.error('Failed to update status');
|
|
},
|
|
complete: function () {
|
|
hideRetailLoader();
|
|
}
|
|
});
|
|
};
|
|
|
|
if (typeof confirmActionSweertAlert === 'function') {
|
|
confirmActionSweertAlert(
|
|
'Mark this policy as renewed?',
|
|
'Yes, Mark Renewed',
|
|
'Cancel',
|
|
'warning'
|
|
).then(function (confirmed) {
|
|
if (confirmed) {
|
|
doMarkRenewed();
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (confirm('Are you sure you want to mark this policy as renewed?')) {
|
|
doMarkRenewed();
|
|
}
|
|
});
|
|
|
|
$('#retail_reminder_template_modal').on('hidden.bs.modal', function () {
|
|
destroyRetailTemplateEditor();
|
|
});
|
|
|
|
$('#retail_reminder_config_form').on('submit', function (e) {
|
|
e.preventDefault();
|
|
$('.loader, .loader-mask').fadeIn();
|
|
|
|
var formData = {
|
|
enabled: $('#cfg_enabled').is(':checked') ? '1' : '0',
|
|
daily: $('#cfg_daily').is(':checked') ? '1' : '0',
|
|
includeClientEmail: $('#cfg_includeClientEmail').is(':checked') ? '1' : '0',
|
|
includeOverdue: $('#cfg_includeOverdue').is(':checked') ? '1' : '0',
|
|
daysBefore: $('#cfg_daysBefore').val(),
|
|
dateField: getRetailDateField(),
|
|
days: $('#cfg_days').val(),
|
|
toEmails: $('#cfg_toEmails').val(),
|
|
ccEmails: $('#cfg_ccEmails').val(),
|
|
bccEmails: $('#cfg_bccEmails').val(),
|
|
fromMail: $('#cfg_fromMail').val(),
|
|
clientTypes: '2'
|
|
};
|
|
|
|
$.ajax({
|
|
url: configUrl,
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: formData,
|
|
success: function (res) {
|
|
if (res && res.status) {
|
|
toastr.success(res.message || 'Config saved');
|
|
hideRetailModal('retail_reminder_config_modal');
|
|
} else {
|
|
toastr.error((res && res.message) || 'Failed to save config');
|
|
}
|
|
},
|
|
error: function () {
|
|
toastr.error('Failed to save config');
|
|
},
|
|
complete: function () {
|
|
$('.loader').fadeOut();
|
|
$('.loader-mask').delay(200).fadeOut('slow');
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#tpl_placeholder').on('change', function () {
|
|
var val = $(this).val();
|
|
if (!val) {
|
|
return;
|
|
}
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
navigator.clipboard.writeText(val);
|
|
toastr.info('Placeholder copied: ' + val);
|
|
} else {
|
|
toastr.info(val);
|
|
}
|
|
$(this).val('');
|
|
});
|
|
|
|
function isValidRetailTestEmail(email) {
|
|
var emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
return emailPattern.test(String(email || '').trim());
|
|
}
|
|
|
|
function showRetailTestEmailError(show) {
|
|
var $error = $('#tpl_test_email_error');
|
|
var $input = $('#tpl_test_email');
|
|
if (show) {
|
|
$error.removeClass('d-none');
|
|
$input.addClass('is-invalid');
|
|
} else {
|
|
$error.addClass('d-none');
|
|
$input.removeClass('is-invalid');
|
|
}
|
|
}
|
|
|
|
$('#tpl_test_email').on('input blur', function () {
|
|
var email = String($(this).val() || '').trim();
|
|
if (email === '') {
|
|
showRetailTestEmailError(false);
|
|
return;
|
|
}
|
|
showRetailTestEmailError(!isValidRetailTestEmail(email));
|
|
});
|
|
|
|
$('#btn_send_test_mail').on('click', function () {
|
|
var testEmail = String($('#tpl_test_email').val() || '').trim();
|
|
if (!isValidRetailTestEmail(testEmail)) {
|
|
showRetailTestEmailError(true);
|
|
toastr.warning('Please enter a valid email address');
|
|
$('#tpl_test_email').focus();
|
|
return;
|
|
}
|
|
showRetailTestEmailError(false);
|
|
|
|
var subject = String($('#tpl_subject').val() || '').trim();
|
|
if (subject === '') {
|
|
toastr.warning('Please enter a subject before sending test mail');
|
|
$('#tpl_subject').focus();
|
|
return;
|
|
}
|
|
|
|
if (!retailUnlayerEditor || typeof retailUnlayerEditor.exportHtml !== 'function') {
|
|
toastr.error('Editor not ready. Please try again.');
|
|
return;
|
|
}
|
|
|
|
$('.loader, .loader-mask').fadeIn();
|
|
retailUnlayerEditor.exportHtml(function (data) {
|
|
var mailContent = (data && data.html) ? data.html : '';
|
|
if (!mailContent) {
|
|
$('.loader').fadeOut();
|
|
$('.loader-mask').delay(200).fadeOut('slow');
|
|
toastr.error('Mail content is empty. Please design the template first.');
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: testMailUrl,
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: {
|
|
test_email: testEmail,
|
|
subject: subject,
|
|
mailContent: mailContent
|
|
},
|
|
success: function (res) {
|
|
if (res && res.status) {
|
|
toastr.success(res.message || 'Test mail sent');
|
|
} else {
|
|
toastr.error((res && res.message) || 'Failed to send test mail');
|
|
}
|
|
},
|
|
error: function (xhr) {
|
|
var message = 'Failed to send test mail';
|
|
if (xhr.responseJSON && xhr.responseJSON.message) {
|
|
message = xhr.responseJSON.message;
|
|
}
|
|
toastr.error(message);
|
|
},
|
|
complete: function () {
|
|
$('.loader').fadeOut();
|
|
$('.loader-mask').delay(200).fadeOut('slow');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
$('#retail_reminder_template_form').on('submit', function (e) {
|
|
e.preventDefault();
|
|
|
|
if (!retailUnlayerEditor || typeof retailUnlayerEditor.exportHtml !== 'function') {
|
|
toastr.error('Editor not ready. Please try again.');
|
|
return;
|
|
}
|
|
|
|
$('.loader, .loader-mask').fadeIn();
|
|
|
|
retailUnlayerEditor.exportHtml(function (data) {
|
|
var formData = new FormData($('#retail_reminder_template_form')[0]);
|
|
formData.set('subject', $('#tpl_subject').val());
|
|
formData.set('mailContent', data.html);
|
|
formData.set('mailJson', JSON.stringify(data.design));
|
|
|
|
$.ajax({
|
|
url: templateUrl,
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: formData,
|
|
processData: false,
|
|
contentType: false,
|
|
success: function (res) {
|
|
if (res && res.status) {
|
|
toastr.success(res.message || 'Template saved');
|
|
hideRetailModal('retail_reminder_template_modal');
|
|
} else {
|
|
toastr.error((res && res.message) || 'Failed to save template');
|
|
}
|
|
},
|
|
error: function (xhr) {
|
|
var message = 'Failed to save template';
|
|
if (xhr.responseJSON && xhr.responseJSON.message) {
|
|
message = xhr.responseJSON.message;
|
|
}
|
|
toastr.error(message);
|
|
},
|
|
complete: function () {
|
|
$('.loader').fadeOut();
|
|
$('.loader-mask').delay(200).fadeOut('slow');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|
|
})();
|
|
</script>
|