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.

1955 lines
75 KiB

2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/modules/base/head :: head}"></head>
  4. <style>
  5. .required{
  6. color: red;
  7. }
  8. /* Mobile screens - targeting devices with a max width of 767px */
  9. @media (max-width: 767px)
  10. {
  11. #campaignrequestform label{
  12. margin-top: 10px;
  13. }
  14. }
  15. </style>
  16. <body>
  17. <!--[if lt IE 8]>
  18. <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>
  19. <![endif]-->
  20. <div class="wrapper">
  21. <!-- header top menu Start -->
  22. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  23. <!-- header top menu end -->
  24. <div class="page-wrap">
  25. <!--=============== Left Menu side Start ================-->
  26. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  27. <!--=============== Left side End ================-->
  28. <div class="main-content">
  29. <div class="container-fluid">
  30. <div class="page-header mb-2">
  31. <div class="row align-items-end">
  32. <div class="col-lg-8">
  33. <div class="page-header-title">
  34. <i class="far fa-calendar-plus bg-blue"></i>
  35. <div class="d-inline">
  36. <h5>Create Campaign</h5>
  37. <span>1913 Campaign creation</span>
  38. </div>
  39. </div>
  40. </div>
  41. <div class="col-lg-4">
  42. <nav class="breadcrumb-container" aria-label="breadcrumb">
  43. <ol class="breadcrumb">
  44. <li class="breadcrumb-item"><a href="/gcc/index"><i
  45. class="ik ik-home"></i></a></li>
  46. <li class="breadcrumb-item" aria-current="page">1913 Campaign</li>
  47. <li class="breadcrumb-item active" aria-current="page">Create Campaign</li>
  48. </ol>
  49. </nav>
  50. </div>
  51. </div>
  52. </div>
  53. <h4 class="h4 text-right text-mute" style="font-size: 12px;">
  54. Auto refresh in <font id="refresh-countdown">00</font> seconds
  55. </h4>
  56. <div class="row">
  57. <div class="col-md-12">
  58. <div class="card" style="margin-top: 0px;">
  59. <div class="card-header justify-content-between align-items-center">
  60. <h3><b>Campaign uploading excel Form</b></h3>
  61. </div>
  62. <div class="card-body">
  63. <form id="campaignrequestform">
  64. <div class="form-group">
  65. <div class="row">
  66. <div class="col-sm-12 col-md-6">
  67. <label for="name">Campaign Name<span class="required">*</span></label>
  68. <input type="text" class="form-control" id="name" placeholder="Enter Name">
  69. </div>
  70. <!-- Category Selection -->
  71. <div class="col-sm-12 col-md-6">
  72. <label for="category">Category<span class="required">*</span></label>
  73. <select class="form-control" id="category">
  74. <option selected value="0">Select category</option>
  75. </select>
  76. <!-- Download Button (Initially Hidden) -->
  77. <div class="mt-2">
  78. <button type="button" class="btn btn-warning btn-sm" id="downloadcategoryExcel" style="display: none;">
  79. <i class="ik ik-download f-16 mr-2"></i>Template Download
  80. </button>
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. <div class="form-group">
  86. <label for="upload">Upload Excelsheet:<span class="required">*</span></label>
  87. <input type="file" class="form-control" id="fileInput">
  88. <small id="fileError" class="text-danger" style="display:none;">Only Excel files (.xlsx, .xls) are allowed.</small>
  89. </div>
  90. <div class="form-group text-center">
  91. <button type="submit" class="btn btn-primary " id="excelsubmit">Submit</button>
  92. <button type="reset" class="btn btn-secondary ml-2" onclick="resetForm()">Reset</button>
  93. </div>
  94. </form>
  95. </div>
  96. </div>
  97. </div>
  98. <!-- card 2-->
  99. <div class="col-md-12">
  100. <div class="card" style="margin-top: 0px;">
  101. <div class="card-header justify-content-between align-items-center">
  102. <h3><b>Campaign Details Form</b></h3>
  103. </div>
  104. <div class="card-body">
  105. <form id="campaignrequestform">
  106. <!-- Dropdown for Category -->
  107. <div class="row">
  108. <div class="form-group col-md-6 col-sm-12">
  109. <label for="campaigncategory">Select Category<span class="required">*</span></label>
  110. <select id="campaigncategory" class="form-control">
  111. </select>
  112. </div>
  113. <!-- Dropdown for Campaigns -->
  114. <div class="form-group col-md-6 col-sm-12">
  115. <label for="campaign">Select Campaign<span class="required">*</span></label>
  116. <select id="campaign" class="form-control" disabled>
  117. </select>
  118. </div>
  119. <div class="form-group col-12 d-flex justify-content-center align-items-center">
  120. <!-- Centered button between the dropdowns -->
  121. <!-- <button id="searchBtn" class="btn btn-primary">Search</button>
  122. <button id="resetBtn" class="btn btn-secondary ml-3">Reset</button> -->
  123. </div>
  124. </div>
  125. <div id="campaignDetailsCard">
  126. <div class="form-group">
  127. <label><b><u>Event Date:</u></b></label>
  128. <div class="row">
  129. <div class="col-sm-12 col-md-6">
  130. <label for="eventstartdate">From Date<span class="required">*</span></label>
  131. <input type="date" class="form-control" id="eventstartdate" onclick="this.showPicker()">
  132. </div>
  133. <div class="col-sm-12 col-md-6">
  134. <label for="eventenddate">To Date<span class="required">*</span></label>
  135. <input type="date" class="form-control" id="eventenddate" onclick="this.showPicker()">
  136. </div>
  137. </div>
  138. </div>
  139. <div class="form-group">
  140. <label for="description">Description<span class="required">*</span></label>
  141. <textarea class="form-control" id="description" rows="2"></textarea>
  142. </div>
  143. <!-- <div class="container mt-4"> -->
  144. <div class="card">
  145. <div class="card-header justify-content-between align-items-center">
  146. <h3><b>Add Questions and Answers</b></h3>
  147. </div>
  148. <div class="card-body">
  149. <div id="questionsContainer">
  150. <!-- Dynamic questions will be added here -->
  151. </div>
  152. <button type="button" class="btn btn-success mt-3" id="addQuestionBtn">+ Add Question</button>
  153. <!-- <button type="button" class="btn btn-primary mt-3" id="saveDataBtn">Save</button> -->
  154. </div>
  155. </div>
  156. <div class="form-group">
  157. <div class="row" style="padding: 10px;border: groove; border-left: 6px solid black;">
  158. <div class="col-sm-6 col-md-4">
  159. <label for="no_of_calls">Total No Data</label>
  160. <input type="number" class="form-control" id="total_no_of_data" readonly>
  161. </div>
  162. <div class="col-sm-6 col-md-4">
  163. <label for="no_of_calls">No of Agents<span class="required">*</span></label>
  164. <input type="number" class="form-control" id="no_of_agents" >
  165. </div>
  166. <div class="col-sm-6 col-md-4">
  167. <label for="no_of_calls">Calls per Agent:</label>
  168. <input type="number" class="form-control" id="no_of_agent_call" readonly>
  169. </div>
  170. </div>
  171. <div class="row mt-2">
  172. <div class="col-sm-12 col-md-6">
  173. <label for="no_of_calls">No of Calls to be Assigned (per Person)<span class="required">*</span></label>
  174. <input type="number" class="form-control" id="no_of_calls">
  175. </div>
  176. <div class="col-sm-12 col-md-6">
  177. <label for="agentDropdown" class="form-label fw-bold">Agent Selection <span class="text-danger">*</span></label>
  178. <div class="dropdown">
  179. <button class="btn btn-light border rounded w-100 text-start"
  180. type="button"
  181. id="agentDropdownBtn"
  182. data-bs-toggle="dropdown"
  183. aria-expanded="false">
  184. Select Agent(s)
  185. </button>
  186. <ul class="dropdown-menu p-3"
  187. aria-labelledby="agentDropdownBtn"
  188. style="max-height: 250px; overflow-y: auto; width: 100%;">
  189. <div id="agentCheckboxContainer">
  190. <!-- Checkboxes will be loaded here -->
  191. </div>
  192. </ul>
  193. </div>
  194. </div>
  195. </div>
  196. </div>
  197. <div class="form-group text-center">
  198. <button type="submit" class="btn btn-primary " id="requestsubmit">Submit</button>
  199. <button type="reset" class="btn btn-secondary ml-2" onclick="resetForm()">Reset</button>
  200. </div>
  201. </div>
  202. </form>
  203. </div>
  204. </div>
  205. </div>
  206. <div class="col-md-12" style="display:none;">
  207. <div class="card">
  208. <div class="card-block">
  209. <div class="page-header-title" >
  210. <h5 style="margin: 0;font-weight: bold;">Campaign Details</h5><hr>
  211. </div>
  212. <div>
  213. <table id="CampaignDatatable" class="table table-striped table-bordered table-hover dataTable" role="grid">
  214. <thead class="thead-dark">
  215. <tr role="row">
  216. <th class="text-center">S.No</th>
  217. <th class="text-center">Name</th>
  218. <th class="text-center">Event Date</th>
  219. <th class="text-center">Description</th>
  220. <th class="text-center">Agents Assigned</th>
  221. <th class="text-center">Calls per Person</th>
  222. <th class="text-center">Total Calls</th>
  223. <th class="text-center no-sort" width="%2">Action</th>
  224. </tr>
  225. </thead>
  226. <tbody>
  227. <tr th:each="campaign, i: ${campaigns}">
  228. <td th:text="${i.count}">0</td>
  229. <td th:text="${campaign.campaign_name}"></td>
  230. <td th:text="${campaign.event_dates}"></td>
  231. <td th:text="${campaign.description}"></td>
  232. <td th:text="${campaign.no_of_agents}" class="text-center"></td>
  233. <td th:text="${campaign.calls_per_agent}" class="text-center"></td>
  234. <td th:text="${campaign.total_calls}" class="text-center"></td>
  235. <td class="text-center">
  236. <a href="#" th:onclick="return callEdit([[${campaign.campaign_id}]])" data-animation="true" data-toggle="tooltip" data-placement="top" title="Edit" data-original-title="Edit">
  237. <i class="ik ik-edit f-16 mr-15 text-green"></i>
  238. </a>
  239. </td>
  240. </tr>
  241. </tbody>
  242. <tfoot class="thead-dark">
  243. <tr>
  244. <th class="text-center">S.No</th>
  245. <th class="text-center">Name</th>
  246. <th class="text-center">Event Date</th>
  247. <th class="text-center">Description</th>
  248. <th class="text-center">Agents Assigned</th>
  249. <th class="text-center">Calls per Person</th>
  250. <th class="text-center">Total Calls</th>
  251. <th class="text-center no-sort" width="%2">Action</th>
  252. </tr>
  253. </tfoot>
  254. </table>
  255. </div>
  256. </div>
  257. </div>
  258. </div>
  259. </div>
  260. </div>
  261. </div>
  262. <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;">
  263. <div style="position: relative; top: 50%; transform: translateY(-50%);">
  264. <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
  265. <span class="sr-only">Loading...</span>
  266. </div>
  267. <!-- Add the 'Please wait' text below the spinner -->
  268. <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
  269. </div>
  270. </div>
  271. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  272. </div>
  273. </div>
  274. <!-- The Modal -->
  275. <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false">
  276. <div class="modal-dialog modal-lg" role="document">
  277. <div class="modal-content">
  278. <div class="modal-header">
  279. <h5 class="modal-title" id="editModalLabel">Edit Campaign</h5>
  280. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  281. <span aria-hidden="true">&times;</span>
  282. </button>
  283. </div>
  284. <div class="modal-body">
  285. <!-- Your form or content for editing can go here -->
  286. <form id="editForm" onsubmit="submitForm(event)" >
  287. <input type="hidden" name="campaign_id" id="campaign_id" />
  288. <div class="form-group">
  289. <label for="campaign_name">Name<span class="required">*</span></label>
  290. <input type="text" class="form-control" id="campaign_name" placeholder="Enter Name" readonly="readonly">
  291. </div>
  292. <div class="form-group">
  293. <label><b><u>Event Date:</u></b></label>
  294. <div class="row">
  295. <div class="col">
  296. <label for="start_date">From Date<span class="required">*</span></label>
  297. <input type="date" class="form-control" id="start_date" onchange="setEndDateMin()" readonly="readonly" >
  298. </div>
  299. <div class="col">
  300. <label for="end_date">To Date<span class="required">*</span></label>
  301. <input type="date" class="form-control" id="end_date" required>
  302. </div>
  303. </div>
  304. </div>
  305. <div class="form-group">
  306. <div class="row">
  307. <!-- <div class="col">
  308. <label for="no_of_agents">No of Agents to be Assigned<span class="required">*</span></label>
  309. <input type="number" class="form-control" id="no_of_agents" required>
  310. </div> -->
  311. <div class="col">
  312. <label for="calls_per_agent">No of Calls to be Assigned (per Person)<span class="required">*</span></label>
  313. <input type="number" class="form-control" id="calls_per_agent" required>
  314. </div>
  315. </div>
  316. </div>
  317. <div class="form-group">
  318. <label for="description_modal">Description<span class="required">*</span></label>
  319. <textarea class="form-control" id="description_modal" rows="2" readonly="readonly"></textarea>
  320. </div>
  321. <div class="form-group text-center">
  322. <button type="submit" class="btn btn-primary" id="editsubmit">Save changes</button>
  323. </div>
  324. </form>
  325. </div>
  326. </div>
  327. </div>
  328. </div>
  329. <div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
  330. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  331. <script src="node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min.js"></script>
  332. <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
  333. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
  334. <script type="text/javascript">
  335. $(document).ready(function() {
  336. var table = $('#CampaignDatatable').DataTable({
  337. dom: 'Bftip',
  338. columnDefs: [
  339. { targets: 'no-sort', orderable: false }
  340. ],
  341. lengthMenu: [
  342. [50, 100, 200, 500, -1],
  343. ['50 rows', '100 rows', '200 rows', 'Show all']
  344. ],
  345. scrollY: '50vh',
  346. fixedColumns: {
  347. left: 1,
  348. right: 1
  349. },
  350. buttons: [
  351. {
  352. extend: 'pageLength',
  353. className: 'btn btn-warning'
  354. },
  355. {
  356. title: 'Data export',
  357. extend: 'copyHtml5',
  358. text: 'Copy',
  359. className: 'btn btn-secondary',
  360. id: 'copyBtn'
  361. },
  362. {
  363. extend: 'excelHtml5',
  364. text: 'Excel',
  365. className: 'btn btn-secondary',
  366. id: 'excelBtn'
  367. },
  368. {
  369. extend: 'csvHtml5',
  370. text: 'CSV',
  371. className: 'btn btn-secondary',
  372. id: 'csvBtn'
  373. },
  374. {
  375. extend: 'pdfHtml5',
  376. text: 'PDF',
  377. className: 'btn btn-secondary',
  378. id: 'pdfBtn'
  379. }
  380. ],
  381. fixedHeader: true,
  382. autoWidth: true,
  383. responsive: true,
  384. searching: false,
  385. select: false,
  386. processing: false
  387. });
  388. });
  389. document.addEventListener('DOMContentLoaded', function() {
  390. const fromDate = document.getElementById('eventstartdate');
  391. const toDate = document.getElementById('eventenddate');
  392. // Initially disable the "To Date" field
  393. toDate.disabled = true;
  394. fromDate.addEventListener('change', function() {
  395. if (fromDate.value) {
  396. // Enable the "To Date" field when "From Date" is selected
  397. toDate.disabled = false;
  398. // Get the selected "From Date"
  399. const selectedFromDate = new Date(fromDate.value);
  400. // Set the "To Date" minimum to the same day as the "From Date"
  401. const sameDayString = selectedFromDate.toISOString().split('T')[0];
  402. toDate.setAttribute('min', sameDayString);
  403. // Set the "To Date" value to the next day by default
  404. toDate.value = sameDayString;
  405. } else {
  406. // Disable the "To Date" field if "From Date" is cleared
  407. toDate.disabled = true;
  408. toDate.value = ''; // Clear the "To Date" input
  409. }
  410. });
  411. });
  412. function resetForm() {
  413. document.getElementById('campaignrequestform').reset(); // Built-in reset functionality
  414. }
  415. function setEndDateMin() {
  416. var fromDate = document.getElementById('start_date').value;
  417. document.getElementById('end_date').min = fromDate;
  418. }
  419. //Update request form details
  420. $(document).ready(function () {
  421. // Function to open the edit modal and populate data
  422. window.callEdit = function (campaignId) {
  423. fetchCampaignDetails(campaignId);
  424. return false; // Prevent default anchor click behavior
  425. };
  426. function fetchCampaignDetails(campaignId) {
  427. $.ajax({
  428. url: `/gcc/api/campaign/getCampaignDetailsbyId?campaign_id=${campaignId}`,
  429. type: 'GET',
  430. success: function (response) {
  431. console.log(response);
  432. if (response) {
  433. // Populate modal fields with data
  434. $('#campaign_id').val(response.campaign_id);
  435. $('#campaign_name').val(response.campaign_name); // Assuming the key in the response is 'campaign_name'
  436. $('#start_date').val(response.start_date);
  437. $('#end_date').val(response.end_date);
  438. $('#no_of_agents').val(response.no_of_agents);
  439. $('#calls_per_agent').val(response.calls_per_agent);
  440. $('#description_modal').val(response.description);
  441. setEndDateMin();
  442. // Open the modal
  443. $('#editModal').modal('show');
  444. } else {
  445. alert('Campaign details not found.');
  446. }
  447. },
  448. error: function (xhr, status, error) {
  449. console.error('Error fetching campaign details:', error);
  450. alert('An error occurred while fetching campaign details.');
  451. }
  452. });
  453. }
  454. window.submitForm = function (event) {
  455. event.preventDefault(); // Prevent the default form submission
  456. var campaignId = $('#campaign_id').val();
  457. var campaignName = $('#campaign_name').val();
  458. var startDate = $('#start_date').val();
  459. var endDate = $('#end_date').val();
  460. var noOfAgents = $('#no_of_agents').val();
  461. var callsPerAgent = $('#calls_per_agent').val();
  462. var description = $('#description_modal').val();
  463. $.ajax({
  464. url: '/gcc/api/campaign/updateCampaign', // Endpoint without query parameters
  465. type: 'POST',
  466. data: {
  467. campaign_id: campaignId,
  468. campaign_name: campaignName,
  469. start_date: startDate,
  470. end_date: endDate,
  471. no_of_agents: noOfAgents,
  472. calls_per_agent: callsPerAgent,
  473. description: description
  474. }, // Send all data as JSON
  475. success: function (response) {
  476. console.log('Campaign ID:',campaign_id);
  477. Swal.fire({
  478. title: 'Success!',
  479. text: response, // Show the success message from the API response
  480. icon: 'success',
  481. confirmButtonText: 'OK'
  482. }).then((result) => {
  483. if (result.isConfirmed) {
  484. $('#editModal').modal('hide'); // Hide the modal
  485. location.reload(); // Optionally reload the page to refresh the data
  486. }
  487. });
  488. },
  489. error: function (xhr, status, error) {
  490. console.error('Error updating campaign details:', error);
  491. Swal.fire({
  492. title: 'Error!',
  493. text: 'An error occurred while updating campaign details.',
  494. icon: 'error',
  495. confirmButtonText: 'OK'
  496. });
  497. }
  498. });
  499. }
  500. });
  501. ///////////////////////For Dropdown excel download/////////////////
  502. // Function to fetch categories and populate dropdown
  503. function fetchCategories() {
  504. $.ajax({
  505. url: '/gcc/api/category/getcategory',
  506. method: 'GET',
  507. success: function (response) {
  508. if (response && response.length > 0) {
  509. console.log("Categories Loaded:", response);
  510. var $categorySelect = $('#category');
  511. $categorySelect.empty().append('<option value="0">Select Category</option>'); // Default option
  512. $.each(response, function (index, category) {
  513. $categorySelect.append(
  514. $('<option>', {
  515. value: category.category_id,
  516. text: category.category_name
  517. })
  518. );
  519. });
  520. }
  521. },
  522. error: function (xhr, status, error) {
  523. console.error('Error fetching categories:', error);
  524. }
  525. });
  526. }
  527. // Function to handle category selection
  528. function handleCategorySelection(categoryId) {
  529. console.log("Selected Category ID:", categoryId);
  530. if (categoryId === "0") {
  531. $('#downloadcategoryExcel').hide(); // Hide button if "Select Category" is chosen
  532. return;
  533. }
  534. // Fetch column titles for selected category
  535. fetchCategoryColumns(categoryId);
  536. }
  537. // Function to fetch category columns based on selected category
  538. function fetchCategoryColumns(categoryId) {
  539. $.ajax({
  540. url: '/gcc/api/category/getCategoryColumns?category_id=' + categoryId,
  541. method: 'GET',
  542. success: function (response) {
  543. console.log("Columns API Response:", response);
  544. if (response && response.length > 0) {
  545. window.categoryColumns = response.map(item => item.column_name); // Correct field name
  546. console.log("Columns Fetched:", window.categoryColumns);
  547. $('#downloadcategoryExcel').show(); // Show button when columns exist
  548. } else {
  549. window.categoryColumns = [];
  550. $('#downloadcategoryExcel').hide(); // Hide button if no columns exist
  551. }
  552. },
  553. error: function (xhr, status, error) {
  554. console.error('Error fetching category columns:', error);
  555. window.categoryColumns = [];
  556. $('#downloadcategoryExcel').hide(); // Hide button if API fails
  557. }
  558. });
  559. }
  560. // Function to handle Excel download
  561. function downloadExcel() {
  562. console.log("Download button clicked!");
  563. if (!window.categoryColumns || window.categoryColumns.length === 0) {
  564. alert("No columns available for the selected category.");
  565. return;
  566. }
  567. // Get selected category name
  568. var categoryName = $("#category option:selected").text().trim();
  569. if (categoryName === "Select Category") {
  570. categoryName = "Category_Template"; // Fallback name if no category selected
  571. }
  572. var wb = XLSX.utils.book_new();
  573. var ws_data = [window.categoryColumns]; // Column titles
  574. var ws = XLSX.utils.aoa_to_sheet(ws_data);
  575. // Set column widths dynamically
  576. ws['!cols'] = window.categoryColumns.map(col => ({ wch: col.length + 5 }));
  577. XLSX.utils.book_append_sheet(wb, ws, 'Category Data');
  578. // Generate file name dynamically based on category
  579. var fileName = categoryName.replace(/\s+/g, "_") + "_Template.xlsx"; // Replace spaces with underscores
  580. XLSX.writeFile(wb, fileName);
  581. }
  582. /////////campaign and category dropdowns/////////////////
  583. // Function to fetch category dropdown
  584. function fetchCategoryDropdown() {
  585. $.ajax({
  586. url: '/gcc/api/callcenter/admin/getcategory',
  587. type: 'GET',
  588. dataType: 'json'
  589. })
  590. .done(function (data) {
  591. let categoryDropdown = $('#campaigncategory');
  592. categoryDropdown.empty();
  593. categoryDropdown.append($('<option selected value="0"></option>').text('Select a category'));
  594. $.each(data, function (index, category) {
  595. categoryDropdown.append($('<option></option>').attr('value', category.category_id).text(category.category_name));
  596. });
  597. })
  598. .fail(function (xhr, status, error) {
  599. console.error('Error fetching category:', error);
  600. });
  601. }
  602. // Function to fetch campaigns based on selected category
  603. function fetchCampaignDropdown(categoryId) {
  604. $('#campaign').prop('disabled', false);
  605. $.ajax({
  606. url: '/gcc/api/callcenter/admin/getcampaignbycategory?id=' + categoryId,
  607. type: 'GET',
  608. dataType: 'json'
  609. })
  610. .done(function (data) {
  611. let campaignDropdown = $('#campaign');
  612. campaignDropdown.empty();
  613. campaignDropdown.append($('<option selected value="0"></option>').text('Select a campaign'));
  614. $.each(data, function (index, campaign) {
  615. campaignDropdown.append($('<option></option>').attr('value', campaign.campaign_id).text(campaign.campaign_name));
  616. });
  617. })
  618. .fail(function (xhr, status, error) {
  619. console.error('Error fetching campaign:', error);
  620. });
  621. }
  622. // Fetch category dropdown on page load
  623. fetchCategoryDropdown();
  624. // Handle category change event to fetch campaigns
  625. $(document).on('change', '#campaigncategory', function() {
  626. let selectedCategoryId = $(this).val();
  627. if (selectedCategoryId != '0') {
  628. fetchCampaignDropdown(selectedCategoryId);
  629. } else {
  630. $('#campaign').empty().prop('disabled', true);
  631. hideAllDetails();
  632. }
  633. });
  634. /* $("#searchBtn").click(function () {
  635. let selectedCampaignId = $('#campaign').val();
  636. if(selectedCampaignId == null || selectedCampaignId=='0'){
  637. Swal.fire({
  638. title: 'Info!',
  639. text: 'Please Select Category and Campaign!',
  640. icon: 'info',
  641. timer: 2000,
  642. //timerProgressBar: true,
  643. showConfirmButton: false
  644. })
  645. hideCampaignAndAgentDetails();
  646. }
  647. else if (selectedCampaignId != '0') {
  648. //fetchCampaignDetails(selectedCampaignId);
  649. fetchCampaignQuestionDetails(selectedCampaignId);
  650. checkCampaignInAssigned(selectedCampaignId);
  651. // Disable the category and campaign dropdowns after search
  652. $('#campaigncategory').prop('disabled', true);
  653. $('#campaign').prop('disabled', true);
  654. }
  655. else {
  656. hideCampaignAndAgentDetails();
  657. }
  658. }); */
  659. /* $("#resetBtn").click(function () {
  660. hideAllDetails() // Reloads the current page
  661. });
  662. */
  663. //Function to hide all details initially
  664. function hideAllDetails() {
  665. // Hide additional form fields
  666. document.getElementById('campaignDetailsCard').style.display = 'none';
  667. }
  668. // Function to validate selected agents count
  669. function validateAgentSelection() {
  670. let noOfAgents = parseInt($('#no_of_agents').val()) || 0;
  671. let selectedAgentsCount = $('.agentCheckbox:checked').length;
  672. if (noOfAgents !== selectedAgentsCount) {
  673. Swal.fire({
  674. icon: 'warning',
  675. title: 'Mismatch in Agent Selection',
  676. text: `You must select exactly ${noOfAgents} agents.`,
  677. });
  678. return false;
  679. }
  680. return true;
  681. }
  682. // Handle form submission or further processing
  683. $('#assignTaskBtn').on('click', function (e) {
  684. if (!validateAgentSelection()) {
  685. e.preventDefault(); // Prevent form submission if validation fails
  686. }
  687. });
  688. $('#no_of_agents').on('input', function () {
  689. let noOfAgents = parseInt($(this).val()) || 0;
  690. let allAgents = $('.agentCheckbox');
  691. // Ensure the number is within limits
  692. if (noOfAgents > allAgents.length) {
  693. Swal.fire({
  694. icon: 'error',
  695. title: 'Too Many Agents',
  696. text: `Only ${allAgents.length} agents are available.`,
  697. allowOutsideClick: false, // Disable clicking outside the modal to close it
  698. allowEscapeKey: false, // Disable escape key to close the modal
  699. allowEnterKey: false, // Disable enter key to close the modal
  700. showConfirmButton: true
  701. });
  702. $(this).val(allAgents.length);
  703. noOfAgents = allAgents.length;
  704. }
  705. // Auto-select the first N agents based on input
  706. allAgents.prop('checked', false);
  707. allAgents.slice(0, noOfAgents).prop('checked', true);
  708. });
  709. // Function to fetch campaign statistics
  710. function fetchCampaignStatistics(campaignId) {
  711. $.ajax({
  712. url: `/gcc/api/campaign/statistics?campaignId=${campaignId}`,
  713. type: 'GET',
  714. dataType: 'json',
  715. success: function (response) {
  716. if (response) {
  717. // Populate total_no_of_data field
  718. $('#total_no_of_data').val(response.totalCount || 0);
  719. // Handle input event for no_of_agents
  720. $('#no_of_agents').on('input', function () {
  721. let totalData = parseInt($('#total_no_of_data').val()) || 0;
  722. let agents = parseInt($('#no_of_agents').val());
  723. // Ensure agents value is not negative
  724. if (agents < 0 || isNaN(agents)) {
  725. $('#no_of_agents').val(''); // Reset input if negative or NaN
  726. $('#no_of_agent_call').val('');
  727. return;
  728. }
  729. // If no_of_agents is empty, set no_of_agent_call to empty
  730. if (!agents) {
  731. $('#no_of_agent_call').val('');
  732. } else {
  733. let perAgentData = Math.floor(totalData / agents); // Round down
  734. $('#no_of_agent_call').val(perAgentData);
  735. }
  736. });
  737. } else {
  738. console.error('No data returned');
  739. }
  740. },
  741. error: function (xhr, status, error) {
  742. console.error('Error fetching campaign statistics:', error);
  743. }
  744. });
  745. }
  746. // Function to show details when category and campaign are selected
  747. function showDetails() {
  748. const categoryValue = document.getElementById('category').value;
  749. const campaignValue = document.getElementById('campaign').value;
  750. if (categoryValue && campaignValue) {
  751. document.getElementById('campaignDetailsCard').style.display = 'block';
  752. fetchCampaignStatistics(campaignValue);
  753. // Show additional form fields
  754. document.getElementById('eventstartdate').closest('.form-group').style.display = 'block';
  755. //document.getElementById('no_of_agent').closest('.form-group').style.display = 'block';
  756. document.getElementById('no_of_calls').closest('.form-group').style.display = 'block';
  757. document.getElementById('description').closest('.form-group').style.display = 'block';
  758. } else {
  759. hideAllDetails(); // Keep everything hidden if conditions are not met
  760. }
  761. }
  762. // Initialize hiding the fields on page load
  763. window.onload = function() {
  764. hideAllDetails();
  765. // Add event listeners for category and campaign selection
  766. document.getElementById('category').addEventListener('change', showDetails);
  767. document.getElementById('campaign').addEventListener('change', showDetails);
  768. }
  769. ///////new function for saving method//////
  770. $(document).ready(function() {
  771. console.log("Document Ready!");
  772. //////////agents loading script /////////////
  773. // Fetch available agents
  774. function loadAgents() {
  775. $.ajax({
  776. url: "/gcc/api/campaign/availableAgents",
  777. type: "GET",
  778. dataType: "json",
  779. success: function (response) {
  780. console.log("Agents:", response);
  781. $("#agentCheckboxContainer").empty(); // Clear previous checkboxes
  782. if(!response || response.length === 0){
  783. $("#agentCheckboxContainer").append(`
  784. <li>
  785. <label class="dropdown-item">
  786. no available agents to assign task
  787. </label>
  788. </li>
  789. `);
  790. }else{
  791. $("#agentCheckboxContainer").append(`
  792. <li>
  793. <label class="dropdown-item">
  794. <input type="checkbox" id="selectAllAgents"> Select All
  795. </label>
  796. </li>
  797. `);
  798. }
  799. // Append "Select All" checkbox
  800. // Append individual agent checkboxes
  801. response.forEach(agent => {
  802. $("#agentCheckboxContainer").append(`
  803. <li>
  804. <label class="dropdown-item">
  805. <input type="checkbox" class="agentCheckbox" value="${agent.agent_id}"> ${agent.agent_name}
  806. </label>
  807. </li>
  808. `);
  809. });
  810. console.log("okkk...");
  811. // "Select All" logic
  812. $("#selectAllAgents").change(function () {
  813. $(".agentCheckbox").prop("checked", this.checked); // Check/uncheck all
  814. });
  815. // If any individual checkbox is unchecked, uncheck "Select All"
  816. $(document).on("change", ".agentCheckbox", function () {
  817. if ($(".agentCheckbox:checked").length === $(".agentCheckbox").length) {
  818. $("#selectAllAgents").prop("checked", true);
  819. } else {
  820. $("#selectAllAgents").prop("checked", false);
  821. }
  822. });
  823. },
  824. error: function (xhr) {
  825. console.error("AJAX Error:", xhr.status, xhr.responseText);
  826. Swal.fire({
  827. icon: "error",
  828. title: "Error Fetching Data",
  829. text: "Failed to load agents. Please try again.",
  830. });
  831. }
  832. });
  833. }
  834. // Load agents on page load
  835. loadAgents();
  836. let questionCount = 0;
  837. let validAnswerTypeIds = [];
  838. // Initially hide the download button
  839. $('#downloadcategoryExcel').hide();
  840. // Load categories into dropdown
  841. fetchCategories();
  842. // Handle category selection change
  843. $('#category').on('change', function () {
  844. var categoryId = $(this).val();
  845. handleCategorySelection(categoryId);
  846. });
  847. // Handle download button click
  848. $('#downloadcategoryExcel').on('click', function () {
  849. downloadExcel();
  850. });
  851. /* // Modify form submission logic
  852. $('#requestsubmit').on('click', function (event) {
  853. event.preventDefault(); // Prevent default form submission
  854. $('#requestsubmit').attr('disabled', true).text('Submitting...');
  855. // Proceed with form submission logic if validation passes...
  856. }); */
  857. // Function to load answer types dynamically
  858. function loadAnswerTypes(callback) {
  859. $.ajax({
  860. url: "/gcc/api/getAnswerTypes",
  861. type: "GET",
  862. success: function(data) {
  863. callback(data);
  864. },
  865. error: function() {
  866. console.log("Error loading answer types.");
  867. }
  868. });
  869. }
  870. // Function to generate answer type dropdown dynamically
  871. function generateAnswerTypeDropdown(questionId, answerTypes) {
  872. let dropdownHtml = `<label for="answerType${questionId}">Select Answer Type<span class="required">*</span></label>
  873. <select class="form-control answer-type" data-question-id="${questionId}">
  874. <option value="">--Select--</option>`;
  875. $.each(answerTypes, function(index, entry) {
  876. dropdownHtml += `<option value="${entry.answer_type_id}">${entry.type_name}</option>`;
  877. if (!validAnswerTypeIds.includes(entry.answer_type_id.toString())) {
  878. validAnswerTypeIds.push(entry.answer_type_id.toString()); // Store as string
  879. }
  880. });
  881. dropdownHtml += `</select>`;
  882. return dropdownHtml;
  883. }
  884. // Add question button
  885. $('#addQuestionBtn').click(function() {
  886. questionCount++;
  887. loadAnswerTypes(function(answerTypes) {
  888. let questionHtml = `
  889. <div class="question-block border p-3 mb-3" data-question-id="${questionCount}">
  890. <label for="question${questionCount}">Enter Question <span class="required">*</span></label>
  891. <input type="text" class="form-control mb-2 question-input" name="question[]" placeholder="Type your question" required>
  892. ${generateAnswerTypeDropdown(questionCount, answerTypes)}
  893. <div class="answers-container mt-3" id="answersContainer${questionCount}"></div>
  894. <button type="button" class="btn btn-danger btn-sm mt-2 remove-question">Remove Question</button>
  895. </div>`;
  896. $('#questionsContainer').append(questionHtml);
  897. });
  898. });
  899. // Handle answer type selection
  900. $(document).on('change', '.answer-type', function() {
  901. let questionId = $(this).data('question-id');
  902. let selectedType = $(this).val(); // Keep as string
  903. let answersContainer = $(`#answersContainer${questionId}`);
  904. answersContainer.html('');
  905. /* if (validAnswerTypeIds.includes(selectedType)) {
  906. let answerBlock = `
  907. <div class="answer-block">
  908. <label>Answers:</label>
  909. <div class="answer-list"></div>
  910. <button type="button" class="btn btn-info btn-sm add-answer mt-2" data-question-id="${questionId}">+ Add Answer</button>
  911. </div>`;
  912. answersContainer.append(answerBlock);
  913. } */
  914. // Check if selected type is valid
  915. if (validAnswerTypeIds.includes(selectedType)) {
  916. let answerBlock = `
  917. <div class="answer-block">
  918. <label>Answers:</label>
  919. <div class="answer-list"></div>
  920. ${selectedType === "1" ? "" : `<button type="button" class="btn btn-info btn-sm add-answer mt-2" data-question-id="${questionId}">+ Add Answer</button>`}
  921. </div>`;
  922. answersContainer.append(answerBlock);
  923. }
  924. });
  925. // Add answer dynamically
  926. $(document).on('click', '.add-answer', function() {
  927. let questionId = $(this).data('question-id');
  928. let answerList = $(`#answersContainer${questionId} .answer-list`);
  929. let answerInput = `
  930. <div class="answer-input d-flex align-items-center mb-2">
  931. <input type="text" class="form-control answer-text" placeholder="Enter answer" required>
  932. <button type="button" class="btn btn-danger btn-sm remove-answer ms-2">X</button>
  933. </div>`;
  934. answerList.append(answerInput);
  935. });
  936. // Load answer types on page load for the first question
  937. loadAnswerTypes(function(answerTypes) {
  938. let initialDropdown = generateAnswerTypeDropdown(0, answerTypes);
  939. $('#questionsContainer').append(`
  940. <div class="question-block border p-3 mb-3" data-question-id="0">
  941. <label for="question0">Enter Question <span class="required">*</span></label>
  942. <input type="text" class="form-control mb-2 question-input" name="question[]" placeholder="Type your question" required>
  943. ${initialDropdown}
  944. <div class="answers-container mt-3" id="answersContainer0"></div>
  945. <button type="button" class="btn btn-danger btn-sm mt-2 remove-question">Remove Question</button>
  946. </div>`);
  947. });
  948. // Remove question
  949. $(document).on('click', '.remove-question', function() {
  950. $(this).closest('.question-block').remove();
  951. });
  952. // Remove answer
  953. $(document).on('click', '.remove-answer', function() {
  954. $(this).closest('.answer-input').remove();
  955. });
  956. /* document.getElementById('fileInput').addEventListener('change', function (event) {
  957. var fileInput = event.target;
  958. var filePath = fileInput.value;
  959. var allowedExtensions = /(\.xlsx|\.xls)$/i;
  960. if (!allowedExtensions.exec(filePath)) {
  961. document.getElementById('fileError').style.display = 'block'; // Show error message
  962. fileInput.value = ''; // Clear the input
  963. } else {
  964. document.getElementById('fileError').style.display = 'none'; // Hide error message
  965. }
  966. });
  967. //excelsubmit funtion
  968. $('#excelsubmit').on('click', function(event) {
  969. event.preventDefault(); // Prevent form from submitting the traditional way
  970. $('#excelsubmit').attr('disabled', true).text('Submitting...');
  971. // Get form values
  972. var name = $('#name').val();
  973. var category = $('#category').val();
  974. var fileInput = $('#fileInput')[0].files[0]; // Get the file from the input
  975. if(!name){
  976. Swal.fire({
  977. icon: 'info',
  978. title: 'Missing Data',
  979. text: 'Please fill the Campaign name.'
  980. });
  981. $('#excelsubmit').attr('disabled', false).text('Submit');
  982. return;
  983. }
  984. // Validation for 'Category'
  985. if (!category || category === "0") {
  986. Swal.fire({
  987. icon: 'info',
  988. title: 'Missing Data',
  989. text: 'Please select a valid category.'
  990. });
  991. $('#excelsubmit').attr('disabled', false).text('Submit');
  992. return;
  993. }
  994. if(!fileInput){
  995. Swal.fire({
  996. icon: 'info',
  997. title: 'Missing Data',
  998. text: 'Please upload the file.'
  999. });
  1000. $('#excelsubmit').attr('disabled', false).text('Submit');
  1001. return;
  1002. }
  1003. var formData = new FormData();
  1004. formData.append('name', name);
  1005. formData.append('category', category);
  1006. formData.append('file', fileInput);
  1007. $('#pageLoader').show();
  1008. $.ajax({
  1009. url: '/gcc/api/campaign/saveexcelcampaign',
  1010. type: 'POST',
  1011. data: formData,
  1012. processData: false,
  1013. contentType: false,
  1014. success: function(response) {
  1015. $('#pageLoader').hide();
  1016. if (response.status === 'column_mismatch') {
  1017. Swal.fire({
  1018. icon: 'error',
  1019. title: 'Need more columns',
  1020. text: response.message
  1021. }).then(() => {
  1022. $('#excelsubmit').attr('disabled', false).text('Submit');
  1023. });
  1024. return; // Stop further execution
  1025. }
  1026. if (response.status === 'header_mismatch') {
  1027. Swal.fire({
  1028. icon: 'error',
  1029. title: 'Header Mismatch',
  1030. text: response.message
  1031. }).then(() => {
  1032. $('#excelsubmit').attr('disabled', false).text('Submit');
  1033. });
  1034. return; // Stop further execution
  1035. }
  1036. if (response.status === 'error') {
  1037. Swal.fire({
  1038. icon: 'error',
  1039. title: 'Error',
  1040. text: response.message
  1041. }).then(() => {
  1042. $('#excelsubmit').attr('disabled', false).text('Submit');
  1043. });
  1044. return; // Stop further execution
  1045. }
  1046. if(response.status === 'success'){
  1047. Swal.fire({
  1048. icon: 'success',
  1049. allowOutsideClick: false,
  1050. allowEscapeKey: false,
  1051. allowEnterKey: false,
  1052. title: 'Success',
  1053. text: 'Campaign data saved successfully!'
  1054. }).then((result) => {
  1055. if (result.isConfirmed) {
  1056. $('#excelsubmit').attr('disabled', false).text('Submit');
  1057. location.reload();
  1058. }
  1059. });
  1060. }
  1061. },
  1062. error: function(xhr) {
  1063. $('#pageLoader').hide();
  1064. Swal.fire({
  1065. icon: 'error',
  1066. title: 'Error',
  1067. text: 'Failed to save campaign details. Please try again.'
  1068. });
  1069. $('#excelsubmit').attr('disabled', false).text('Submit');
  1070. }
  1071. });
  1072. }); */
  1073. document.getElementById('fileInput').addEventListener('change', function (event) {
  1074. var fileInput = event.target;
  1075. var filePath = fileInput.value;
  1076. var allowedExtensions = /(\.xlsx|\.xls)$/i;
  1077. if (!allowedExtensions.exec(filePath)) {
  1078. document.getElementById('fileError').style.display = 'block'; // Show error message
  1079. fileInput.value = ''; // Clear the input
  1080. } else {
  1081. document.getElementById('fileError').style.display = 'none'; // Hide error message
  1082. }
  1083. });
  1084. // Function to read Excel file and count rows
  1085. /* function readExcelFile(file) {
  1086. return new Promise((resolve, reject) => {
  1087. var reader = new FileReader();
  1088. reader.onload = function (e) {
  1089. var data = new Uint8Array(e.target.result);
  1090. var workbook = XLSX.read(data, { type: 'array' });
  1091. var sheet = workbook.Sheets[workbook.SheetNames[0]];
  1092. var jsonData = XLSX.utils.sheet_to_json(sheet, { header: 1 });
  1093. if (jsonData.length <= 1) {
  1094. reject('Excel file is empty or does not contain valid data.');
  1095. } else {
  1096. resolve(jsonData.length - 1); // Exclude header row
  1097. }
  1098. };
  1099. reader.onerror = function () {
  1100. reject('Error reading the file. Please try again.');
  1101. };
  1102. reader.readAsArrayBuffer(file);
  1103. });
  1104. } */
  1105. function readExcelFile(file) {
  1106. return new Promise((resolve, reject) => {
  1107. var reader = new FileReader();
  1108. reader.onload = function (e) {
  1109. var data = new Uint8Array(e.target.result);
  1110. var workbook = XLSX.read(data, { type: 'array' });
  1111. var sheet = workbook.Sheets[workbook.SheetNames[0]];
  1112. var jsonData = XLSX.utils.sheet_to_json(sheet, { header: 1, raw: false, defval: "" }); // Ensure empty cells are not skipped
  1113. if (jsonData.length <= 1) {
  1114. reject('Excel file is empty or does not contain valid data.');
  1115. return;
  1116. }
  1117. let emptyCells = 0;
  1118. // Loop through rows and columns to check for empty cells
  1119. for (let i = 1; i < jsonData.length; i++) { // Start from 1 to exclude header
  1120. for (let j = 0; j < jsonData[0].length; j++) { // Ensure checking all expected columns
  1121. let cellValue = jsonData[i][j];
  1122. if (cellValue === "" || cellValue === undefined || cellValue === null) {
  1123. emptyCells++;
  1124. }
  1125. }
  1126. }
  1127. if (emptyCells > 0) {
  1128. reject(`The uploaded Excel file contains ${emptyCells} empty cells. Please fill them before proceeding.`);
  1129. } else {
  1130. resolve(jsonData.length - 1); // Exclude header row
  1131. }
  1132. };
  1133. reader.onerror = function () {
  1134. reject('Error reading the file. Please try again.');
  1135. };
  1136. reader.readAsArrayBuffer(file);
  1137. });
  1138. }
  1139. // Excel submit function
  1140. $('#excelsubmit').on('click', function (event) {
  1141. event.preventDefault(); // Prevent traditional form submission
  1142. $('#excelsubmit').attr('disabled', true).text('Reading file...');
  1143. var name = $('#name').val();
  1144. var category = $('#category').val();
  1145. var fileInput = $('#fileInput')[0].files[0]; // Get the file
  1146. if (!name) {
  1147. Swal.fire({
  1148. icon: 'info',
  1149. title: 'Missing Data',
  1150. text: 'Please fill in the campaign name.'
  1151. });
  1152. $('#excelsubmit').attr('disabled', false).text('Submit');
  1153. return;
  1154. }
  1155. if (!category || category === "0") {
  1156. Swal.fire({
  1157. icon: 'info',
  1158. title: 'Missing Data',
  1159. text: 'Please select a valid category.'
  1160. });
  1161. $('#excelsubmit').attr('disabled', false).text('Submit');
  1162. return;
  1163. }
  1164. if (!fileInput) {
  1165. Swal.fire({
  1166. icon: 'info',
  1167. title: 'Missing Data',
  1168. text: 'Please upload a file.'
  1169. });
  1170. $('#excelsubmit').attr('disabled', false).text('Submit');
  1171. return;
  1172. }
  1173. $('#pageLoader').show();
  1174. // Read the Excel file
  1175. readExcelFile(fileInput).then((recordCount) => {
  1176. $('#pageLoader').hide();
  1177. Swal.fire({
  1178. icon: 'question',
  1179. title: 'Confirm Submission',
  1180. text: `The uploaded Excel file contains ${recordCount} records. Do you want to proceed?`,
  1181. allowOutsideClick: false, // Disable clicking outside the modal to close it
  1182. allowEscapeKey: false, // Disable escape key to close the modal
  1183. allowEnterKey: false, // Disable enter key to close the modal
  1184. showCancelButton: true,
  1185. confirmButtonText: 'Yes, Submit',
  1186. cancelButtonText: 'No, Cancel'
  1187. }).then((result) => {
  1188. if (result.isConfirmed) {
  1189. // Proceed with submission
  1190. submitExcelData(name, category, fileInput);
  1191. } else {
  1192. $('#excelsubmit').attr('disabled', false).text('Submit');
  1193. }
  1194. });
  1195. }).catch((error) => {
  1196. $('#pageLoader').hide();
  1197. Swal.fire({
  1198. icon: 'info',
  1199. title: 'Validation Error',
  1200. text: error,
  1201. allowOutsideClick: false, // Disable clicking outside the modal to close it
  1202. allowEscapeKey: false, // Disable escape key to close the modal
  1203. allowEnterKey: false, // Disable enter key to close the modal
  1204. });
  1205. $('#excelsubmit').attr('disabled', false).text('Submit');
  1206. });
  1207. });
  1208. // Function to submit the form data
  1209. function submitExcelData(name, category, fileInput) {
  1210. var formData = new FormData();
  1211. formData.append('name', name);
  1212. formData.append('category', category);
  1213. formData.append('file', fileInput);
  1214. $('#pageLoader').show();
  1215. $.ajax({
  1216. url: '/gcc/api/campaign/saveexcelcampaign',
  1217. type: 'POST',
  1218. data: formData,
  1219. processData: false,
  1220. contentType: false,
  1221. success: function (response) {
  1222. $('#pageLoader').hide();
  1223. if (response.status === 'column_mismatch') {
  1224. Swal.fire({
  1225. icon: 'error',
  1226. title: 'Need more columns',
  1227. text: response.message
  1228. }).then(() => {
  1229. $('#excelsubmit').attr('disabled', false).text('Submit');
  1230. });
  1231. return;
  1232. }
  1233. if (response.status === 'header_mismatch') {
  1234. Swal.fire({
  1235. icon: 'error',
  1236. title: 'Header Mismatch',
  1237. text: response.message
  1238. }).then(() => {
  1239. $('#excelsubmit').attr('disabled', false).text('Submit');
  1240. });
  1241. return;
  1242. }
  1243. if (response.status === 'error') {
  1244. Swal.fire({
  1245. icon: 'error',
  1246. title: 'Error',
  1247. text: response.message
  1248. }).then(() => {
  1249. $('#excelsubmit').attr('disabled', false).text('Submit');
  1250. });
  1251. return;
  1252. }
  1253. Swal.fire({
  1254. icon: 'success',
  1255. title: 'Success',
  1256. allowOutsideClick: false,
  1257. allowEscapeKey: false,
  1258. allowEnterKey: false,
  1259. showConfirmButton: true,
  1260. text: 'Campaign data saved successfully!'
  1261. }).then((result) => {
  1262. if (result.isConfirmed) {
  1263. $('#excelsubmit').attr('disabled', false).text('Submit');
  1264. location.reload();
  1265. }
  1266. });
  1267. },
  1268. error: function () {
  1269. $('#pageLoader').hide();
  1270. Swal.fire({
  1271. icon: 'error',
  1272. title: 'Error',
  1273. text: 'Failed to save campaign details. Please try again.'
  1274. });
  1275. $('#excelsubmit').attr('disabled', false).text('Submit');
  1276. }
  1277. });
  1278. }
  1279. /////// Campaign request question and answers function ////////
  1280. $('#requestsubmit').on('click', function(event) {
  1281. event.preventDefault(); // Prevent traditional form submission
  1282. $('#requestsubmit').attr('disabled', true).text('Submitting...');
  1283. // Get form values
  1284. var campaignId = $('#campaign').val();
  1285. var categoryId = $('#campaigncategory').val();
  1286. var eventStartDate = $('#eventstartdate').val();
  1287. var eventEndDate = $('#eventenddate').val();
  1288. var noOfCalls = $('#no_of_calls').val();
  1289. var description = $('#description').val();
  1290. console.log("campaign ",campaignId);
  1291. console.log("category ",categoryId);
  1292. // Check for empty values
  1293. if (!eventStartDate || !eventEndDate || !noOfCalls || !description || !campaignId || !categoryId || campaignId === "0" || categoryId==="0") {
  1294. Swal.fire({
  1295. icon: 'info',
  1296. title: 'Info',
  1297. text: 'Please fill in all mandatory fields before submitting.',
  1298. });
  1299. $('#requestsubmit').attr('disabled', false).text('Submit');
  1300. return;
  1301. }
  1302. // // Collect selected agent IDs
  1303. /* let selectedAgents = [];
  1304. $('.agentCheckbox:checked').each(function () {
  1305. selectedAgents.push($(this).val());
  1306. console.log("selectedagents",selectedAgents);
  1307. });
  1308. // Ensure at least one agent is selected
  1309. if (selectedAgents.length === 0) {
  1310. Swal.fire({
  1311. icon: 'info',
  1312. title: 'Info',
  1313. text: 'Please select at least one agent before submitting.'
  1314. });
  1315. $('#requestsubmit').attr('disabled', false).text('Submit');
  1316. return;
  1317. } */
  1318. let noOfAgents = parseInt($('#no_of_agents').val()) || 0;
  1319. let selectedAgents = $('.agentCheckbox:checked').map(function () {
  1320. return $(this).val();
  1321. }).get();
  1322. if (noOfAgents !== selectedAgents.length) {
  1323. Swal.fire({
  1324. icon: 'warning',
  1325. title: 'Mismatch in Agent Selection',
  1326. text: `You must select exactly ${noOfAgents} agents.`,
  1327. allowOutsideClick: false, // Disable clicking outside the modal to close it
  1328. allowEscapeKey: false, // Disable escape key to close the modal
  1329. allowEnterKey: false, // Disable enter key to close the modal
  1330. showConfirmButton: true
  1331. });
  1332. $('#requestsubmit').attr('disabled', false).text('Submit');
  1333. return;
  1334. }
  1335. let questionsData = [];
  1336. let isValid = true;
  1337. $('.question-block').each(function() {
  1338. let questionText = $(this).find('.question-input').val().trim();
  1339. let answerType = $(this).find('.answer-type').val();
  1340. let selectedType = answerType.toString(); // Keep as string for comparison
  1341. let answers = [];
  1342. // Validate question text
  1343. if (!questionText) {
  1344. Swal.fire({
  1345. icon: 'info',
  1346. title: 'Info',
  1347. text: 'Please enter a question before submitting.'
  1348. });
  1349. isValid = false;
  1350. return false; // Exit loop
  1351. }
  1352. // Validate answer type selection
  1353. if (!answerType) {
  1354. Swal.fire({
  1355. icon: 'info',
  1356. title: 'Info',
  1357. text: 'Please select an answer type for each question.'
  1358. });
  1359. isValid = false;
  1360. return false; // Exit loop
  1361. }
  1362. // Skip answer validation for "Text" answer type (ID = 1)
  1363. let answersContainer = $(this).find('.answer-list');
  1364. if (answerType !== "1" && answersContainer.children().length === 1) {
  1365. Swal.fire({
  1366. icon: 'info',
  1367. title: 'Info',
  1368. text: 'Each question must have at least two answer (except for Text type).'
  1369. });
  1370. isValid = false;
  1371. return false; // Exit loop
  1372. }
  1373. // Validate answers (only if not Text type)
  1374. if (selectedType !== "1") {
  1375. let hasEmptyAnswer = false;
  1376. $(this).find('.answer-text').each(function () {
  1377. let answer = $(this).val().trim();
  1378. if (answer) {
  1379. answers.push(answer);
  1380. } else {
  1381. hasEmptyAnswer = true;
  1382. }
  1383. });
  1384. if (hasEmptyAnswer || answers.length < 2) {
  1385. Swal.fire({
  1386. icon: 'info',
  1387. title: 'Info',
  1388. text: 'Please fill in all answer fields before submitting.',
  1389. //text: 'Each question must have at least two valid answers (except for Text type).',
  1390. });
  1391. isValid = false;
  1392. return false; // Stop processing further
  1393. }
  1394. }
  1395. questionsData.push({
  1396. question: questionText,
  1397. answerType: answerType,
  1398. answers: answers
  1399. });
  1400. });
  1401. console.log("questionsData ",questionsData);
  1402. console.log("isvalid outside",isValid);
  1403. if (!isValid) {
  1404. $('#requestsubmit').attr('disabled', false).text('Submit');
  1405. console.log("isvalid inside",isValid);
  1406. return;
  1407. }
  1408. let questionsJson = JSON.stringify(questionsData);
  1409. // Create FormData object
  1410. var formData = new FormData();
  1411. formData.append('categoryId',categoryId);
  1412. formData.append('campaignId',campaignId);
  1413. formData.append('eventStartDate',eventStartDate);
  1414. formData.append('eventEndDate',eventEndDate);
  1415. formData.append('noOfCalls',noOfCalls);
  1416. formData.append('description',description);
  1417. formData.append('questionsData', questionsJson);
  1418. formData.append('selectedAgents', JSON.stringify(selectedAgents));
  1419. //formData.append('questionsData', new Blob([questionsJson], { type: 'application/json' }));
  1420. //formData.append('selectedAgents', new Blob([JSON.stringify(selectedAgents)], { type: 'application/json' }));
  1421. // Append agent IDs as JSON array
  1422. //formData.append('selectedAgents', JSON.stringify(selectedAgents));
  1423. console.log("formdata "+ formData);
  1424. $('#pageLoader').show();
  1425. $.ajax({
  1426. //url: `/gcc/api/campaign/savecampaign?categoryId=${encodeURIComponent(categoryId)}&campaignId=${encodeURIComponent(campaignId)}&eventStartDate=${encodeURIComponent(eventStartDate)}&eventEndDate=${encodeURIComponent(eventEndDate)}&noOfCalls=${encodeURIComponent(noOfCalls)}&description=${encodeURIComponent(description)}`,
  1427. url: '/gcc/api/campaign/savecampaign',
  1428. type: 'POST',
  1429. data: formData,
  1430. processData: false,
  1431. contentType: false,
  1432. success: function(response) {
  1433. $('#pageLoader').hide();
  1434. if(response.status==='success'){
  1435. Swal.fire({
  1436. icon: 'success',
  1437. title: 'Success',
  1438. allowOutsideClick: false,
  1439. allowEscapeKey: false,
  1440. allowEnterKey: false,
  1441. text: response.message
  1442. }).then((result) => {
  1443. if (result.isConfirmed) {
  1444. $('#requestsubmit').attr('disabled', false).text('Submit');
  1445. location.reload();
  1446. }
  1447. });
  1448. }
  1449. else{
  1450. $('#requestsubmit').attr('disabled', false).text('Submit');
  1451. Swal.fire({
  1452. icon: 'error',
  1453. title: 'Error',
  1454. text: response.message
  1455. });
  1456. }
  1457. },
  1458. error: function(xhr) {
  1459. $('#pageLoader').hide();
  1460. Swal.fire({
  1461. icon: 'error',
  1462. title: 'Error',
  1463. text: 'Something went wrong. Please try again later.'
  1464. });
  1465. $('#requestsubmit').attr('disabled', false).text('Submit');
  1466. }
  1467. });
  1468. });
  1469. /* //campaign request question and answers function
  1470. $('#requestsubmit').on('click', function(event) {
  1471. event.preventDefault(); // Prevent form from submitting the traditional way
  1472. $('#requestsubmit').attr('disabled', true).text('Submitting...');
  1473. // Get form values
  1474. //var name = $('#name').val();
  1475. //var category = $('#category').val();
  1476. var eventStartDate = $('#eventstartdate').val();
  1477. var eventEndDate = $('#eventenddate').val();
  1478. var noOfAgent = $('#no_of_agent').val();
  1479. var noOfCalls = $('#no_of_calls').val();
  1480. var description = $('#description').val();
  1481. //var fileInput = $('#fileInput')[0].files[0]; // Get the file from the input
  1482. // Check for empty values and trigger Swal error
  1483. if ( !eventStartDate || !eventEndDate || !noOfAgent || !noOfCalls || !description) {
  1484. Swal.fire({
  1485. icon: 'info',
  1486. title: 'Info',
  1487. text: 'Please fill in all mandatory fields and upload a file before submitting.',
  1488. });
  1489. $('#requestsubmit').attr('disabled', false).text('Submit');
  1490. return; // Stop form submission if any field is empty
  1491. }
  1492. let questionsData = [];
  1493. let isValid = true; // Validation flag
  1494. $('.question-block').each(function() {
  1495. let questionText = $(this).find('.question-input').val().trim();
  1496. let answerType = $(this).find('.answer-type').val();
  1497. let selectedType = answerType.toString(); // Keep as string for comparison
  1498. let answers = [];
  1499. // Validate question text
  1500. if (!questionText) {
  1501. Swal.fire({
  1502. icon: 'info',
  1503. title: 'Info',
  1504. text: 'Please enter a question before submitting.'
  1505. });
  1506. isValid = false;
  1507. return false; // Exit loop
  1508. }
  1509. // Validate answer type selection
  1510. if (!answerType) {
  1511. Swal.fire({
  1512. icon: 'info',
  1513. title: 'Info',
  1514. text: 'Please select an answer type for each question.'
  1515. });
  1516. isValid = false;
  1517. return false; // Exit loop
  1518. }
  1519. // Skip answer validation for "Text" answer type (ID = 1)
  1520. let answersContainer = $(this).find('.answer-list');
  1521. if (answerType !== "1" && answersContainer.children().length === 0) {
  1522. Swal.fire({
  1523. icon: 'info',
  1524. title: 'Info',
  1525. text: 'Each question must have at least one answer (except for Text type).'
  1526. });
  1527. isValid = false;
  1528. return false; // Exit loop
  1529. }
  1530. // Validate answers (only if not Text type)
  1531. if (selectedType !== "1") {
  1532. let hasEmptyAnswer = false;
  1533. $(this).find('.answer-text').each(function () {
  1534. let answer = $(this).val().trim();
  1535. if (answer) {
  1536. answers.push(answer);
  1537. } else {
  1538. hasEmptyAnswer = true;
  1539. }
  1540. });
  1541. if (hasEmptyAnswer || answers.length === 0) {
  1542. Swal.fire({
  1543. icon: 'info',
  1544. title: 'Info',
  1545. text: 'Please fill in all answer fields before submitting.',
  1546. });
  1547. isValid = false;
  1548. return false; // Stop processing further
  1549. }
  1550. }
  1551. let questionObj = {
  1552. question: questionText,
  1553. answerType: answerType,
  1554. answers: answers,
  1555. };
  1556. questionsData.push(questionObj);
  1557. });
  1558. if (!isValid) {
  1559. $('#requestsubmit').attr('disabled', false).text('Submit');
  1560. return; // Stop AJAX call if validation fails
  1561. }
  1562. // Convert questionsData array to JSON string
  1563. let questionsJson = JSON.stringify(questionsData);
  1564. console.log("Q&A data:",questionsJson);
  1565. // Create FormData object
  1566. var formData = new FormData();
  1567. formData.append('file', fileInput);
  1568. formData.append('questionsData', new Blob([questionsJson], { type: 'application/json' }));
  1569. console.log("formdata",formData);
  1570. $('#pageLoader').show();
  1571. // Send the AJAX request with query parameters and multipart data
  1572. $.ajax({
  1573. url: `/gcc/api/campaign/savecampaign?name=${encodeURIComponent(name)}&category=${encodeURIComponent(category)}&eventStartDate=${encodeURIComponent(eventStartDate)}&eventEndDate=${encodeURIComponent(eventEndDate)}&noOfAgent=${encodeURIComponent(noOfAgent)}&noOfCalls=${encodeURIComponent(noOfCalls)}&description=${encodeURIComponent(description)}`,
  1574. type: 'POST',
  1575. data: formData,
  1576. processData: false,
  1577. contentType: false,
  1578. success: function(response) {
  1579. $('#pageLoader').hide();
  1580. if (response.status === "error") {
  1581. Swal.fire({
  1582. icon: 'error',
  1583. title: 'Column Mismatch ',
  1584. text: response.message // Displays error message for column mismatch
  1585. }).then(() => {
  1586. $('#requestsubmit').attr('disabled', false).text('Submit');
  1587. });
  1588. return; // Stop further execution
  1589. }
  1590. console.log("Response:", response);
  1591. Swal.fire({
  1592. icon: 'success',
  1593. title: 'Success',
  1594. text: 'Campaign data saved successfully!',
  1595. }).then((result) => {
  1596. if (result.isConfirmed) {
  1597. $('#requestsubmit').attr('disabled', false).text('Submit');
  1598. location.reload();
  1599. }
  1600. });
  1601. },
  1602. error: function(xhr) {
  1603. $('#pageLoader').hide();
  1604. }
  1605. });
  1606. }); */
  1607. });
  1608. </script>
  1609. </body>
  1610. </html>