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

1361 lines
45 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/modules/base/head :: head}"></head>
  4. <link
  5. href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap"
  6. rel="stylesheet">
  7. <!-- <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">-->
  8. <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">
  9. <script
  10. src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
  11. <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
  12. <style>
  13. .required {
  14. color: red;
  15. }
  16. /* Mobile screens - targeting devices with a max width of 767px */
  17. @media ( max-width : 767px) {
  18. #complaintform label {
  19. margin-top: 10px;
  20. }
  21. }
  22. .form-row {
  23. margin-bottom: 20px;
  24. }
  25. .form-step {
  26. display: none;
  27. }
  28. .form-step.active {
  29. display: block;
  30. }
  31. .container {
  32. max-width: 100%;
  33. }
  34. /*css for step 3*/
  35. .complaint-icons {
  36. display: flex;
  37. justify-content: space-around;
  38. margin-bottom: 20px;
  39. }
  40. .complaint-icon {
  41. text-align: center;
  42. cursor: pointer;
  43. }
  44. .complaint-icon img {
  45. width: 50px;
  46. height: 50px;
  47. }
  48. .complaint-fields {
  49. display: none;
  50. }
  51. .complaint-fields.active {
  52. display: block;
  53. }
  54. /*for radio button style*/
  55. .radio-group {
  56. display: flex;
  57. align-items: center;
  58. /* Ensures all items are aligned to the center */
  59. }
  60. .radio-item {
  61. display: flex;
  62. align-items: center;
  63. margin-right: 20px;
  64. /* Adds space between each radio item */
  65. }
  66. .radio-item input[type="radio"] {
  67. margin-right: 10px;
  68. /* Adds space between the radio button and its label */
  69. vertical-align: middle;
  70. /* Ensures vertical alignment */
  71. }
  72. .radio-item label {
  73. margin: 0;
  74. /* Removes any default margins that might affect alignment */
  75. }
  76. .back-button {
  77. background: none;
  78. border: none;
  79. color: #000;
  80. font-size: 16px;
  81. cursor: pointer;
  82. padding: 0;
  83. margin-right: auto;
  84. /* Align the button to the left */
  85. }
  86. .title {
  87. text-align: center;
  88. flex-grow: 1;
  89. font-size: 24px;
  90. font-weight: bold;
  91. margin: 0;
  92. }
  93. /*css for map in step2*/
  94. #map {
  95. height: 300px;
  96. width: 100%;
  97. position: relative;
  98. overflow: hidden;
  99. max-width: 100%;
  100. }
  101. #search-container {
  102. position: absolute;
  103. top: 10px;
  104. left: 50%;
  105. transform: translateX(-50%);
  106. z-index: 1000;
  107. width: 500px;
  108. box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);
  109. background-color: white;
  110. border-radius: 4px;
  111. padding: 0;
  112. /* Removed extra padding to match the input width */
  113. }
  114. #search-box {
  115. width: 100%;
  116. /* Ensures the input takes up the entire width of the container */
  117. padding: 5px;
  118. font-size: 16px;
  119. border: 1px solid #ccc;
  120. border-radius: 4px;
  121. /* Rounded corners matching the container */
  122. box-sizing: border-box;
  123. /* Makes sure padding is considered in width */
  124. }
  125. #suggestions {
  126. border: 1px solid #ccc;
  127. border-radius: 4px;
  128. max-height: 200px;
  129. overflow-y: auto;
  130. margin-top: 5px;
  131. background-color: white;
  132. display: none;
  133. width: 100%;
  134. /* Matches the width of the container and input */
  135. box-sizing: border-box;
  136. /* Ensures the width includes borders and padding */
  137. }
  138. #suggestions ul {
  139. list-style: none;
  140. padding: 0;
  141. margin: 0;
  142. }
  143. #suggestions ul li {
  144. padding: 5px;
  145. cursor: pointer;
  146. }
  147. #suggestions ul li:hover {
  148. background-color: #f0f0f0;
  149. }
  150. #reader-btn, #invertColorBtn {
  151. padding: 5px 10px;
  152. font-size: 14px;
  153. cursor: pointer;
  154. }
  155. .loader {
  156. border: 16px solid #f3f3f3;
  157. /* Light grey */
  158. border-top: 16px solid #3498db;
  159. /* Blue */
  160. border-radius: 50%;
  161. width: 120px;
  162. height: 120px;
  163. animation: spin 2s linear infinite;
  164. position: absolute;
  165. top: 50%;
  166. left: 50%;
  167. margin: -60px 0 0 -100px;
  168. /* Center the loader */
  169. z-index: 9999;
  170. /* Ensure it's on top of everything */
  171. display: none;
  172. /* Initially hidden */
  173. }
  174. @keyframes spin { 0%
  175. {
  176. transform: rotate(0deg);
  177. }
  178. 100%
  179. {
  180. transform:rotate(360deg);
  181. }
  182. }
  183. #snackbar {
  184. visibility: hidden;
  185. min-width: 250px;
  186. background-color: #333;
  187. color: #fff;
  188. text-align: center;
  189. border-radius: 2px;
  190. padding: 16px;
  191. position: fixed;
  192. z-index: 1;
  193. left: 50%;
  194. bottom: 30px;
  195. font-size: 17px;
  196. transform: translateX(-50%);
  197. }
  198. #snackbar.show {
  199. visibility: visible;
  200. -webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
  201. animation: fadein 0.5s, fadeout 0.5s 2.5s;
  202. }
  203. @-webkit-keyframes fadein {from { bottom:0;
  204. opacity: 0;
  205. }
  206. to {
  207. bottom: 30px;
  208. opacity: 1;
  209. }
  210. }
  211. @keyframes fadein {from { bottom:0;
  212. opacity: 0;
  213. }
  214. to {
  215. bottom: 30px;
  216. opacity: 1;
  217. }
  218. }
  219. @-webkit-keyframes fadeout {from { bottom:30px;
  220. opacity: 1;
  221. }
  222. to {
  223. bottom: 0;
  224. opacity: 0;
  225. }
  226. }
  227. @keyframes fadeout {from { bottom:30px;
  228. opacity: 1;
  229. }
  230. to {
  231. bottom: 0;
  232. opacity: 0;
  233. }
  234. }
  235. /*for snack bar*/
  236. </style>
  237. <body>
  238. <div id="snackbar"></div>
  239. <!--[if lt IE 8]>
  240. <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>
  241. <![endif]-->
  242. <div class="wrapper">
  243. <!-- header top menu Start -->
  244. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  245. <!-- header top menu end -->
  246. <div class="page-wrap">
  247. <!--=============== Left Menu side Start ================-->
  248. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  249. <!--=============== Left side End ================-->
  250. <div class="main-content">
  251. <div class="container-fluid">
  252. <div class="page-header mb-2">
  253. <div class="row align-items-end">
  254. <div class="col-lg-8">
  255. <div class="page-header-title">
  256. <i class="fas fa-ticket-alt bg-blue"></i>
  257. <div class="d-inline">
  258. <h5>PGR Complaint Registration</h5>
  259. <span>1913 PGR Complaint Registration</span>
  260. </div>
  261. </div>
  262. </div>
  263. <div class="col-lg-4">
  264. <nav class="breadcrumb-container" aria-label="breadcrumb">
  265. <ol class="breadcrumb">
  266. <li class="breadcrumb-item"><a href="index"><i
  267. class="ik ik-home"></i></a></li>
  268. <li class="breadcrumb-item" aria-current="page">PGR Register Complaint</li>
  269. <li class="breadcrumb-item active" aria-current="page">Complaint Registration</li>
  270. </ol>
  271. </nav>
  272. </div>
  273. </div>
  274. </div>
  275. <div class="row inside mt-4">
  276. <div class="col-md-12">
  277. <div class="card" style="margin-top: 0px;">
  278. <div class="card-body">
  279. <!-- Step 1 -->
  280. <!-- Step 1 -->
  281. <div class=" form-step active" id="step-1">
  282. <!-- <div class="card-body"> -->
  283. <h5 class="card-title">1. Complaining Person's Details:</h5>
  284. <div class="form-row">
  285. <div class="col-md-4">
  286. <label for="mobile">Mobile Number:<span class="required">*</span></label>
  287. <div class="input-group">
  288. <input type="text" id="mobileNo" name="mobileNo"
  289. class="form-control mb-1"
  290. placeholder="Enter Mobile Number" maxlength="10"
  291. minlength="10" required>
  292. </div>
  293. </div>
  294. </div>
  295. <div class="form-row">
  296. <div class="col-md-4">
  297. <label for="name">Name:<span class="required">*</span></label>
  298. <input type="text" class="form-control" id="name"
  299. placeholder="Enter your name" required>
  300. </div>
  301. <div class="col-md-4">
  302. <label for="gender" class="ml-4">Gender/பாலினம்:<span
  303. class="required">*</span></label>
  304. <div class="radio-group mt-2 ml-4">
  305. <div class="radio-item">
  306. <input type="radio" id="male" name="gender" value="male"
  307. checked> <label for="male">Male</label>
  308. </div>
  309. <div class="radio-item">
  310. <input type="radio" id="female" name="gender"
  311. value="female"> <label for="female">Female</label>
  312. </div>
  313. <div class="radio-item">
  314. <input type="radio" id="transgender" name="gender"
  315. value="transgender"> <label for="transgender">Transgender</label>
  316. </div>
  317. </div>
  318. </div>
  319. <div class="col-md-4">
  320. <label for="email">Email:</label> <input type="email"
  321. class="form-control" id="email"
  322. placeholder="Enter your email">
  323. </div>
  324. </div>
  325. <button id="nextStep1" class="btn btn-primary float-right"
  326. onclick="nextStep('nextStep1')"
  327. style="background-color: #414f69;">Next</button>
  328. <!-- </div> -->
  329. </div>
  330. <!--step-2-->
  331. <div class=" form-step readable" id="step-2">
  332. <!-- <div class="card-body"> -->
  333. <h5 class="card-title">2. Complaint Location Details:</h5>
  334. <div class="form-row">
  335. <!-- loader section -->
  336. <div id="loader" class="loader" style="display: none;"></div>
  337. <!--map fields-->
  338. <div class="col-md-12">
  339. <div id="map"></div>
  340. <div id="search-container">
  341. <input type="text" id="search-box"
  342. placeholder="Search for a location...">
  343. <div id="suggestions"></div>
  344. </div>
  345. <div class="row">
  346. <div class="col-md-6">
  347. <label for="street">Street:</label> <input type="text"
  348. class="form-control" id="street">
  349. </div>
  350. <div class="col-md-6">
  351. <label for="longitude_field">Longtitude</label> <input
  352. type="text" class="form-control" id="longitude_field"
  353. name="longtitude">
  354. </div>
  355. <div class="col-md-6">
  356. <label for="latitude_field">Latitide</label> <input
  357. type="text" class="form-control" id="latitude_field">
  358. </div>
  359. <div class="col-md-6">
  360. <label for="street_id">Street Id</label> <input
  361. type="text" class="form-control" id="street_id">
  362. </div>
  363. <div class="col-md-6">
  364. <label for="landmark">Landmark</label> <input type="text"
  365. class="form-control" id="landmark">
  366. </div>
  367. </div>
  368. </div>
  369. </div>
  370. <button id="prevStep2" class="btn btn-secondary"
  371. onclick="prevStep('prevStep2')">Previous</button>
  372. <button id="nextStep2" class="btn btn-primary float-right"
  373. onclick="nextStep('nextStep2')"
  374. style="background-color: #414f69;">Next</button>
  375. <!-- </div> -->
  376. </div>
  377. <!-- Step 3 -->
  378. <div class=" form-step active readable" id="step-3">
  379. <div class="card-body">
  380. <h5 class="card-title">3. Complaint Type:</h5>
  381. <!-- Icons -->
  382. <div class="complaint-icons">
  383. <div class="complaint-icon" data-type="specific"
  384. data-id="112">
  385. <img src="/gcc/assets/images/road.png" alt="Pothole">
  386. <p>Pothole</p>
  387. </div>
  388. <div class="complaint-icon" data-type="specific"
  389. data-id="97">
  390. <img src="/gcc/assets/images/recycle.png" alt="garbage">
  391. <p>Garbage</p>
  392. </div>
  393. <div class="complaint-icon" data-type="specific"
  394. data-id="104">
  395. <img src="/gcc/assets/images/waste-bin.png" alt="broken-bin">
  396. <p>Broken-Bin</p>
  397. </div>
  398. <div class="complaint-icon" data-type="specific"
  399. data-id="146">
  400. <img src="/gcc/assets/images/street-lamp.png" alt="StreetLight">
  401. <p>StreetLight</p>
  402. </div>
  403. <div class="complaint-icon" data-type="specific"
  404. data-id="199">
  405. <img src="/gcc/assets/images/portable-bathroom.png"
  406. alt="public-toilet">
  407. <p>Public Toilet</p>
  408. </div>
  409. <div class="complaint-icon" data-type="specific"
  410. data-id="118">
  411. <img src="/gcc/assets/images/mosquito.png" alt="mosquito">
  412. <p>Mosquito Menace</p>
  413. </div>
  414. <div class="complaint-icon" data-type="specific"
  415. data-id="138">
  416. <img src="/gcc/assets/images/tsunami.png" alt="waterstag">
  417. <p>WaterStagnation</p>
  418. </div>
  419. <div class="complaint-icon" data-type="specific"
  420. data-id="142">
  421. <img src="/gcc/assets/images/sewage.png" alt="sewage">
  422. <p>Storm Water Drains</p>
  423. </div>
  424. <div class="complaint-icon" data-type="specific"
  425. data-id="119">
  426. <img src="/gcc/assets/images/dog.png" alt="dog">
  427. <p>Street Dog</p>
  428. </div>
  429. <!--<div class="complaint-icon" data-type="specific" data-id="">
  430. <img src="images/bad-weather.png" alt="weather">
  431. <p>Tree Fallen</p>
  432. </div>-->
  433. <div class="complaint-icon" data-type="others">
  434. <img src="/gcc/assets/images/menu.png" alt="Others">
  435. <p>Others</p>
  436. </div>
  437. </div>
  438. <!-- Specific Complaint Fields -->
  439. <div class="complaint-fields active" id="specific-fields">
  440. <div class="form-row">
  441. <div class="col-md-6">
  442. <label for="complaint-title">Complaint Title:</label> <input
  443. type="text" class="form-control" id="complaint-title"
  444. placeholder="Enter complaint title">
  445. </div>
  446. <div class="col-md-6">
  447. <label for="complaint-id">Complaint Type:</label> <input
  448. type="text" class="form-control" id="complaint-id"
  449. disabled>
  450. </div>
  451. </div>
  452. <div class="form-row">
  453. <div class="col-md-6">
  454. <label for="othercomplaint-details">Details of
  455. Complaint:</label>
  456. <textarea class="form-control" id="othercomplaint-details"
  457. rows="3" placeholder="Enter complaint details"
  458. maxlength="400"></textarea>
  459. </div>
  460. <div class="col-md-6">
  461. <label for="complaint-image">Upload Photo:</label> <input
  462. type="file" class="form-control" id="complaint-image"
  463. name="Comp_Image"> <span style="color: red;">
  464. <p>Upload Photo Less Than 1mb*.</p>
  465. </span>
  466. </div>
  467. </div>
  468. </div>
  469. <!-- Others Complaint Fields -->
  470. <div class="complaint-fields" id="others-fields">
  471. <div class="form-row">
  472. <div class="col-md-4">
  473. <label for="type">Type:</label> <select
  474. class="form-control" id="type">
  475. <option value="">Please Select</option>
  476. </select>
  477. </div>
  478. <div class="col-md-4">
  479. <label for="sub-type">Sub-Type:</label> <select
  480. class="form-control" id="sub-type">
  481. <option value="">Select complaint</option>
  482. </select>
  483. </div>
  484. <div class="col-md-4">
  485. <label for="uploadothers">Upload Photo:</label> <input
  486. type="file" class="form-control" id="uploadothers"
  487. accept="image/*"> <span style="color: red;">
  488. <p>Upload Photo Less Than 1mb*.</p>
  489. </span>
  490. </div>
  491. </div>
  492. <div class="form-row">
  493. <div class="col-md-6">
  494. <label for="othercomplaintdetailsss">Details of
  495. Complaint:</label>
  496. <textarea class="form-control"
  497. id="othercomplaintdetailsss" rows="3"
  498. placeholder="Enter complaint details" maxlength="400"></textarea>
  499. </div>
  500. </div>
  501. </div>
  502. <button id="prevStep3" class="btn btn-secondary"
  503. onclick="prevStep('prevStep3')">Previous</button>
  504. <button id="nextStep3" class="btn btn-primary float-right"
  505. onclick="nextStep('nextStep3')"
  506. style="background-color: #414f69;">Next</button>
  507. </div>
  508. </div>
  509. <!-- Step 4 -->
  510. <div class=" form-step readable" id="step-4">
  511. <div class="card-body">
  512. <h5 class="card-title">4. Complaint Details:</h5>
  513. <table class="table">
  514. <tbody>
  515. <tr>
  516. <td><strong>Name</strong></td>
  517. <td>: <span id="summaryName"></span></td>
  518. <td><strong>Complaint Location</strong></td>
  519. <td>: <span id="summaryStreet"></span></td>
  520. </tr>
  521. <tr>
  522. <td><strong>Mobile Number</strong></td>
  523. <td>: <span id="summaryMobile"></span></td>
  524. <td><strong>Email Address</strong></td>
  525. <td>: <span id="summaryEmail"></span></td>
  526. </tr>
  527. <tr>
  528. <td><strong>Complaint Type</strong></td>
  529. <td>: <span id="summaryComplaintType"></span></td>
  530. <td><strong>Complaint Title</strong></td>
  531. <td>: <span id="summaryComplaintTitle"></span></td>
  532. </tr>
  533. <tr>
  534. <td><strong>Description</strong></td>
  535. <td>: <span id="summaryDescription"></span></td>
  536. <td><strong>Street Id</strong></td>
  537. <td>: <span id="summaryStreetId"></span></td>
  538. </tr>
  539. <tr>
  540. <td><strong>Landmark</strong></td>
  541. <td>: <span id="summaryLandmark"></span></td>
  542. <td><strong>Latitude</strong></td>
  543. <td>: <span id="summaryLatitude"></span></td>
  544. </tr>
  545. <tr>
  546. <td><strong>Longitude</strong></td>
  547. <td>: <span id="summaryLongitude"></span></td>
  548. <td><strong>Gender</strong></td>
  549. <td>: <span id="summaryGender"></span></td>
  550. </tr>
  551. <tr>
  552. <td><strong>Image / Video</strong></td>
  553. <td>: <img id="summaryImage" src="#"
  554. alt="Uploaded Image/Video" width="100"
  555. style="display: none;">
  556. </td>
  557. </tr>
  558. </tbody>
  559. </table>
  560. <button id="prevStep4" class="btn btn-secondary"
  561. onclick="prevStep('prevStep4')">Previous</button>
  562. <button id="submitButton" class="btn btn-success float-right">Submit</button>
  563. </div>
  564. </div>
  565. </div>
  566. </div>
  567. </div>
  568. </div>
  569. </div>
  570. </div>
  571. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  572. </div>
  573. </div>
  574. <div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
  575. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  576. <script
  577. src="node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min.js"></script>
  578. <script
  579. src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
  580. <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  581. <script src="https://kit.fontawesome.com/a076d05399.js"></script>
  582. <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
  583. <script th:src="@{/js/screenreader.js}"></script>
  584. <script type="text/javascript">
  585. //for snackbar script
  586. function showSnackbar(message) {
  587. var snackbar = document.getElementById("snackbar");
  588. snackbar.innerHTML = message;
  589. snackbar.className = "show";
  590. setTimeout(function () {snackbar.className = snackbar.className.replace("show", "");}, 3000);
  591. }
  592. //for snackbar script
  593. let currentStep = 1;
  594. let mapInitialized = false;
  595. function showStep(step) {
  596. $('.form-step').removeClass('active');
  597. $('#step-' + step).addClass('active');
  598. /* updateProgressBar(step); */
  599. if (step === 2 && !mapInitialized) {
  600. document.getElementById('loader').style.display = 'block'; // Show loader before map initialization
  601. setTimeout(initializeMap, 3000); // Load the map after 3 seconds
  602. mapInitialized = true; // Ensure the map is only initialized once
  603. }
  604. // If we're on step 4, populate the summary fields
  605. if (step === 4) {
  606. populateSummary();
  607. }
  608. }
  609. function nextStep() {
  610. if (currentStep < 4) {
  611. // Perform validation for the current step
  612. if (validateStep(currentStep)) {
  613. currentStep++;
  614. showStep(currentStep);
  615. }
  616. }
  617. }
  618. function prevStep() {
  619. if (currentStep > 1) {
  620. currentStep--;
  621. showStep(currentStep);
  622. }
  623. }
  624. /* function updateProgressBar(step) {
  625. const progress = (step / 4) * 100;
  626. $('.progress-bar').css('width', progress + '%').attr('aria-valuenow', progress);
  627. } */
  628. function validateStep(step) {
  629. let isValid = true;
  630. if (step === 1) {
  631. const mobileNo = $('#mobileNo').val().trim();
  632. const name = $('#name').val().trim();
  633. let email = $('#email').val().trim();
  634. // Validate mobile number
  635. if (mobileNo === '' || !/^\d{10}$/.test(mobileNo)) {
  636. isValid = false;
  637. showSnackbar("Please enter a valid 10-digit mobile number.");
  638. }
  639. // Validate name
  640. if (name === '') {
  641. isValid = false;
  642. showSnackbar("Please enter your name.");
  643. }
  644. // Check email
  645. if (email === '') {
  646. email = 'N/A'; // Set N/A if empty
  647. $('#email').val(email); // Update the input field with N/A
  648. } else if (!/^\S+@\S+\.\S+$/.test(email)) {
  649. isValid = false;
  650. showSnackbar("Please enter a valid email address.");
  651. }
  652. } else if (step === 2) {
  653. const street = $('#street').val().trim();
  654. const longitude = $('#longitude_field').val().trim();
  655. const latitude = $('#latitude_field').val().trim();
  656. const streetId = $('#street_id').val().trim();
  657. const landmark = $('#landmark').val().trim();
  658. // Validate street
  659. if (street === '') {
  660. isValid = false;
  661. showSnackbar("Please enter the street.");
  662. }
  663. // Validate longitude and latitude
  664. if (longitude === '' || isNaN(longitude)) {
  665. isValid = false;
  666. showSnackbar("Please enter a valid longitude.");
  667. }
  668. if (latitude === '' || isNaN(latitude)) {
  669. isValid = false;
  670. showSnackbar("Please enter a valid latitude.");
  671. }
  672. // Validate street ID
  673. if (streetId === '') {
  674. isValid = false;
  675. showSnackbar("Please enter the street ID.");
  676. }
  677. // Validate landmark
  678. if (landmark === '') {
  679. isValid = false;
  680. showSnackbar("Please enter the landmark.");
  681. }
  682. }
  683. return isValid;
  684. }
  685. function populateSummary() {
  686. const name = $('#name').val();
  687. const street = $('#street').val();
  688. const mobileNo = $('#mobileNo').val();
  689. const gender = $('input[name="gender"]:checked').val();
  690. const email = $('#email').val();
  691. // Check if 'specific-fields' is active and use its values
  692. if ($('#specific-fields').hasClass('active')) {
  693. const complaintTitle = $('#complaint-title').val();
  694. const complaintid = $('#complaint-id').val();
  695. const complaintDetails = $('#othercomplaint-details').val(); // Specific complaint details
  696. $('#summaryComplaintTitle').text(complaintTitle);
  697. $('#summaryComplaintType').text(complaintid);
  698. $('#summaryDescription').text(complaintDetails);
  699. } else if ($('#others-fields').hasClass('active')) {
  700. const complaintTitle = $('#type').find('option:selected').text();
  701. const complaintSubType = $('#sub-type').find('option:selected').text();
  702. const complaintDetails = $('#othercomplaintdetailsss').val(); // Others complaint details
  703. $('#summaryComplaintTitle').text(complaintTitle + ' - ' + complaintSubType);
  704. $('#summaryComplaintType').text('Other Complaint');
  705. $('#summaryDescription').text(complaintDetails);
  706. }
  707. const streetid = $('#street_id').val();
  708. const landmark = $('#landmark').val();
  709. const latitude = $('#latitude_field').val();
  710. const longtitude = $('#longitude_field').val();
  711. $('#summaryName').text(name);
  712. $('#summaryStreet').text(street);
  713. $('#summaryMobile').text(mobileNo);
  714. $('#summaryGender').text(gender);
  715. $('#summaryEmail').text(email);
  716. $('#summaryStreetId').text(streetid);
  717. $('#summaryLandmark').text(landmark);
  718. $('#summaryLatitude').text(latitude);
  719. $('#summaryLongitude').text(longtitude);
  720. // Handle image preview
  721. /* const fileInput = $('#complaint-image')[0]; // Assuming this is for the "Others" section
  722. if (fileInput.files && fileInput.files[0]) {
  723. const reader = new FileReader();
  724. reader.onload = function (e) {
  725. $('#summaryImage').attr('src', e.target.result).show();
  726. }
  727. reader.readAsDataURL(fileInput.files[0]);
  728. } else {
  729. $('#summaryImage').hide();
  730. }*/
  731. // If there's a separate image input for the specific form, handle it similarly:
  732. // Check if specific fields section is active
  733. if ($('#specific-fields').hasClass('active')) {
  734. const specificFileInput = $('#complaint-image')[0]; // Example ID for specific form
  735. if (specificFileInput.files && specificFileInput.files[0]) {
  736. const reader = new FileReader();
  737. reader.onload = function (e) {
  738. $('#summaryImage').attr('src', e.target.result).show();
  739. };
  740. reader.readAsDataURL(specificFileInput.files[0]);
  741. } else {
  742. $('#summaryImage').hide(); // Hide the image if no file is selected
  743. }
  744. }
  745. // Check if "Others" section is active
  746. else if ($('#others-fields').hasClass('active')) {
  747. const fileInput = $('#uploadothers')[0]; // Assuming this is for the "Others" section
  748. if (fileInput.files && fileInput.files[0]) {
  749. const reader = new FileReader();
  750. reader.onload = function (e) {
  751. $('#summaryImage').attr('src', e.target.result).show();
  752. };
  753. reader.readAsDataURL(fileInput.files[0]);
  754. } else {
  755. $('#summaryImage').hide(); // Hide the image if no file is selected
  756. }
  757. } else {
  758. $('#summaryImage').hide(); // Default hide if no section is active
  759. }
  760. }
  761. $(document).ready(function () {
  762. showStep(currentStep);
  763. });
  764. $(document).ready(function () {
  765. showStep(currentStep);
  766. });
  767. //for step3 onclick function
  768. $(document).ready(function () {
  769. // On icon click
  770. $('.complaint-icon').click(function () {
  771. const type = $(this).data('type'); // Get the type (specific or others)
  772. const title = $(this).find('p').text().trim(); // Get the icon name (complaint title)
  773. const complaintId = $(this).data('id'); // Get the complaint ID
  774. // Toggle complaint fields based on type
  775. $('.complaint-fields').removeClass('active');
  776. if (type === 'specific') {
  777. $('#specific-fields').addClass('active'); // Show specific fields form
  778. $('#others-fields').removeClass('active'); // Hide others form
  779. $('#complaint-title').val(title); // Set the complaint title to the icon name
  780. $('#complaint-id').val(complaintId); // Set the complaint ID to the corresponding ID
  781. } else if (type === 'others') {
  782. $('#others-fields').addClass('active'); // Show others form
  783. $('#specific-fields').removeClass('active'); // Hide specific fields form
  784. $('#complaint-title').val(''); // Clear the complaint title for 'Others'
  785. $('#complaint-id').val(''); // Clear the complaint ID for 'Others'
  786. }
  787. });
  788. });
  789. //for complaint group and complainttype wise options dropdown api
  790. $(document).ready(function () {
  791. const $type = $('#type');
  792. const $subType = $('#sub-type');
  793. $subType.prop('disabled', true);
  794. // Fetch and populate the Type dropdown
  795. $.ajax({
  796. url: '/gcc/api/callcenterqaqc/pgrcomplaint/getComplaintCategories',
  797. method: 'GET',
  798. success: function (response) {
  799. const data = typeof response === 'string' ? JSON.parse(response) : response;
  800. //console.log('Response:', response); // Log the response to verify
  801. let optionsHtml = '<option value="">Please Select</option>';
  802. data.ComplaintCategoryListResult.forEach(function (group) {
  803. optionsHtml += `<option value="${group.groupid}">${group.groupname}</option>`;
  804. });
  805. $type.html(optionsHtml);
  806. },
  807. error: function (error) {
  808. console.error('Error fetching complaint categories:', error);
  809. }
  810. });
  811. // Handle Type dropdown change
  812. $type.change(function () {
  813. const selectedType = $(this).val();
  814. $subType.empty().append('<option value="">Select complaint</option>');
  815. if (selectedType) {
  816. $.ajax({
  817. url: `/gcc/api/callcenterqaqc/pgrcomplaint/getComplaintSubTypes?groupId=${selectedType}`,
  818. method: 'GET',
  819. success: function (response) {
  820. const data = typeof response === 'string' ? JSON.parse(response) : response;
  821. const selectedGroup = data.ComplaintCategoryListResult[0];
  822. //console.log(data);
  823. if (selectedGroup && selectedGroup.group) {
  824. $subType.prop('disabled', false);
  825. selectedGroup.group.forEach(function (complaint) {
  826. $subType.append(`<option value="${complaint.id}">${complaint.complaintname}</option>`);
  827. });
  828. } else {
  829. $subType.prop('disabled', true);
  830. }
  831. },
  832. error: function (error) {
  833. console.error('Error fetching sub-types:', error);
  834. $subType.prop('disabled', true);
  835. }
  836. });
  837. } else {
  838. $subType.prop('disabled', true);
  839. }
  840. });
  841. });
  842. //api for saving
  843. //for sweet alert
  844. /* function showSuccessAlert() {
  845. Swal.fire({
  846. icon: 'success',
  847. title: 'Complaint Registration Success',
  848. text: 'Complaint Number 123456. Use this Number for Complaint Status Check.',
  849. confirmButtonText: 'Back to Home',
  850. confirmButtonColor: '#3085d6',
  851. }).then((result) => {
  852. if (result.isConfirmed) {
  853. window.location.href = 'home';
  854. }
  855. });
  856. } */
  857. //Script For Map
  858. var suggestedRoadName;
  859. var suggestedWard;
  860. var suggestedZone;
  861. var suggestedRoadId;
  862. function initializeMap() {
  863. // Create the map
  864. var map = L.map('map', {attributionControl: false}).setView([13.0827, 80.2707], 9);
  865. // Add tile layer and track loading status
  866. var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  867. maxZoom: 19,
  868. attributionControl: false,
  869. }).addTo(map);
  870. // Hide loader once the map tiles are fully loaded
  871. tileLayer.on('load', function () {
  872. document.getElementById('loader').style.display = 'none';
  873. document.getElementById('map').style.visibility = 'visible'; // Ensure map is visible
  874. });
  875. var currentMarker = null;
  876. // Handle map click events
  877. map.on('click', function (e) {
  878. var lat = e.latlng.lat;
  879. var lng = e.latlng.lng;
  880. if (currentMarker) {
  881. map.removeLayer(currentMarker);
  882. }
  883. currentMarker = L.marker([lat, lng]).addTo(map);
  884. fetchLocationInfoByMap(lat, lng, currentMarker);
  885. });
  886. // Handle input events in the search box
  887. document.getElementById('search-box').addEventListener('input', function () {
  888. var query = this.value.trim();
  889. if (query.length > 2) {
  890. fetchSuggestions(query);
  891. } else {
  892. document.getElementById('suggestions').style.display = 'none';
  893. }
  894. });
  895. // Handle click events on suggestions
  896. document.getElementById('suggestions').addEventListener('click', function (e) {
  897. if (e.target.tagName === 'LI') {
  898. var latlngArray = JSON.parse(e.target.dataset.latlng);
  899. suggestedRoadId = e.target.dataset.roadId;
  900. suggestedRoadName = e.target.dataset.roadName;
  901. suggestedWard = e.target.dataset.ward;
  902. suggestedZone = e.target.dataset.zone;
  903. // Check if the data is in the correct format
  904. if (Array.isArray(latlngArray) && latlngArray.every(item => Array.isArray(item) && item.length === 2 && typeof item[0] === 'number' && typeof item[1] === 'number')) {
  905. // Calculate the average latitude and longitude
  906. var totalLat = 0;
  907. var totalLng = 0;
  908. latlngArray.forEach(function (coords) {
  909. totalLat += coords[1]; // Latitude
  910. totalLng += coords[0]; // Longitude
  911. });
  912. var avgLat = totalLat / latlngArray.length;
  913. var avgLng = totalLng / latlngArray.length;
  914. var latlng = [avgLat, avgLng];
  915. map.setView(latlng, 14);
  916. if (currentMarker) {
  917. map.removeLayer(currentMarker);
  918. }
  919. currentMarker = L.marker(latlng).addTo(map);
  920. fetchLocationInfoBySuggestions(latlng[0], latlng[1], currentMarker);
  921. // Clear the search box value
  922. document.getElementById('search-box').value = '';
  923. // Hide the suggestions
  924. document.getElementById('suggestions').style.display = 'none';
  925. } else {
  926. // Convert the incorrect format into the correct format
  927. const flattenCoordinates = (data) => {
  928. return data.reduce((acc, item) => {
  929. if (Array.isArray(item) && Array.isArray(item[0])) {
  930. // If item is a nested array, flatten it
  931. acc.push(...flattenCoordinates(item));
  932. } else if (Array.isArray(item) && item.length === 2 && typeof item[0] === 'number' && typeof item[1] === 'number') {
  933. // If item is a coordinate pair, add it to the list
  934. acc.push(item);
  935. }
  936. return acc;
  937. }, []);
  938. };
  939. // Flatten the nested latlngArray
  940. var flattenedLatlngArray = flattenCoordinates(latlngArray);
  941. // Now, continue with the same logic as before
  942. var totalLat = 0;
  943. var totalLng = 0;
  944. flattenedLatlngArray.forEach(function (coords) {
  945. totalLat += coords[1]; // Latitude
  946. totalLng += coords[0]; // Longitude
  947. });
  948. var avgLat = totalLat / flattenedLatlngArray.length;
  949. var avgLng = totalLng / flattenedLatlngArray.length;
  950. var latlng = [avgLat, avgLng];
  951. map.setView(latlng, 14);
  952. if (currentMarker) {
  953. map.removeLayer(currentMarker);
  954. }
  955. currentMarker = L.marker(latlng).addTo(map);
  956. fetchLocationInfoBySuggestions(latlng[0], latlng[1], currentMarker);
  957. // Clear the search box value
  958. document.getElementById('search-box').value = '';
  959. // Hide the suggestions
  960. document.getElementById('suggestions').style.display = 'none';
  961. }
  962. }
  963. });
  964. }
  965. function fetchSuggestions(query) {
  966. // ArcGIS API URL to fetch suggestions based on the input query
  967. const arcgisSuggestionUrl = `https://gisgcc.chennaicorporation.gov.in/server/rest/services/Hosted/Road_API/FeatureServer/0/query?where=UPPER(road_name)%20LIKE%20'%25${query.toUpperCase()}%25'&outFields=road_name,zone,ward,road_id&returnGeometry=true&f=geojson`;
  968. fetch(arcgisSuggestionUrl)
  969. .then(response => response.json())
  970. .then(data => {
  971. var suggestions = document.getElementById('suggestions');
  972. suggestions.innerHTML = '';
  973. if (data.features && data.features.length > 0) {
  974. suggestions.style.display = 'block';
  975. var ul = document.createElement('ul');
  976. data.features.forEach(function (result) {
  977. var lat = result.geometry.coordinates[1];
  978. var lng = result.geometry.coordinates[0];
  979. var roadName = result.properties.road_name || 'Unknown Road';
  980. var zone = result.properties.zone || 'Unknown Zone';
  981. var ward = result.properties.ward || 'Unknown Ward';
  982. var roadId = result.properties.road_id || 'Unknown Road ID'
  983. // Creating the suggestion item with road name, zone, and ward
  984. var li = document.createElement('li');
  985. li.textContent = `${roadName} - Zone: ${zone}, Ward: ${ward}`;
  986. li.dataset.latlng = JSON.stringify([lat, lng]);
  987. li.dataset.roadName = roadName;
  988. li.dataset.roadId = roadId;
  989. li.dataset.zone = zone;
  990. li.dataset.ward = ward;
  991. ul.appendChild(li);
  992. });
  993. suggestions.appendChild(ul);
  994. } else {
  995. suggestions.style.display = 'none';
  996. }
  997. })
  998. .catch(error => console.error('Error fetching suggestions:', error));
  999. }
  1000. function fetchLocationInfoByMap(lat, lng, marker) {
  1001. const arcgisUrl = `https://gisgcc.chennaicorporation.gov.in/server/rest/services/Hosted/Road_API/FeatureServer/0/query?where=&objectIds=&time=&geometry=%7B%22y%22%3A${lat}%2C%22x%22%3A${lng}%7D&geometryType=esriGeometryEnvelope&inSR=4326&defaultSR=4326&spatialRel=esriSpatialRelIntersects&distance=25&units=esriSRUnit_Meter&relationParam=&outFields=zone%2Cward%2Croad_id%2Croad_name&returnGeometry=false&maxAllowableOffset=&geometryPrecision=&outSR=&havingClause=&gdbVersion=&historicMoment=&returnDistinctValues=false&returnIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&multipatchOption=xyFootprint&resultOffset=&resultRecordCount=&returnTrueCurves=false&returnCentroid=false&timeReferenceUnknownClient=false&maxRecordCountFactor=&sqlFormat=none&resultType=&datumTransformation=&lodType=geohash&lod=&lodSR=&f=geojson`;
  1002. fetch(arcgisUrl)
  1003. .then(response => response.json())
  1004. .then(data => {
  1005. console.log(data);
  1006. let info;
  1007. if (data.features && data.features.length > 0) {
  1008. const properties = data.features[0].properties;
  1009. const roadName = properties.road_name || 'N/A';
  1010. const zone = properties.zone || 'N/A';
  1011. const ward = properties.ward || 'N/A';
  1012. const roadId = properties.road_id || 'N/A';
  1013. info = `Road Name: ${roadName}<br>Zone: ${zone}<br>Ward: ${ward}<br>Latitude: ${lat}<br>Longitude: ${lng}`;
  1014. document.getElementById("street").value = roadName;
  1015. document.getElementById("latitude_field").value = lat;
  1016. document.getElementById("longitude_field").value = lng;
  1017. document.getElementById("street_id").value = roadId;
  1018. document.getElementById("landmark").value = roadName;
  1019. marker.bindTooltip(info, {permanent: false, direction: 'top'}).openTooltip();
  1020. } else {
  1021. document.getElementById("street").value = "No road data found for this location";
  1022. document.getElementById("latitude_field").value = "No latitude data found for this location";
  1023. document.getElementById("longitude_field").value = "No latitude data found for this location";
  1024. document.getElementById("street_id").value = "No street id data found for this location";
  1025. document.getElementById("landmark").value = "No landmark data found for this location";
  1026. info = `No road data found for this location`
  1027. marker.bindTooltip(info, {permanent: false, direction: 'top'}).openTooltip();
  1028. }
  1029. })
  1030. .catch(error => {
  1031. console.error('Error fetching road data:', error);
  1032. marker.bindTooltip(`Error fetching road data.<br>Latitude: ${lat}<br>Longitude: ${lng}`, {permanent: false, direction: 'top'}).openTooltip();
  1033. });
  1034. }
  1035. function fetchLocationInfoBySuggestions(lat, lng, marker) {
  1036. const arcgisUrl = `https://gisgcc.chennaicorporation.gov.in/server/rest/services/Hosted/Road_API/FeatureServer/0/query?where=&objectIds=&time=&geometry=%7B%22y%22%3A${lat}%2C%22x%22%3A${lng}%7D&geometryType=esriGeometryEnvelope&inSR=4326&defaultSR=4326&spatialRel=esriSpatialRelIntersects&distance=25&units=esriSRUnit_Meter&relationParam=&outFields=zone%2Cward%2Croad_id%2Croad_name&returnGeometry=false&maxAllowableOffset=&geometryPrecision=&outSR=&havingClause=&gdbVersion=&historicMoment=&returnDistinctValues=false&returnIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&multipatchOption=xyFootprint&resultOffset=&resultRecordCount=&returnTrueCurves=false&returnCentroid=false&timeReferenceUnknownClient=false&maxRecordCountFactor=&sqlFormat=none&resultType=&datumTransformation=&lodType=geohash&lod=&lodSR=&f=geojson`;
  1037. fetch(arcgisUrl)
  1038. .then(response => response.json())
  1039. .then(data => {
  1040. console.log(data);
  1041. let info;
  1042. if (data.features && data.features.length > 0) {
  1043. const properties = data.features[0].properties;
  1044. const roadName = properties.road_name || 'N/A';
  1045. const zone = properties.zone || 'N/A';
  1046. const ward = properties.ward || 'N/A';
  1047. const roadId = properties.road_id || 'N/A';
  1048. info = `Road Name: ${roadName}<br>Zone: ${zone}<br>Ward: ${ward}<br>Latitude: ${lat}<br>Longitude: ${lng}`;
  1049. document.getElementById("street").value = roadName;
  1050. document.getElementById("latitude_field").value = lat;
  1051. document.getElementById("longitude_field").value = lng;
  1052. document.getElementById("street_id").value = roadId;
  1053. document.getElementById("landmark").value = roadName;
  1054. marker.bindTooltip(info, {permanent: false, direction: 'top'}).openTooltip();
  1055. } else {
  1056. document.getElementById("street").value = suggestedRoadName;
  1057. document.getElementById("latitude_field").value = lat;
  1058. document.getElementById("longitude_field").value = lng;
  1059. document.getElementById("street_id").value = suggestedRoadId;
  1060. document.getElementById("landmark").value = suggestedRoadName;
  1061. info = `Road Name: ${suggestedRoadName}<br>Zone: ${suggestedZone}<br>Ward: ${suggestedWard}<br>Latitude: ${lat}<br>Longitude: ${lng}`
  1062. marker.bindTooltip(info, {permanent: false, direction: 'top'}).openTooltip();
  1063. }
  1064. })
  1065. .catch(error => {
  1066. console.error('Error fetching road data:', error);
  1067. marker.bindTooltip(`Error fetching road data.<br>Latitude: ${lat}<br>Longitude: ${lng}`, {permanent: false, direction: 'top'}).openTooltip();
  1068. });
  1069. }
  1070. $(document).ready(function () {
  1071. $('#submitButton').click(function (e) {
  1072. e.preventDefault(); // Prevent the default form submission
  1073. // Collect data from the form fields
  1074. var complainantName = $('#summaryName').text().trim();
  1075. var complainantAddr = $('#summaryStreet').text().trim();
  1076. var mobileNo = $('#summaryMobile').text().trim();
  1077. var email = $('#summaryEmail').text().trim();
  1078. var complaintType = $('#summaryComplaintType').text().trim();
  1079. var complaintTitle = $('#summaryComplaintTitle').text().trim();
  1080. var complaintDetails = $('#summaryDescription').text().trim();
  1081. var streetId = $('#summaryStreetId').text().trim();
  1082. var landmark = $('#summaryLandmark').text().trim();
  1083. var latitude = $('#summaryLatitude').text().trim();
  1084. var longtitude = $('#summaryLongitude').text().trim(); // Note the misspelling
  1085. var gender = $('#summaryGender').text().trim();
  1086. var imageSrc = $('#summaryImage').attr('src');
  1087. /* console.log({
  1088. ComplainantName: complainantName,
  1089. ComplainantAddr: complainantAddr,
  1090. MobileNo: mobileNo,
  1091. Email: email,
  1092. ComplaintType: complaintType,
  1093. ComplaintTitle: complaintTitle,
  1094. ComplaintDetails: complaintDetails,
  1095. StreetId: streetId,
  1096. Comp_Image: imageSrc,
  1097. latitude: latitude,
  1098. longtitude: longtitude,
  1099. Landmark: landmark,
  1100. gender: gender
  1101. }); */
  1102. // AJAX call to your backend controller
  1103. $.ajax({
  1104. url: '/gcc/api/callcenterqaqc/pgrcomplaint/register', // Update to your Spring Boot endpoint
  1105. type: 'POST',
  1106. data: {
  1107. ComplainantName: complainantName,
  1108. ComplainantAddr: complainantAddr,
  1109. MobileNo: mobileNo,
  1110. Email: email,
  1111. ComplaintType: complaintType,
  1112. ComplaintTitle: complaintTitle,
  1113. ComplaintDetails: complaintDetails,
  1114. StreetId: streetId,
  1115. Comp_Image: imageSrc,
  1116. latitude: latitude,
  1117. longtitude: longtitude,
  1118. Landmark: landmark,
  1119. gender: gender
  1120. },
  1121. success: function (response) {
  1122. // SweetAlert upon success
  1123. //console.log("API Response:", response);
  1124. // Ensure response is a JavaScript object
  1125. if (typeof response === "string") {
  1126. try {
  1127. response = JSON.parse(response);
  1128. } catch (error) {
  1129. console.error("Failed to parse response:", error);
  1130. }
  1131. }
  1132. // Access the Complaint Number safely
  1133. let complaintNumber = response["Complaint Number"];
  1134. if (!complaintNumber || complaintNumber === "null" || complaintNumber === null) {
  1135. complaintNumber = "N/A";
  1136. }
  1137. Swal.fire({
  1138. title: 'Success!',
  1139. text: `Your complaint has been submitted successfully. Your Complaint Number is ${complaintNumber}. It will be sent to your mobile number.`,
  1140. icon: 'success',
  1141. allowOutsideClick: false, // Disable clicking outside the modal to close it
  1142. allowEscapeKey: false, // Disable escape key to close the modal
  1143. allowEnterKey: false, // Disable enter key to close the modal
  1144. showConfirmButton: true, // Ensure the confirm button is visible
  1145. confirmButtonText: 'OK'
  1146. }).then((result) => {
  1147. if (result.isConfirmed) {
  1148. window.location.href = '/gcc/callcenterqaqc/pgrcomplaint';
  1149. }
  1150. });
  1151. },
  1152. error: function (xhr, status, error) {
  1153. // Improved error handling
  1154. console.log('Error:', xhr.responseText, status, error);
  1155. alert('Error: ' + xhr.status + ' ' + xhr.statusText);
  1156. }
  1157. });
  1158. });
  1159. });
  1160. /* html: `Your complaint has been submitted successfully. Your Complaint Number is <strong>${complaintNumber}</strong>. It will be sent to your mobile number.`, */
  1161. </script>
  1162. </body>
  1163. </html>