This portal only for GCC Officers. Based on there roles and Group ID they can view there module`s Like PGR, QR Public Asset Feedback, Makkalai Thedi Mayor,etc...
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

902 lines
32 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/modules/base/head :: head}">
  4. </head>
  5. <style>
  6. .required {
  7. color: red;
  8. }
  9. .card-box {
  10. box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 8px;
  11. height: 140px;
  12. }
  13. @media ( max-width : 768px) {
  14. .card-box {
  15. text-align: center;
  16. }
  17. }
  18. /* .d-none {
  19. display: none;
  20. } */
  21. .custom-width1 {
  22. width: 120px; /* Adjust the width as needed */
  23. }
  24. #modalBody h4 {
  25. font-weight: bold;
  26. margin-top: 15px;
  27. margin-bottom: 10px;
  28. }
  29. #modalBody p {
  30. margin: 5px 0;
  31. }
  32. #modalBody hr {
  33. margin: 15px 0;
  34. }
  35. .comment {
  36. margin-bottom: 20px;
  37. }
  38. .comment p {
  39. margin: 0;
  40. }
  41. hr {
  42. border: 1px solid #ccc;
  43. }
  44. .col-4 {
  45. font-weight: bold;
  46. text-align: right;
  47. }
  48. .col-8 {
  49. padding-left: 20px;
  50. }
  51. .comment {
  52. padding: 10px 0;
  53. }
  54. .comment .text-muted {
  55. font-size: 0.9em;
  56. color: #6c757d;
  57. }
  58. .comment hr {
  59. border-top: 1px solid #ccc;
  60. }
  61. .comment .btn-link {
  62. font-size: 0.9em;
  63. text-decoration: underline;
  64. color: #007bff;
  65. }
  66. /* Make the modal body scrollable */
  67. #detailsModal .modal-body {
  68. max-height: 70vh; /* Limit the height to 70% of the viewport */
  69. overflow-y: auto; /* Enable vertical scrolling */
  70. }
  71. </style>
  72. <body>
  73. <div class="wrapper">
  74. <!-- Header -->
  75. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  76. <div class="page-wrap">
  77. <!-- Left Menu -->
  78. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  79. <div class="main-content">
  80. <div class="container-fluid">
  81. <div class="page-header">
  82. <div class="row align-items-end">
  83. <div class="col-lg-6">
  84. <div class="page-header-title">
  85. <i class="ik ik-layers bg-blue"></i>
  86. <div class="d-inline">
  87. <h5>Agent's Inprogress Calls</h5>
  88. <span>1913 Inprogress Call List</span>
  89. </div>
  90. </div>
  91. </div>
  92. <div class="col-lg-6">
  93. <nav class="breadcrumb-container" aria-label="breadcrumb">
  94. <ol class="breadcrumb">
  95. <li class="breadcrumb-item"><a href="/gcc/index"><i
  96. class="ik ik-home"></i></a></li>
  97. <li class="breadcrumb-item" aria-current="page">1913 QAQC</li>
  98. <li class="breadcrumb-item" aria-current="page">Agents
  99. QAQC</li>
  100. <li class="breadcrumb-item active" aria-current="page">Inprogress
  101. Calls</li>
  102. </ol>
  103. </nav>
  104. </div>
  105. </div>
  106. </div>
  107. <div class="row mt-4">
  108. <div class="col-md-12">
  109. <div class="card">
  110. <div class="card-body">
  111. <div class="page-header-title">
  112. <h5 style="margin: 0; font-weight: bold;">Today Assigned
  113. Calls</h5>
  114. </div>
  115. <div>
  116. <div class="row mt-2">
  117. <!-- Total Calls Assigned -->
  118. <div class="col-xl-3 col-md-6 col-sm-12">
  119. <div class="card card-box p-3 text-center mt-4">
  120. <h6 class="text-facebook mb-4">
  121. <b>Total Calls Assigned</b>
  122. </h6>
  123. <h4 class="text-twitter fw-700 mt-4"
  124. th:text="${details[0]?.Total_Calls_assigned}">
  125. <!-- Display Total Calls Assigned -->
  126. </h4>
  127. </div>
  128. </div>
  129. <!-- QA&QC Calls -->
  130. <div class="col-xl-3 col-md-6 col-sm-12">
  131. <div class="card card-box p-3 text-center mt-4">
  132. <h6 class="text-facebook mb-4">
  133. <b>QA&QC Calls</b>
  134. </h6>
  135. <h4 class="text-twitter fw-700 mt-4"
  136. th:text=" ${details[0]?.Closed_Call_count}">
  137. <!-- Display Closed Calls Count -->
  138. </h4>
  139. </div>
  140. </div>
  141. <!-- In-progress Calls -->
  142. <div class="col-xl-2 col-md-6 col-sm-12" style="background-color: aqua;">
  143. <div class="card card-box p-3 text-center mt-4 ">
  144. <h6 class="text-facebook mb-4">
  145. <b>In-progress Calls</b>
  146. </h6>
  147. <h4 class="text-twitter fw-700 mt-4"
  148. th:text="${details[0]?.Inprogress_Call_count}">
  149. <!-- Display In-progress Calls Count -->
  150. </h4>
  151. </div>
  152. </div>
  153. <!-- Follow-up Calls -->
  154. <div class="col-xl-2 col-md-6 col-sm-12">
  155. <div class="card card-box p-3 text-center mt-4">
  156. <h6 class="text-facebook mb-2">
  157. <b>Official Follow-up Calls</b>
  158. </h6>
  159. <h4 class="text-twitter fw-700 mt-3"
  160. th:text="${details[0]?.Followup_Call_count}">
  161. <!-- Display Follow-up Calls Count -->
  162. </h4>
  163. </div>
  164. </div>
  165. <div class="col-xl-2 col-md-6 col-sm-12">
  166. <div class="card card-box p-3 text-center mt-4">
  167. <h6 class="text-facebook mb-2">
  168. <b>Public Follow-up Calls</b>
  169. </h6>
  170. <h4 class="text-twitter fw-700 mt-3"
  171. th:text="${details[0]?.PublicFollowup_Call_count}">
  172. <!-- Display Follow-up Calls Count -->
  173. </h4>
  174. </div>
  175. </div>
  176. </div>
  177. <div class="row mt-2">
  178. <div class="col-md-12">
  179. <div class="card-header">
  180. <h3 style="font-weight: bold; font-size: large;"><span th:text="${userId}" style="display:none;" id="userIdSpan"></span>
  181. <span th:text="${agent[0]['agent_name']}"
  182. style="font-weight: bold; font-size: large;"></span>'s
  183. Inprogress Calls List
  184. </h3>
  185. </div>
  186. <div class="card-block">
  187. <div class="col-md-12">
  188. <div class="row">
  189. <button id="primaryButton" class="btn btn-success">Non-Processed
  190. Calls</button>
  191. <button id="secondaryButton"
  192. class="btn btn-secondary btn-custom ml-3">Processed
  193. Calls</button>
  194. </div>
  195. </div>
  196. </div>
  197. <div class="card-body">
  198. <div class="table-responsive" id="primaryTable"
  199. style="display: block;">
  200. <table id="QaqcDatatable"
  201. class="table table-striped table-bordered table-hover dataTable"
  202. role="grid">
  203. <thead class="thead-dark">
  204. <tr>
  205. <th class="text-center">S.No</th>
  206. <th class="text-center">ID</th>
  207. <th class="text-center">Complaint Date</th>
  208. <th class="text-center">Officer Name</th>
  209. <th class="text-center">Phone No</th>
  210. <th class="text-center">Complaint Type</th>
  211. <th class="text-center">Type</th>
  212. <!-- Added Date Column -->
  213. <th class="text-center">View Details</th>
  214. <th class="text-center custom-width1">Actions</th>
  215. <th class="text-center">Remarks</th>
  216. <th class="text-center">Submit</th>
  217. </tr>
  218. </thead>
  219. <tbody>
  220. <!-- Rows will be dynamically populated using AJAX -->
  221. <!-- Thymeleaf loop for populating data -->
  222. <tr th:each="call, iterStat : ${inprogresslists}">
  223. <td th:text="${iterStat.index + 1}" class="text-center"></td>
  224. <td th:text="${call['complaint_number']}"
  225. class="text-center complaint-select"></td>
  226. <td th:text="${call['complaint_date']}"
  227. class="text-center"></td>
  228. <td th:text="${call['official_name']}"
  229. class="text-center"></td>
  230. <td th:text="${call['official_mobilenum']}"
  231. class="text-center"></td>
  232. <td th:text="${call['complaint_type']}"
  233. class="text-center"></td>
  234. <td th:text="${call['call_category']}"
  235. class="text-center"></td>
  236. <td class="text-center">
  237. <button type="button" class="btn btn-info"
  238. th:data-complaint-number="${call['complaint_number']}">
  239. View</button>
  240. </td>
  241. <td class="text-center"><select
  242. class="form-control form-control-sm action-select action-dropdown">
  243. <option value="" selected>Select</option>
  244. <option th:each="status : ${qaqcactionlists}"
  245. th:value="${status.call_status}"
  246. th:text="${status.call_status}"></option>
  247. </select>
  248. <div class="schedule-call d-none mt-2">
  249. <!-- <span class="schedule-text">Schedule Call</span> -->
  250. <input type="date" class="date-picker form-control"
  251. name="remainderDate">
  252. </div>             </td>
  253. <td class="text-center"><input type="text"
  254. class="form-control form-control-sm"
  255. placeholder="Remarks"></td>
  256. <td class="text-center">
  257. <button class="btn btn-primary btn-sm submit-btn submitid"
  258. th:data-id="${call['data_id']}"
  259. onclick="submitComplaint(this)" disabled="disabled">
  260. Submit</button>
  261. </td>
  262. </tr>
  263. <!-- End loop -->
  264. </tbody>
  265. </table>
  266. </div>
  267. <div class="table-responsive" id="secondaryTable"
  268. style="display: none;">
  269. <table id="SecondaryDatatable"
  270. class="table table-striped table-bordered table-hover dataTable"
  271. role="grid">
  272. <thead class="thead-dark">
  273. <tr role="row">
  274. <th class="text-center">S.No</th>
  275. <th class="text-center">ID</th>
  276. <th class="text-center">Complaint Date</th>
  277. <th class="text-center">Officer Name</th>
  278. <th class="text-center">Officer PhoneNo</th>
  279. <th class="text-center">Complaint Type</th>
  280. <th class="text-center">View Details</th>
  281. <th class="text-center custom-width1">Actions</th>
  282. <th class="text-center">Remarks</th>
  283. </tr>
  284. </thead>
  285. <tbody>
  286. <tr th:each="call, iterStat : ${inSubmitDetails}">
  287. <td th:text="${iterStat.index + 1}" class="text-center"></td>
  288. <td th:text="${call['complaint_number']}"
  289. class="text-center complaint-select"></td>
  290. <td th:text="${call['complaint_date']}"
  291. class="text-center"></td>
  292. <td th:text="${call['official_name']}"
  293. class="text-center"></td>
  294. <td th:text="${call['official_mobilenum']}"
  295. class="text-center"></td>
  296. <td th:text="${call['complaint_type']}"
  297. class="text-center"></td>
  298. <td class="text-center">
  299. <button type="button" class="btn btn-info"
  300. th:data-complaint-number="${call['complaint_number']}">View</button>
  301. </td>
  302. <td th:text="${call['call_status']}" class="text-center"></td>
  303. <td th:text="${call['remarks']}" class="text-center"></td>
  304. </tr>
  305. </tbody>
  306. </table>
  307. </div>
  308. </div>
  309. </div>
  310. </div>
  311. </div>
  312. </div>
  313. </div>
  314. </div>
  315. </div>
  316. </div>
  317. </div>
  318. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  319. </div>
  320. </div>
  321. <!-- Modal -->
  322. <div class="modal fade" id="detailsModal" tabindex="-1" role="dialog"
  323. aria-labelledby="detailsModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false">
  324. <div class="modal-dialog modal-lg" role="document">
  325. <div class="modal-content">
  326. <div class="modal-header">
  327. <h5 class="modal-title" id="detailsModalLabel">Complaint
  328. Details</h5>
  329. <button type="button" class="close" data-dismiss="modal"
  330. aria-label="Close">
  331. <span aria-hidden="true">&times;</span>
  332. </button>
  333. </div>
  334. <div class="modal-body" id="modalBody">
  335. <!-- Details will be populated here -->
  336. </div>
  337. <div class="modal-footer">
  338. <button type="button" class="btn btn-secondary"
  339. data-dismiss="modal">Close</button>
  340. </div>
  341. </div>
  342. </div>
  343. </div>
  344. <!-- Include jQuery and Bootstrap JavaScript -->
  345. <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  346. <script
  347. src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
  348. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  349. <!-- sweet alert -->
  350. <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
  351. <script type="text/javascript">
  352. $(document).ready(function () {
  353. $(document).on('click', '.btn-info', function () {
  354. // Retrieve the complaint number from the data attribute
  355. var complaintNumber = $(this).data('complaint-number');
  356. var complaintDept = $(this).data('complaint-department');
  357. var complaintMode = $(this).data('complaint-mode');
  358. // Call the viewDetails function with the complaint number
  359. viewDetails(complaintNumber);
  360. });
  361. $('#primaryButton').addClass('btn-success').removeClass('btn-secondary');
  362. $('#secondaryButton').addClass('btn-secondary').removeClass('btn-success');
  363. // Toggle functionality for Primary and Secondary buttons
  364. $('#primaryButton').click(function () {
  365. $('#primaryTable').show();
  366. $('#secondaryTable').hide();
  367. $(this).addClass('btn-success').removeClass('btn-secondary');
  368. $('#secondaryButton').addClass('btn-secondary').removeClass('btn-success');
  369. $('#QaqcDatatable').DataTable().columns.adjust().draw();
  370. });
  371. $('#secondaryButton').click(function () {
  372. $('#primaryTable').hide();
  373. $('#secondaryTable').show();
  374. $(this).addClass('btn-success').removeClass('btn-secondary');
  375. $('#primaryButton').addClass('btn-secondary').removeClass('btn-success');
  376. $('#SecondaryDatatable').DataTable().columns.adjust().draw();
  377. });
  378. var table = $('#QaqcDatatable').DataTable({
  379. dom: 'Bftip',
  380. columnDefs: [
  381. { targets: 'no-sort', orderable: false }
  382. ],
  383. lengthMenu: [
  384. [50, 100, 200, 500, -1],
  385. ['50 rows', '100 rows', '200 rows', 'Show all']
  386. ],
  387. scrollY: '50vh',
  388. fixedColumns: {
  389. left: 1,
  390. right: 1
  391. },
  392. buttons: [
  393. {
  394. extend: 'pageLength',
  395. className: 'btn btn-warning'
  396. },
  397. {
  398. title: 'Data export',
  399. extend: 'copyHtml5',
  400. text: 'Copy',
  401. className: 'btn btn-secondary',
  402. id: 'copyBtn'
  403. },
  404. {
  405. extend: 'excelHtml5',
  406. text: 'Excel',
  407. className: 'btn btn-secondary',
  408. id: 'excelBtn'
  409. },
  410. {
  411. extend: 'csvHtml5',
  412. text: 'CSV',
  413. className: 'btn btn-secondary',
  414. id: 'csvBtn'
  415. },
  416. {
  417. extend: 'pdfHtml5',
  418. text: 'PDF',
  419. className: 'btn btn-secondary',
  420. id: 'pdfBtn'
  421. }
  422. ],
  423. fixedHeader: true,
  424. autoWidth: true,
  425. responsive: true,
  426. searching: true,
  427. select: false,
  428. processing: true
  429. });
  430. var table1 = $('#SecondaryDatatable').DataTable({
  431. dom: 'Bftip',
  432. columnDefs: [
  433. { targets: 'no-sort', orderable: false }
  434. ],
  435. lengthMenu: [
  436. [50, 100, 200, 500, -1],
  437. ['50 rows', '100 rows', '200 rows', 'Show all']
  438. ],
  439. scrollY: '50vh',
  440. fixedColumns: {
  441. left: 1,
  442. right: 1
  443. },
  444. buttons: [
  445. {
  446. extend: 'pageLength',
  447. className: 'btn btn-warning'
  448. },
  449. {
  450. title: 'Data export',
  451. extend: 'copyHtml5',
  452. text: 'Copy',
  453. className: 'btn btn-secondary',
  454. id: 'copyBtn'
  455. },
  456. {
  457. extend: 'excelHtml5',
  458. text: 'Excel',
  459. className: 'btn btn-secondary',
  460. id: 'excelBtn'
  461. },
  462. {
  463. extend: 'csvHtml5',
  464. text: 'CSV',
  465. className: 'btn btn-secondary',
  466. id: 'csvBtn'
  467. },
  468. {
  469. extend: 'pdfHtml5',
  470. text: 'PDF',
  471. className: 'btn btn-secondary',
  472. id: 'pdfBtn'
  473. }
  474. ],
  475. fixedHeader: true,
  476. autoWidth: true,
  477. responsive: true,
  478. searching: true,
  479. select: false,
  480. processing: false
  481. });
  482. // // Event listeners for changes in dropdown, remarks, and date picker
  483. $(document).on('change', '.action-dropdown', function () {
  484. const parentRow = $(this).closest('tr');
  485. const schedulerDiv = parentRow.find('.schedule-call');
  486. schedulerDiv.toggleClass('d-none', $(this).val() !== 'FOLLOWUP');
  487. validateFields(parentRow);
  488. });
  489. $(document).on('input', 'input[type="text"]', function () {
  490. const parentRow = $(this).closest('tr');
  491. validateFields(parentRow);
  492. });
  493. $(document).on('change', '.date-picker', function () {
  494. const parentRow = $(this).closest('tr');
  495. validateFields(parentRow);
  496. });
  497. // Validate function to check conditions for enabling/disabling submit button
  498. function validateFields(row) {
  499. const actionSelect = row.find('.action-select');
  500. const remarksInput = row.find('input[type="text"]');
  501. const submitButton = row.find('.submit-btn');
  502. const actionValue = actionSelect.val().trim();
  503. const remarksFilled = remarksInput.val().trim() !== "";
  504. const followUpSelected = actionValue === "FOLLOWUP";
  505. const remainderDateFilled = row.find('.date-picker').val()?.trim() !== ""; // Check if date is selected
  506. // Enable submit button based on conditions
  507. if (
  508. (followUpSelected && remainderDateFilled && remarksFilled) || (actionValue !== "FOLLOWUP" && actionValue !=="Select") // FOLLOWUP requires remainder date and remarks
  509. ) {
  510. submitButton.prop('disabled', false); // Enable submit button
  511. } else {
  512. submitButton.prop('disabled', true); // Disable submit button
  513. }
  514. }
  515. // Initial validation for all rows on page load
  516. $("#QaqcDatatable tbody tr").each(function () {
  517. const row = $(this);
  518. const submitButton = row.find('.submit-btn');
  519. submitButton.prop('disabled', true); // Ensure submit button is initially disabled
  520. validateFields(row); // Validate fields for further interaction
  521. });
  522. // Re-validate fields on input changes
  523. $("#QaqcDatatable").on('input change', '.action-select, input[type="text"], .date-picker', function () {
  524. const row = $(this).closest('tr');
  525. validateFields(row);
  526. });
  527. });
  528. function submitComplaint(button) {
  529. var userId = document.getElementById('userIdSpan').textContent;
  530. const row = button.parentNode.parentNode;
  531. const dataId = row.querySelector('.submit-btn').getAttribute('data-id'); // Fetch the data_id
  532. const action = row.querySelector('.action-select').value.trim(); // Fetch the action value
  533. const complaintNumber = row.querySelector('.complaint-select').innerText.trim(); // Fetch complaint number
  534. const remarks = row.querySelector('input[type="text"]').value.trim(); // Fetch the remarks value
  535. const remainderDate = row.querySelector('.date-picker')?.value.trim(); // Fetch the remainder date (if any)
  536. /* console.log(row);
  537. console.log(dataId);
  538. console.log(action);
  539. console.log(complaintNumber);
  540. console.log(remarks);
  541. console.log(remainderDate); */
  542. //console.log("outside ajax");
  543. $('.submitid').prop('disabled', true).text('Submitting...');
  544. // Validation
  545. if (!dataId || !action || action === "Select") {
  546. Swal.fire("Error", "Action is required!", "error");
  547. $('.submitid').prop('disabled', false).text('Submit');
  548. return;
  549. }
  550. if (action === 'FOLLOWUP' && remarks === "" && (!remainderDate || remainderDate === "")) {
  551. Swal.fire("Error", "Schedule Date is required for Follow-Up!", "error");
  552. $('.submitid').prop('disabled', false).text('Submit');
  553. return;
  554. }
  555. if(action === 'MOBILE_NUM' && remarks === "")
  556. {
  557. Swal.fire("Error", "remarks is required for Mobile_Num!", "error");
  558. $('.submitid').prop('disabled', false).text('Submit');
  559. return;
  560. }
  561. // AJAX Request
  562. $.ajax({
  563. url: '/gcc/api/callcenterqaqc/agent/inprogresscalls/update',
  564. type: 'POST',
  565. data: {
  566. dataId: dataId,
  567. complaintNumber: complaintNumber,
  568. action: action,
  569. remarks: remarks,
  570. remainderDate: remainderDate,
  571. userId:userId
  572. },
  573. success: function (response) {
  574. if (response === "Success") {
  575. //console.log("inside ajax success");
  576. Swal.fire({
  577. icon: 'success',
  578. title: 'Success',
  579. text: 'Complaint updated successfully!',
  580. allowOutsideClick: false, // Disable clicking outside the modal to close it
  581. allowEscapeKey: false, // Disable escape key to close the modal
  582. allowEnterKey: false, // Disable enter key to close the modal
  583. showConfirmButton: true, // Ensure the confirm button is visible
  584. }).then((result) => {
  585. if (result.isConfirmed) {
  586. //console.log("ok button");
  587. $('.submitid').prop('disabled', false).text('Submit');
  588. const table = $('#QaqcDatatable').DataTable();
  589. // Remove the row
  590. table.row($(row)).remove();
  591. // Reorder S.No column
  592. table.rows().every(function (index) {
  593. const row = this.node();
  594. $(row).find('td:first-child').text(index + 1); // Update S.No
  595. });
  596. // Redraw the table
  597. table.draw(false);
  598. }
  599. });
  600. }
  601. else if (response === "error") {
  602. $('.submitid').prop('disabled', false).text('Submit');
  603. Swal.fire("Error", "Failed to update complaint. Please try again later.", "error");
  604. }
  605. else {
  606. $('.submitid').prop('disabled', false).text('Submit');
  607. Swal.fire("Error", "Failed to update complaint. Please try again.", "error");
  608. }
  609. },
  610. error: function (xhr, status, error) {
  611. $('.submitid').prop('disabled', false).text('Submit');
  612. Swal.fire("Error", `An error occurred: ${xhr.responseText || error}`, "error");
  613. }
  614. });
  615. // $('.submitid').prop('disabled', false).text('Submit');
  616. }
  617. function viewDetails(complaintNumber) {
  618. document.getElementById('modalBody').innerHTML = '<p style="text-align:center;">Please wait, loading data...</p>';
  619. $('#detailsModal').modal('show');
  620. // Fetch the main complaint details
  621. $.ajax({
  622. url: '/gcc/api/callcenterqaqc/agent/qaqccalls/getComplaintDetails',
  623. type: 'GET',
  624. data:{complaintNumber:complaintNumber},
  625. success: function (data) {
  626. //console.log('Complaint Data:', data);
  627. // Fetch agent response details
  628. $.ajax({
  629. url: '/gcc/api/callcenterqaqc/agent/attendedcomplaintshistory',
  630. type: 'GET',
  631. data: { complaintNumber },
  632. success: function (agentResponse) {
  633. //console.log('Agent Response:', agentResponse);
  634. // Use the logic for building complaint and agent details as HTML
  635. const detailsHtml = generateDetailsHtml(data, agentResponse);
  636. // Update modal content
  637. document.getElementById('modalBody').innerHTML = detailsHtml;
  638. },
  639. error: function () {
  640. document.getElementById('modalBody').innerHTML = '<p>Error loading agent details. Please try again later.</p>';
  641. }
  642. });
  643. },
  644. error: function () {
  645. document.getElementById('modalBody').innerHTML = '<p>Error loading complaint details. Please try again later.</p>';
  646. }
  647. });
  648. }
  649. // Function to generate complaint and agent details HTML
  650. function generateDetailsHtml(data, agentResponse) {
  651. // Helper function to format date to yyyy-mm-dd
  652. function formatDate(dateStr) {
  653. if (!dateStr) return 'N/A';
  654. const date = new Date(dateStr);
  655. return date.toISOString().split('T')[0]; // Formats to yyyy-mm-dd
  656. }
  657. // Format complaint messages
  658. let messagesHtml = '';
  659. if (data.comments && data.comments.length > 0) {
  660. data.comments.forEach((comment) => {
  661. const commentImageLink = comment.Comp_Image && comment.Comp_Image !== "No image available"
  662. ? `<a href="${comment.Comp_Image}" target="_blank" style="color: green; text-decoration: underline;">View Image</a>`
  663. : '<p style="color: red;">No image available for this comment.</p>';
  664. messagesHtml += `
  665. <div class="comment mb-4">
  666. <div class="row">
  667. <div class="col-2 text-center">
  668. <p class="text-muted">${comment.comment_date}</p>
  669. </div>
  670. <div class="col-10">
  671. <p><strong>${comment.user || 'N/A'}</strong> Says:</p>
  672. <p>${comment.message || 'No message available'}</p>
  673. <div class="user-image">${commentImageLink}</div>
  674. </div>
  675. </div>
  676. </div>
  677. `;
  678. });
  679. } else {
  680. messagesHtml = '<p>No comments available.</p>';
  681. }
  682. // Format agent responses
  683. let agentRepliedHtml = '';
  684. if (agentResponse.length > 0) {
  685. agentResponse.forEach((agentItem) => {
  686. agentRepliedHtml += `
  687. <div class="comment mb-4">
  688. <div class="row">
  689. <div class="col-2 text-center">
  690. <p class="text-muted"><strong>${formatDate(agentItem.created_date) || 'N/A'}</strong></p>
  691. </div>
  692. <div class="col-10">
  693. <p><strong>${agentItem.agent_name || 'N/A'}</strong>, Says: ${agentItem.call_status || 'N/A'}</p>
  694. <p><strong>Remarks: </strong>${agentItem.remarks || 'N/A'}</p>
  695. <p><strong>Remainder Date: </strong> ${formatDate(agentItem.remainder_date) || 'N/A'}</p>
  696. </div>
  697. </div>
  698. </div>
  699. `;
  700. });
  701. } else {
  702. agentRepliedHtml = '<p>No agent replied messages available.</p>';
  703. }
  704. // Check for user images
  705. const userImages = data.userimages && data.userimages.length > 0 ? data.userimages[0] : {};
  706. const imageLink = userImages.Comp_Image && userImages.Comp_Image !== "null" && userImages.Comp_Image !== ""
  707. ? `<a href="${userImages.Comp_Image}" target="_blank" style="color: green; text-decoration: underline;">UserImages: View Image</a>`
  708. : '<p style="color: red;">UserImages: No image available.</p>';
  709. // Combine all sections into the final HTML
  710. const detailsHtml = `
  711. <div class="row">
  712. <div class="col-md-12">
  713. <h4>Complaint Person's Details:</h4>
  714. <div class="row">
  715. <div class="col-6">
  716. <p><strong>Complaint Number:</strong> ${data.complaintid || 'N/A'}</p>
  717. </div>
  718. <div class="col-6">
  719. <p><strong>Complaint Date:</strong> ${data.complaintdate}</p>
  720. </div>
  721. </div>
  722. <div class="row">
  723. <div class="col-6">
  724. <p><strong>Complainant's Name:</strong> ${data.complainantName || 'N/A'}</p>
  725. </div>
  726. <div class="col-6">
  727. <p><strong>Phone Number:</strong> ${data.mobileNumber || 'N/A'}</p>
  728. </div>
  729. </div>
  730. <div class="row">
  731. <div class="col-6">
  732. <p><strong>Zone:</strong> ${data.Zone || 'N/A'}</p>
  733. </div>
  734. <div class="col-6">
  735. <p><strong>Division:</strong> ${data.Division || 'N/A'}</p>
  736. </div>
  737. </div>
  738. <div class="row">
  739. <div class="col-6">
  740. <p><strong>Gender:</strong> ${data.gender || 'N/A'}</p>
  741. </div>
  742. <div class="col-6">
  743. <p><strong>Complainant's Address:</strong> ${data.Street || 'N/A'}, ${data.Area || 'N/A'}, ${data.Landmark || 'N/A'}, ${data.Location || 'N/A'}</p>
  744. </div>
  745. </div>
  746. </div>
  747. </div>
  748. <hr>
  749. <h4>Complaint Details:</h4>
  750. <div class="row">
  751. <div class="col-6">
  752. <p><strong>Complaint Dept:</strong> ${data.deptname || 'N/A'}</p>
  753. </div>
  754. <div class="col-6">
  755. <p><strong>Complaint Mode:</strong> ${data.compmode || 'N/A'}</p>
  756. </div>
  757. </div>
  758. <div class="row">
  759. <div class="col-6">
  760. <p><strong>Complaint Type:</strong> ${data.complaintType || 'N/A'}</p>
  761. </div>
  762. <div class="col-6">
  763. <p><strong>Details of Complaint:</strong> ${data.description || 'N/A'}</p>
  764. </div>
  765. </div>
  766. <div class="row">
  767. <div class="col-6">
  768. <p><strong>Current Status:</strong> ${data.currentStatus || 'N/A'}</p>
  769. </div>
  770. <div class="col-6">
  771. <p><strong style="color:blue;">Official Mobile:</strong> ${data.OfficialMobile || 'N/A'}</p>
  772. </div>
  773. </div>
  774. <div class="row">
  775. <div class="col-6">
  776. <p><strong>Last Updated Date:</strong> ${data.greatestDate || 'N/A'}</p>
  777. </div>
  778. </div>
  779. <hr>
  780. <h4>Complaint Messages:</h4>
  781. ${messagesHtml}
  782. <hr>
  783. <h4>Agent Replied Messages:</h4>
  784. ${agentRepliedHtml}
  785. <hr>
  786. ${imageLink}
  787. `;
  788. return detailsHtml;
  789. }
  790. </script>
  791. </body>
  792. </html>