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.

536 lines
18 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/modules/base/head :: head}">
  4. <style>
  5. body {
  6. background-color: #f8f9fa;
  7. }
  8. .header {
  9. font-size: 22px;
  10. font-weight: bold;
  11. margin-bottom: 20px;
  12. }
  13. .table {
  14. border: 1px solid #dee2e6;
  15. }
  16. .table th,
  17. .table td {
  18. border: 1px solid #dee2e6;
  19. padding: 10px;
  20. }
  21. .section-title {
  22. font-size: 18px;
  23. font-weight: bold;
  24. margin-top: 20px;
  25. border-bottom: 2px solid #007bff;
  26. padding-bottom: 5px;
  27. }
  28. .form-group {
  29. margin-top: 15px;
  30. }
  31. .radio-group {
  32. display: flex;
  33. gap: 20px;
  34. margin-top: 10px;
  35. }
  36. </style>
  37. </head>
  38. <body>
  39. <div class="wrapper">
  40. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  41. <div class="page-wrap">
  42. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  43. <div class="card">
  44. <div class="main-content" style="background-color: white;">
  45. <div class="container">
  46. <div class="col-md-12">
  47. <div style="padding: 0px;margin-top:-58px;margin-left: -233px;">
  48. <div class="card-header">
  49. <b>Toilets</b>
  50. </div>
  51. <br>
  52. <!-- View Table -->
  53. <div id="toiletDataContainer" style="display: none;">
  54. <table class="table table-bordered">
  55. <tr>
  56. <th>No of Toilet Blocks</th>
  57. <td id="td_blocks"></td>
  58. <th>Male Toilets (Urinals)</th>
  59. <td id="td_urinals"></td>
  60. </tr>
  61. <tr>
  62. <th>Male Toilets (W.C)</th>
  63. <td id="td_wc_male"></td>
  64. <th>Female Toilets (W.C)</th>
  65. <td id="td_wc_female"></td>
  66. </tr>
  67. <tr>
  68. <th>Differently Abled Toilets</th>
  69. <td id="td_disabled"></td>
  70. <th>Incinerator for Napkin Disposal</th>
  71. <td id="td_napkins"></td>
  72. </tr>
  73. </table>
  74. <div class="text-center">
  75. <button class="btn btn-primary" id="editToiletBtn">Update</button>
  76. </div>
  77. </div>
  78. <!-- Entry Form -->
  79. <form id="toiletForm" novalidate>
  80. <input type="hidden" name="school_id">
  81. <input type="hidden" id="toilet_id" name="toilet_id" />
  82. <div class="row p-3">
  83. <div class="col-md-6 form-group">
  84. <label>No of Toilet Blocks *</label>
  85. <input type="text" class="form-control" name="total_toiletBlocks"
  86. id="total_toiletBlocks" required>
  87. </div>
  88. <div class="col-md-6 form-group">
  89. <label>Total Male Toilets (Urinals) *</label>
  90. <input type="text" class="form-control" name="total_male_urinals"
  91. id="total_male_urinals" required>
  92. </div>
  93. </div>
  94. <div class="row p-3">
  95. <div class="col-md-6 form-group">
  96. <label>Total Male Toilets (W.C) *</label>
  97. <input type="text" class="form-control" name="total_wc_male"
  98. id="total_wc_male" required>
  99. </div>
  100. <div class="col-md-6 form-group">
  101. <label>Total Female Toilets (W.C) *</label>
  102. <input type="text" class="form-control" name="total_wc_female"
  103. id="total_wc_female" required>
  104. </div>
  105. <div class="col-md-6 form-group">
  106. <label>Incinerator for Napkins Disposal *</label>
  107. <div class="radio-group">
  108. <input type="radio" name="is_napkins" value="true"> Yes
  109. <input type="radio" name="is_napkins" value="false"> No
  110. </div>
  111. </div>
  112. <div class="col-md-6 form-group">
  113. <label>Differently Abled Toilets *</label>
  114. <input type="text" class="form-control" name="total_diffAbled_toilet"
  115. id="total_diffAbled_toilet" required>
  116. </div>
  117. </div>
  118. <div class="card-footer text-center">
  119. <button type="submit" class="btn btn-primary"><i class="ik ik-save"></i>
  120. Submit</button>
  121. <button type="reset" class="btn btn-secondary"><i class="ik ik-refresh-cw"></i>
  122. Reset</button>
  123. </div>
  124. </form>
  125. </div>
  126. </div>
  127. </div>
  128. </div>
  129. </div>
  130. </div>
  131. <!-- Modal -->
  132. <div class="modal fade" id="toiletModal" tabindex="-1" aria-labelledby="toiletModalLabel" aria-hidden="true">
  133. <div class="modal-dialog">
  134. <div class="modal-content">
  135. <form id="toiletUpdateForm">
  136. <div class="modal-header">
  137. <h5 class="modal-title">Update Toilet Details</h5>
  138. <button type="button" class="close" data-bs-dismiss="modal"
  139. aria-label="Close"><span aria-hidden="true">&times;</span></button>
  140. </div>
  141. <div class="modal-body">
  142. <input type="hidden" id="modal_toilet_id" />
  143. <input type="hidden" id="modal_school_id" />
  144. <div class="mb-2"><label>No of Toilet Blocks *</label><input type="number" id="modal_blocks"
  145. class="form-control" required /></div>
  146. <div class="mb-2"><label>Male Toilets (Urinals) *</label><input type="number"
  147. id="modal_urinals" class="form-control" required /></div>
  148. <div class="mb-2"><label>Male Toilets (W.C) *</label><input type="number" id="modal_wc_male"
  149. class="form-control" required /></div>
  150. <div class="mb-2"><label>Female Toilets (W.C) *</label><input type="number"
  151. id="modal_wc_female" class="form-control" required /></div>
  152. <div class="mb-2"><label>Differently Abled Toilets *</label><input type="number"
  153. id="modal_disabled" class="form-control" required /></div>
  154. <div class="mb-2">
  155. <label>Incinerator for Napkin Disposal *</label><br>
  156. <input type="radio" name="modal_napkins" value="true" /> Yes
  157. <input type="radio" name="modal_napkins" value="false" /> No
  158. </div>
  159. </div>
  160. <div class="modal-footer">
  161. <button type="submit" class="btn btn-success">Save Changes</button>
  162. </div>
  163. </form>
  164. </div>
  165. </div>
  166. </div>
  167. <!-- Scripts -->
  168. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
  169. <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
  170. <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  171. <script>
  172. $(document).ready(function () {
  173. const schoolId = new URLSearchParams(window.location.search).get("schoolId");
  174. $('input[name="school_id"]').val(schoolId);
  175. $('#modal_school_id').val(schoolId);
  176. /*$('#total_toiletBlocks').on('input', function () {
  177. const value = parseInt($(this).val()) || 0;
  178. if (value === 0) {
  179. $('#total_male_urinals').val(0);
  180. $('#total_wc_male').val(0);
  181. $('#total_wc_female').val(0);
  182. $('#total_diffAbled_toilet').val(0);
  183. }
  184. else{
  185. $('#total_male_urinals').val('');
  186. $('#total_wc_male').val('');
  187. $('#total_wc_female').val('');
  188. $('#total_diffAbled_toilet').val('');
  189. }
  190. });*/
  191. /* $('#modal_blocks').on('input', function () {
  192. const value = parseInt($(this).val()) || 0;
  193. if (value === 0) {
  194. $('#modal_urinals').val(0);
  195. $('#modal_wc_male').val(0);
  196. $('#modal_wc_female').val(0);
  197. $('#modal_disabled').val(0);
  198. }
  199. else{
  200. $('#modal_urinals').val('');
  201. $('#modal_wc_male').val('');
  202. $('#modal_wc_female').val('');
  203. $('#modal_disabled').val('');
  204. }
  205. });*/
  206. // ✅ Enforce only numeric input
  207. ['total_toiletBlocks', 'total_male_urinals', 'total_wc_male', 'total_wc_female', 'total_diffAbled_toilet']
  208. .forEach(id => {
  209. document.getElementById(id).addEventListener('input', function () {
  210. this.value = this.value.replace(/[^0-9]/g, '');
  211. if (parseInt(this.value) < 0) this.value = '';
  212. });
  213. });
  214. // ✅ Function to reload table data after update
  215. function reloadToiletTable() {
  216. $.get('/gcc/api/gccschool/schoolproperty/checkToiletDetails', { school_id: schoolId }, function (res) {
  217. if (res && res[0]?.Data?.length > 0) {
  218. const d = res[0].Data[0];
  219. // Update table with fresh values
  220. $('#td_blocks').text(d.total_toiletBlocks);
  221. $('#td_urinals').text(d.total_male_urinals);
  222. $('#td_wc_male').text(d.total_wc_male);
  223. $('#td_wc_female').text(d.total_wc_female);
  224. $('#td_disabled').text(d.total_diffAbled_toilet);
  225. $('#td_napkins').text(d.is_napkins === true || d.is_napkins === "true" ? 'Yes' : 'No');
  226. $('#toiletDataContainer').show();
  227. $('#editToiletBtn').data('toiletData', d);
  228. }
  229. });
  230. }
  231. // ✅ Initial load
  232. $.get('/gcc/api/gccschool/schoolproperty/checkToiletDetails', { school_id: schoolId }, function (res) {
  233. if (res && res[0]?.Data?.length > 0) {
  234. const d = res[0].Data[0];
  235. $('#toilet_id').val(d.toilet_id);
  236. $('#toiletForm').hide();
  237. $('#toiletDataContainer').show();
  238. $('#td_blocks').text(d.total_toiletBlocks);
  239. $('#td_urinals').text(d.total_male_urinals);
  240. $('#td_wc_male').text(d.total_wc_male);
  241. $('#td_wc_female').text(d.total_wc_female);
  242. $('#td_disabled').text(d.total_diffAbled_toilet);
  243. $('#td_napkins').text(d.is_napkins === true ? 'Yes' : 'No');
  244. $('#editToiletBtn').data('toiletData', d);
  245. } else {
  246. $('#toiletForm').show();
  247. $('#toiletDataContainer').hide();
  248. }
  249. });
  250. // ✅ Save new toilet form (first time entry)
  251. $('#toiletForm').submit(function (e) {
  252. e.preventDefault();
  253. const blocks = parseInt($('#total_toiletBlocks').val()) || 0;
  254. const urinals = parseInt($('#total_male_urinals').val()) || 0;
  255. const wc_male = parseInt($('#total_wc_male').val()) || 0;
  256. const wc_female = parseInt($('#total_wc_female').val()) || 0;
  257. const diff_abled = parseInt($('#total_diffAbled_toilet').val()) || 0;
  258. const isNapkins = $('input[name="is_napkins"]:checked').val();
  259. /* if (blocks === 0) {
  260. $('#total_male_urinals').val(0);
  261. $('#total_wc_male').val(0);
  262. $('#total_wc_female').val(0);
  263. $('#total_diffAbled_toilet').val(0);
  264. }*/
  265. if ($('#total_toiletBlocks').val().trim() === '') {
  266. return Swal.fire({
  267. icon: 'warning',
  268. title: 'Validation Error',
  269. text: 'Enter Total Toilet Blocks ',
  270. allowOutsideClick: false,
  271. allowEscapeKey: false,
  272. allowEnterKey: false,
  273. showConfirmButton: true
  274. });
  275. }
  276. if ($('#total_male_urinals').val().trim() === '') {
  277. return Swal.fire({
  278. icon: 'warning',
  279. title: 'Validation Error',
  280. text: 'Enter number of Male Urinals (0 or more).',
  281. allowOutsideClick: false,
  282. allowEscapeKey: false,
  283. allowEnterKey: false,
  284. showConfirmButton: true
  285. });
  286. }
  287. if ($('#total_wc_male').val().trim() === '') {
  288. return Swal.fire({
  289. icon: 'warning',
  290. title: 'Validation Error',
  291. text: 'Enter number of Male WC (0 or more).',
  292. allowOutsideClick: false,
  293. allowEscapeKey: false,
  294. allowEnterKey: false,
  295. showConfirmButton: true
  296. });
  297. }
  298. if ($('#total_wc_female').val().trim() === '') {
  299. return Swal.fire({
  300. icon: 'warning',
  301. title: 'Validation Error',
  302. text: 'Enter number of Female WC (0 or more).',
  303. allowOutsideClick: false,
  304. allowEscapeKey: false,
  305. allowEnterKey: false,
  306. showConfirmButton: true
  307. });
  308. }
  309. if (typeof isNapkins === 'undefined') {
  310. return Swal.fire({
  311. icon: 'warning',
  312. title: 'Validation Error',
  313. text: 'Please select whether there is an Incinerator for Napkins Disposal.',
  314. allowOutsideClick: false,
  315. allowEscapeKey: false,
  316. allowEnterKey: false,
  317. showConfirmButton: true
  318. });
  319. }
  320. if ($('#total_diffAbled_toilet').val().trim() === '') {
  321. return Swal.fire({
  322. icon: 'warning',
  323. title: 'Validation Error',
  324. text: 'Enter number of Differently Abled Toilets (0 or more).',
  325. allowOutsideClick: false,
  326. allowEscapeKey: false,
  327. allowEnterKey: false,
  328. showConfirmButton: true
  329. });
  330. }
  331. // Total toilets entered
  332. /* const totalToilets = urinals + wc_male + wc_female + diff_abled;
  333. if (blocks !== totalToilets) {
  334. Swal.fire({
  335. icon: 'warning',
  336. title: 'Mismatch Detected',
  337. text: `The number of toilet blocks (${blocks}) must match the total toilets (${totalToilets}) entered.`,
  338. allowOutsideClick: false,
  339. allowEscapeKey: false,
  340. allowEnterKey: false,
  341. showConfirmButton: true
  342. });
  343. return;
  344. }*/
  345. const formData = new FormData(this);
  346. $.ajax({
  347. type: 'POST',
  348. url: '/gcc/api/gccschool/schoolproperty/saveToilets',
  349. data: formData,
  350. processData: false,
  351. contentType: false,
  352. success: res => {
  353. // Swal.fire('Saved', res, 'success').then(() => {
  354. Swal.fire({
  355. title: 'Saved',
  356. text: res,
  357. icon: 'success',
  358. allowOutsideClick: false,
  359. allowEscapeKey: false,
  360. allowEnterKey: false,
  361. showConfirmButton: true
  362. }).then(() => {
  363. location.reload();
  364. // $('#toiletForm').hide();
  365. // reloadToiletTable(); // refresh table
  366. });
  367. },
  368. error: xhr =>Swal.fire({
  369. title: 'Error',
  370. text: xhr.responseText || 'Unknown error',
  371. icon: 'error',
  372. allowOutsideClick: false,
  373. allowEscapeKey: false,
  374. allowEnterKey: false,
  375. showConfirmButton: true
  376. })
  377. //Swal.fire('Error', xhr.responseText || 'Unknown error', 'error')
  378. });
  379. });
  380. let originalModalData = {};
  381. $('#editToiletBtn').click(function () {
  382. const d = $(this).data("toiletData");
  383. $('#modal_toilet_id').val(d.toilet_id);
  384. $('#modal_blocks').val(d.total_toiletBlocks);
  385. $('#modal_urinals').val(d.total_male_urinals);
  386. $('#modal_wc_male').val(d.total_wc_male);
  387. $('#modal_wc_female').val(d.total_wc_female);
  388. $('#modal_disabled').val(d.total_diffAbled_toilet);
  389. $(`input[name="modal_napkins"][value="${d.is_napkins}"]`).prop('checked', true);
  390. // ✅ Store original values
  391. originalModalData = {
  392. total_toiletBlocks: d.total_toiletBlocks.toString(),
  393. total_male_urinals: d.total_male_urinals.toString(),
  394. total_wc_male: d.total_wc_male.toString(),
  395. total_wc_female: d.total_wc_female.toString(),
  396. total_diffAbled_toilet: d.total_diffAbled_toilet.toString(),
  397. is_napkins: d.is_napkins.toString()
  398. };
  399. const modal = new bootstrap.Modal(document.getElementById('toiletModal'));
  400. modal.show();
  401. });
  402. $('#toiletUpdateForm').submit(function (e) {
  403. e.preventDefault();
  404. const updateBlocks = parseInt($('#modal_blocks').val()) || 0;
  405. const updateUrinals = parseInt($('#modal_urinals').val()) || 0;
  406. const updateWCMale = parseInt($('#modal_wc_male').val()) || 0;
  407. const updateWCFemale = parseInt($('#modal_wc_female').val()) || 0;
  408. const updateDisabled = parseInt($('#modal_disabled').val()) || 0;
  409. /* if (!updateBlocks ) {
  410. return Swal.fire({
  411. icon: 'warning',
  412. title: 'Validation Error',
  413. text: 'Enter Total Toilet Blocks greater than 0.',
  414. allowOutsideClick: false,
  415. allowEscapeKey: false,
  416. allowEnterKey: false,
  417. showConfirmButton: true
  418. });
  419. }*/
  420. /* const updateTotal = updateUrinals + updateWCMale + updateWCFemale + updateDisabled;
  421. if (updateBlocks !== updateTotal) {
  422. Swal.fire({
  423. icon: 'warning',
  424. title: 'Mismatch Detected',
  425. text: `The number of toilet blocks (${updateBlocks}) must match the total toilets (${updateTotal}) entered.`,
  426. allowOutsideClick: false,
  427. allowEscapeKey: false,
  428. allowEnterKey: false,
  429. showConfirmButton: true
  430. });
  431. return;
  432. }*/
  433. const currentData = {
  434. total_toiletBlocks: $('#modal_blocks').val(),
  435. total_male_urinals: $('#modal_urinals').val(),
  436. total_wc_male: $('#modal_wc_male').val(),
  437. total_wc_female: $('#modal_wc_female').val(),
  438. total_diffAbled_toilet: $('#modal_disabled').val(),
  439. is_napkins: $('input[name="modal_napkins"]:checked').val()
  440. };
  441. // ✅ Check if any value has changed
  442. const hasChanged = Object.keys(currentData).some(key => currentData[key] !== originalModalData[key]);
  443. /* if (!hasChanged) {
  444. Swal.fire('No Changes', 'Please make a change before submitting.', 'info');
  445. return;
  446. }*/
  447. currentData.school_id = $('#modal_school_id').val();
  448. $.post('/gcc/api/gccschool/schoolproperty/updateToiletDetails', currentData, function () {
  449. // Swal.fire('Updated', 'Toilet data updated successfully!', 'success').then(() => {
  450. Swal.fire({
  451. title: 'Updated',
  452. text: 'Toilet data updated successfully!',
  453. icon: 'success',
  454. allowOutsideClick: false,
  455. allowEscapeKey: false,
  456. allowEnterKey: false,
  457. showConfirmButton: true
  458. }).then(() => {
  459. const modalInstance = bootstrap.Modal.getInstance(document.getElementById('toiletModal'));
  460. modalInstance.hide();
  461. location.reload();
  462. });
  463. }).fail(() => {
  464. // Swal.fire('Error', 'Update failed', 'error');
  465. Swal.fire({
  466. title: 'Error',
  467. text: 'Update failed',
  468. icon: 'error',
  469. allowOutsideClick: false,
  470. allowEscapeKey: false,
  471. allowEnterKey: false,
  472. showConfirmButton: true
  473. });
  474. });
  475. });
  476. });
  477. </script>
  478. </body>
  479. </html>