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.

1255 lines
54 KiB

2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/modules/base/head :: head}"></head>
  4. <style>
  5. /* .modal-body {
  6. max-height: 70vh;
  7. overflow-y: auto;
  8. overflow-x: hidden;
  9. padding-right: 15px;
  10. } */
  11. .edit-campaign{
  12. max-height: 70vh;
  13. overflow-y: auto; /* Enables vertical scrolling */
  14. overflow-x: hidden; /* Hides horizontal scrolling */
  15. padding-right: 15px; /* Prevents content cutoff */
  16. }
  17. </style>
  18. <body>
  19. <!--[if lt IE 8]>
  20. <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
  21. <![endif]-->
  22. <div class="wrapper">
  23. <!-- header top menu Start -->
  24. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  25. <!-- header top menu end -->
  26. <div class="page-wrap">
  27. <!--=============== Left Menu side Start ================-->
  28. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  29. <!--=============== Left side End ================-->
  30. <div class="main-content">
  31. <div class="container-fluid">
  32. <div class="page-header mb-2">
  33. <div class="row align-items-end">
  34. <div class="col-lg-8">
  35. <div class="page-header-title">
  36. <i class="fa fa-list-alt bg-blue"></i>
  37. <div class="d-inline">
  38. <h5>Campaign List</h5>
  39. <span>1913 Campaign List</span>
  40. </div>
  41. </div>
  42. </div>
  43. <div class="col-lg-4">
  44. <nav class="breadcrumb-container" aria-label="breadcrumb">
  45. <ol class="breadcrumb">
  46. <li class="breadcrumb-item"><a href="/gcc/index"><i
  47. class="ik ik-home"></i></a></li>
  48. <li class="breadcrumb-item" aria-current="page">1913 Campaign</li>
  49. <li class="breadcrumb-item active" aria-current="page">Campaign List</li>
  50. </ol>
  51. </nav>
  52. </div>
  53. </div>
  54. </div>
  55. <h4 class="h4 text-right text-mute" style="font-size: 12px;">
  56. Auot refresh in <font id="refresh-countdown">00</font> seconds
  57. </h4>
  58. <div class="row">
  59. <div class="col-md-12">
  60. <div class="card">
  61. <div class="card-body">
  62. <div class="page-header-title" >
  63. <h5 style="margin: 0;font-weight: bold;">Campaigns List</h5><hr>
  64. </div>
  65. <table id="StartCampaigntable" class="table table-striped table-bordered table-hover dataTable" role="grid">
  66. <thead class="thead-dark">
  67. <tr role="row">
  68. <th>S.No</th>
  69. <th class="text-center">Campaign</th>
  70. <th class="text-center">Category</th>
  71. <th class="text-center">Date</th>
  72. <th class="text-center">Action</th>
  73. </tr>
  74. </thead>
  75. <tbody>
  76. <tr th:each="campaign, iterStat : ${campaigns}">
  77. <td th:text="${iterStat.index + 1}" class="text-center"></td> <!-- Serial number -->
  78. <td th:text="${campaign['campaign_name']}" class="text-center"></td> <!-- Campaign name -->
  79. <td th:text="${campaign['category_name']}" class="text-center"></td> <!-- Category name -->
  80. <td th:text="${campaign['start_date']}" class="text-center"></td> <!-- Total calls -->
  81. <td class="text-center">
  82. <button type="button" class="btn btn-success"
  83. th:onclick="return callCampEdit([[${campaign.campaign_id}]], [[${campaign.category_id}]])"
  84. data-animation="true"
  85. data-toggle="tooltip"
  86. data-placement="top"
  87. title="Edit">
  88. View
  89. </button>
  90. </td>
  91. </tr>
  92. </tbody>
  93. <tfoot class="thead-dark">
  94. <tr role="row">
  95. <th>S.No</th>
  96. <th class="text-center">Campaign</th>
  97. <th class="text-center">Category</th>
  98. <th class="text-center">Date</th>
  99. <th class="text-center">Action</th>
  100. </tr>
  101. </tfoot>
  102. </table>
  103. </div>
  104. </div>
  105. </div>
  106. <div class="col-md-12">
  107. <div class="card">
  108. <div class="card-block">
  109. <div class="page-header-title" >
  110. <h5 style="margin: 0;font-weight: bold;">Campaign Status List</h5><hr>
  111. </div>
  112. <div>
  113. <table id="CampaignDatatable" class="table table-striped table-bordered table-hover dataTable" role="grid">
  114. <thead class="thead-dark">
  115. <tr role="row">
  116. <th>S.No</th>
  117. <th class="text-center">Name</th>
  118. <th class="text-center">Category</th>
  119. <th class="text-center">Event Date</th>
  120. <th class="text-center">Description</th>
  121. <th class="text-center">Status</th>
  122. <th class="text-center">Action</th>
  123. </tr>
  124. </thead>
  125. <tbody>
  126. <tr th:each="activeCampaign, iterStat : ${activeCampaigns}">
  127. <td th:text="${iterStat.index + 1}" class="text-center"></td> <!-- Serial number -->
  128. <td th:text="${activeCampaign['campaign_name']}" class="text-center"></td>
  129. <td th:text="${activeCampaign['category_name']}" class="text-center"></td>
  130. <td th:text="${activeCampaign['start_date']} + ' - ' + ${activeCampaign['end_date']}" class="text-center"></td>
  131. <td th:text="${activeCampaign['description']}" class="text-center"></td> <!-- Calls per agent -->
  132. <td class="text-center">
  133. <th:block th:switch="${activeCampaign['campaign_status']}">
  134. <th:block th:case="'ONGOING'">
  135. <button type="button" class="status-button btn btn-danger"
  136. th:data-id="${activeCampaign['campaign_id']}">Ongoing</button>
  137. </th:block>
  138. <th:block th:case="'CLOSED'">
  139. <span class="text-success">Closed</span>
  140. </th:block>
  141. </th:block>
  142. </td>
  143. <td class="text-center">
  144. <th:block th:switch="${activeCampaign['campaign_status']}">
  145. <th:block th:case="'ONGOING'">
  146. <a href="#" th:onclick="return callEdit([[${activeCampaign.campaign_id}]])" data-animation="true" data-toggle="tooltip" data-placement="top" title="Edit" data-original-title="Edit">
  147. <i class="ik ik-edit f-16 mr-15 text-green"></i>
  148. </a>
  149. </th:block>
  150. <th:block th:case="'CLOSED'">
  151. <button type="button" class="btn btn-primary" th:onclick="return callEdit([[${activeCampaign.campaign_id}]])">View</button>
  152. </th:block>
  153. </th:block>
  154. </td>
  155. </tr>
  156. </tbody>
  157. </table>
  158. </div>
  159. </div>
  160. </div>
  161. </div>
  162. </div>
  163. </div>
  164. </div>
  165. <div id="pageLoader" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;">
  166. <div style="position: relative; top: 50%; transform: translateY(-50%);">
  167. <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
  168. <span class="sr-only">Loading...</span>
  169. </div>
  170. <!-- Add the 'Please wait' text below the spinner -->
  171. <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
  172. </div>
  173. </div>
  174. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  175. </div>
  176. </div>
  177. <!-- Edit campaign Category List Modal -->
  178. <div class="modal fade" id="editcampaignModal" tabindex="-1" role="dialog" aria-labelledby="editcampaignModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
  179. <div class="modal-dialog modal-lg" role="document">
  180. <div class="modal-content">
  181. <div class="modal-header">
  182. <h5 class="modal-title" id="editModalLabel">Details of Campaign</h5>
  183. <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
  184. <span aria-hidden="true">&times;</span>
  185. </button>
  186. </div>
  187. <div class="modal-body">
  188. <input type="hidden" name="modal_campaign_id" id="modal_campaign_id" />
  189. <!-- Row 1: Total Count, Completed, Pending -->
  190. <div class="form-group row">
  191. <div class="col-md-3">
  192. <label for="totalCount">Overall Data</label>
  193. <input type="text" class="form-control" id="totalCount" readonly>
  194. </div>
  195. <div class="col-md-3">
  196. <label for="overallpendingCount">Overall Pending</label>
  197. <input type="text" class="form-control" id="overallpendingCount" readonly>
  198. </div>
  199. <div class="col-md-3">
  200. <label for="completedCount">Assigned Completed</label>
  201. <input type="text" class="form-control" id="completedCount" readonly>
  202. </div>
  203. <div class="col-md-3">
  204. <label for="pendingCount">Assigned Pending</label>
  205. <input type="text" class="form-control" id="pendingCount" readonly>
  206. </div>
  207. </div>
  208. <!-- Row 2: Call Per Agent, Select Agents, Count -->
  209. <div class="form-group">
  210. <label><b><u>Today Assign:</u></b></label>
  211. <div class="row">
  212. <div class="col-md-4">
  213. <label for="call_per_agent">Call Per Agent<span class="text-danger">*</span></label>
  214. <input type="text" class="form-control" id="call_per_agent" required>
  215. </div>
  216. <div class="col-md-4">
  217. <label for="agentDropdown" class="form-label fw-bold">Agent Selection <span class="text-danger">*</span></label>
  218. <div class="dropdown">
  219. <button class="btn btn-light border rounded w-100 text-start"
  220. type="button"
  221. id="agentDropdownBtn"
  222. data-bs-toggle="dropdown"
  223. aria-expanded="false">
  224. Select Agent(s)
  225. </button>
  226. <ul class="dropdown-menu p-3"
  227. aria-labelledby="agentDropdownBtn"
  228. style="max-height: 250px; overflow-y: auto; width: 100%;">
  229. <div id="agentCheckboxContainer">
  230. <!-- Checkboxes will be loaded here -->
  231. </div>
  232. </ul>
  233. </div>
  234. </div>
  235. <div class="col-md-4">
  236. <label for="call_count">Today calls Count</label>
  237. <input type="text" class="form-control" id="call_count" readonly>
  238. </div>
  239. </div>
  240. </div>
  241. <div class="form-group">
  242. <input type="hidden" name="modal_category_id" class="form-control" id="modal_category_id" readonly>
  243. </div>
  244. <div class="form-group text-center">
  245. <button type="button" class="btn btn-primary" id="furtherAssign">Click to Assign</button>
  246. </div>
  247. </div>
  248. </div>
  249. </div>
  250. </div>
  251. <!-- Edit campaign Modal -->
  252. <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
  253. <div class="modal-dialog modal-lg" role="document">
  254. <div class="modal-content">
  255. <div class="modal-header">
  256. <h5 class="modal-title" id="editModalLabel">Edit Campaign</h5>
  257. <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close" onclick="location.reload();">
  258. <span aria-hidden="true">&times;</span>
  259. </button>
  260. </div>
  261. <div class="modal-body">
  262. <div class="edit-campaign">
  263. <form id="editForm" onsubmit="submitForm(event)">
  264. <input type="hidden" name="campaign_id" id="campaign_id" />
  265. <div class="form-group">
  266. <label for="campaign_name">Name<span class="text-danger">*</span></label>
  267. <input type="text" class="form-control" id="campaign_name" readonly>
  268. </div>
  269. <div class="form-group">
  270. <input type="hidden" name ="category_id" class="form-control" id="category_id" readonly>
  271. </div>
  272. <div class="form-group">
  273. <label><b><u>Event Date:</u></b></label>
  274. <div class="row">
  275. <div class="col">
  276. <label for="start_date">From Date<span class="text-danger">*</span></label>
  277. <input type="date" class="form-control" id="start_date" readonly>
  278. </div>
  279. <div class="col">
  280. <label for="end_date">To Date<span class="text-danger">*</span></label>
  281. <input type="date" class="form-control" id="end_date" required>
  282. </div>
  283. </div>
  284. </div>
  285. <div class="form-group">
  286. <label for="description_modal">Description<span class="text-danger">*</span></label>
  287. <textarea class="form-control" id="description_modal" rows="2" readonly></textarea>
  288. </div>
  289. <!-- Questions & Answers Section -->
  290. <h5><b>Questions & Answers</b></h5>
  291. <div class="table-responsive">
  292. <table class="table table-bordered" id="questionTable">
  293. <thead>
  294. <tr>
  295. <th>Question</th>
  296. <th>Answers</th>
  297. </tr>
  298. </thead>
  299. <tbody>
  300. <!-- Dynamic content will be inserted here -->
  301. </tbody>
  302. </table>
  303. </div>
  304. <div class="card" id="campaignaddquestion">
  305. <div class="card-header justify-content-between align-items-center">
  306. <h3><b>Add Questions</b></h3>
  307. </div>
  308. <div class="card-body">
  309. <div id="questionsContainer">
  310. <!-- Dynamic questions will be added here -->
  311. </div>
  312. <button type="button" class="btn btn-success mt-3" id="addQuestionBtn">+ Add Question</button>
  313. </div>
  314. </div>
  315. <div class="form-group text-center" id="savebuttonhide">
  316. <button type="submit" class="btn btn-primary" id="editsubmit">Save changes</button>
  317. </div>
  318. </form>
  319. </div>
  320. </div>
  321. </div>
  322. </div>
  323. </div>
  324. <div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
  325. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  326. <script src="node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min.js"></script>
  327. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
  328. <script type="text/javascript">
  329. $(document).ready(function () {
  330. // Define buttons for DataTables
  331. var buttons = [
  332. {
  333. extend: 'pageLength',
  334. className: 'btn btn-warning'
  335. },
  336. {
  337. title: 'Data export',
  338. extend: 'copyHtml5',
  339. text: 'Copy',
  340. className: 'btn btn-secondary'
  341. },
  342. {
  343. extend: 'excelHtml5',
  344. text: 'Excel',
  345. className: 'btn btn-secondary'
  346. },
  347. {
  348. extend: 'csvHtml5',
  349. text: 'CSV',
  350. className: 'btn btn-secondary'
  351. },
  352. {
  353. extend: 'pdfHtml5',
  354. text: 'PDF',
  355. className: 'btn btn-secondary'
  356. }
  357. ];
  358. // DataTables initialization for #StartCampaigntable
  359. $('#StartCampaigntable').DataTable({
  360. dom: 'Bftip',
  361. columnDefs: [
  362. {targets: 'no-sort', orderable: false}
  363. ],
  364. lengthMenu: [
  365. [50, 100, 200, 500, -1],
  366. ['50 rows', '100 rows', '200 rows', '500 rows', 'Show all']
  367. ],
  368. scrollY: '30vh',
  369. fixedColumns: {
  370. left: 1,
  371. right: 1
  372. },
  373. buttons: buttons,
  374. fixedHeader: true,
  375. autoWidth: true,
  376. responsive: true,
  377. searching: true,
  378. select: false,
  379. processing: false,
  380. });
  381. // DataTables initialization for #CampaignDatatable
  382. $('#CampaignDatatable').DataTable({
  383. dom: 'Bftip',
  384. columnDefs: [
  385. {targets: 'no-sort', orderable: false}
  386. ],
  387. lengthMenu: [
  388. [50, 100, 200, 500, -1],
  389. ['50 rows', '100 rows', '200 rows', '500 rows', 'Show all']
  390. ],
  391. scrollY: '50vh',
  392. fixedColumns: {
  393. left: 1,
  394. right: 1
  395. },
  396. buttons: buttons,
  397. fixedHeader: true,
  398. autoWidth: true,
  399. responsive: true,
  400. searching: true,
  401. select: false,
  402. processing: false,
  403. });
  404. /* const rows = document.querySelectorAll("#CampaignDatatable tbody tr");
  405. rows.forEach(row => {
  406. const eventDateText = row.querySelector('td:nth-child(4)').innerText; // Get the event date text
  407. const statusButton = row.querySelector('.status-button'); // Select the status button
  408. // Parse start and end dates
  409. const dates = eventDateText.split(' - ');
  410. const endDate = new Date(dates[1].trim()); // Extract the end date
  411. // Get the current date
  412. const currentDate = new Date();
  413. currentDate.setHours(0, 0, 0, 0); // Reset time to compare dates only
  414. // Compare dates and update button text and class
  415. if (endDate >= currentDate) {
  416. statusButton.classList.remove('btn-success');
  417. statusButton.classList.add('btn-danger');
  418. statusButton.innerText = 'Ongoing';
  419. } else {
  420. statusButton.classList.remove('btn-danger');
  421. statusButton.classList.add('btn-success');
  422. statusButton.innerText = 'Completed';
  423. }
  424. }); */
  425. });
  426. // Start campaign function
  427. function startCampaign(callsPerAgent, campaignId) {
  428. $.ajax({
  429. url: '/gcc/api/campaign/startcampaign?campaign_id=' + campaignId + '&calls_per_agent=' + callsPerAgent, // URL to your Spring Boot controller
  430. type: 'GET', // GET request
  431. contentType: 'application/json',
  432. success: function (response) {
  433. if (response && response.length > 0 && response != 0) {
  434. // If the response contains values
  435. console.log('Campaign started successfully:', response);
  436. Swal.fire({
  437. allowOutsideClick: false,
  438. allowEscapeKey: false,
  439. allowEnterKey: false,
  440. title: 'Success!',
  441. text: 'Data transferred successfully!',
  442. icon: 'success',
  443. timer: 2000,
  444. showConfirmButton: false
  445. }).then(() => {
  446. location.reload(); // Reload after success
  447. });
  448. } else {
  449. // If the response is empty, null, or 0
  450. Swal.fire({
  451. title: 'Error!',
  452. text: 'No data was transferred ,Please check Agents are assigned!.',
  453. icon: 'error',
  454. timer: 3000,
  455. showConfirmButton: true
  456. });
  457. }
  458. },
  459. error: function (xhr, status, error) {
  460. // Handle error scenario here
  461. console.error('Error starting campaign:', error);
  462. // You can show an error message to the user
  463. Swal.fire({
  464. title: 'Error!',
  465. text: 'An error occurred while transferring data.',
  466. icon: 'error',
  467. timer: 3000,
  468. showConfirmButton: true
  469. });
  470. }
  471. });
  472. }
  473. $(document).ready(function () {
  474. window.callCampEdit = function (campaignId,categoryId) {
  475. fetchCampaignStatistics(campaignId,categoryId);
  476. return false; // Prevent default anchor click behavior
  477. };
  478. function fetchCampaignStatistics(campaignId,categoryId) {
  479. $.ajax({
  480. url: `/gcc/api/campaign/statistics?campaignId=${campaignId}`,
  481. type: 'GET',
  482. dataType: 'json',
  483. success: function (response) {
  484. if (response) {
  485. $('#totalCount').val(response.totalCount || 0);
  486. $('#completedCount').val(response.completedCount || 0);
  487. $('#pendingCount').val(response.pendingCount || 0);
  488. // Set values in the modal
  489. $('#modal_campaign_id').val(campaignId);
  490. $('#modal_category_id').val(categoryId);
  491. // Correctly calculate and display Overall Pending Count
  492. let overallPendingCount = (response.totalCount || 0) - (response.completedCount || 0);
  493. $('#overallpendingCount').val(overallPendingCount);
  494. // Show the modal after populating the fields
  495. $('#editcampaignModal').modal('show');
  496. } else {
  497. console.error('No data returned');
  498. }
  499. },
  500. error: function (xhr, status, error) {
  501. console.error('Error fetching campaign statistics:', error);
  502. }
  503. });
  504. }
  505. $(document).ready(function () {
  506. function loadAgents() {
  507. $.ajax({
  508. url: "/gcc/api/campaign/assignagentid",
  509. type: "GET",
  510. dataType: "json",
  511. success: function (response) {
  512. console.log("Agents:", response);
  513. $("#agentCheckboxContainer").empty(); // Clear previous checkboxes
  514. // Append "Select All" checkbox
  515. $("#agentCheckboxContainer").append(`
  516. <li>
  517. <label class="dropdown-item">
  518. <input type="checkbox" id="selectAllAgents"> Select All
  519. </label>
  520. </li>
  521. `);
  522. // Append individual agent checkboxes
  523. response.forEach(agent => {
  524. $("#agentCheckboxContainer").append(`
  525. <li>
  526. <label class="dropdown-item">
  527. <input type="checkbox" class="agentCheckbox" value="${agent.agent_id}" data-name="${agent.agent_name}">
  528. ${agent.agent_name}
  529. </label>
  530. </li>
  531. `);
  532. });
  533. // "Select All" checkbox logic
  534. $("#selectAllAgents").change(function () {
  535. $(".agentCheckbox").prop("checked", this.checked);
  536. calculateCallCount(); // Recalculate count when selecting all
  537. });
  538. // If any individual checkbox is unchecked, uncheck "Select All"
  539. $(document).on("change", ".agentCheckbox", function () {
  540. let allChecked = $(".agentCheckbox").length === $(".agentCheckbox:checked").length;
  541. $("#selectAllAgents").prop("checked", allChecked);
  542. calculateCallCount(); // Recalculate count on checkbox change
  543. });
  544. console.log("Agents Loaded...");
  545. },
  546. error: function (xhr) {
  547. console.error("AJAX Error:", xhr.status, xhr.responseText);
  548. Swal.fire({
  549. icon: "error",
  550. title: "Error Fetching Data",
  551. text: "Failed to load agents. Please try again.",
  552. });
  553. }
  554. });
  555. }
  556. // Function to calculate Count = Call Per Agent * Selected Agents
  557. function calculateCallCount() {
  558. let callPerAgent = parseInt($("#call_per_agent").val()) || 0;
  559. let selectedAgentsCount = $(".agentCheckbox:checked").length;
  560. let totalCount = callPerAgent * selectedAgentsCount;
  561. let totalCountValue = parseInt($("#totalCount").val()) || 0;
  562. let completedCountValue = parseInt($("#completedCount").val()) || 0;
  563. let pendingCount = totalCountValue - completedCountValue; // Pending count calculation
  564. if (totalCount > pendingCount) {
  565. Swal.fire({
  566. icon: "warning",
  567. title: "Warning",
  568. text: "you can't assign more than overall pending count, now you can assign.",
  569. //text: `Assigned Pending count (${totalCount}) cannot exceed the today calls count (${pendingCount}).`,
  570. });
  571. totalCount = pendingCount; // Restrict value to pending count
  572. }
  573. $("#call_count").val(totalCount); // Update the Count field
  574. }
  575. // Load agents when the page loads
  576. loadAgents();
  577. // Update count when Call Per Agent changes
  578. $("#call_per_agent").on("input", function () {
  579. calculateCallCount();
  580. });
  581. // Update count when agents are selected/deselected
  582. $(document).on("change", ".agentCheckbox", function () {
  583. calculateCallCount();
  584. });
  585. });
  586. // On 'Save Changes' button click
  587. $('#furtherAssign').click(function () {
  588. let campaign_id = $('#modal_campaign_id').val();
  589. let category_id = $('#modal_category_id').val();
  590. let call_per_agent = $('#call_per_agent').val();
  591. // Get selected agent IDs
  592. let fselectedAgents = [];
  593. $(".agentCheckbox:checked").each(function () {
  594. fselectedAgents.push($(this).val());
  595. });
  596. // Validation check
  597. if (!call_per_agent) {
  598. Swal.fire({
  599. icon: "info",
  600. title: "Missing Information",
  601. text: "Please fill in 'Call Per Agent'.",
  602. });
  603. return; // Stop further execution
  604. }
  605. if (fselectedAgents.length === 0) {
  606. Swal.fire({
  607. icon: "info",
  608. title: "Missing Information",
  609. text: "Select at least one agent.",
  610. });
  611. return; // Stop further execution
  612. }
  613. console.log("campaign_id=",campaign_id);
  614. console.log("category_id=",category_id);
  615. console.log("call_per_agent=",call_per_agent);
  616. console.log("fselectedAgents=",fselectedAgents);
  617. $('#furtherAssign').prop('disabled', true).text('Processing');//Click to Assign
  618. $('#pageLoader').show();
  619. // AJAX POST request to submit data
  620. $.ajax({
  621. url: "/gcc/api/agents/furtherAssignedAgents",
  622. type: "POST",
  623. contentType: "application/json",
  624. data: JSON.stringify({
  625. campaign_id: campaign_id,
  626. category_id: category_id,
  627. call_per_agent: call_per_agent,
  628. selected_agents: fselectedAgents // Ensure key matches your controller parameter
  629. }),
  630. success: function (response) {
  631. $('#pageLoader').hide();
  632. $('#furtherAssign').prop('disabled', false).text('Click to Assign');
  633. if(response.status ==='success'){
  634. Swal.fire({
  635. allowOutsideClick: false,
  636. allowEscapeKey: false,
  637. allowEnterKey: false,
  638. icon: "success",
  639. title: "Success",
  640. text: "Agents successfully assigned to the campaign.",
  641. }).then((result) => {
  642. if (result.isConfirmed) {
  643. $('#furtherAssign').prop('disabled', false).text('Click to Assign');
  644. $('#editcampaignModal').modal('hide'); // Close modal on success
  645. location.reload();
  646. }
  647. });
  648. }
  649. if(response.status ==='error'){
  650. $('#furtherAssign').prop('disabled', false).text('Click to Assign');
  651. Swal.fire({
  652. icon: 'error',
  653. title: 'Error',
  654. text: response.message
  655. });
  656. }
  657. },
  658. error: function (xhr) {
  659. $('#pageLoader').hide();
  660. console.error("AJAX Error:", xhr.status, xhr.responseText);
  661. $('#furtherAssign').prop('disabled', false).text('Click to Assign');
  662. Swal.fire({
  663. icon: "error",
  664. title: "Error",
  665. text: "Failed to assign agents. Please try again.",
  666. });
  667. }
  668. });
  669. });
  670. });
  671. //Update request form details
  672. $(document).ready(function () {
  673. // Function to open the edit modal and populate data
  674. window.callEdit = function (campaignId) {
  675. fetchCampaignDetails(campaignId);
  676. return false; // Prevent default anchor click behavior
  677. };
  678. function setEndDateMin() {
  679. var fromDate = document.getElementById('start_date').value;
  680. document.getElementById('end_date').min = fromDate;
  681. }
  682. // Function to load answer types dynamically
  683. function loadAnswerTypes(callback) {
  684. $.ajax({
  685. url: "/gcc/api/getAnswerTypes",
  686. type: "GET",
  687. success: function(data) {
  688. callback(data);
  689. },
  690. error: function() {
  691. console.log("Error loading answer types.");
  692. }
  693. });
  694. }
  695. function fetchCampaignDetails(campaignId) {
  696. $.ajax({
  697. url: `/gcc/api/campaign/getCampaignDetailsById?campaign_id=${campaignId}`,
  698. type: 'GET',
  699. success: function (response) {
  700. console.log("API Response:", response); // Debugging output
  701. if (!response) {
  702. console.log("Response is null or undefined");
  703. alert("API returned an empty response.");
  704. return;
  705. }
  706. if (Array.isArray(response)) {
  707. console.log("Response is an array with length:", response.length);
  708. } else {
  709. console.log("Response is not an array, type:", typeof response);
  710. }
  711. if (Array.isArray(response) && response.length > 0) {
  712. let campaign = response[0]; // Extract first object for campaign details
  713. // Ensure category_id is set
  714. if (campaign.category_id) {
  715. $('#category_id').val(campaign.category_id);
  716. console.log("Category ID set:", campaign.category_id);
  717. } else {
  718. console.warn("Category ID is missing in API response");
  719. }
  720. // Campaign status check
  721. if (campaign.campaign_status === "CLOSED") {
  722. $('#campaignaddquestion, #savebuttonhide').hide();
  723. $('#end_date').prop('readonly', true);
  724. } else {
  725. $('#campaignaddquestion, #savebuttonhide').show();
  726. }
  727. let campaignid = campaign.campaign_id;
  728. console.log("campaignid ",campaignid);
  729. // Populate campaign details in the modal
  730. $('#campaign_id').val(campaign.campaign_id);
  731. $('#campaign_name').val(campaign.campaign_name);
  732. $('#start_date').val(campaign.start_date);
  733. $('#end_date').val(campaign.end_date);
  734. $('#no_of_agents').val(campaign.no_of_agents);
  735. $('#calls_per_agent').val(campaign.calls_per_agent);
  736. $('#description_modal').val(campaign.description);
  737. // Handle questions and answers dynamically
  738. let questionHtml = "";
  739. response.forEach(q => {
  740. let answers = Array.isArray(q.campaign_answer) ? q.campaign_answer.join(", ") : "No Answers";
  741. questionHtml += `<tr>
  742. <td>${q.questions}</td>
  743. <td>${answers}</td>
  744. </tr>`;
  745. });
  746. // Populate table inside the modal
  747. $('#questionTable tbody').html(questionHtml);
  748. /////////////this is for adding questions and answers dynamically //////////////
  749. let questionCount = 0;
  750. let validAnswerTypeIds = [];
  751. // Function to generate answer type dropdown dynamically
  752. function generateAnswerTypeDropdown(questionId, answerTypes) {
  753. let dropdownHtml = `<label for="answerType${questionId}">Select Answer Type<span class="text-danger">*</span></label>
  754. <select class="form-control answer-type" data-question-id="${questionId}">
  755. <option value="">--Select--</option>`;
  756. $.each(answerTypes, function(index, entry) {
  757. dropdownHtml += `<option value="${entry.answer_type_id}">${entry.type_name}</option>`;
  758. if (!validAnswerTypeIds.includes(entry.answer_type_id.toString())) {
  759. validAnswerTypeIds.push(entry.answer_type_id.toString()); // Store as string
  760. }
  761. });
  762. dropdownHtml += `</select>`;
  763. return dropdownHtml;
  764. }
  765. // Add question button
  766. $('#addQuestionBtn').click(function() {
  767. if ($('#questionsContainer').is(':hidden')) {
  768. $('#questionsContainer').show(); // Show container on first click
  769. }
  770. questionCount++;
  771. loadAnswerTypes(function(answerTypes) {
  772. let questionHtml = `
  773. <div class="question-block border p-3 mb-3" data-question-id="${questionCount}">
  774. <label for="question${questionCount}">Enter Question <span class="text-danger">*</span></label>
  775. <input type="text" class="form-control mb-2 question-input" name="question[]" placeholder="Type your question" required>
  776. ${generateAnswerTypeDropdown(questionCount, answerTypes)}
  777. <div class="answers-container mt-3" id="answersContainer${questionCount}"></div>
  778. <button type="button" class="btn btn-danger btn-sm mt-2 remove-question">Remove Question</button>
  779. </div>`;
  780. $('#questionsContainer').append(questionHtml);
  781. });
  782. });
  783. // Handle answer type selection
  784. $(document).on('change', '.answer-type', function() {
  785. let questionId = $(this).data('question-id');
  786. let selectedType = $(this).val(); // Keep as string
  787. let answersContainer = $(`#answersContainer${questionId}`);
  788. answersContainer.html('');
  789. // Check if selected type is valid
  790. if (validAnswerTypeIds.includes(selectedType)) {
  791. let answerBlock = `
  792. <div class="answer-block">
  793. <label>Answers:</label>
  794. <div class="answer-list"></div>
  795. ${selectedType === "1" ? "" : `<button type="button" class="btn btn-info btn-sm add-answer mt-2" data-question-id="${questionId}">+ Add Answer</button>`}
  796. </div>`;
  797. answersContainer.append(answerBlock);
  798. }
  799. });
  800. // Add answer dynamically
  801. $(document).on('click', '.add-answer', function() {
  802. let questionId = $(this).data('question-id');
  803. let answerList = $(`#answersContainer${questionId} .answer-list`);
  804. let answerInput = `
  805. <div class="answer-input d-flex align-items-center mb-2">
  806. <input type="text" class="form-control answer-text" placeholder="Enter answer" required>
  807. <button type="button" class="btn btn-danger btn-sm remove-answer ms-2">X</button>
  808. </div>`;
  809. answerList.append(answerInput);
  810. });
  811. // Load answer types on page load for the first question
  812. loadAnswerTypes(function(answerTypes) {
  813. let initialDropdown = generateAnswerTypeDropdown(0, answerTypes);
  814. $('#questionsContainer').append(`
  815. <div class="question-block border p-3 mb-3" data-question-id="0">
  816. <label for="question0">Enter Question <span class="text-danger">*</span></label>
  817. <input type="text" class="form-control mb-2 question-input" name="question[]" placeholder="Type your question" required>
  818. ${initialDropdown}
  819. <div class="answers-container mt-3" id="answersContainer0"></div>
  820. <button type="button" class="btn btn-danger btn-sm mt-2 remove-question">Remove Question</button>
  821. </div>`);
  822. });
  823. // Remove question
  824. $(document).on('click', '.remove-question', function() {
  825. $(this).closest('.question-block').remove();
  826. });
  827. // Remove answer
  828. $(document).on('click', '.remove-answer', function() {
  829. $(this).closest('.answer-input').remove();
  830. });
  831. // Ensure modal is displayed
  832. setEndDateMin();
  833. $('#editModal').modal('show');
  834. } else {
  835. alert('Campaign details not found.');
  836. }
  837. },
  838. error: function (xhr, status, error) {
  839. console.error('Error fetching campaign details:', error);
  840. alert('An error occurred while fetching campaign details.');
  841. }
  842. });
  843. $('#editsubmit').click(function (event) {
  844. event.preventDefault(); // Prevent default form submission
  845. let campaignId = $('#campaign_id').val();
  846. if (!campaignId) {
  847. Swal.fire({
  848. icon: 'warning',
  849. title: 'Validation Error',
  850. text: 'Campaign ID is required.'
  851. });
  852. return;
  853. }
  854. var campaignData = {
  855. campaign_id: parseInt(campaignId), // Ensure it's converted to a number
  856. end_date: $('#end_date').val().trim(),
  857. questionsData: []
  858. };
  859. console.log("campaignData ",campaignData);
  860. let isValid = true; // Validation flag
  861. // Validate campaign details
  862. if ( !campaignData.end_date) {
  863. Swal.fire({
  864. icon: 'warning',
  865. title: 'Validation Error',
  866. text: 'Please select enddate.'
  867. });
  868. return;
  869. }
  870. // Validate questions and answers
  871. $('.question-block').each(function () {
  872. let category = $('#category_id').val()?.trim();
  873. if (!category) {
  874. console.warn("Category ID is empty or undefined!");
  875. } else {
  876. console.log("Captured Category ID:", category);
  877. }
  878. // Keep as string for comparison
  879. let questionText = $(this).find('.question-input').val().trim();
  880. let answerType = $(this).find('.answer-type').val();
  881. let selectedType = answerType.toString();
  882. let answers = [];
  883. // Validate question text
  884. if (!questionText) {
  885. Swal.fire({
  886. icon: 'info',
  887. title: 'Info',
  888. text: 'Please enter a question before submitting.'
  889. });
  890. isValid = false;
  891. return false; // Exit loop
  892. }
  893. // Validate answer type selection
  894. if (!answerType) {
  895. Swal.fire({
  896. icon: 'info',
  897. title: 'Info',
  898. text: 'Please select an answer type for each question.'
  899. });
  900. isValid = false;
  901. return false; // Exit loop
  902. }
  903. // Skip answer validation for "Text" answer type (ID = 1)
  904. let answersContainer = $(this).find('.answer-list');
  905. if (answerType !== "1" && answersContainer.children().length === 1) {
  906. Swal.fire({
  907. icon: 'info',
  908. title: 'Info',
  909. text: 'Each question must have at least two answer (except for Text type).'
  910. });
  911. isValid = false;
  912. return false; // Exit loop
  913. }
  914. // Validate answers (only if not Text type)
  915. if (selectedType !== "1") {
  916. let hasEmptyAnswer = false;
  917. $(this).find('.answer-text').each(function () {
  918. let answer = $(this).val().trim();
  919. if (answer) {
  920. answers.push(answer);
  921. } else {
  922. hasEmptyAnswer = true;
  923. }
  924. });
  925. if (hasEmptyAnswer || answers.length === 0) {
  926. Swal.fire({
  927. icon: 'info',
  928. title: 'Info',
  929. text: 'Please fill in all answer fields before submitting.',
  930. });
  931. isValid = false;
  932. return false; // Stop processing further
  933. }
  934. }
  935. campaignData.questionsData.push({ category: category, question: questionText, answerType: answerType, answers: answers });
  936. });
  937. if (!isValid) return;
  938. // Disable submit button to prevent duplicate submissions
  939. $('#editsubmit').prop('disabled', true).text('Saving...');
  940. // Send data via AJAX
  941. $.ajax({
  942. url: '/gcc/api/campaign/updateCampaign',
  943. type: 'POST',
  944. contentType: 'application/json',
  945. data: JSON.stringify(campaignData),
  946. success: function (response) {
  947. $('#editsubmit').prop('disabled', false).text('Save changes');
  948. Swal.fire({
  949. allowOutsideClick: false,
  950. allowEscapeKey: false,
  951. allowEnterKey: false,
  952. title: 'Success!',
  953. text: response,
  954. icon: 'success',
  955. confirmButtonText: 'OK'
  956. }).then(() => {
  957. $('#editsubmit').prop('disabled', false).text('Save changes');
  958. $('#editModal').modal('hide');
  959. location.reload();
  960. });
  961. },
  962. error: function (xhr) {
  963. Swal.fire({ title: 'Error!', text: xhr.responseText, icon: 'error' });
  964. $('#editsubmit').prop('disabled', false).text('Save Changes');
  965. }
  966. });
  967. });
  968. }
  969. });
  970. /////////////dizo///////////////
  971. $(document).ready(function () {
  972. /* function checkExpiredCampaigns() {
  973. $(".status-button").each(function () {
  974. let button = $(this);
  975. let campaignId = button.data("id");
  976. let endDate = button.closest("tr").find("td:nth-child(4)").text().split(" - ")[1].trim(); // Extracting end_date
  977. let today = new Date().toISOString().split("T")[0]; // Get current date in YYYY-MM-DD format
  978. if (endDate < today) {
  979. $.ajax({
  980. url: "/gcc/api/campaign/auto-close",
  981. type: "POST",
  982. data: { campaignId: campaignId },
  983. success: function (response) {
  984. console.log("Campaign ID " + campaignId + " auto-closed.");
  985. button.replaceWith('<span class="text-success">Closed</span>'); // Update UI
  986. },
  987. error: function (xhr) {
  988. console.error("Error closing campaign:", xhr.responseText);
  989. }
  990. });
  991. }
  992. });
  993. }
  994. checkExpiredCampaigns(); // Run on page load */
  995. $(document).on("click", ".status-button", function () {
  996. let button = $(this);
  997. let campaignId = button.data("id"); // Get campaign ID from data attribute
  998. if (!campaignId) {
  999. Swal.fire("Error!", "Campaign ID is missing.", "error");
  1000. return;
  1001. }
  1002. if (button.text().trim() === "Close") {
  1003. return;
  1004. }
  1005. Swal.fire({
  1006. title: "Are you sure?",
  1007. text: "Do you want to close the Campaign?",
  1008. icon: "warning",
  1009. showCancelButton: true,
  1010. confirmButtonText: "Yes",
  1011. cancelButtonText: "No",
  1012. confirmButtonColor: "#007bff",
  1013. cancelButtonColor: "#dc3545",
  1014. allowOutsideClick: false,
  1015. allowEscapeKey: false,
  1016. allowEnterKey: false
  1017. }).then((result) => {
  1018. if (result.isConfirmed) {
  1019. console.log("Closing campaign with ID:", campaignId); // Debugging log
  1020. $.ajax({
  1021. url: "/gcc/api/campaign/close?campaignId=" + campaignId, // ✅ Ensure query parameter
  1022. type: "POST",
  1023. success: function (response) {
  1024. console.log("Success Response:", response);
  1025. Swal.fire({
  1026. allowOutsideClick: false,
  1027. allowEscapeKey: false,
  1028. allowEnterKey: false,
  1029. title: "Success!",
  1030. text: "Campaign has been closed.",
  1031. icon: "success",
  1032. allowOutsideClick: false,
  1033. allowEscapeKey: false
  1034. }).then((result) => {
  1035. if (result.isConfirmed) {
  1036. location.reload();
  1037. }
  1038. });
  1039. },
  1040. error: function (xhr, status, error) {
  1041. console.error("Error Details:", xhr.responseText);
  1042. Swal.fire("Error!", "Failed to close campaign.", "error");
  1043. }
  1044. });
  1045. }
  1046. });
  1047. });
  1048. });
  1049. </script>
  1050. </body>
  1051. </html>