nhance/app/Views/thz_notes.php

731 lines
33 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<style>
.notes-box {
display: flex;
align-items: center;
border: 1px solid #00aaff;
border-radius: 6px;
padding: 5px;
}
.notes-box textarea {
flex: 1;
border: none;
outline: none;
resize: none;
padding: 8px;
font-size: 14px;
background-color: transparent !important;
border-radius: 0px !important;
box-shadow: 0px 0px 0px 0px transparent !important;
border-color: transparent !important;
}
.icon-buttons {
display: flex;
gap: 6px;
margin-left: 5px;
}
.btn-icon {
background: #008b8b;
border: none;
border-radius: 50%;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.btn-icon i {
color: #ffffff !important;
font-size: 18px;
}
.conversation-card{
border-radius: 25px !important;
box-shadow: 0 2px 4px 0 #00000040;
}
.card-scroll{
overflow-y:auto;
min-height:380px;
max-height:380px;
}
.recard-scroll{
overflow-y:auto;
min-height:295px;
max-height:295px;
}
.edit-icon {
font-size: 17px; /* keep fixed size */
color: #555 !important;
cursor: pointer;
transition: transform 0.2s, color 0.2s; /* smooth hover effect */
display: inline-block; /* important for transform */
}
.edit-icon:hover {
color: #00999E !important;
transform: scale(1.5);
}
.conversation-card,
.conversation-card .card-header,
.conversation-card .card-body {
background: #F5FFFF !important;
}
.conversation-card{
box-shadow: 0 2px 4px 0 #00000040;
border-radius : 15px !important;
}
.master-card{
border-radius: 15px !important;
box-shadow: 0 2px 4px 0 #00000040;
}
</style>
<style>
.related-ticket-card
.related-ticket-card .card-header,
.related-ticket-card .card-body {
background: #F5FFFF !important;
overflow-y:auto;
box-shadow: 0 2px 4px 0 #00000040;
}
hr{
margin-top: 5px;
margin-bottom: 5px;
}
.related-ticket-card {
margin-bottom: 6px;
}
.related-ticket-card .card-body {
border-radius: 15px;
padding: 6px 15px !important;
}
.related-ticket-card h5,
.related-ticket-card p,
.related-ticket-card small {
margin: 0 !important;
}
</style>
<style>
/* Select2 box */
.select2-container .select2-selection--single {
background-color: #ECECEC !important;
border: 1px solid #ccc !important;
height: 38px !important;
}
/* Text inside */
.select2-container .select2-selection__rendered {
/* color: #000 !important; */
line-height: 36px !important;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background-color: #00999E !important;
}
</style>
<div class="row" id="notespage">
<h3 class="secondary-title">
<a href="#" onclick="history.back(); return false;">
<i class="mdi mdi-chevron-left" title="Back"></i>
</a>
<span>Ticket ID - <?= $master[0]['thz_id']; ?></span>
</h3>
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="row" id="notes-body">
<!-- Left Details -->
<div class="col-5" id="notes-body-left">
<div class="card master-card" style="background:#F5FFFF; border-radius: 15px;">
<div class="card-header d-flex justify-content-between align-items-center" style="background:none; border:none;">
<h3 class="mb-0">Details</h3>
<?php if($master[0]['status'] !== "Closed") : ?>
<a href="javascript:void(0);" onclick="openEditTicket()">
<i class="mdi mdi-pencil edit-icon" title="Edit"></i>
<!-- <i class="mdi mdi-pencil"
title="Edit"
style="font-size:15px; color:#555; cursor:pointer; transition:0.2s;"
onmouseover="this.style.color='#02a8b5'; this.style.fontSize='17px';"
onmouseout="this.style.color='#555'; this.style.fontSize='15px';">
</i> -->
</a>
<?php endif; ?>
</div>
<div class="card-body card-scroll " style="padding:0 27px !important; background:#F5FFFF; border-radius: 15px !important;">
<div class="row mb-2 ml-o">
<div class="col-4 app-subtitle app-text-grey ">Ticket ID</div>
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['thz_id'];?></div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Name</div>
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['name'];?></div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Mobile</div>
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['mobile'];?></div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Policy Number</div>
<div class="col-8 text-end font-color-black" style="font-weight: 500 !important;">
<?= (!empty($master[0]['policy_no']) && strtolower($master[0]['policy_no']) !== 'null')
? '<u class="font-color-black">
<a href="javascript:void(0);"
class="font-color-black"
data-toggle="modal"
data-target="#PolicyModal"
title="Click to view Policy Terms"
data-id="'.$master[0]['policy_id'].'">'
.$master[0]['policy_no'].'
</a>
</u>'
: 'N/A'; ?>
</div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Assigned To</div>
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['assignee_name'];?></div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Status</div>
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;">
<?= (!empty($master[0]['status']) && strtolower($master[0]['status']) !== 'null')
? '<u class="font-color-black">
<a href="javascript:void(0);"
class="font-color-black"
onclick="statusHistory('.$master[0]['thz_id'].')"
data-toggle="modal"
data-target="#StatusModal"
title="Click to view Status History">'
.$master[0]['status'].'
</a>
</u>'
: 'N/A'; ?>
</div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Ticket Type</div>
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important;"><?= $master[0]['ticket_type'];?></div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Subject</div>
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important; text-align: justify;"><?= $master[0]['subject'];?></div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Message</div>
<div class="col-8 font-color-black text-end " style="font-weight: 500 !important; text-align: justify;"><?= $master[0]['message'];?></div>
</div>
<div class="row mb-2">
<div class="col-4 app-subtitle app-text-grey ">Related Tickets</div>
<div class="col-8 text-end " style="font-weight: 500 !important;">
<u class="text-warning">
<a href="javascript:void(0);"
class="text-warning"
data-toggle="modal"
data-target="#relatedTicketModal"
title="<?= empty($master[0]['created_by']) ? 'No related tickets' : 'Click to view related tickets'; ?>"
data-id="<?= $master[0]['created_by']; ?>">
View
</a>
</u>
</div>
</div>
<!-- add more fields -->
</div>
</div>
</div>
<!-- Right Conversation -->
<div class="col-7" id="notes-body-right">
<!-- Conversation Card -->
<div class="card mb-3 conversation-card" style="background:#F5FFFF; border-radius: 15px !important;">
<div class="card-header d-flex justify-content-between align-items-center" style="background:none; border:none; padding-bottom: 0px; border-radius: 15px !important;">
<h3 class="font-color-black" >Conversation</h3>
</div>
<div class="card-body recard-scroll" style="padding:0 27px !important; margin:0 !important; background:#F5FFFF; border-radius: 15px !important;">
<?php if(!empty($notes)): ?>
<?php foreach($notes as $i => $conv): ?>
<div style="border:none; padding: 0px; margin: 0px;">
<hr/>
<!-- Top Row: Message + Badge -->
<div class="d-flex justify-content-between align-items-start font-color-black ">
<p class="mb-1 ml-0 mr-0 " style="font-weight: 400 !important;"><?= $conv['notes'] ?></p>
<!-- <?php if(!empty($conv['notes_by'])): ?>
<span class="badge bg-warning text-dark"><?= $conv['notes_by'] ?></span>
<?php endif; ?> -->
<?php if (!empty($conv['notes_type']) && $conv['notes_type'] === "Internal"): ?>
<span class="badge app-badge-secondary app-text-white " style="font-size:10px;"><?= $conv['notes_type'] ?></span>
<?php endif; ?>
</div>
<!-- Bottom Row: Name + Date -->
<div class="d-flex justify-content-between small text-muted" style="padding-top: 5px;">
<span class="" style="font-weight: 400 !important;"><i class="mdi mdi-account"></i> <?= $conv['name'] ?></span>
<span style="font-size:9px; font-weight: 400 !important;" class=""><?= date("j F Y h:i A", strtotime($conv['created_at'])) ?></span>
</div>
<!-- <?php echo $i < count($notes)-1 ? '<hr/>' : ''; ?> -->
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="d-flex justify-content-center align-items-center "
style="height: 45vh; width:100%;">
<p class="text-center font-color-black"><i>No Data Found</i></p>
</div>
<?php endif; ?>
</div>
</div>
<!-- Input Card -->
<div class="card">
<form id="conversationForm">
<input type="hidden" id="notes_type" name="notes_type">
<input type="hidden" id="thz_id" name="thz_id">
<input type="hidden" id="notes_by" name="notes_by" value="Staff">
<input type="hidden" id="created_by" name="created_by" value="<?= get_session_userid(); ?>">
<div class="notes-box">
<textarea class="form-control" id="notes" name="notes" placeholder="Write your notes here..." required maxlength="1500"></textarea>
<div class="icon-buttons">
<!-- save btn means local - internal -->
<button type="button" class="btn-icon" onclick="submitConverstionTicket('Internal', this)"><i class="mdi mdi-content-save"></i></button>
<!-- mail btn means notify - external -->
<button type="button" class="btn-icon" onclick="submitConverstionTicket('External', this)"><i class="mdi mdi-email"></i></button>
</div>
</div>
<small id="messageCounter" class="form-text text-muted text-end text-right">0/1500</small>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade font-color-black " id="EditModal" tabindex="-1" role="dialog" aria-hidden="true"
data-backdrop="static"
data-keyboard="false"
data-bs-backdrop="static"
data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<form id="ticketForm">
<div class="modal-header">
<h4 class="modal-title title-text" id="EditModalLabel" style="font-size:27px !important">Update</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" data-bs-dismiss="modal">×</button>
</div>
<div class="modal-body">
<div class="form-row">
<input type="hidden" id="edit_thz_id" name="thz_id">
<input type="hidden" id="updated_by" name="updated_by" value="<?= get_session_userid(); ?>">
<div class="form-group col-md-12">
<label for="ticket_type">Ticket Type<span class="text-danger">*</span></label>
<select class="form-control" id="ticket_type" name="ticket_type" required>
<option value="">Select Ticket Type</option>
<!-- <option value="Sales">Sales</option>
<option value="Service">Service</option> -->
<?php if (!empty($ticket_type)): ?>
<?php foreach ($ticket_type as $t): ?>
<option value="<?= esc($t['name']) ?>" >
<?= esc($t['name']) ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>
<div class="form-group col-md-12">
<label for="status">Status</label>
<select class="form-control" id="status" name="status">
<option value="">Select Status</option>
<option value="Open">Open</option>
<option value="In Progress">In Progress</option>
<option value="Resolved">Resolved</option>
<option value="Closed">Closed</option>
</select>
</div>
<!-- // enga 5-"head" and 1-"admin" assign pannvaga dropdown-data la varakudhathu. but dropdown display aganum
// 2,3,4 dropdown data'va varannum but dropdown hide pannanum -->
<?php if(in_array(get_role_id(), [1,5]) ) { ?>
<div class="form-group col-md-12">
<label for="assign_to">Assign To</label>
<select class="form-control" id="assign_to" name="assign_to">
<option value="">Select Assign To</option>
<?php if(isset($assignee)) { ?>
<?php foreach ($assignee as $a) { ?>
<option value="<?= $a['id']?>"><?= $a['emp_code'] ?> - <?= $a['first_name'] ?> <?= $a['last_name'] ?></option>
<?php } ?>
<?php } ?>
</select>
</div>
<?php } ?>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn app-btn-secondary" onclick="submitTicket()">Save</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade " id="relatedTicketModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content" style="border-radius:15px;">
<div class="modal-header" style="border-bottom-width:0;">
<h4 class="modal-title title-text " style="font-size:27px !important">Related Tickets</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" data-bs-dismiss="modal">×</button>
</div>
<div class="modal-body card-scroll" style="padding-top:5px!important;">
<?php if(!empty($related_tickets)): foreach($related_tickets as $j => $rt): ?>
<div class="card related-ticket-card app-text"
style="cursor: pointer;"
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-text"><?php echo '# '.$rt['thz_id']." / ".$rt['ticket_type']; ?></h5>
<small classs="" style="font-size:7px;">
<?php if (!empty($rt['created_at'])):
$cd = date("j F Y", strtotime($rt['created_at']));
$ct = date("h:i A", strtotime($rt['created_at']));
echo $cd . " " . $ct;
endif;
?>
</small>
</div>
<p class="mt-1 "
style="font-size:9px; font-weight:400; margin:4px;">
<?= $rt['subject'] ? $rt['subject'] : "&nbsp;"; ?>
</p>
<small class="" style="font-size:7px;"><span style="color: green !important; font-weight: 500;">Status: </span><?php echo $rt['status']; ?></small>
</div>
</div>
<?php endforeach;
else: ?>
<div class="d-flex justify-content-center align-items-center"
style="height: 50vh; width:100%;">
<p class="text-center font-color-black" ><i>No Data Found</i></p>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div class="modal fade " id="PolicyModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content" style="border-radius:15px;">
<div class="modal-header" style="border-bottom-width:0;">
<h4 class="modal-title title-text ">Policy Terms</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" data-bs-dismiss="modal">×</button>
</div>
<div class="modal-body card-scroll" style="padding-top:5px!important;">
<?php if(!empty($policy_terms)):
echo $policy_terms;
else: ?>
<div class="d-flex justify-content-center align-items-center"
style="height: 50vh; width:100%;">
<p class="text-center font-color-black"><i>No Data Found</i></p>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div class="modal fade " id="StatusModal" tabindex="-1" role="dialog" aria-hidden="true">
<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;">
<h4 class="modal-title title-text ">Status History</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" data-bs-dismiss="modal">×</button>
</div>
<div class="modal-body card-scroll history-container" style="padding:5px 11px 11px 11px!important;">
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
// Initialize select2
$("#ticket_type, #status, #assign_to").select2();
const messageInput = document.getElementById("notes");
const messageCounter = document.getElementById("messageCounter");
messageInput.addEventListener("input", function () {
const messageLength = messageInput.value.length;
messageCounter.textContent = `${messageLength}/1500`;
if (messageLength > 1500) {
toastr.error('Message cannot exceed 1500 characters', 'Warning');
messageInput.classList.add('is-invalid');
} else {
messageInput.classList.remove('is-invalid');
}
});
const btn = document.querySelector("button[onclick='submitTicket()']");
$("#ticket_type, #status, #assign_to").on('change', function() {
if (btn.disabled) {
btn.disabled = false;
btn.innerText = "Save";
}
});
});
function openEditTicket() {
var form = document.getElementById('ticketForm');
form.reset();
form.classList.remove('was-validated'); // remove Bootstrap validation styling
var btn = document.querySelector("button[onclick='submitTicket()']");
btn.disabled = false;
btn.innerText = "Save";
var masterData = <?= json_encode($master[0]); ?>;
console.log(masterData);
$("#edit_thz_id").val(masterData.thz_id);
// $("#updated_by").val("<?= get_session_userid(); ?>");
$("#ticket_type").val(masterData.ticket_type).trigger("change");
$("#status").val(masterData.status).trigger("change");
$("#assign_to").val(masterData.assign_to).trigger("change");
$("#EditModalLabel").text("Update #" + masterData.thz_id);
var myModal = new bootstrap.Modal(document.getElementById('EditModal'));
myModal.show();
}
function submitTicket() {
var form = document.getElementById("ticketForm");
var id = form.querySelector("[name='thz_id']").value;
var formData = new FormData(form);
form.classList.remove('was-validated');
var btn = document.querySelector("button[onclick='submitTicket()']");
btn.disabled = true;
btn.innerText = "Saving...";
var ticketType = document.getElementById('ticket_type').value.trim();
if (ticketType === "") {
toastr.warning('Please fill all required fields.', 'Warning');
form.classList.add('was-validated');
return;
}
$.ajax({
url: "<?= base_url('ticketSave') ?>",
type: "POST",
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(response) {
if (response.status === "success") {
toastr.success(response.message, 'Success');
$('#ticketModal').modal('hide');
form.reset();
window.location.href = "<?= base_url('ticketConversationList?return_type=web&thz_id=') ?>" + id;
} else {
toastr.error(response.message, 'Error');
}
},
error: function(xhr) {
if (xhr.status === 400) {
let response = JSON.parse(xhr.responseText);
if (response.errors) {
$.each(response.errors, function (field, message) {
toastr.warning(message, 'Validation Error');
});
} else {
toastr.warning(response.message || 'Validation failed', 'Warning');
}
}else{ toastr.error("Something went wrong!", 'Error'); }
console.error(xhr.responseText);
},
complete: function() {
btn.disabled = false;
btn.innerText = "Save";
}
});
}
function submitConverstionTicket(notetype,btn) {
btn.disabled = true;
document.getElementById("notes_type").value = notetype;
const urlParams = new URLSearchParams(window.location.search);
document.getElementById("thz_id").value = urlParams.get('thz_id');
var id = urlParams.get('thz_id');
var form = document.getElementById("conversationForm");
// reset any old error styles
form.classList.remove('was-validated');
var notes = document.getElementById('notes').value.trim();
if (notes === "") {
toastr.warning('Please enter notes', 'Warning');
form.classList.add('was-validated');
return;
}
var formData = new FormData(form);
$.ajax({
url: "<?= base_url('ticketConversationSave') ?>",
type: "POST",
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(response) {
if (response.status === "success") {
toastr.success(response.message, 'Success');
form.reset();
window.location.href = "<?= base_url('ticketConversationList?return_type=web&thz_id=') ?>" + id;
} else {
toastr.error(response.message, 'Error');
}
},
error: function(xhr) {
if (xhr.status === 400) {
let response = JSON.parse(xhr.responseText);
if (response.errors) {
$.each(response.errors, function (field, message) {
toastr.warning(message, 'Validation Error');
});
} else {
toastr.warning(response.message || 'Validation failed', 'Warning');
}
}else{
toastr.error("Something went wrong!", 'Error');
console.error(xhr.responseText);
}
},
complete: function() { btn.disabled = false;}
});
}
</script>
<script>
function statusHistory(thzId) {
console.log("*****");
$.ajax({
url: "<?= base_url('ticketHistoryList?thz_id=') ?>" + thzId,
type: "GET",
dataType: "json",
success: function(response) {
let container = $(".history-container");
container.empty(); // clear old content
if (response.status === "success" && response.data.length > 0) {
let table = `
<div class="table-responsive">
<table data-custom-table-css="table" class="table w-100 nowrap text-custom-black text-custom app-datatable">
<thead class="bg-light">
<tr>
<th class="app-text-white">S.No</th>
<th class="app-text-white">Old Status</th>
<th class="app-text-white">New Status</th>
<th class="app-text-white">Updated By</th>
<th class="app-text-white">Date/Time</th>
</tr>
</thead>
<tbody class="app-table-body">
`;
response.data.forEach((row, index) => {
table += `
<tr>
<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: 'long',
year: 'numeric'
});
let timeStr = dt.toLocaleTimeString('en-US', {
hour: '2-digit',
minute: '2-digit',
hour12: true
}).toLowerCase();
return `${dateStr} ${timeStr}`;
})()
: '-'
}</td>
</tr>
`;
});
table += `</tbody></table></div>`;
container.html(table);
} else {
container.html(`
<div class="d-flex justify-content-center align-items-center" style="height: 50vh; width:100%;">
<p class="text-center font-color-black"><i>${response.message ?? 'No history found'}</i></p>
</div>
`);
}
$("#StatusModal").modal("show");
},
error: function(xhr) {
$(".history-container").html(`
<div class="d-flex justify-content-center align-items-center" style="height: 50vh; width:100%;">
<p class="text-center font-color-black"><i>No Data Found</i></p>
</div>
`);
$("#StatusModal").modal("show");
// toastr.error("Something went wrong!", "Error");
console.error(xhr.responseText);
}
});
}
</script>