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.

557 lines
19 KiB

1 year ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/head-admin :: head}"></head>
  4. </head>
  5. <style>
  6. .header-class {
  7. position: fixed;
  8. top: 50;
  9. left: 0;
  10. width: 100%;
  11. z-index: 1000;
  12. }
  13. .main-content {
  14. margin-top: 70px;
  15. }
  16. body,
  17. html {
  18. margin: 0;
  19. padding: 0;
  20. width: 100%;
  21. height: 100%;
  22. overflow: auto;
  23. }
  24. .bookings-list {
  25. display: flex;
  26. justify-content: center;
  27. align-items: center;
  28. height: 100vh;
  29. padding: 20px;
  30. box-sizing: border-box;
  31. }
  32. .booking-card {
  33. max-width: 600px;
  34. width: 100%;
  35. background-color: #fff;
  36. border-radius: 8px;
  37. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  38. padding: 20px;
  39. box-sizing: border-box;
  40. overflow: hidden;
  41. }
  42. .booking-details p {
  43. margin: 10px 0;
  44. }
  45. .settlement-btn {
  46. display: block;
  47. width: 100%;
  48. padding: 10px;
  49. background-color: #4caf50;
  50. color: white;
  51. border: none;
  52. border-radius: 5px;
  53. cursor: pointer;
  54. font-size: 16px;
  55. margin-top: 20px;
  56. }
  57. .settlement-btn:hover {
  58. background-color: #45a049;
  59. }
  60. </style>
  61. <body>
  62. <div id="page-container"
  63. class="sidebar-o sidebar-dark enable-page-overlay side-scroll page-header-fixed page-header-dark">
  64. <aside th:replace="~{fragments/aside-right :: aside}"></aside>
  65. <nav th:replace="~{fragments/nav-caretaker :: nav}"></nav>
  66. <header th:replace="~{fragments/header-caretaker :: header}"></header>
  67. <div class="content" style="margin-top: 77px;">
  68. <div class="block block-rounded">
  69. <div class="block-header bg-success text-white" style="background-color: #2c726c !important">
  70. <h3 class="block-title">Current Bookings</h3>
  71. </div>
  72. <div class="block-content">
  73. <div class="table-responsive">
  74. <table id="bookingTable" class="table table-bordered table-vcenter">
  75. <thead>
  76. <tr>
  77. <th>Hall Name</th>
  78. <th>Booking Id</th>
  79. <th>Reason for Booking</th>
  80. <th>Start Date</th>
  81. <th>End Date</th>
  82. <th>No of Days</th>
  83. <th>Starting Period</th>
  84. <th>Ending Period</th>
  85. <th>Actions</th>
  86. </tr>
  87. </thead>
  88. <tbody>
  89. <tr th:each="booking : ${bookings}">
  90. <td th:text="${booking.hallDetails.hallName}"></td>
  91. <td th:text="${booking.bookingId}"></td>
  92. <td th:text="${booking.reason}"></td>
  93. <td th:text="${booking.startDate}"></td>
  94. <td th:text="${booking.endDate}"></td>
  95. <td th:text="${booking.noOfDays}"></td>
  96. <td th:text="${booking.startingSlot == 1 ? 'Morning' : 'Evening'}"></td>
  97. <td th:text="${booking.endingSlot == 1 ? 'Morning' : 'Evening'}"></td>
  98. <td>
  99. <!-- Implement your logic for viewing details -->
  100. <button type="button" class="btn btn-primary view-details"
  101. th:onclick="bookingDetails([[${booking.bookingId}]])">View</button>
  102. <button type="button" class="btn btn-primary settlement"
  103. th:if="${booking.ebDetails != null and booking.settlement == null}"
  104. th:onclick="settleTheAmount([[${booking.bookingId}]])">Settlement</button>
  105. <button type="button" class="btn btn-primary" th:if="${booking.ebDetails==null}"
  106. th:onclick="enterStartingReading([[${booking.bookingId}]], '[[${booking.hallDetails.ebNumber}]]')"
  107. id="ebDetails">EB Details</button>
  108. </td>
  109. </tr>
  110. </tbody>
  111. </table>
  112. </div>
  113. </div>
  114. </div>
  115. </div>
  116. <br>
  117. <br>
  118. <div class="modal fade backdrop" id="bookingModal" tabindex="-1" role="dialog"
  119. aria-labelledby="staticBackdropLabel" aria-hidden="true">
  120. <div class="modal-dialog modal-lg" role="document">
  121. <div class="modal-content">
  122. <div class="block block-rounded block-themed block-transparent mb-0">
  123. <div class="block-header bg-primary-dark">
  124. <h3 class="block-title">Booking Details</h3>
  125. <div class="block-options">
  126. <button type="button" class="btn-block-option" data-bs-dismiss="modal"
  127. aria-label="Close">
  128. <i class="fa fa-fw fa-times"></i>
  129. </button>
  130. </div>
  131. </div>
  132. <div class="block-content row">
  133. <div class="col-sm-4">
  134. <div class="form-group">
  135. <label for="name">Name<span class="required">*</span>:</label>
  136. <input type="text" class="form-control text-center" id="name" name="name"
  137. placeholder="First Name" readonly>
  138. </div>
  139. <small id="emailHelp" class="form-text text-muted"></small>
  140. </div>
  141. <div class="col-sm-4">
  142. <div class="form-group">
  143. <label for="mobileno">Mobile Number<span class="required">*</span>:</label>
  144. <input type="text" class="form-control text-center" id="mobileno" name="mobileno"
  145. placeholder="Mobile Number" minlength="10" maxlength="10" pattern="[0-9]{10}"
  146. readonly>
  147. </div>
  148. </div>
  149. <div class="col-sm-4">
  150. <div class="form-group">
  151. <label for="email">E-Mail ID<span class="required"></span>:</label>
  152. <input type="email" class="form-control text-center" id="email" name="email"
  153. placeholder="Email" maxlength="255" readonly>
  154. </div>
  155. <small id="emailHelps" class="form-text text-muted"></small>
  156. </div>
  157. <div class="col-sm-4">
  158. <div class="form-group">
  159. <label for="doorNo">DoorNo<span class="required">*</span>:</label>
  160. <input type="text" class="form-control text-center" id="doorNo" name="doorNo"
  161. placeholder="Door No" readonly>
  162. </div>
  163. </div>
  164. <div class="col-sm-4">
  165. <div class="form-group">
  166. <label for="street">Street<span class="required">*</span>:</label>
  167. <input type="text" class="form-control text-center" id="street" name="street"
  168. placeholder="Street" readonly>
  169. </div>
  170. </div>
  171. <div class="col-sm-4">
  172. <div class="form-group">
  173. <label for="area">Area<span class="required">*</span>:</label>
  174. <input type="text" class="form-control text-center" id="area" name="area"
  175. placeholder="Area" readonly>
  176. </div>
  177. <small id="emailHelped" class="form-text text-muted"></small>
  178. </div>
  179. <div class="col-sm-4">
  180. <div class="form-group">
  181. <label for="location">Location<span class="required">*</span>:</label>
  182. <input type="text" class="form-control text-center" id="location" name="location"
  183. placeholder="Location" readonly>
  184. </div>
  185. </div>
  186. <div class="col-sm-4">
  187. <div class="form-group">
  188. <label for="pincode">Pincode<span class="required">*</span>:</label>
  189. <input type="text" class="form-control text-center" id="pincode" name="pincode"
  190. placeholder="Pincode" readonly>
  191. </div>
  192. </div>
  193. <div class="col-sm-4" style="margin-left:0%">
  194. <div class="form-group">
  195. <label for="userType">User Type<span class="required">*</span>:</label>
  196. <input class="form-control" id="usertype" name="usertype"
  197. placeholder="User Type" readonly>
  198. </div>
  199. </div>
  200. <div class="col-sm-4 hidden" id="employeeFields">
  201. <!-- Employee fields here -->
  202. </div>
  203. <div class="col-sm-4 hidden" id="pensionerFields">
  204. <!-- Pensioner fields here -->
  205. </div>
  206. <div class="col-sm-4 hidden" id="wardnoFields">
  207. <!-- Ward number fields here -->
  208. </div>
  209. </div>
  210. </div>
  211. <div class="modal-footer">
  212. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
  213. </div>
  214. </div>
  215. </div>
  216. </div>
  217. <div class="modal fade backdrop" id="EBdestailsModal" tabindex="-1" role="dialog"
  218. aria-labelledby="staticBackdropLabel" aria-hidden="true">
  219. <div class="modal-dialog modal-lg" role="document">
  220. <div class="modal-content">
  221. <div class="block block-rounded block-themed block-transparent mb-0">
  222. <div class="block-header bg-primary-dark">
  223. <h3 class="block-title">EB Details</h3>
  224. <div class="block-options">
  225. <button type="button" class="btn-block-option" data-bs-dismiss="modal"
  226. aria-label="Close">
  227. <i class="fa fa-fw fa-times"></i>
  228. </button>
  229. </div>
  230. </div>
  231. <div class="block-content row">
  232. <input type="hidden" class="form-control text-center" id="bookingId" name="bookingId"
  233. readonly>
  234. <div class="col-sm-6">
  235. <div class="form-group">
  236. <label for="ebNumber">Consumer Number<span class="required">*</span>:</label>
  237. <input type="text" class="form-control text-center" id="ebNumber" name="ebNumber"
  238. placeholder="EB Number" readonly>
  239. </div>
  240. </div>
  241. <div class="col-sm-6">
  242. <div class="form-group">
  243. <label for="startingReading">Starting Reading<span
  244. class="required">*</span>:</label>
  245. <input type="text" class="form-control text-center" id="startingReading"
  246. name="startingReading">
  247. </div>
  248. </div>
  249. <div class="col-sm-6">
  250. <div class="form-group">
  251. <label for="startingReadingimage">Starting Reading Image<span
  252. class="required"></span>:</label>
  253. <input type="file" class="form-control text-center startreading-image" id="startingReadingimage"
  254. name="startingReadingimage">
  255. </div>
  256. </div>
  257. </div>
  258. </div><br><br>
  259. <div class="modal-footer">
  260. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
  261. <button type="button" class="btn btn-primary" id="submitEbDetails">Submit</button>
  262. </div>
  263. </div>
  264. </div>
  265. </div>
  266. <footer th:replace="~{fragments/footer2 :: footer}"></footer>
  267. </div>
  268. <div th:replace="~{fragments/resetpassword :: div}"></div>
  269. <script th:replace="~{fragments/script :: script}"></script>
  270. <script th:replace="~{fragments/loginscript :: script}"></script>
  271. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
  272. <script type="text/javascript">
  273. $(document).ready(
  274. function () {
  275. // DataTables buttons configuration
  276. var buttons = [{
  277. extend: 'pageLength',
  278. className: 'btn btn-primary'
  279. }, {
  280. title: 'Data export',
  281. extend: 'copyHtml5',
  282. text: 'Copy',
  283. className: 'btn btn-primary',
  284. id: 'copyBtn'
  285. }, {
  286. extend: 'excelHtml5',
  287. text: 'Excel',
  288. className: 'btn btn-primary',
  289. id: 'excelBtn'
  290. }, {
  291. extend: 'csvHtml5',
  292. text: 'CSV',
  293. className: 'btn btn-primary',
  294. id: 'csvBtn'
  295. }, {
  296. extend: 'pdfHtml5',
  297. text: 'PDF',
  298. className: 'btn btn-primary',
  299. id: 'pdfBtn'
  300. },
  301. ];
  302. $('#bookingTable').DataTable(
  303. {
  304. dom: 'Bftip',
  305. columnDefs: [{
  306. targets: 'no-sort',
  307. orderable: false
  308. }],
  309. lengthMenu: [
  310. [50, 100, 200, 500, -1],
  311. ['50 rows', '100 rows', '200 rows',
  312. '500 rows', 'Show all']],
  313. scrollY: '50vh',
  314. fixedColumns: {
  315. left: 1,
  316. right: 1
  317. },
  318. buttons: [buttons],
  319. responsive: true,
  320. searching: true, // Enable search
  321. select: false,
  322. processing: false,
  323. });
  324. // Link the search input to DataTable
  325. $('#searchInput').on('keyup', function () {
  326. dataTable.search(this.value).draw();
  327. });
  328. });
  329. function settleTheAmount(bookingId) {
  330. window.location.href = '/communityhall/caretaker/caretakerpage?bookingId=' + bookingId;
  331. }
  332. function bookingDetails(bookingId) {
  333. $.ajax({
  334. url: '/communityhall/careTaker/api/viewuserDetails',
  335. method: 'GET',
  336. data: {bookingId: bookingId},
  337. success: function (response) {
  338. $('#name').val(response.users.name);
  339. $('#mobileno').val(response.users.mobileNo);
  340. $('#email').val(response.users.email);
  341. $('#doorNo').val(response.users.doorNo);
  342. $('#street').val(response.users.street);
  343. $('#area').val(response.users.area);
  344. $('#location').val(response.users.location);
  345. $('#pincode').val(response.users.pinCode);
  346. $('#usertype').val(response.users.usertype);
  347. // Show the modal
  348. $('#bookingModal').modal('show');
  349. },
  350. error: function () {
  351. alert('Failed to fetch user details.');
  352. }
  353. });
  354. }
  355. function enterStartingReading(bookingId, ebNumber) {
  356. $('#bookingId').val(bookingId);
  357. $('#ebNumber').val(ebNumber);
  358. $('#EBdestailsModal').modal('show');
  359. }
  360. let isCompressing = false;
  361. // Attach the validation function to file input change event
  362. $(document).on('change', '.startreading-image', function () {
  363. validateFile(this);
  364. });
  365. function validateFile(fileInput) {
  366. const allowedExtensions = /(\.jpg|\.jpeg|\.pdf)$/i;
  367. const file = fileInput.files[0];
  368. const filePath = fileInput.value;
  369. let errorMessage = '';
  370. // Clear any previous error message
  371. clearError(fileInput);
  372. // Check for duplicate files
  373. if (isDuplicateFile(file.name, fileInput)) {
  374. errorMessage = 'This file has already been selected. Please choose a different file.';
  375. fileInput.value = ''; // Clear the file input
  376. displayError(fileInput, errorMessage);
  377. return;
  378. }
  379. // Validate file type
  380. if (!allowedExtensions.exec(filePath)) {
  381. errorMessage = 'Only JPG, JPEG, and PDF files are allowed.';
  382. fileInput.value = ''; // Clear the file input
  383. displayError(fileInput, errorMessage);
  384. }
  385. // Handle image files separately
  386. else if (/(\.jpg|\.jpeg)$/i.test(filePath) && file.size > 2097152) {
  387. compressImage(file).then(compressedFile => {
  388. const dataTransfer = new DataTransfer();
  389. dataTransfer.items.add(compressedFile);
  390. fileInput.files = dataTransfer.files;
  391. // Validate file size after compression
  392. validateFileSize(fileInput);
  393. }).catch(error => {
  394. errorMessage = 'Error compressing image.';
  395. displayError(fileInput, errorMessage);
  396. });
  397. }
  398. // Directly validate PDF file size
  399. else if (/(\.pdf)$/i.test(filePath) && file.size > 2097152) {
  400. errorMessage = 'PDF file size exceeds the 2MB limit.';
  401. fileInput.value = ''; // Clear the file input
  402. displayError(fileInput, errorMessage);
  403. }
  404. else {
  405. // console.log('File size is within limit:', file.size, 'bytes');
  406. clearError(fileInput);
  407. }
  408. }
  409. function isDuplicateFile(fileName, currentInput) {
  410. const fileInputs = document.querySelectorAll('.file-upload-field');
  411. for (let input of fileInputs) {
  412. if (input !== currentInput && input.files.length > 0 && input.files[0].name === fileName) {
  413. return true;
  414. }
  415. }
  416. return false;
  417. }
  418. function clearError(fileInput) {
  419. const errorElements = fileInput.parentNode.getElementsByClassName('error-message');
  420. while (errorElements.length > 0) {
  421. errorElements[0].remove();
  422. }
  423. }
  424. // Function to compress image using canvas
  425. function compressImage(file) {
  426. return new Promise((resolve, reject) => {
  427. const reader = new FileReader();
  428. reader.onload = function (event) {
  429. const img = new Image();
  430. img.onload = function () {
  431. const canvas = document.createElement('canvas');
  432. const ctx = canvas.getContext('2d');
  433. const maxSize = 2097152; // 2MB in bytes
  434. let scale = 1;
  435. if (file.size > maxSize) {
  436. scale = Math.sqrt(maxSize / file.size);
  437. }
  438. canvas.width = img.width * scale;
  439. canvas.height = img.height * scale;
  440. ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  441. // Convert canvas content to blob
  442. canvas.toBlob(blob => {
  443. resolve(new File([blob], file.name, {type: 'image/jpeg', lastModified: Date.now()}));
  444. }, 'image/jpeg', 0.7); // Adjust JPEG quality as needed (0.7 is 70% quality)
  445. };
  446. img.src = event.target.result;
  447. };
  448. reader.readAsDataURL(file);
  449. });
  450. }
  451. // Function to validate file size after compression
  452. function validateFileSize(fileInput) {
  453. const file = fileInput.files[0];
  454. if (file && file.size > 2097152) {
  455. //console.log('File size is still greater than 2MB after compression.');
  456. // Handle the situation where the file size is still greater than 2MB
  457. displayError(fileInput, 'File size is still greater than 2MB after compression.');
  458. fileInput.value = ''; // Clear the file input
  459. } else {
  460. //console.log('File size is within limit after compression.');
  461. // Handle the situation where the file size is within the limit
  462. }
  463. }
  464. // Function to display error messages
  465. function displayError(fileInput, errorMessage) {
  466. // Example implementation: show error message near the file input
  467. let errorContainer = fileInput.nextElementSibling;
  468. if (!errorContainer || !errorContainer.classList.contains('error-message')) {
  469. errorContainer = document.createElement('div');
  470. errorContainer.classList.add('error-message');
  471. fileInput.parentNode.insertBefore(errorContainer, fileInput.nextSibling);
  472. }
  473. errorContainer.textContent = errorMessage;
  474. }
  475. $(document).ready(function () {
  476. $("#submitEbDetails").click(function () {
  477. var bookid = parseInt($("#bookingId").val());
  478. var startingReading = $("#startingReading").val();
  479. var startingReadingimage = $("#startingReadingimage")[0].files[0]; // Get the file
  480. var formData = new FormData();
  481. formData.append("bookingId", bookid);
  482. formData.append("startingReading", startingReading);
  483. formData.append("startingReadingimage", startingReadingimage);
  484. $.ajax({
  485. type: "POST",
  486. url: "/communityhall/careTaker/api/saveEbDetails",
  487. data: formData,
  488. contentType: false, // Prevent jQuery from setting content type
  489. processData: false, // Prevent jQuery from processing the data
  490. success: function (response) {
  491. $("#EBdestailsModal").modal('hide');
  492. // Show SweetAlert success message
  493. Swal.fire({
  494. title: 'Success!',
  495. text: 'EB details saved successfully.',
  496. icon: 'success',
  497. confirmButtonText: 'OK'
  498. }).then(function() {
  499. // Reload the page after the alert is dismissed
  500. location.reload();
  501. });
  502. },
  503. error: function (xhr, status, error) {
  504. console.error(xhr.responseText);
  505. alert("Error occurred while saving EbDetails.");
  506. }
  507. });
  508. });
  509. });
  510. document.getElementById('EBdetailsModal').addEventListener('hide.bs.modal', function () {
  511. // Clear the startingReading input field
  512. document.getElementById('startingReading').value = '';
  513. // Clear the startingReadingimage file input field
  514. document.getElementById('startingReadingimage').value = '';
  515. });
  516. </script>
  517. </body>
  518. </html>