nhance/app/Views/ticket_reply.php

608 lines
25 KiB
PHP

<div class="row">
<div class="col-12">
<div class="card-body">
<form role="form" class="parsley-examples" style="color:black;" method="post" id="ticket_reply_form" enctype="multipart/form-data">
<div class="form-group">
<div class="form-row">
<?php
$showApprovedStatusDropdown =
isset($ticket_data['claim_status_id'], $ticket_data['ticket_type_id']) && (int) $ticket_data['claim_status_id'] === 10 && (int) $ticket_data['ticket_type_id'] === 1 &&
(
(isset($ticket_data['claim_created_by']) && $ticket_data['claim_created_by'] == 'TPA') ||
(array_key_exists('tpa_claim_push_reference_no', $ticket_data) && $ticket_data['tpa_claim_push_reference_no'] !== null)
);
?>
<?php if ($showApprovedStatusDropdown): ?>
<div class="form-group col-md-4">
<label for="status_back_option">Status</label>
<select class="form-control" id="status_back_option">
<option value="">Select</option>
<option value="9">APPROVED</option>
</select>
</div>
<?php endif; ?>
<!-- Email To Field -->
<div class="form-group col-md-4">
<label for="emp_mail_for_to">To</label>
<input type="text" value="<?= isset($ticket_data['emp_mail'])?$ticket_data['emp_mail']:'' ?>" class="form-control" id="emp_mail_for_to" name="emp_mail" placeholder="Recipient email" readonly>
</div>
<!-- Subject Field -->
<div class="form-group col-md-8">
<label for="mail_subject">Subject</label>
<input type="text" class="form-control" value="<?= isset($reply_data['subject'])?$reply_data['subject']:'' ?>" id="mail_subject" name="mail_subject" placeholder="Mail subject">
</div>
<!-- Mail Content Field -->
<div class="form-group col-md-12">
<!-- <textarea class="form-control" rows="5" placeholder="Enter Mail Content"></textarea> -->
<div class="form-row" id="rac_rate_dropdown">
<div class="form-group col-md-12">
<select id="ticket_mail_customButton" class="form-control" style="border:none;right: 6px;width: auto;position: absolute;z-index: 1;top: 17px;height: 32px;float: right;">
<option value="">PlaceHolders</option>
<?php foreach ($placeHolders as $key => $value): ?>
<!-- <?php // if($value == 'member_name' || $value == 'member_mobile' || $value == 'nhance_logo' || $value == 'client_logo' || $value == 'app_link' || $value == 'client_name'){ ?>member_mobile -->
<?php $valueChange = str_replace('_', ' ', $value); $valueChange = ucwords($valueChange); ?>
<option value="<?php echo $key; ?>"><?php echo $valueChange; ?></option>
<?php //} ?>
<?php endforeach; ?>
</select>
</div>
</div>
<div id="ticket_mail_editor" name="content" style="height: 300px;"></div>
</div>
</div><input type="hidden" id="claim_status" name="claim_status" value="<?= isset($reply_data['claim_status_id'])??'' ?>">
</div>
<!-- Submit Button -->
<div class="form-group text-right">
<button type="submit" class="btn btn-primary" id="ticket_reply_submit">Send Mail</button>
</div>
</form>
</div>
</div>
</div>
<style>
.approved-letter-mode-option {
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 10px 12px;
margin-bottom: 10px;
cursor: pointer;
}
.approved-letter-mode-option.selected {
border-color: #0a8794;
background-color: #f2fbfc;
}
</style>
<div class="modal fade" id="approvedLetterUploadModal" tabindex="-1" role="dialog" aria-labelledby="approvedLetterUploadModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="approvedLetterUploadModalLabel">Upload Approved Letter</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="approved-letter-mode-option selected" onclick="selectApprovedLetterOption(this, 'approved_letter_mode_url')">
<div class="form-check">
<input class="form-check-input" type="radio" name="approved_letter_mode" id="approved_letter_mode_url" value="url" checked>
<label class="form-check-label" for="approved_letter_mode_url">Approved Letter URL</label>
</div>
</div>
<div class="approved-letter-mode-option" onclick="selectApprovedLetterOption(this, 'approved_letter_mode_pdf')">
<div class="form-check">
<input class="form-check-input" type="radio" name="approved_letter_mode" id="approved_letter_mode_pdf" value="pdf">
<label class="form-check-label" for="approved_letter_mode_pdf">Approved Letter PDF</label>
</div>
</div>
<div class="form-group" id="approved_letter_url_block">
<label for="approved_letter_reply_url">Approved Letter URL</label>
<input type="text" class="form-control" id="approved_letter_reply_url" placeholder="Enter Approved Letter URL">
<small class="text-danger d-none" id="approved_letter_reply_url_error"></small>
</div>
<div class="form-group mb-0" id="approved_letter_pdf_block" style="display:none;">
<label for="approved_letter_reply_file">Approved Letter PDF</label>
<input type="file" class="form-control" id="approved_letter_reply_file" accept=".pdf,application/pdf">
<small class="text-muted">Only PDF is allowed for file upload.</small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="uploadApprovedLetterBtn">Upload</button>
</div>
</div>
</div>
</div>
<script>
var toolbar = "bold,italic,strikethrough,|,superscript,subscript,|,align,";
function selectApprovedLetterOption(element, inputId) {
$('.approved-letter-mode-option').removeClass('selected');
$(element).addClass('selected');
$('#' + inputId).prop('checked', true).trigger('change');
}
function validateApprovedLetterPdf(fileInput) {
const file = fileInput.files && fileInput.files[0] ? fileInput.files[0] : null;
if (!file) {
return true;
}
const fileName = (file.name || '').toLowerCase();
const isPdfByName = fileName.endsWith('.pdf');
const mimeType = (file.type || '').toLowerCase();
const isPdfByType = mimeType === '' || mimeType === 'application/pdf' || mimeType === 'application/x-pdf';
if (!isPdfByName || !isPdfByType) {
fileInput.value = '';
toastr.warning('Only PDF files are allowed for Approved Letter.', 'Warning');
return false;
}
return true;
}
function isValidApprovedLetterUrl(urlValue) {
const url = (urlValue || '').trim();
if (!url) {
return false;
}
try {
const normalizedUrl = /^https?:\/\//i.test(url) ? url : `https://${url}`;
const parsed = new URL(normalizedUrl);
if (!['http:', 'https:'].includes(parsed.protocol)) {
return false;
}
const host = (parsed.hostname || '').toLowerCase();
if (!host) {
return false;
}
if (host === 'localhost') {
return true;
}
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host)) {
return true;
}
return host.includes('.');
} catch (e) {
return false;
}
}
function setApprovedLetterUrlError(message) {
const $urlInput = $('#approved_letter_reply_url');
const $errorEl = $('#approved_letter_reply_url_error');
if (message) {
$urlInput.addClass('is-invalid');
$errorEl.text(message).removeClass('d-none');
} else {
$urlInput.removeClass('is-invalid');
$errorEl.text('').addClass('d-none');
}
}
const editorConfig = {
buttons: toolbar.concat(['fontsize']),
fontsize: [8, 10, 12, 14, 16, 18, 20, 22, 24], // Customize font sizes
showPlaceholder: false,
toolbarButtonSize: 'small',
toolbarAdaptive: false,
saveHeightInStorage: true,
minHeight: 400,
extraButtons: [
{
name: 'info',
iconURL: '<?= base_url()."public"; ?>/assets/images/image-solid.svg', // Replace with the actual icon URL
exec: function (editor) {
const fileInput = document.getElementById("Question_title_fileInput");
fileInput.click();
},
},
],
};
$(document).ready(function() {
const replyTicketId = `<?= isset($ticket_data['id']) ? (int) $ticket_data['id'] : 0 ?>`;
let replyApprovedLetter = <?= json_encode($ticket_data['approved_letter'] ?? null) ?>;
console.log('Approved Letter from server:', replyApprovedLetter);
function hasApprovedLetterValue(value) {
return value !== null && value !== undefined && String(value).trim() !== '';
}
var toolbar = "bold,italic,strikethrough,|,superscript,subscript,|,align,";
const editorConfig = {
buttons: toolbar.concat(['fontsize']),
fontsize: [8, 10, 12, 14, 16, 18, 20, 22, 24], // Customize font sizes
showPlaceholder: false,
toolbarButtonSize: 'small',
toolbarAdaptive: false,
saveHeightInStorage: true,
minHeight: 400,
extraButtons: [
{
name: 'info',
iconURL: '<?= base_url()."public"; ?>/assets/images/image-solid.svg', // Replace with the actual icon URL
exec: function (editor) {
const fileInput = document.getElementById("Question_title_fileInput");
fileInput.click();
},
},
],
};
const editor = Jodit.make("#ticket_mail_editor", editorConfig);
var mail_content = `<?=isset($reply_data['mail_content'])?$reply_data['mail_content']:'' ?>`;
// console.log(mail_content);
if (editor) {
editor.value = mail_content;
}
// $('.jodit-wysiwyg').html(mail_content);
let lastActiveField = null;
// Track last active input field
$("#mail_subject").on("focus", function() {
lastActiveField = this;
});
// Track Jodit editor focus separately
editor.events.on("focus", function() {
lastActiveField = editor;
});
document.addEventListener('change', function(event) {
var target = event.target;
if (target.matches('#ticket_mail_customButton')) {
let placeholderValue = $(target).val();
if (!placeholderValue) return;
if (lastActiveField) {
if (lastActiveField.id === "mail_subject") {
insertAtCursor(lastActiveField, placeholderValue);
} else {
editor.selection.insertHTML(placeholderValue);
}
}
$(target).val('');
}
});
async function loadClaimTemplateForStatus(ticketId, statusId) {
if (!ticketId || !statusId) {
return;
}
$.ajax({
url: '<?= base_url('/ticket/getClaimTemplateData') ?>',
type: 'POST',
dataType: 'json',
data: {
ticket_id: ticketId,
status_id: statusId
},
success: function(res) {
if (res && res.status && res.data) {
if (typeof res.data.subject !== 'undefined') {
$('#mail_subject').val(res.data.subject || '');
}
if (typeof res.data.message !== 'undefined') {
editor.value = res.data.message || '';
}
} else {
toastr.warning(res.message || 'Failed to load mail template', 'Warning');
}
},
error: function(xhr) {
console.error(xhr.responseText);
toastr.error('Unable to fetch mail template.', 'Error');
}
});
}
function openApprovedLetterUploadModalAndHandle(ticketId, statusId) {
const dfd = $.Deferred();
const $modal = $('#approvedLetterUploadModal');
const $modeUrl = $('#approved_letter_mode_url');
const $modePdf = $('#approved_letter_mode_pdf');
const $urlBlock = $('#approved_letter_url_block');
const $pdfBlock = $('#approved_letter_pdf_block');
const $urlInput = $('#approved_letter_reply_url');
const $fileInput = $('#approved_letter_reply_file');
const $uploadBtn = $('#uploadApprovedLetterBtn');
const approvedLetterModalEl = document.getElementById('approvedLetterUploadModal');
const approvedLetterModalInstance = new bootstrap.Modal(approvedLetterModalEl, {
backdrop: 'static',
keyboard: false
});
$urlInput.val('');
$fileInput.val('');
$modeUrl.prop('checked', true).trigger('change');
$('.approved-letter-mode-option').removeClass('selected');
$('.approved-letter-mode-option').first().addClass('selected');
$uploadBtn.prop('disabled', false);
approvedLetterModalInstance.show();
function cleanup() {
$uploadBtn.off('click.approvedUpload');
$modal.off('hidden.bs.modal.approvedUpload');
$modeUrl.off('change.approvedUpload');
$modePdf.off('change.approvedUpload');
}
$modal.on('hidden.bs.modal.approvedUpload', function() {
cleanup();
if (dfd.state() === 'pending') {
dfd.reject('Upload cancelled');
}
});
$modeUrl.on('change.approvedUpload', function() {
if ($(this).is(':checked')) {
$urlBlock.show();
$pdfBlock.hide();
$fileInput.val('');
}
});
$modePdf.on('change.approvedUpload', function() {
if ($(this).is(':checked')) {
$pdfBlock.show();
$urlBlock.hide();
$urlInput.val('');
}
});
$urlInput.on('input.approvedUpload', function() {
const currentValue = $.trim($(this).val());
if (currentValue === '') {
setApprovedLetterUrlError('');
return;
}
if (!isValidApprovedLetterUrl(currentValue)) {
setApprovedLetterUrlError('Approved Letter URL format is invalid.');
} else {
setApprovedLetterUrlError('');
}
});
$urlInput.on('blur.approvedUpload', function() {
const currentValue = $.trim($(this).val());
if (currentValue === '') {
setApprovedLetterUrlError('');
return;
}
if (!isValidApprovedLetterUrl(currentValue)) {
setApprovedLetterUrlError('Approved Letter URL format is invalid.');
} else {
setApprovedLetterUrlError('');
}
});
$fileInput.on('change.approvedUpload', function() {
validateApprovedLetterPdf(this);
});
$uploadBtn.on('click.approvedUpload', function() {
const selectedMode = $('input[name="approved_letter_mode"]:checked').val();
const urlValue = $.trim($urlInput.val());
const file = $fileInput[0].files && $fileInput[0].files[0] ? $fileInput[0].files[0] : null;
if (selectedMode === 'url' && !urlValue) {
setApprovedLetterUrlError('Please enter Approved Letter URL.');
return;
}
if (selectedMode === 'url' && !isValidApprovedLetterUrl(urlValue)) {
setApprovedLetterUrlError('Approved Letter URL format is invalid.');
return;
}
setApprovedLetterUrlError('');
if (selectedMode === 'pdf' && !file) {
toastr.warning('Please select Approved Letter PDF.', 'Warning');
return;
}
if (selectedMode === 'pdf' && file) {
if (!validateApprovedLetterPdf($fileInput[0])) {
return;
}
}
const formData = new FormData();
formData.append('ticket_id', ticketId);
formData.append('status_id', statusId);
formData.append('approved_letter', selectedMode === 'url' ? urlValue : '');
if (selectedMode === 'pdf' && file) {
formData.append('approved_letter_file', file);
}
$uploadBtn.prop('disabled', true);
$.ajax({
url: '<?= base_url('/ticket/uploadApprovedLetterFromReply') ?>',
type: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(res) {
if (res && res.status) {
replyApprovedLetter = (res.data && res.data.approved_letter) ? res.data.approved_letter : replyApprovedLetter;
toastr.success(res.message || 'Approved letter uploaded successfully', 'Success');
cleanup();
approvedLetterModalInstance.hide();
dfd.resolve();
} else {
$uploadBtn.prop('disabled', false);
toastr.error((res && res.message) ? res.message : 'Approved letter upload failed', 'Error');
}
},
error: function(xhr) {
$uploadBtn.prop('disabled', false);
console.error(xhr.responseText);
toastr.error('Unable to upload approved letter.', 'Error');
}
});
});
return dfd.promise();
}
function handleStatusTemplateFlow() {
const selectedStatusId = $('#status_back_option').val();
if (!selectedStatusId || !replyTicketId) {
return;
}
if (String(selectedStatusId) === '9' && !hasApprovedLetterValue(replyApprovedLetter)) {
openApprovedLetterUploadModalAndHandle(replyTicketId, selectedStatusId)
.done(function() {
loadClaimTemplateForStatus(replyTicketId, selectedStatusId);
});
return;
}
loadClaimTemplateForStatus(replyTicketId, selectedStatusId);
}
$('#status_back_option').on('change', function() {
handleStatusTemplateFlow();
});
if ($('#status_back_option').length && hasApprovedLetterValue(replyApprovedLetter)) {
const selectedStatusId = $('#status_back_option').val();
if (selectedStatusId) {
loadClaimTemplateForStatus(replyTicketId, selectedStatusId);
}
}
function insertAtCursor(input, textToInsert) {
if (document.selection) {
input.focus();
var sel = document.selection.createRange();
sel.text = textToInsert;
} else if (input.selectionStart || input.selectionStart === 0) {
let startPos = input.selectionStart;
let endPos = input.selectionEnd;
input.value = input.value.substring(0, startPos) + textToInsert + input.value.substring(endPos, input.value.length);
input.selectionStart = input.selectionEnd = startPos + textToInsert.length;
} else {
input.value += textToInsert;
}
}
$("#ticket_reply_form").submit(function(event) {
event.preventDefault();
var joditEditor = editor;
if (joditEditor)
{
var mailContent = $(joditEditor.currentPlace.container).find('.jodit-wysiwyg').html();
var formData = $(this).serializeArray();
formData.push({ name: 'mail_content', value: mailContent });
// formData.push({ name: 'client_id', value: $('#general_PrimaryKey').val() });
// var isAutoMailEnabled = $('#statusSwitch').is(':checked') ? 1 : 0;
// formData.push({ name: 'is_auto_mail', value: isAutoMailEnabled });
var ticket_id = $('#ticket_master_id').val();
if (ticket_id != null && ticket_id != ''){
formData.push({ name: 'ticket_id', value: ticket_id});
}
// console.log(formData);
$('.loader').fadeIn();
$('.loader-mask').fadeIn();
var form_action = '<?= base_url("/ticket/reply"); ?>';
$.ajax({
url: form_action,
type: "POST",
data: formData,
dataType: 'json',
success: function(res)
{
if(res.status == true){
// $('#new_mail_template').find('.close').click();
$('.loader').fadeOut();
$('.loader-mask').delay(350).fadeOut('slow');
toastr.success('Message Sent successfully!', 'Success');
reloadTicket_conversation();
}else if (res.status == false){
toastr.error('Failed to Send Message', 'error');
}
},
error: function (xhr, status, error)
{
console.error(xhr.responseText);
console.error(status, error);
setTimeout(function()
{
$('.loader').fadeOut();
$('.loader-mask').delay(350).fadeOut('slow');
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');
} else {
toastr.error('An unexpected error occurred. Please try again later.', 'Error');
}
}, 1000);
}
});
}
else
{
console.error("Jodit editor instance is not defined.");
}
});
});
</script>
<script>
function reloadTicket_conversation() {
$("#ticket_messages_div").load(location.href + " #ticket_messages_div");
}
</script>