987 lines
40 KiB
PHP
987 lines
40 KiB
PHP
<?php
|
||
helper('datatable_view');
|
||
$thz_header_labels = [
|
||
'Ticket ID', 'Name', 'Policy Number', 'Ticket Type', 'Subject', 'Status', 'Assign To', 'Created At', 'Updated At',
|
||
];
|
||
$thz_col_count = count($thz_header_labels);
|
||
$thz_col_max_len = array_fill(0, $thz_col_count, 0);
|
||
for ($i = 0; $i < $thz_col_count; $i++) {
|
||
$thz_col_max_len[$i] = mb_strlen($thz_header_labels[$i]);
|
||
}
|
||
$ticket_data = $ticket_data ?? [];
|
||
foreach ($ticket_data as $row) {
|
||
$thz_col_max_len[0] = max($thz_col_max_len[0], mb_strlen((string) ($row['thz_id'] ?? '')));
|
||
$namePlain = (string) ($row['name'] ?? '');
|
||
if (! empty($row['empcode'])) {
|
||
$namePlain .= ' (' . $row['empcode'] . ')';
|
||
}
|
||
if (! empty($row['mobile'])) {
|
||
$namePlain .= ' ' . $row['mobile'];
|
||
}
|
||
$thz_col_max_len[1] = max($thz_col_max_len[1], mb_strlen($namePlain));
|
||
$pol = (! empty($row['policy_no']) && strtolower((string) $row['policy_no']) !== 'null') ? (string) $row['policy_no'] : 'N/A';
|
||
$thz_col_max_len[2] = max($thz_col_max_len[2], mb_strlen($pol));
|
||
$tt = $row['ticket_type'] ? (string) $row['ticket_type'] : 'N/A';
|
||
$thz_col_max_len[3] = max($thz_col_max_len[3], mb_strlen($tt));
|
||
$subject = $row['subject'] ? (string) $row['subject'] : 'N/A';
|
||
$subDisp = (strlen($subject) > 18) ? substr($subject, 0, 18) . '...' : $subject;
|
||
$thz_col_max_len[4] = max($thz_col_max_len[4], mb_strlen($subDisp));
|
||
$st = $row['status'] ? (string) $row['status'] : 'N/A';
|
||
$thz_col_max_len[5] = max($thz_col_max_len[5], mb_strlen($st));
|
||
$as = $row['assignee_name'] ? (string) $row['assignee_name'] : 'N/A';
|
||
$thz_col_max_len[6] = max($thz_col_max_len[6], mb_strlen($as));
|
||
$cr = '';
|
||
if (! empty($row['created_at'])) {
|
||
$cr = date('j M Y', strtotime((string) $row['created_at'])) . ' ' . date('h:i A', strtotime((string) $row['created_at']));
|
||
}
|
||
$thz_col_max_len[7] = max($thz_col_max_len[7], mb_strlen($cr));
|
||
$ur = '';
|
||
if (! empty($row['updated_at'])) {
|
||
$ur = date('j M Y', strtotime((string) $row['updated_at'])) . ' ' . date('h:i A', strtotime((string) $row['updated_at']));
|
||
}
|
||
$thz_col_max_len[8] = max($thz_col_max_len[8], mb_strlen($ur));
|
||
}
|
||
$thz_col_min_px = [72, 160, 120, 100, 120, 88, 120, 140, 140];
|
||
$thz_col_max_px = [120, 360, 280, 220, 400, 160, 280, 220, 220];
|
||
$thz_col_width_px = nhance_dt_column_widths_px($thz_header_labels, $thz_col_max_len, $thz_col_min_px, $thz_col_max_px);
|
||
?>
|
||
<style>
|
||
.table th,
|
||
.table td {
|
||
padding: 8px;
|
||
}
|
||
|
||
table.dataTable tbody td {
|
||
padding: 4px 4px !important;
|
||
}
|
||
|
||
.col-12 {
|
||
max-width: 98% !important;
|
||
}
|
||
|
||
.dataTables_filter {
|
||
position: absolute;
|
||
}
|
||
|
||
.column-header {
|
||
margin-right: 10px;
|
||
}
|
||
|
||
|
||
.btn {
|
||
font-size: 0.9rem;
|
||
padding: 0.5rem 1rem;
|
||
}
|
||
|
||
</style>
|
||
|
||
<style>
|
||
|
||
.text-custom-grey{
|
||
font-size: 0.85em;
|
||
color: #6c757d !important;
|
||
}
|
||
|
||
/* don't erase it. keep it safe
|
||
beccause = dataTables_length and dataTables_paginate need in same line thats why i tried in css ...
|
||
.dataTables_info,
|
||
.dataTables_length,
|
||
.dataTables_paginate {
|
||
display: flex;
|
||
align-items: center;
|
||
} */
|
||
|
||
.dataTables_length label {
|
||
height: 21px !important;
|
||
}
|
||
|
||
|
||
</style>
|
||
|
||
<style>
|
||
<?php for ($i = 0; $i < $thz_col_count; $i++) : ?>
|
||
#thz-table_wrapper .dataTables_scrollHead table thead th:nth-child(<?= $i + 1 ?>),
|
||
#thz-table thead th:nth-child(<?= $i + 1 ?>) {
|
||
min-width: <?= (int) $thz_col_width_px[$i] ?>px;
|
||
width: <?= (int) $thz_col_width_px[$i] ?>px;
|
||
box-sizing: border-box;
|
||
vertical-align: middle;
|
||
overflow: visible !important;
|
||
}
|
||
#thz-table tbody td:nth-child(<?= $i + 1 ?>) {
|
||
width: <?= (int) $thz_col_width_px[$i] ?>px;
|
||
max-width: <?= (int) $thz_col_width_px[$i] ?>px;
|
||
min-width: <?= (int) $thz_col_width_px[$i] ?>px;
|
||
box-sizing: border-box;
|
||
vertical-align: middle;
|
||
}
|
||
<?php endfor; ?>
|
||
#thz-table tbody td:nth-child(1),
|
||
#thz-table tbody td:nth-child(2),
|
||
#thz-table tbody td:nth-child(3),
|
||
#thz-table tbody td:nth-child(4),
|
||
#thz-table tbody td:nth-child(5),
|
||
#thz-table tbody td:nth-child(6),
|
||
#thz-table tbody td:nth-child(7),
|
||
#thz-table tbody td:nth-child(8),
|
||
#thz-table tbody td:nth-child(9) {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
#thz-table tbody td {
|
||
padding: 5px 11px !important;
|
||
font-size: 13px;
|
||
line-height: 1.25;
|
||
}
|
||
#thz-table thead th {
|
||
padding: 5px 2.35rem 5px 11px !important;
|
||
font-size: 13px;
|
||
line-height: 1.25;
|
||
}
|
||
</style>
|
||
|
||
<div class="row" id="ticket_list">
|
||
<div class="col-12">
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<div>
|
||
<div class="table-responsive">
|
||
<table data-custom-table-css="table" class="table mb-0 nowrap w-100 table-centered" cellspacing="0" id="thz-table">
|
||
|
||
<thead class="bg-light">
|
||
<tr>
|
||
<th><div class="column-header">Ticket ID </div></th>
|
||
<th class="text-left"><div class="column-header">Name </div></th>
|
||
<th><div class="column-header">Policy Number </div></th>
|
||
<th><div class="column-header">Ticket Type </div></th>
|
||
<th><div class="column-header">Subject </div></th>
|
||
<th><div class="column-header">Status </div></th>
|
||
<th class="text-left"><div class="column-header">Assign To </div></th>
|
||
<th><div class="column-header">Created At </div></th>
|
||
<th><div class="column-header">Updated At </div></th>
|
||
</tr>
|
||
</thead>
|
||
|
||
<tbody class="app-table-body">
|
||
<?php if(isset($ticket_data)) { ?>
|
||
<?php foreach($ticket_data as $index => $row){ ?>
|
||
<tr data-id="<?= $row['thz_id']; ?>" style="cursor: pointer;">
|
||
<td><?php echo $row['thz_id']; ?></td>
|
||
<td class="text-left"><?php echo $row['name']; ?>
|
||
<span class="text-custom-grey"><?php if (!empty($row['empcode'])): echo '('.$row['empcode'].')'; endif; ?></span><br>
|
||
<span class="text-custom-grey"><?php if (!empty($row['mobile'])): echo $row['mobile']; endif; ?></span>
|
||
</td>
|
||
<td class="text-center"><?php echo (!empty($row['policy_no']) && strtolower($row['policy_no']) !== 'null')
|
||
? $row['policy_no']
|
||
: 'N/A'; ?>
|
||
</td>
|
||
<td class="text-center"><?php echo $row['ticket_type'] ? $row['ticket_type'] : 'N/A'; ?></td>
|
||
<td class="text-center wrap" title="<?php echo htmlspecialchars($row['subject']); ?>">
|
||
<?php
|
||
$subject = $row['subject'] ? $row['subject'] : 'N/A';
|
||
echo (strlen($subject) > 18)
|
||
? htmlspecialchars(substr($subject, 0, 18)) . "..."
|
||
: htmlspecialchars($subject);
|
||
?>
|
||
</td>
|
||
<td class="text-center"><?php echo $row['status'] ? $row['status'] : 'N/A' ; ?></td>
|
||
<td class="text-left"><?php echo $row['assignee_name'] ? $row['assignee_name'] : 'N/A'; ?></td>
|
||
<td class="text-left">
|
||
<?php if (!empty($row['created_at'])):
|
||
$cd = date("j/m/Y", strtotime($row['created_at']));
|
||
$ct = date("h:i A", strtotime($row['created_at']));
|
||
echo $cd . "<br><span class='time'> " . $ct . "</span>";
|
||
endif;
|
||
?>
|
||
</td>
|
||
<td class="text-left">
|
||
<?php if (!empty($row['updated_at'])):
|
||
$ud = date("j/m/Y", strtotime($row['updated_at']));
|
||
$ut = date("h:i A", strtotime($row['updated_at']));
|
||
echo $ud . "<br><span class='time'> " . $ut . "</span>";
|
||
endif;
|
||
?>
|
||
</td>
|
||
</tr>
|
||
<?php } ?>
|
||
<?php } else { ?>
|
||
<tr>
|
||
<td colspan="9" class="text-center">No data available</td>
|
||
</tr>
|
||
<?php } ?>
|
||
</tbody>
|
||
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><!-- end col -->
|
||
</div>
|
||
|
||
<div class="modal fade " id="ticketModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||
<div class="modal-dialog modal-dialog-centered modal-xl" style="margin:5px auto!important;">
|
||
<div class="modal-content">
|
||
<form class="parsley-examples" id="ticketForm">
|
||
<!-- <div class="modal-header">
|
||
<h4 class="modal-title" id="modalLabel">New Ticket</h4>
|
||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||
</div> -->
|
||
<div class="modal-header flex-column">
|
||
|
||
<!-- first row -->
|
||
<div class="d-flex w-100 justify-content-between align-items-center">
|
||
<h4 class="modal-title mb-0" id="modalLabel" style="font-size:27px !important">New Ticket</h4>
|
||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||
</div>
|
||
|
||
<!-- second row -->
|
||
<div class="form-row mt-3 w-100 ">
|
||
<div class="form-group col-md-6 ">
|
||
<label for="client_id">Client</label>
|
||
<select class="form-control app-field-grey font-color-black" id="client_id" name="client_id">
|
||
<option value="">Select Client</option>
|
||
<?php if(isset($client_list)) { ?>
|
||
<?php foreach ($client_list as $c) { ?>
|
||
<option value="<?= $c->id ?>"><?= $c->client_name ?> (<?= $c->short_name ?>) </option>
|
||
<?php } ?>
|
||
<?php } ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group col-md-5 ">
|
||
<label for="mobile">Mobile<span class="text-danger">*</span></label>
|
||
<input type="tel" class="form-control app-field-grey" id="mobile" placeholder="Enter Mobile Number"
|
||
name="mobile"
|
||
required pattern="[0-9]{10}" maxlength="10" inputmode="numeric"
|
||
oninput="this.value=this.value.replace(/[^0-9]/g,'');"
|
||
title="Please enter a valid 10-digit mobile number">
|
||
<small class="text-danger d-block mt-1 field-error" id="mobile_error"></small>
|
||
</div>
|
||
|
||
<div class="form-group col-md-1" style="padding:32.5px 0 0 18px;">
|
||
<button type="button" class="btn-custom app-btn-primary " style="padding: 0 10px !important; border-radius:13px;" onclick="getAutoFetchDetails()"><i class="mdi mdi-cached " style="font-size:24px;"></i></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-body" style="padding: 12px 15px 0px 15px !important;">
|
||
<div class="form-row">
|
||
<input type="hidden" id="thz_id" name="thz_id">
|
||
<input type="hidden" id="return_type" name="return_type">
|
||
<input type="hidden" id="branch_id" name="branch_id">
|
||
<input type="hidden" id="policy_id" name="policy_id">
|
||
<input type="hidden" id="created_by" name="created_by" value="<?= get_session_userid(); ?>">
|
||
|
||
<div class="form-group col-md-4 ">
|
||
<label for="name">Name<span class="text-danger">*</span></label>
|
||
<input type="text" class="form-control" id="name" name="name" placeholder="Enter Name" required>
|
||
<small class="text-danger d-block mt-1 field-error" id="name_error"></small>
|
||
</div>
|
||
|
||
<div class="form-group col-md-4 ">
|
||
<label for="email">Email Id<span class="text-danger">*</span></label>
|
||
<input type="email" class="form-control" id="email"
|
||
name="email" placeholder="Enter Email"
|
||
required
|
||
title="Please enter a valid email address">
|
||
<small class="text-danger d-block mt-1 field-error" id="email_error"></small>
|
||
</div>
|
||
|
||
<div class="form-group col-md-4 ">
|
||
<label for="empcode">Employee code</label>
|
||
<input type="text" class="form-control" id="empcode" name="empcode" placeholder="Enter Employee code">
|
||
<small class="text-danger d-block mt-1 field-error" id="empcode_error"></small>
|
||
</div>
|
||
|
||
|
||
<div class="form-group col-md-4 ">
|
||
<label for="ticket_type">Ticket Type<span class="text-danger">*</span></label>
|
||
<select class="form-control" id="ticket_type" name="ticket_type" required onchange="hideandshowpolicy()">
|
||
<option value="">Select Ticket Type</option>
|
||
<!-- <option value="Sales" selected >Sales</option> -->
|
||
<!-- <option value="Service">Service</option> -->
|
||
<!-- <option value="0">+ Add New</option> -->
|
||
<?php if (!empty($ticket_type)): ?>
|
||
<?php foreach ($ticket_type as $t): ?>
|
||
<option value="<?= esc($t['name']) ?>"
|
||
<?= (strtolower($t['name']) === "sales") ? 'selected' : '' ?>>
|
||
<?= esc($t['name']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</select>
|
||
<small class="text-danger d-block mt-1 field-error" id="ticket_type_error"></small>
|
||
</div>
|
||
|
||
<div class="form-group col-md-4 " id="policy_container">
|
||
<label for="policy_no">Policy Number</label>
|
||
<select class="form-control" id="policy_no" name="policy_no" onchange="changevalue()">
|
||
<option value="" selected data-id="">Select Policy</option>
|
||
</select>
|
||
</div>
|
||
|
||
|
||
<!-- <div class="form-group col-md-6">
|
||
<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,2,5])): ?>
|
||
<div class="form-group col-md-4">
|
||
<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 (!empty($assignee)): ?>
|
||
<?php foreach ($assignee as $a): ?>
|
||
<option value="<?= esc($a['id']) ?>">
|
||
<?= esc($a['emp_code']) ?> - <?= esc($a['first_name']) ?> <?= esc($a['last_name']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</select>
|
||
<small class="text-danger d-block mt-1 field-error" id="assign_to_error"></small>
|
||
</div>
|
||
<?php else: ?>
|
||
<input type="hidden" id="hide_assign_to" name="assign_to" value="<?= esc(get_session_userid()); ?>">
|
||
<?php endif; ?>
|
||
|
||
<!-- <div class="form-group col-md-12 ">
|
||
<label for="subject">Subject<span class="text-danger">*</span></label>
|
||
<small id="subjectCounter" class="form-text text-muted text-right">0/150</small>
|
||
</div> -->
|
||
<div class="form-group col-md-12 ">
|
||
<div class="d-flex justify-content-between">
|
||
<label for="subject" class="mb-1">Subject <span class="text-danger">*</span></label>
|
||
<small id="subjectCounter" class="form-text text-muted">0/150</small>
|
||
</div>
|
||
<input type="text" class="form-control" id="subject" name="subject" placeholder="Enter Subject" required maxlength="150">
|
||
<small class="text-danger d-block mt-1 field-error" id="subject_error"></small>
|
||
</div>
|
||
|
||
<div class="form-group col-md-12 ">
|
||
<div class="d-flex justify-content-between">
|
||
<label for="message">Message<span class="text-danger">*</span></label>
|
||
<small id="messageCounter" class="form-text text-muted text-end text-right">0/1500</small>
|
||
</div>
|
||
<!-- <input type="text" class="form-control" id="message" name="message" placeholder="Enter Message"> -->
|
||
<textarea class="form-control" id="message" name="message" placeholder="Enter Message" rows="3" required maxlength="1500"></textarea>
|
||
<small class="text-danger d-block mt-1 field-error" id="message_error"></small>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn app-btn-primary mr-2 " onclick="resetTicket()">Reset</button>
|
||
<button type="submit" class="btn app-btn-secondary " onclick="submitTicket(event)">Save</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="modal fade " id="AssignModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||
<div class="modal-dialog modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h4 class="modal-title" id="assignModalLabel">Ticket</h4>
|
||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="form-row">
|
||
<input type="hidden" id="hidden_thz_id" name="hidden_thz_id">
|
||
<div class="form-group col-md-12">
|
||
<label for="modal_assignee">Assign To<span class="text-danger">*</span></label>
|
||
<select class="form-control" id="modal_assignee" name="modal_assignee" required>
|
||
<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>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn-custom app-btn-secondary " onclick="updateAssignTo()">Save</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
<script>
|
||
|
||
// Datatable document ready
|
||
$(document).ready(function() {
|
||
|
||
var ticketsTable = $('#thz-table');
|
||
|
||
if (ticketsTable.length) {
|
||
nhanceListDataTableBeforeInit();
|
||
var nhThzTable = ticketsTable.DataTable(nhanceMergeListDataTableOptions({
|
||
// dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right
|
||
// "<'row'<'col-sm-12'tr>>" +
|
||
// "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector
|
||
dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right
|
||
"<'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>>",
|
||
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
|
||
buttons: [
|
||
{
|
||
text: '<i class="mdi mdi-plus" ></i><span class=" btn-custom"> Add </span>',
|
||
className: 'btn app-btn-primary mr-2',
|
||
action: function(e, dt, node, config) {
|
||
openTicket();
|
||
}
|
||
},
|
||
{
|
||
extend: 'collection',
|
||
text: '<span class=" btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>',
|
||
className: 'btn app-btn-secondary ',
|
||
buttons: [
|
||
{
|
||
extend: 'csv',
|
||
text: '<i class="mdi mdi-file-delimited " ></i><span class=" btn-custom"> CSV </span>',
|
||
className: 'app-btn-primary ',
|
||
title: 'Tickets',
|
||
},
|
||
{
|
||
extend: 'excel',
|
||
text: '<i class="mdi mdi-file-excel " ></i><span class=" btn-custom"> EXCEL </span>',
|
||
exportOptions: {
|
||
orthogonal: 'sort'
|
||
},
|
||
className: 'app-btn-primary ',
|
||
title: 'Tickets',
|
||
sheetName: 'Tickets',
|
||
}
|
||
]
|
||
}
|
||
],
|
||
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>
|
||
<i class="mdi mdi-close-circle datatable-clear-icon"
|
||
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
|
||
</div>`,
|
||
searchPlaceholder: "Search",
|
||
emptyTable: '<div class="text-center text-muted">No Data found</div>'
|
||
},
|
||
paging: true,
|
||
pageLength: 10,
|
||
order: [[0, 'desc']],
|
||
columnDefs: [
|
||
<?php for ($i = 0; $i < $thz_col_count; $i++) : ?>
|
||
{ targets: <?= $i ?>, width: '<?= (int) $thz_col_width_px[$i] ?>px' },
|
||
<?php endfor; ?>
|
||
],
|
||
}));
|
||
nhanceListDataTableAfterInit();
|
||
nhanceListDataTableBindAdjust(nhThzTable);
|
||
} else {
|
||
console.error("Table not found.");
|
||
}
|
||
|
||
$(document).on('click', '.datatable-clear-icon', function () {
|
||
const input = $(this).closest('.datatable-search-wrapper').find('input');
|
||
input.val('').trigger('input');
|
||
$('#thz-table').DataTable().search('').draw();
|
||
});
|
||
});
|
||
|
||
|
||
function openTicket(){
|
||
var form = document.getElementById('ticketForm');
|
||
form.reset();
|
||
$("#client_id").select2();
|
||
$("#ticket_type").select2();
|
||
clearAllFieldErrors();
|
||
document.getElementById('thz_id').value = '';
|
||
document.getElementById('modalLabel').innerText = "New Ticket";
|
||
document.getElementById('return_type').innerText = "Web";
|
||
var myModal = new bootstrap.Modal(document.getElementById('ticketModal'));
|
||
myModal.show();
|
||
}
|
||
|
||
function resetTicket(){
|
||
var form = document.getElementById('ticketForm');
|
||
form.reset();
|
||
$("#client_id").select2();
|
||
$("#ticket_type").select2();
|
||
clearAllFieldErrors();
|
||
}
|
||
|
||
function showFieldError(fieldId, message) {
|
||
var field = document.getElementById(fieldId);
|
||
var error = document.getElementById(fieldId + "_error");
|
||
if (!field || !error) return;
|
||
error.textContent = message || "";
|
||
if (message) {
|
||
field.classList.add("is-invalid");
|
||
} else {
|
||
field.classList.remove("is-invalid");
|
||
}
|
||
}
|
||
|
||
function clearAllFieldErrors() {
|
||
document.querySelectorAll(".field-error").forEach(function (el) {
|
||
el.textContent = "";
|
||
});
|
||
["mobile", "name", "email", "empcode", "ticket_type", "assign_to", "subject", "message"].forEach(function (id) {
|
||
var field = document.getElementById(id);
|
||
if (field) field.classList.remove("is-invalid");
|
||
});
|
||
}
|
||
|
||
function validateMobile(value) {
|
||
if (!value) return "Mobile number is required";
|
||
if (!/^[0-9]{10}$/.test(value)) return "Mobile number must be exactly 10 digits";
|
||
return "";
|
||
}
|
||
|
||
function validateName(value) {
|
||
if (!value) return "Name is required";
|
||
if (value.length < 3) return "Name must be at least 3 characters";
|
||
if (value.length > 100) return "Name must be at most 100 characters";
|
||
if (!/^[A-Za-z ]+$/.test(value)) return "Name can contain only letters and spaces";
|
||
return "";
|
||
}
|
||
|
||
function validateEmail(value) {
|
||
if (!value) return "Email address is required.";
|
||
if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
|
||
return "Please enter a valid email format (e.g., name@domain.com).";
|
||
}
|
||
return "";
|
||
}
|
||
|
||
function validateEmpcode(value) {
|
||
if (!value) return "";
|
||
if (value.length > 50) return "Employee code is too long";
|
||
if (!/^[A-Za-z0-9 ~!#\$%\^&\*\(\)_\+\-\=\{\}\[\]\|:;\"'<>,\.\/\?`]+$/.test(value)) {
|
||
return "Employee code contains invalid characters.";
|
||
}
|
||
return "";
|
||
}
|
||
|
||
function validateTicketType(value) {
|
||
if (!value) return "Ticket Type is required";
|
||
return "";
|
||
}
|
||
|
||
function validateAssignTo(value) {
|
||
if (!value) return "";
|
||
if (!/^\d+$/.test(value)) return "Invalid assignee selected";
|
||
return "";
|
||
}
|
||
|
||
function validateSubject(value) {
|
||
if (!value) return "Subject is required.";
|
||
if (value.length < 3) return "Subject must be at least 3 characters long.";
|
||
if (value.length > 150) return "Subject cannot exceed 150 characters";
|
||
if (!/^[a-zA-Z0-9 .,\-_()&\/\?]+$/.test(value)) {
|
||
return "Subject contains invalid characters (Avoid quotes and special symbols).";
|
||
}
|
||
return "";
|
||
}
|
||
|
||
function validateMessage(value) {
|
||
if (!value) return "Message is required";
|
||
if (value.length < 10) return "Message must be at least 10 characters";
|
||
if (value.length > 1500) return "Message cannot exceed 1500 characters";
|
||
return "";
|
||
}
|
||
|
||
function validateField(fieldId) {
|
||
var field = document.getElementById(fieldId);
|
||
if (!field) return true;
|
||
var value = (field.value || "").trim();
|
||
var error = "";
|
||
switch (fieldId) {
|
||
case "mobile": error = validateMobile(value); break;
|
||
case "name": error = validateName(value); break;
|
||
case "email": error = validateEmail(value); break;
|
||
case "empcode": error = validateEmpcode(value); break;
|
||
case "ticket_type": error = validateTicketType(value); break;
|
||
case "assign_to": error = validateAssignTo(value); break;
|
||
case "subject": error = validateSubject(value); break;
|
||
case "message": error = validateMessage(value); break;
|
||
}
|
||
showFieldError(fieldId, error);
|
||
return !error;
|
||
}
|
||
|
||
function validateTicketForm() {
|
||
var fields = ["mobile", "name", "email", "empcode", "ticket_type", "subject", "message"];
|
||
if (document.getElementById("assign_to")) {
|
||
fields.push("assign_to");
|
||
}
|
||
|
||
var firstInvalid = null;
|
||
var isValid = true;
|
||
fields.forEach(function (fieldId) {
|
||
var ok = validateField(fieldId);
|
||
if (!ok && !firstInvalid) firstInvalid = document.getElementById(fieldId);
|
||
if (!ok) isValid = false;
|
||
});
|
||
|
||
if (!isValid && firstInvalid) firstInvalid.focus();
|
||
return isValid;
|
||
}
|
||
|
||
function submitTicket(event) {
|
||
|
||
event.preventDefault();
|
||
|
||
var form = document.getElementById('ticketForm');
|
||
if (!validateTicketForm()) {
|
||
toastr.warning('Please correct highlighted fields.', 'Warning');
|
||
return;
|
||
}
|
||
|
||
var form = document.getElementById("ticketForm"); // your form ID
|
||
var formData = new FormData(form);
|
||
|
||
var btn = event.target;
|
||
btn.disabled = true;
|
||
btn.innerText = "Saving...";
|
||
|
||
$.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('ticketList?return_type=web') ?>";
|
||
} else {
|
||
toastr.error(response.message, 'Error');
|
||
}
|
||
},
|
||
error: function(xhr) {
|
||
console.error(xhr.responseText);
|
||
if (xhr.status === 400) {
|
||
let response = JSON.parse(xhr.responseText);
|
||
clearAllFieldErrors();
|
||
let errorMessages = "";
|
||
let seenMessages = []; // Array to store unique messages
|
||
if (response.errors) {
|
||
$.each(response.errors, function (field, message) {
|
||
showFieldError(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');
|
||
}
|
||
},
|
||
complete: function() {
|
||
btn.disabled = false;
|
||
btn.innerText = "Save";
|
||
}
|
||
});
|
||
}
|
||
|
||
</script>
|
||
|
||
|
||
<script>
|
||
function getAutoFetchDetails() {
|
||
var client_id = document.getElementById('client_id').value.trim();
|
||
var mobile = document.getElementById('mobile').value.trim();
|
||
|
||
// reset fields
|
||
document.getElementById('name').value = "";
|
||
document.getElementById('email').value = "";
|
||
document.getElementById('empcode').value = "";
|
||
document.getElementById('branch_id').value = "";
|
||
document.getElementById('policy_id').value = "";
|
||
|
||
// reset select dropdown
|
||
var policySelect = document.getElementById('policy_no');
|
||
policySelect.innerHTML = '<option value="" data-id="">Select Policy</option>';
|
||
|
||
if (client_id === "") {
|
||
toastr.warning('Please Select Client.', 'Warning');
|
||
return;
|
||
}
|
||
|
||
if (mobile === "") {
|
||
toastr.warning('Please Enter a mobile number.', 'Warning');
|
||
return;
|
||
}
|
||
|
||
var mobilePattern = /^[0-9]{10}$/;
|
||
if (!mobilePattern.test(mobile)) {
|
||
toastr.warning('Please enter a valid 10-digit mobile number.', 'Warning');
|
||
document.getElementById('mobile').focus();
|
||
return;
|
||
}
|
||
|
||
$.ajax({
|
||
url: "<?= base_url('ticketAutoFetchDetails') ?>",
|
||
type: "POST",
|
||
data: { client_id: client_id, mobile: mobile },
|
||
dataType: 'json',
|
||
success: function(response) {
|
||
if (response.status === "success") {
|
||
let client = response.data.client_details[0];
|
||
let policies = response.data.policy_details;
|
||
|
||
document.getElementById('name').value = client.name || "";
|
||
document.getElementById('email').value = client.email_corporate || "";
|
||
document.getElementById('empcode').value = client.emp_code || "";
|
||
document.getElementById('branch_id').value = client.branch_id || "";
|
||
|
||
if (policies && policies.length > 0) {
|
||
policies.forEach(function(p) {
|
||
let opt = document.createElement("option");
|
||
opt.value = p.policy_no;
|
||
opt.text = p.policy_no;
|
||
opt.setAttribute("data-id", p.id);
|
||
policySelect.appendChild(opt);
|
||
});
|
||
|
||
// If you want to auto-select the first real policy instead of "Select Policy"
|
||
policySelect.value = policies[0].policy_no;
|
||
document.getElementById('policy_no').value = policies[0].policy_no || "";
|
||
document.getElementById('policy_id').value = policies[0].id;
|
||
}
|
||
} else {
|
||
toastr.warning(response.message || "No details found.", 'Warning');
|
||
}
|
||
},
|
||
error: function(xhr) {
|
||
toastr.error("Something went wrong!", 'Error');
|
||
console.error(xhr.responseText);
|
||
}
|
||
});
|
||
}
|
||
|
||
</script>
|
||
|
||
<script>
|
||
function changevalue() {
|
||
var select = document.getElementById('policy_no');
|
||
var selectedOption = select.options[select.selectedIndex];
|
||
var policyId = selectedOption.getAttribute("data-id");
|
||
document.getElementById('policy_id').value = policyId || "";
|
||
}
|
||
|
||
// function hideandshowpolicy() {
|
||
// var select = document.getElementById('ticket_type').value;
|
||
// var policyContainer = document.getElementById('policy_container');
|
||
|
||
// if (select === 'Service') {
|
||
// policyContainer.style.display = "block"; // show
|
||
// } else {
|
||
// policyContainer.style.display = "none"; // hide
|
||
// document.getElementById('policy_no').value = "";
|
||
// document.getElementById('policy_id').value = "";
|
||
// }
|
||
// }
|
||
|
||
function hideandshowpolicy() {
|
||
var select = document.getElementById('ticket_type');
|
||
var value = select.value;
|
||
var policyContainer = document.getElementById('policy_container');
|
||
|
||
if (value === "0") {
|
||
let newType = prompt("Enter new ticket type:");
|
||
if (newType && newType.trim() !== "") {
|
||
|
||
var formData = new FormData(form);
|
||
|
||
$.ajax({
|
||
url: "<?= base_url('ticketType') ?>",
|
||
type: "POST",
|
||
data: formData,
|
||
processData: false,
|
||
contentType: false,
|
||
dataType: 'json',
|
||
success: function(response) {
|
||
if (response.status === "success") {
|
||
|
||
let option = new Option(newType, newType);
|
||
let addNewOption = select.querySelector('option[value="0"]');
|
||
select.insertBefore(option, addNewOption);
|
||
select.value = newType;
|
||
value = newType;
|
||
console.log(response.message);
|
||
|
||
} else { console.log(response.message); value = ""; }
|
||
},
|
||
error: function(xhr) { console.log("Error: " + xhr.statusText); value = ""; }
|
||
});
|
||
} else {
|
||
select.value = "";
|
||
value = "";
|
||
}
|
||
}
|
||
|
||
if (value === 'Service') {
|
||
policyContainer.style.display = "block";
|
||
} else {
|
||
policyContainer.style.display = "none";
|
||
document.getElementById('policy_no').value = "";
|
||
document.getElementById('policy_id').value = "";
|
||
}
|
||
|
||
}
|
||
</script>
|
||
|
||
<script>
|
||
|
||
function updateAssignTo(){
|
||
console.log('function called then call the api then refresh the updateAssignTo');
|
||
}
|
||
|
||
</script>
|
||
|
||
|
||
|
||
<!-------------------------------------------------------------------------------------------------->
|
||
|
||
<script>
|
||
$(document).ready(function() {
|
||
$('[data-toggle="tooltip"]').tooltip();
|
||
// Initialize select2
|
||
$("#client_id").select2();
|
||
$("#ticket_type").select2();
|
||
$("#status").select2();
|
||
$("#assign_to").select2();
|
||
$("#policy_no").select2();
|
||
$("#modal_assignee").select2();
|
||
hideandshowpolicy();
|
||
|
||
const subjectInput = document.getElementById("subject");
|
||
const subjectCounter = document.getElementById("subjectCounter");
|
||
|
||
subjectInput.addEventListener("input", function () {
|
||
const subjectLength = subjectInput.value.length;
|
||
subjectCounter.textContent = `${subjectLength}/150`;
|
||
|
||
if (subjectLength > 150) {
|
||
subjectInput.classList.add('is-invalid');
|
||
} else {
|
||
subjectInput.classList.remove('is-invalid');
|
||
}
|
||
validateField("subject");
|
||
});
|
||
|
||
|
||
const messageInput = document.getElementById("message");
|
||
const messageCounter = document.getElementById("messageCounter");
|
||
|
||
messageInput.addEventListener("input", function () {
|
||
const messageLength = messageInput.value.length;
|
||
messageCounter.textContent = `${messageLength}/1500`;
|
||
|
||
if (messageLength > 1500) {
|
||
messageInput.classList.add('is-invalid');
|
||
} else {
|
||
messageInput.classList.remove('is-invalid');
|
||
}
|
||
validateField("message");
|
||
});
|
||
|
||
[
|
||
{ id: "mobile", event: "input" },
|
||
{ id: "name", event: "input" },
|
||
{ id: "email", event: "input" },
|
||
{ id: "empcode", event: "input" },
|
||
{ id: "ticket_type", event: "change" },
|
||
{ id: "assign_to", event: "change" }
|
||
].forEach(function (cfg) {
|
||
var el = document.getElementById(cfg.id);
|
||
if (el) {
|
||
el.addEventListener(cfg.event, function () {
|
||
validateField(cfg.id);
|
||
});
|
||
}
|
||
});
|
||
|
||
|
||
});
|
||
|
||
function viewTicket(ticket_id){
|
||
|
||
// $('.loader').fadeIn();
|
||
// $('.loader-mask').fadeIn();
|
||
|
||
let url = '<?= base_url('ticketConversationList?return_type=web&thz_id='); ?>' + ticket_id;
|
||
window.location.href = url;
|
||
|
||
|
||
}
|
||
|
||
function removeticket(input, ticket_id) {
|
||
|
||
confirmActionSweertAlert("Do you want to delete this ticket?", "Yes, Proceed!", "No, Cancel").then((confirmed) => {
|
||
if (confirmed) {
|
||
let url = '<?= base_url('ticket/remove') ?>';
|
||
|
||
// Include `pt_id` in the AJAX request if necessary
|
||
let requestData = { ticket_id: ticket_id };
|
||
|
||
sendAjaxRequestForGlobal(url, 'GET', requestData, function(response) {
|
||
console.log('Data fetched successfully:', response);
|
||
|
||
if (response.status === true) {
|
||
toastr.success(response.message, 'Success');
|
||
window.location.reload();
|
||
} else {
|
||
toastr.warning(response.message, 'Warning');
|
||
}
|
||
}, function(xhr, status, error) {
|
||
console.error('Error fetching data:', error);
|
||
console.error(xhr.responseText);
|
||
});
|
||
}
|
||
});
|
||
|
||
}
|
||
|
||
$(document).on('click', 'tbody tr', function (e) {
|
||
// Exclude clicks on any elements inside the last column (actions)
|
||
if ($(e.target).closest('td').index() !== $(this).children('td').length - 1) {
|
||
const id = $(this).data('id');
|
||
console.log('Ticket ID', id)
|
||
viewTicket(id);
|
||
}
|
||
});
|
||
|
||
|
||
</script>
|