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.

3569 lines
201 KiB

2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
​
​
​
​
2 years ago
​
​
​
​
​
​
​
​
​
2 years ago
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
​
2 years ago
​
2 years ago
​
2 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
2 years ago
​
​
2 years ago
​
​
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
  3. <head th:replace="~{fragments/head :: head}">
  4. </head>
  5. <!--datatables-->
  6. <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
  7. <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/2.4.1/css/buttons.dataTables.min.css">
  8. <style>
  9. .card-body table {
  10. width: 100%;
  11. padding: 100px;
  12. }
  13. .card-body th,
  14. td {
  15. padding: 8px;
  16. text-align: left;
  17. }
  18. .amount-cell {
  19. text-align: right;
  20. padding-right: 1rem;
  21. /* Adjust padding as needed */
  22. }
  23. .ui-datepicker-container {
  24. width: 100%;
  25. }
  26. .fixedcontainer {
  27. width: 250%;
  28. margin: 40px 0;
  29. display: none
  30. }
  31. .disabled {
  32. cursor: not-allowed;
  33. opacity: 1;
  34. }
  35. /* Move pointer-events:none to the inner anchor so the <td> can still receive
  36. mouse events (needed for title-attribute tooltips and event delegation) */
  37. .disabled a,
  38. .disabled .ui-state-default {
  39. pointer-events: none;
  40. cursor: not-allowed;
  41. }
  42. /* ── Custom datepicker tooltip (works even when .disabled has pointer-events:none) ── */
  43. #dp-tooltip {
  44. position: fixed;
  45. z-index: 9999;
  46. background: rgba(30, 30, 30, 0.92);
  47. color: #fff;
  48. padding: 5px 11px;
  49. border-radius: 6px;
  50. font-size: 12px;
  51. font-weight: 600;
  52. pointer-events: none;
  53. white-space: nowrap;
  54. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  55. display: none;
  56. transition: opacity 0.15s;
  57. }
  58. .ui-widget {
  59. width: 40%
  60. }
  61. .ui-datepicker {
  62. padding: 3px;
  63. border: 1px solid #ccc;
  64. border-radius: 5px;
  65. background-color: white;
  66. left: 29.1418px;
  67. }
  68. .ui-datepicker-header {
  69. background-color: #f0f0f0;
  70. border: none;
  71. border-radius: 5px 5px 0 0;
  72. }
  73. .ui-datepicker-title {
  74. font-size: 1.2em;
  75. margin: 0;
  76. padding: 10px;
  77. text-align: center;
  78. }
  79. .ui-datepicker-calendar {
  80. margin: 0;
  81. padding: 0;
  82. font-weight: bold;
  83. }
  84. .ui-datepicker-calendar th,
  85. .ui-datepicker-calendar td {
  86. padding: 5px;
  87. text-align: center;
  88. }
  89. .ui-datepicker-calendar .ui-state-default {
  90. cursor: pointer;
  91. width: 100%;
  92. height: 100%;
  93. display: flex;
  94. justify-content: center;
  95. align-items: center;
  96. }
  97. .ui-datepicker-week-end {
  98. color: black;
  99. font-weight: bold;
  100. }
  101. .ui-datepicker-calendar th span {
  102. color: black;
  103. font-weight: bold;
  104. }
  105. .highlight-blue .ui-state-default {
  106. background: blue !important;
  107. color: #FFF !important;
  108. }
  109. .highlight-greens .ui-state-default {
  110. background: green !important;
  111. color: #FFF !important;
  112. }
  113. .highlight-yellow .ui-state-default {
  114. background: yellow !important;
  115. color: #000 !important;
  116. }
  117. .highlight-violet .ui-state-default {
  118. background: #a93da9 !important;
  119. color: #000 !important;
  120. }
  121. .highlight-pink .ui-state-default {
  122. background: red !important;
  123. color: #000 !important;
  124. }
  125. .form-control[readonly] {
  126. background-color: white;
  127. }
  128. .modal {
  129. overflow-y: auto;
  130. }
  131. .stepper-wrapper {
  132. display: flex;
  133. justify-content: space-between;
  134. margin-bottom: 20px;
  135. position: relative;
  136. }
  137. .stepper-item {
  138. display: flex;
  139. flex-direction: column;
  140. position: relative;
  141. width: 100%;
  142. z-index: 1;
  143. }
  144. .stepper-item::before {
  145. content: '';
  146. position: absolute;
  147. top: 15px;
  148. left: 50%;
  149. height: 4px;
  150. background-color: #dcdcdc;
  151. /* Default grey line */
  152. z-index: -1;
  153. }
  154. .stepper-item:first-child::before {
  155. left: 50%;
  156. width: 0;
  157. }
  158. .stepper-item:last-child::before {
  159. content: none;
  160. }
  161. .stepper-item.completed:not(:last-child)::after {
  162. content: '';
  163. position: absolute;
  164. top: 15px;
  165. left: 50%;
  166. width: calc(100% - 30px);
  167. height: 4px;
  168. background-color: #28a745;
  169. z-index: -1;
  170. transform: translateX(-50%);
  171. }
  172. .step-counter {
  173. width: 30px;
  174. height: 30px;
  175. border-radius: 50%;
  176. background-color: #dcdcdc;
  177. display: flex;
  178. justify-content: center;
  179. align-items: center;
  180. font-weight: bold;
  181. color: white;
  182. }
  183. .step-name {
  184. margin-top: 10px;
  185. font-size: 11px;
  186. }
  187. .stepper-item.completed .step-counter {
  188. background-color: #28a745;
  189. }
  190. .stepper-item.completed .step-name {
  191. font-weight: bold;
  192. }
  193. .tracking-container {
  194. padding: 10px;
  195. background: #f9f9f9;
  196. border-radius: 8px;
  197. overflow: hidden;
  198. max-height: 500px;
  199. }
  200. .tracking-steps {
  201. list-style: none;
  202. padding: 0;
  203. margin: 0;
  204. position: relative;
  205. }
  206. .tracking-steps::before {
  207. content: '';
  208. position: absolute;
  209. top: 0;
  210. left: 8px;
  211. width: 4px;
  212. height: 100%;
  213. background: yellowgreen;
  214. z-index: 0;
  215. }
  216. .tracking-step {
  217. display: flex;
  218. align-items: flex-start;
  219. margin-bottom: 20px;
  220. position: relative;
  221. padding-left: 40px;
  222. text-align: center;
  223. border-bottom: 1px solid #ddd;
  224. transition: background-color 0.3s ease-in-out;
  225. background-color: #fff;
  226. /* White background for steps */
  227. border-radius: 5px;
  228. /* Optional rounded corners */
  229. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  230. }
  231. /* Line adjustments between steps */
  232. .tracking-step::before {
  233. width: 100%;
  234. height: 5px;
  235. background: yellowgreen;
  236. /* Line color */
  237. position: absolute;
  238. top: 10px;
  239. /* Adjust position to connect icons */
  240. left: 8px;
  241. /* Aligns with step icons */
  242. margin: 0;
  243. }
  244. .tracking-step:first-child::before {
  245. background: none;
  246. /* No line before the first step */
  247. }
  248. /* Step icon styling */
  249. .step-icon {
  250. flex-shrink: 0;
  251. font-size: 1.5em;
  252. margin-right: 15px;
  253. position: absolute;
  254. left: 0;
  255. top: 0;
  256. width: 20px;
  257. height: 20px;
  258. border-radius: 50%;
  259. display: flex;
  260. justify-content: center;
  261. align-items: center;
  262. background: #ccc;
  263. /* Default icon background */
  264. border: 4px solid #ccc;
  265. /* Default border */
  266. color: #eee;
  267. font-size: 14px;
  268. line-height: 20px;
  269. z-index: 1;
  270. font-family: "Ionicons";
  271. /* Icon font */
  272. }
  273. /* Completed step icon and line color */
  274. .tracking-step.completed .step-icon {
  275. background: #56B500;
  276. /* Green for completed */
  277. border-color: #56B500;
  278. color: #fff;
  279. }
  280. .tracking-step.completed::before {
  281. background: #56B500;
  282. /* Green line for completed steps */
  283. }
  284. .tracking-step.completed {
  285. background-color: #e6ffe6;
  286. }
  287. /* Waiting step icon and line color */
  288. .tracking-step.waiting .step-icon {
  289. background: #ffeb3b;
  290. /* Yellow for waiting */
  291. border-color: #ffeb3b;
  292. }
  293. .tracking-step.waiting {
  294. background-color: #fff3cd;
  295. }
  296. /* Initiated step icon and line color */
  297. .tracking-step.initiated .step-icon {
  298. background: #03a9f4;
  299. /* Blue for initiated */
  300. border-color: #03a9f4;
  301. }
  302. .tracking-step.initiated {
  303. background-color: #cce5ff;
  304. }
  305. /* Pending step icon and line color */
  306. .tracking-step.pending .step-icon {
  307. background: #9e9e9e;
  308. /* Grey for pending */
  309. border-color: #9e9e9e;
  310. }
  311. /* Cancelled step icon and line color */
  312. .tracking-step.cancelled .step-icon {
  313. background: #dc3545 !important;
  314. /* Red for cancelled */
  315. border-color: #dc3545 !important;
  316. color: #fff !important;
  317. }
  318. .tracking-step.cancelled::before {
  319. background: #dc3545 !important;
  320. /* Red line for cancelled steps */
  321. }
  322. .tracking-step.cancelled {
  323. background-color: #fdecea;
  324. /* Light red background for cancelled steps */
  325. }
  326. /* Rejected step icon and line color */
  327. .tracking-step.rejected .step-icon {
  328. background: #ff0000;
  329. /* Dark red for rejected */
  330. border-color: #ff0000;
  331. color: #fff;
  332. }
  333. .tracking-step.rejected {
  334. background-color: #ffe6e6;
  335. }
  336. .tracking-step.rejected::before {
  337. background: #ff0000;
  338. /* Dark red line for rejected steps */
  339. }
  340. /* GCC Blocked step icon and line color */
  341. .tracking-step.gcc-blocked .step-icon {
  342. background: #ff6600;
  343. /* Orange for GCC blocked */
  344. border-color: #ff6600;
  345. color: #fff;
  346. }
  347. .tracking-step.gcc-blocked {
  348. background-color: #ffe0cc;
  349. }
  350. .tracking-step.gcc-blocked::before {
  351. background: #ff6600;
  352. /* Orange line for GCC blocked steps */
  353. }
  354. /* Step content styling */
  355. .step-content {
  356. padding: 2px 15px;
  357. background: #fff;
  358. border: 1px solid #ddd;
  359. border-radius: 5px;
  360. width: 100%;
  361. flex-grow: 1;
  362. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  363. }
  364. .step-content h5 {
  365. margin: 0 0 5px;
  366. font-size: 16px;
  367. font-weight: bold;
  368. }
  369. .step-date {
  370. color: #666;
  371. font-size: 14px;
  372. }
  373. /* Icon color customization */
  374. .fas,
  375. .fa-solid {
  376. font-weight: 900;
  377. color: white;
  378. }
  379. #transactionmodel {
  380. max-width: 90%;
  381. /* Make modal wider */
  382. }
  383. .table-responsive {
  384. max-height: 400px;
  385. /* Adjust the table's maximum height */
  386. overflow-y: auto;
  387. /* Enable vertical scrolling if needed */
  388. }
  389. body {
  390. font-family: Arial, sans-serif;
  391. }
  392. .chat-icon {
  393. position: fixed;
  394. bottom: 20px;
  395. right: 20px;
  396. width: 60px;
  397. height: 60px;
  398. background-color: #007bff;
  399. border-radius: 50%;
  400. cursor: pointer;
  401. display: flex;
  402. align-items: center;
  403. justify-content: center;
  404. }
  405. .chat-icon img {
  406. width: 30px;
  407. height: 30px;
  408. }
  409. .chat-notification {
  410. position: absolute;
  411. top: -10px;
  412. right: -10px;
  413. background-color: red;
  414. color: white;
  415. border-radius: 50%;
  416. padding: 5px;
  417. font-size: 12px;
  418. }
  419. .chat-box {
  420. position: fixed;
  421. bottom: 90px;
  422. right: 20px;
  423. width: 300px;
  424. height: 400px;
  425. background-color: white;
  426. border: 1px solid #ccc;
  427. display: none;
  428. flex-direction: column;
  429. box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
  430. }
  431. .chat-header {
  432. background-color: #007bff;
  433. color: white;
  434. padding: 10px;
  435. display: flex;
  436. justify-content: space-between;
  437. align-items: center;
  438. }
  439. .chat-body {
  440. flex-grow: 1;
  441. padding: 10px;
  442. overflow-y: scroll;
  443. border-top: 1px solid #ccc;
  444. border-bottom: 1px solid #ccc;
  445. }
  446. .chat-footer {
  447. display: flex;
  448. padding: 10px;
  449. }
  450. .chat-footer input {
  451. flex-grow: 1;
  452. padding: 5px;
  453. margin-right: 10px;
  454. }
  455. .chat-footer button {
  456. background-color: #007bff;
  457. color: white;
  458. border: none;
  459. padding: 5px 10px;
  460. cursor: pointer;
  461. }
  462. .otp-input-box {
  463. display: flex;
  464. justify-content: center;
  465. gap: 10px;
  466. margin: 20px 0;
  467. }
  468. .otp-input-box .otp-input {
  469. width: 40px;
  470. height: 40px;
  471. text-align: center;
  472. font-size: 16px;
  473. border: 1px solid #ccc;
  474. border-radius: 5px;
  475. }
  476. td.highlight-blue.ui-state-disabled {
  477. opacity: 1 !important;
  478. }
  479. td.highlight-blue.ui-state-disabled .ui-state-default,
  480. td.highlight-blue.ui-state-disabled a,
  481. td.highlight-blue.ui-state-disabled span {
  482. background: blue !important;
  483. color: #fff !important;
  484. cursor: not-allowed !important;
  485. pointer-events: auto !important;
  486. }
  487. td.highlight-violet.ui-state-disabled {
  488. opacity: 1 !important;
  489. }
  490. td.highlight-yellow.ui-state-disabled {
  491. opacity: 1 !important;
  492. }
  493. td.highlight-pink.ui-state-disabled {
  494. opacity: 1 !important;
  495. }
  496. </style>
  497. <body>
  498. <!-- Pre-loader start -->
  499. <div class="theme-loader">
  500. <div class="ball-scale">
  501. <div class='contain'>
  502. <div class="ring">
  503. <div class="frame"></div>
  504. </div>
  505. <div class="ring">
  506. <div class="frame"></div>
  507. </div>
  508. <div class="ring">
  509. <div class="frame"></div>
  510. </div>
  511. <div class="ring">
  512. <div class="frame"></div>
  513. </div>
  514. <div class="ring">
  515. <div class="frame"></div>
  516. </div>
  517. <div class="ring">
  518. <div class="frame"></div>
  519. </div>
  520. <div class="ring">
  521. <div class="frame"></div>
  522. </div>
  523. <div class="ring">
  524. <div class="frame"></div>
  525. </div>
  526. <div class="ring">
  527. <div class="frame"></div>
  528. </div>
  529. <div class="ring">
  530. <div class="frame"></div>
  531. </div>
  532. </div>
  533. </div>
  534. </div>
  535. <!-- Pre-loader end -->
  536. <div id="pcoded" class="pcoded">
  537. <div class="pcoded-container">
  538. <!-- Menu header start -->
  539. <nav th:replace="~{fragments/nav-user :: nav}"></nav>
  540. <!-- Menu header end -->
  541. <div class="pcoded-main-container">
  542. <nav th:replace="~{fragments/nav-usermenu :: nav}"></nav>
  543. <div class="pcoded-wrapper">
  544. <div class="pcoded-content">
  545. <div class="pcoded-inner-content">
  546. <!-- Main-body start -->
  547. <div class="main-body" style="background-color: white">
  548. <div class="page-wrapper" style="padding: 0;">
  549. <!-- Page-header start -->
  550. <div class="page-header m-t-50">
  551. </div>
  552. <div id="futureEventsContainer" class="page-body" style="display: none;"></div>
  553. <div class="card">
  554. <div class="card-header">
  555. <h5>Hall Booking Details</h5>
  556. <button type="button" class="btn btn-primary btn-square-md"
  557. th:if="${userBookingspast.size() > 0}"
  558. th:onclick="'transactionHistory(' + ${userBookingspast[0].users_user_id} + ')'">
  559. Transaction History
  560. </button>
  561. </div>
  562. <div class="card-block">
  563. <div class="table-responsive">
  564. <table
  565. class="table table-bordered table-striped table-vcenter js-dataTable-responsive"
  566. id="detailstable" style="width: 100%">
  567. <thead class="thead-light">
  568. <tr>
  569. <th class="text-center no-sort" width="10%">S.No</th>
  570. <th>Booking Id</th>
  571. <th>Booking date</th>
  572. <th>Hall Name</th>
  573. <th>Starting Date</th>
  574. <th>Ending Date</th>
  575. <th>Starting Period</th>
  576. <th>Ending Period</th>
  577. <th>Reason for booking</th>
  578. <th>Booking Status</th>
  579. <th>Payment Status</th>
  580. <th>Event Status</th>
  581. <th class="text-center no-sort" width="10%">Action</th>
  582. <th>View</th>
  583. </tr>
  584. </thead>
  585. <tbody>
  586. <tr th:each="booking, i : ${userBookingspast}"
  587. class="${userBookingspast}">
  588. <td th:text="${i.count}"></td>
  589. <td th:text="${booking.booking_id}"></td>
  590. <td th:text="${booking.booking_date}"></td>
  591. <td th:text="${booking.hall_name}"></td>
  592. <td th:text="${booking.start_date}"></td>
  593. <td th:text="${booking.end_date}"></td>
  594. <td
  595. th:text="${booking.starting_slot == 1 ? 'morning' : (booking.starting_slot == 2 ? 'evening' : '')}">
  596. </td>
  597. <td
  598. th:text="${booking.ending_slot == 1 ? 'morning' : (booking.ending_slot == 2 ? 'evening' : '')}">
  599. </td>
  600. <td th:text="${booking.reason}"></td>
  601. <td
  602. th:text="${#strings.replace(booking.booking_status, '_', ' ')}">
  603. </td>
  604. <td
  605. th:text="${booking.payment_status != null ? booking.payment_status : 'NA'}">
  606. </td>
  607. <td>
  608. <span th:if="${booking.booking_status == 'APPROVED'}">
  609. <span th:switch="${booking.event_category}">
  610. <span th:case="'Current'">Current Event</span>
  611. <span th:case="'Past'">Completed Event</span>
  612. <span th:case="'Future'">Upcoming Event</span>
  613. <span th:case="'Reschedule'">Upcoming
  614. Event</span>
  615. <span th:case="'noaction'">Govt Event</span>
  616. </span>
  617. </span>
  618. <span th:if="${booking.booking_status == 'COMPLETED'}">
  619. <span>Refund Completed Event</span>
  620. </span>
  621. <span th:if="${booking.booking_status == 'CANCELED'}">
  622. <span>User Canceled Event</span>
  623. </span>
  624. <span th:if="${booking.booking_status == 'REJECTED'}">
  625. <span>GCC Rejected Event</span>
  626. </span>
  627. <span
  628. th:if="${booking.booking_status == 'GCC_BLOCKED'}">
  629. <span>GCC Blocked Event</span>
  630. </span>
  631. <span
  632. th:if="${booking.booking_status == 'WAITING_FOR_NOC'}">
  633. <span>Waiting For NOC Document</span>
  634. </span>
  635. <span
  636. th:if="${booking.booking_status == 'WAITING_FOR_NOC_APPROVAL'}">
  637. <span>Waiting For Admin Approval</span>
  638. </span>
  639. </td>
  640. <td th:switch="${booking.event_category}">
  641. <p th:case="'Future'">
  642. <a class="view-button"
  643. th:if="${booking.booking_status == 'APPROVED'}">
  644. <span class="badge bg-danger"
  645. style="cursor: pointer;"
  646. th:onclick="cancelBooking([[${booking.booking_id}]], [[${booking.mobile_no}]], [[${booking.booking_type}]])">Cancel
  647. Booking</span>
  648. </a>
  649. </p>
  650. <p th:case="'waitingfornoc'">
  651. <a class="view-button"
  652. th:if="${booking.booking_status == 'WAITING_FOR_NOC'}">
  653. <span class="badge bg-danger"
  654. style="cursor: pointer;"
  655. data-bs-toggle="modal"
  656. data-bs-target="#uploadNocModal"
  657. th:attr="data-booking-id=${booking.booking_id}">Upload
  658. NOC</span>
  659. </a>
  660. <a class="view-button"
  661. th:if="${booking.booking_status == 'WAITING_FOR_NOC'}">
  662. <span class="badge bg-danger"
  663. style="cursor: pointer;"
  664. th:onclick="cancelBooking([[${booking.booking_id}]], [[${booking.mobile_no}]], [[${booking.booking_type}]])">Cancel
  665. Booking</span>
  666. </a>
  667. <a class="reschedule-button"
  668. th:if="${booking.booking_status == 'WAITING_FOR_NOC' and booking.schedule_count < 1}">
  669. <span class="badge bg-danger"
  670. style="cursor: pointer;"
  671. th:onclick="openRescheduleModal([[${booking.booking_id}]], [[${booking.start_date}]], [[${booking.end_date}]],[[${booking.no_of_days}]],
  672. [[${booking.hall_details_hall_id}]],[[${booking.starting_slot}]],[[${booking.ending_slot}]],[[${booking.reason}]])">Reschedule
  673. Booking</span>
  674. </a>
  675. </p>
  676. <p th:case="'waitingfornocapproval'">
  677. <a class="view-button"
  678. th:if="${booking.booking_status == 'WAITING_FOR_NOC_APPROVAL'}">
  679. <span class="badge bg-danger"
  680. style="cursor: pointer;"
  681. th:onclick="cancelBooking([[${booking.booking_id}]], [[${booking.mobile_no}]], [[${booking.booking_type}]])">Cancel
  682. Booking</span>
  683. </a>
  684. <a class="reschedule-button"
  685. th:if="${booking.booking_status == 'WAITING_FOR_NOC_APPROVAL' and booking.schedule_count < 1}">
  686. <span class="badge bg-danger"
  687. style="cursor: pointer;"
  688. th:onclick="openRescheduleModal([[${booking.booking_id}]], [[${booking.start_date}]], [[${booking.end_date}]],[[${booking.no_of_days}]],
  689. [[${booking.hall_details_hall_id}]],[[${booking.starting_slot}]],[[${booking.ending_slot}]],[[${booking.reason}]])">Reschedule
  690. Booking</span>
  691. </a>
  692. </p>
  693. <!--<p th:case="'noaction'">
  694. <a class="view-button">
  695. <span>&#45;&#45;No Action&#45;&#45;</span>
  696. </a>
  697. </p>-->
  698. <p th:case="'noaction'">
  699. <a class="view-button">
  700. <a class="view-button"
  701. th:if="${booking.booking_status == 'APPROVED'}">
  702. <span class="badge bg-danger"
  703. style="cursor: pointer;"
  704. th:onclick="cancelBooking([[${booking.booking_id}]], [[${booking.mobile_no}]], [[${booking.booking_type}]])">Cancel
  705. Booking</span>
  706. </a>
  707. </a>
  708. </p>
  709. <p th:case="'noaction'">
  710. <a class="view-button">
  711. <span>--No Action--</span>
  712. </a>
  713. </p>
  714. <p th:case="'Reschedule'">
  715. <a class="view-button"
  716. th:if="${booking.booking_status == 'APPROVED'}">
  717. <span class="badge bg-danger"
  718. style="cursor: pointer;"
  719. th:onclick="cancelBooking([[${booking.booking_id}]], [[${booking.mobile_no}]], [[${booking.booking_type}]])">Cancel
  720. Booking</span>
  721. </a>
  722. <!-- <a class="reschedule-button" th:if="${booking.booking_status == 'APPROVED' and booking.reason != 'Commercial'}"> -->
  723. <a class="reschedule-button"
  724. th:if="${booking.booking_status == 'APPROVED'
  725. and !#lists.contains({'Commercial', 'State Govt Event', 'Central Govt Event'}, booking.reason)}">
  726. <span class="badge bg-danger"
  727. style="cursor: pointer;"
  728. th:onclick="openRescheduleModal([[${booking.booking_id}]], [[${booking.start_date}]], [[${booking.end_date}]],[[${booking.no_of_days}]],
  729. [[${booking.hall_details_hall_id}]],[[${booking.starting_slot}]],[[${booking.ending_slot}]],[[${booking.reason}]])">Reschedule
  730. Booking</span>
  731. </a>
  732. <a class="reschedule-button"
  733. th:if="${booking.booking_status == 'WAITING_FOR_NOC'}">
  734. <span class="badge bg-danger"
  735. style="cursor: pointer;"
  736. th:onclick="openRescheduleModal([[${booking.booking_id}]], [[${booking.start_date}]], [[${booking.end_date}]],[[${booking.no_of_days}]],
  737. [[${booking.hall_details_hall_id}]],[[${booking.starting_slot}]],[[${booking.ending_slot}]],[[${booking.reason}]])">Reschedule
  738. Booking</span>
  739. </a>
  740. </p>
  741. </td>
  742. <td>
  743. <a class="view-button">
  744. <!-- <span class="badge bg-primary"
  745. style="cursor: pointer;"
  746. th:onclick="showBookingDetails([[${booking.booking_id}]])">View</span>-->
  747. <span class="badge bg-primary"
  748. style="cursor: pointer;"
  749. th:onclick="showBookingDetails([[${booking.booking_id}]], [[${bookingRefIds[booking.booking_id]}]])">
  750. View
  751. </span>
  752. </a>
  753. <!--<a class="view-button">
  754. <span class="badge bg-primary"
  755. style="cursor: pointer;"
  756. th:onclick="trackBooking([[${booking.booking_id}]])">Track</span>
  757. </a>-->
  758. </td>
  759. </tr>
  760. </tbody>
  761. </table>
  762. </div>
  763. </div>
  764. </div>
  765. <input type="hidden" id="serverDate" th:value=${serverDate}>
  766. <div class="modal fade backdrop" id="showBookingDetails" data-backdrop="static"
  767. tabindex="-1" role="dialog" aria-labelledby="staticBackdropLabel"
  768. aria-hidden="true">
  769. <div class="modal-dialog modal-lg" role="document">
  770. <div class="modal-content" id="printableContent">
  771. <form id="regform" onsubmit="return rejectsubmit();">
  772. <!--ak-->
  773. <!-- Add these -->
  774. <input type="hidden" id="modalBookingId">
  775. <input type="hidden" id="modalRefId">
  776. <div
  777. class="block block-rounded block-themed block-transparent mb-0">
  778. <div class="block-header bg-primary-dark">
  779. <h3 class="block-title" id="2mtitle">Booking
  780. Information</h3>
  781. <div class="block-options">
  782. <button type="button" class="btn-block-option"
  783. data-bs-dismiss="modal" aria-label="Close">
  784. <i class="fa fa-fw fa-times"></i>
  785. </button>
  786. </div>
  787. </div>
  788. <div class="block-content row"
  789. style="margin-right:0px;margin:0;padding:0;">
  790. <div class="col-md-12 col-lg-12 col-sm-12">
  791. <div class="card-body">
  792. <table>
  793. <tr>
  794. <th colspan="10"
  795. style="background-color: lightgrey;">
  796. User Details
  797. </th>
  798. </tr>
  799. <tr>
  800. <th
  801. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  802. User Name:
  803. </th>
  804. <td class="fw-semibold"
  805. style="padding: 0.45rem 0.45rem;"
  806. id="td_userName"></td>
  807. <th
  808. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  809. Mobile Number:
  810. </th>
  811. <td class="fw-semibold"
  812. style="padding: 0.45rem 0.45rem;"
  813. id="td_mobileNumber"></td>
  814. <th
  815. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  816. User Type:
  817. </th>
  818. <td class="fw-semibold"
  819. style="padding: 0.45rem 0.45rem;"
  820. id="td_usertype"></td>
  821. </tr>
  822. <tr>
  823. <th
  824. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  825. User Address:
  826. </th>
  827. <td colspan="5" class="fw-semibold"
  828. style="padding: 0.45rem 0.45rem;text-wrap: pretty;"
  829. id="td_useraddress"></td>
  830. </tr>
  831. <input type="hidden"
  832. class="form-control text-center"
  833. name="bookingid" id="bookingid" disabled />
  834. <tr>
  835. <th colspan="10"
  836. style="background-color: lightgrey;">
  837. Hall Details
  838. </th>
  839. </tr>
  840. <tr>
  841. <th
  842. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  843. Hall Name:
  844. </th>
  845. <td colspan="10" class="fw-semibold"
  846. style="padding: 0.45rem 0.45rem;text-wrap:pretty;"
  847. id="td_hallName"></td>
  848. </tr>
  849. <th
  850. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  851. Hall Address:
  852. </th>
  853. <td colspan="10" class="fw-semibold"
  854. style="padding: 0.45rem 0.45rem;text-wrap: pretty;"
  855. id="td_halladdress"></td>
  856. </tr>
  857. <tr>
  858. <th
  859. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  860. Caretaker Name:
  861. </th>
  862. <td colspan="2" class="fw-semibold"
  863. style="padding: 0.45rem 0.45rem;"
  864. id="td_caretakername"></td>
  865. <th
  866. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  867. Caretaker Mobile Number:
  868. </th>
  869. <td colspan="2" class="fw-semibold"
  870. style="padding: 0.45rem 0.45rem;"
  871. id="td_caretakermobileNumber"></td>
  872. </tr>
  873. <tr>
  874. <th colspan="10"
  875. style="background-color: lightgrey;">
  876. Booking
  877. Details (Booking Id:-<span
  878. id="booking_id"
  879. style="color:blue"></span>)
  880. </th>
  881. </tr>
  882. <tr>
  883. <th
  884. style="padding: 0.45rem 0.45rem;font-weight: normal">
  885. Booking Date:
  886. </th>
  887. <td colspan="2" class="fw-semibold"
  888. style="padding: 0.45rem 0.45rem;"
  889. id="td_bookingDate"></td>
  890. <th
  891. style="padding: 0.45rem 0.45rem;font-weight: normal">
  892. Deposit Amount (in Rs):
  893. </th>
  894. <td colspan="2"
  895. class="fw-semibold amount-cell"
  896. style="padding: 0.45rem 0.45rem;"
  897. id="td_depositeAmount"></td>
  898. </tr>
  899. <tr>
  900. <th
  901. style="padding: 0.45rem 0.45rem;font-weight: normal">
  902. Start Date:
  903. </th>
  904. <td colspan="2" class="fw-semibold"
  905. style="padding: 0.45rem 0.45rem;"
  906. id="td_startDate"></td>
  907. <th
  908. style="padding: 0.45rem 0.45rem;font-weight: normal">
  909. Hall Amount (in Rs):
  910. </th>
  911. <td colspan="2"
  912. class="fw-semibold amount-cell"
  913. style="padding: 0.45rem 0.45rem;"
  914. id="td_hallAmount"></td>
  915. </tr>
  916. <tr>
  917. <th
  918. style="padding: 0.45rem 0.45rem;font-weight: normal">
  919. END Date:
  920. </th>
  921. <td colspan="2" class="fw-semibold"
  922. style="padding: 0.45rem 0.45rem;"
  923. id="td_endDate"></td>
  924. <th
  925. style="padding: 0.45rem 0.45rem;font-weight: normal">
  926. GST @18% (in Rs):
  927. </th>
  928. <td colspan="2"
  929. class="fw-semibold amount-cell"
  930. style="padding: 0.45rem 0.45rem;"
  931. id="td_gst"></td>
  932. </tr>
  933. <tr>
  934. <th
  935. style="padding: 0.45rem 0.45rem;font-weight: normal">
  936. Starting Slot:
  937. </th>
  938. <td colspan="2" class="fw-semibold"
  939. style="padding: 0.45rem 0.45rem;"
  940. id="td_startingSlot"></td>
  941. <th
  942. style="padding: 0.45rem 0.45rem;font-weight: normal">
  943. Total Amount (in Rs):
  944. </th>
  945. <td colspan="2"
  946. class="fw-semibold amount-cell"
  947. style="padding: 0.45rem 0.45rem;"
  948. id="td_totalAmount"></td>
  949. </tr>
  950. <tr>
  951. <th
  952. style="padding: 0.45rem 0.45rem;font-weight: normal">
  953. Ending Slot:
  954. </th>
  955. <td colspan="2" class="fw-semibold"
  956. style="padding: 0.45rem 0.45rem;"
  957. id="td_endingSlot"></td>
  958. <!--<th style="display:none;padding: 0.45rem 0.45rem;border:none"
  959. id="rejectionreasondiv">Rejection
  960. Reason:</th>
  961. <td class="fw-semibold"
  962. style="padding: 0.45rem 0.45rem;"
  963. id="reasonforrejection"></td>-->
  964. <th
  965. style="padding: 0.45rem 0.45rem;border:none">
  966. Booking Status:
  967. </th>
  968. <td colspan="2" class="fw-semibold"
  969. style="padding: 0.45rem 0.45rem;text-wrap: pretty;"
  970. id="bookingstatus_td"></td>
  971. </tr>
  972. <tr>
  973. <th style="display:none;padding: 0.45rem 0.45rem;border:none"
  974. id="rejectionreasondiv">Rejection
  975. Reason:
  976. </th>
  977. <td class="fw-semibold"
  978. style="padding: 0.45rem 0.45rem;text-wrap: pretty;"
  979. id="reasonforrejection"></td>
  980. </tr>
  981. </table>
  982. </div>
  983. </div>
  984. <div class="row col-md-12 col-lg-12 col-sm-12"
  985. style="margin-left:6px;margin-top:-21px">
  986. <div class="documents" id="documents"></div>
  987. </div>
  988. <div class="col-md-12 col-lg-12 col-sm-12 mb-2"
  989. id="paymentsdetails"
  990. style="display:none; margin-top: -26px;">
  991. <div class="card-body">
  992. <table>
  993. <tr>
  994. <th colspan="10"
  995. style="background-color: lightgrey;">
  996. Booking Payment Details
  997. </th>
  998. </tr>
  999. <tr>
  1000. <th
  1001. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  1002. Transaction ID:
  1003. </th>
  1004. <td colspan="10" class="fw-semibold"
  1005. style="padding: 0.45rem 0.45rem;"
  1006. id="td_transactionId"></td>
  1007. </tr>
  1008. <th
  1009. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  1010. Amount Received (in Rs):
  1011. </th>
  1012. <td colspan="10" class="fw-semibold"
  1013. style="padding: 0.45rem 0.45rem;"
  1014. id="td_payamountReceived"></td>
  1015. </tr>
  1016. <tr>
  1017. <th
  1018. style="padding: 0.45rem 0.45rem;font-weight: normal;">
  1019. Transaction Status:
  1020. </th>
  1021. <td class="fw-semibold"
  1022. style="padding: 0.45rem 0.45rem;"
  1023. id="td_paymentStatus"></td>
  1024. </tr>
  1025. </table>
  1026. </div>
  1027. </div>
  1028. <div class="row col-md-12 col-lg-12 col-sm-12"
  1029. id="ebdetails"
  1030. style="display:none;margin-left: 0px;margin-top: -49px">
  1031. <div class="card-body">
  1032. <table>
  1033. <tr>
  1034. <th colspan="4"
  1035. style="background-color: lightgrey;">EB
  1036. Details
  1037. </th>
  1038. </tr>
  1039. <tr>
  1040. <th
  1041. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1042. Consumer Number:
  1043. </th>
  1044. <td class="fw-semibold"
  1045. style="padding: 0.45rem 0.45rem;"
  1046. id="td_EBNumber"></td>
  1047. <th
  1048. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1049. EB Amount Per Unit (in Rs):
  1050. </th>
  1051. <td class="fw-semibold"
  1052. style="padding: 0.45rem 0.45rem;"
  1053. id="td_ebamountperunit"></td>
  1054. </tr>
  1055. <tr>
  1056. <th
  1057. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1058. Start Reading:
  1059. </th>
  1060. <td class="fw-semibold"
  1061. style="padding: 0.45rem 0.45rem;"
  1062. id="td_startingReading"></td>
  1063. <th
  1064. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1065. Unit Consumed:
  1066. </th>
  1067. <td class="fw-semibold"
  1068. style="padding: 0.45rem 0.45rem;"
  1069. id="td_usedunit"></td>
  1070. </tr>
  1071. <tr>
  1072. <th
  1073. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1074. END Reading:
  1075. </th>
  1076. <td class="fw-semibold"
  1077. style="padding: 0.45rem 0.45rem;"
  1078. id="td_endingReading"></td>
  1079. <th
  1080. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1081. EB Amount (in Rs):
  1082. </th>
  1083. <td class="fw-semibold"
  1084. style="padding: 0.45rem 0.45rem;"
  1085. id="td_electricityamount"></td>
  1086. </tr>
  1087. </tbody>
  1088. </table>
  1089. </div>
  1090. </div>
  1091. <div class="row col-md-12 col-lg-12 col-sm-12"
  1092. id="damagelist" style="disaply:none">
  1093. <div id="damageDetails"></div>
  1094. </div>
  1095. <div class="col-md-12 col-lg-12 col-sm-12"
  1096. id="refunddetails" style="margin-top:-41px">
  1097. <div class="card-body">
  1098. <table>
  1099. <tr>
  1100. <th colspan="2"
  1101. style="background-color: lightgrey;">
  1102. Amount to be Refunded (in Rs)
  1103. </th>
  1104. </tr>
  1105. <tr>
  1106. <th
  1107. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1108. Deposit Amount:
  1109. </th>
  1110. <td class="fw-semibold amount-cell"
  1111. style="padding: 0.45rem 0.45rem;"
  1112. id="td_depositeamountforrefund">0
  1113. </td>
  1114. </tr>
  1115. <tr>
  1116. <th
  1117. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1118. EB Amount:
  1119. </th>
  1120. <td class="fw-semibold amount-cell"
  1121. style="padding: 0.45rem 0.45rem;"
  1122. id="td_ebAmount"></td>
  1123. </tr>
  1124. <tr>
  1125. <th
  1126. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1127. Damage Amount:
  1128. </th>
  1129. <td class="fw-semibold amount-cell"
  1130. style="padding: 0.45rem 0.45rem;"
  1131. id="td_damage"></td>
  1132. </tr>
  1133. <tr id="pendingcolumn">
  1134. <th id="th_settel_label"
  1135. style="padding: 0.45rem 0.45rem; background-color: #f2f2f2;font-weight: normal">
  1136. Collection Pending Amount:
  1137. </th>
  1138. <td class="fw-semibold amount-cell"
  1139. style="padding: 0.45rem 0.45rem; color: green;"
  1140. id="td_pending_amt">0
  1141. </td>
  1142. </tr>
  1143. <tr id="collectionstatuscolumn">
  1144. <th id="label"
  1145. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1146. Collection Pending Status
  1147. :
  1148. </th>
  1149. <td class="fw-semibold amount-cell"
  1150. style="padding: 0.45rem 0.45rem; color: green;"
  1151. id="td_collection_status">
  1152. </td>
  1153. </tr>
  1154. <tr>
  1155. <th
  1156. style="padding: 0.45rem 0.45rem; background-color: #f2f2f2;font-weight: normal">
  1157. Actual refundable Amount:
  1158. </th>
  1159. <td class="fw-semibold amount-cell"
  1160. style="padding: 0.45rem 0.45rem; color: green;"
  1161. id="td_settel_amt">0
  1162. </td>
  1163. </tr>
  1164. </table>
  1165. </div>
  1166. </div>
  1167. <div class="row col-md-12 col-lg-12 col-sm-12"
  1168. id="refundamountDetails"
  1169. style="display:none;margin-left: 0px;margin-top: -49px">
  1170. <div class="card-body">
  1171. <table>
  1172. <tr>
  1173. <th colspan="4"
  1174. style="background-color: lightgrey;">
  1175. Refund Details
  1176. </th>
  1177. </tr>
  1178. <tr>
  1179. <th
  1180. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1181. Booking Status:
  1182. </th>
  1183. <td class="fw-semibold"
  1184. style="padding: 0.45rem 0.45rem;"
  1185. id="td_bookingStatus"></td>
  1186. <th
  1187. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1188. Refund Status:
  1189. </th>
  1190. <td class="fw-semibold"
  1191. style="padding: 0.45rem 0.45rem;"
  1192. id="td_refundStatus"></td>
  1193. </tr>
  1194. <tr>
  1195. <th
  1196. style="padding: 0.45rem 0.45rem;font-weight: normal;text-wrap: pretty;">
  1197. Refund amount:
  1198. </th>
  1199. <td class="fw-semibold" colspan="5"
  1200. style="padding: 0.45rem 0.45rem;"
  1201. id="td_refundamount"></td>
  1202. </tr>
  1203. </tbody>
  1204. </table>
  1205. </div>
  1206. </div>
  1207. <div id="refundMessage" style="display: none;">
  1208. <h1 id="refundText"
  1209. style="font-size: 17px;margin-left: 20px;color: darkgreen;">
  1210. </h1>
  1211. </div>
  1212. <div id="rejectrefundMessage" style="display: none;">
  1213. <h1 id="rejectrefundText"
  1214. style="font-size: 17px;margin-left: 20px;color: darkgreen;">
  1215. </h1>
  1216. </div>
  1217. <div id="blockedrefundMessage" style="display: none;">
  1218. <h1 id="blockedrefundText"
  1219. style="font-size: 17px;margin-left: 20px;color: darkgreen;">
  1220. </h1>
  1221. </div>
  1222. <!--Newly added for Reschedule Details-->
  1223. <!--<div class="row col-md-12 col-lg-12 col-sm-12"
  1224. id="rescheduleDetails"
  1225. style="display:none;margin-left: 0px;margin-top: -49px">
  1226. <div class="card-body">
  1227. <table>
  1228. <tr>
  1229. <th colspan="4"
  1230. style="background-color: lightgrey;">
  1231. Reschedule Details
  1232. </th>
  1233. </tr>
  1234. <tr>
  1235. <th
  1236. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1237. Event Start Date:
  1238. </th>
  1239. <td class="fw-semibold"
  1240. style="padding: 0.45rem 0.45rem;"
  1241. id="td_res_start_date"></td>
  1242. <th
  1243. style="padding: 0.45rem 0.45rem;font-weight: normal">
  1244. Event End Date:
  1245. </th>
  1246. <td class="fw-semibold"
  1247. style="padding: 0.45rem 0.45rem;"
  1248. id="td_res_end_date"></td>
  1249. </tr>
  1250. <tr>
  1251. <th
  1252. style="padding: 0.45rem 0.45rem;font-weight: normal;text-wrap: pretty;">
  1253. Rescheduled Date:</th>
  1254. <td class="fw-semibold" colspan="5"
  1255. style="padding: 0.45rem 0.45rem;"
  1256. id="td_res_date"></td>
  1257. </tr>
  1258. </tbody>
  1259. </table>
  1260. </div>
  1261. </div>-->
  1262. </div>
  1263. </div>
  1264. <div class="block-content block-content-full text-end bg-body"
  1265. id="mbutton">
  1266. <button class="btn btn-success"
  1267. onclick="downloadAcknowledgment(event)"
  1268. style="background: #FB6340;">View
  1269. Acknowledgement
  1270. </button>
  1271. <button type="button"
  1272. style="background-color: rgb(21,69,93);color: white;"
  1273. class="btn btn-sm btn-alt-secondary"
  1274. data-bs-dismiss="modal">Close
  1275. </button>
  1276. </div>
  1277. </form>
  1278. </div>
  1279. </div>
  1280. </div>
  1281. </div>
  1282. <br>
  1283. </div>
  1284. </div>
  1285. <div class="modal fade" id="fileModal" tabindex="-1" role="dialog"
  1286. aria-labelledby="fileModalLabel" aria-hidden="true">
  1287. <div class="modal-dialog modal-lg" role="document">
  1288. <div class="modal-content">
  1289. <div class="modal-header">
  1290. <h5 class="modal-title" id="fileModalLabel">File Preview</h5>
  1291. <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close"
  1292. style="border: 1px solid black; padding: 5px;
  1293. display: inline-flex; align-items: center; justify-content: center;
  1294. background-color: transparent; color: black; font-size: 20px;">
  1295. <span aria-hidden="true">&times;</span>
  1296. </button>
  1297. </div>
  1298. <div class="modal-body">
  1299. <embed id="filePreview" src="" width="100%" height="600px">
  1300. </div>
  1301. <div class="modal-footer">
  1302. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close
  1303. </button>
  1304. </div>
  1305. </div>
  1306. </div>
  1307. </div>
  1308. </div>
  1309. <!-- Reschedule Booking Modal -->
  1310. <div class="modal fade" id="bookingRescheduleModal" tabindex="-1"
  1311. aria-labelledby="bookingModalLabel" aria-hidden="true">
  1312. <div class="modal-dialog modal-dialog-centered modal-lg">
  1313. <div class="modal-content">
  1314. <!-- Modal Header -->
  1315. <div class="modal-header" style="color:black">
  1316. <h5 class="modal-title" id="bookingModalLabel" style="color:black">Booking
  1317. Reschedule</h5>
  1318. <br>
  1319. <br>
  1320. <div style="margin-bottom: -59px; margin-left: -185px;">
  1321. <!-- Adding margin-top for separation -->
  1322. <p style="font-size: 14px; color: #6c757d;"> the Start Date & Slot can be
  1323. changed.</p>
  1324. </div>
  1325. <button type="button" class="btn-close" data-bs-dismiss="modal"
  1326. aria-label="Close"></button>
  1327. </div>
  1328. <!-- Modal Body -->
  1329. <div class="modal-body">
  1330. <div class="container-fluid">
  1331. <div class="row">
  1332. <!-- Datepicker and Availability Buttons Column -->
  1333. <div id="datepicker-container" class="fixedcontainer"></div>
  1334. <!-- Start Date, End Date, Number of Days Inputs Column -->
  1335. <div class="col">
  1336. <input type="hidden" class="form-control" id="bookingId"
  1337. name="bookingId" required>
  1338. <label for="startDateInput" class="form-label">Start Date:</label>
  1339. <input type="text" class="form-control" id="startDateInput"
  1340. name="startDateInput" required readonly>
  1341. <input type="hidden" class="form-control" id="startDatetext"
  1342. name="startDatetext" required>
  1343. </div>
  1344. <div class="col">
  1345. <label for="endDateInput" class="form-label">End Date:</label>
  1346. <input type="date" class="form-control" id="endDateInput"
  1347. name="endDateInput" readonly>
  1348. </div>
  1349. <div class="col">
  1350. <label for="noOfDaysInput" class="form-label">Number of Days:</label>
  1351. <input type="number" class="form-control" id="noOfDaysInput"
  1352. name="noOfDaysInput" readonly>
  1353. </div>
  1354. </div>
  1355. <div class="row">
  1356. <div class="col">
  1357. <input type="hidden" id="daysDiff">
  1358. <label for="startingSlot" class="form-label">Starting Slot:</label>
  1359. <select class="form-control" id="startingSlot" name="startingSlot">
  1360. <option value="1">Morning (6:00 AM)</option>
  1361. <option value="2">Afternoon (2:00 PM)</option>
  1362. </select>
  1363. </div>
  1364. <div class="col">
  1365. <label for="endingSlot" class="form-label">Ending Slot:</label>
  1366. <select class="form-control" id="endingSlot" name="endingSlot" disabled>
  1367. <option value="1">Afternoon (2:00 PM)</option>
  1368. <option value="2">Evening (10:00 PM)</option>
  1369. </select>
  1370. <!-- mirrors endingSlot for form submission since disabled fields are excluded -->
  1371. <input type="hidden" id="endingSlotHidden" name="endingSlot">
  1372. </div>
  1373. </div>
  1374. <div class="row" style="margin-top: 39px;">
  1375. <div class="col col-lg-2 col-sm-2 col-md-2">
  1376. <button type="button" class="btn btn-primary btn-square-md"
  1377. style="background-color:#008000;"></button>
  1378. <p style="margin-left: 14px;">Day<br>(Available)</p>
  1379. </div>
  1380. <div class="col col-lg-2 col-sm-2 col-md-2">
  1381. <button type="button" class="btn btn-primary btn-square-md"
  1382. style="background-color: #ac2bac;"></button>
  1383. <p style="margin-left: 14px;">Morning<br>(Available)</p>
  1384. </div>
  1385. <div class="col col-lg-2 col-sm-2 col-md-2">
  1386. <button type="button" class="btn btn-primary btn-square-md"
  1387. style="background-color:#FFEA00;"></button>
  1388. <p style="margin-left: 14px;">Evening<br>(Available)</p>
  1389. </div>
  1390. <div class="col col-lg-2 col-sm-2 col-md-2">
  1391. <button type="button" class="btn btn-primary btn-square-md"
  1392. style="background-color: red;"></button>
  1393. <p style="margin-left: 14px;">Not Available</p>
  1394. </div>
  1395. <div class="col col-lg-2 col-sm-2 col-md-2">
  1396. <button type="button" class="btn btn-primary btn-square-md"
  1397. style="background-color: blue;"></button>
  1398. <p style="margin-left: 14px;">GCC Blocked</p>
  1399. </div>
  1400. <!--<div class="col col-lg-2 col-sm-2 col-md-2">
  1401. <button type="button" class="btn btn-primary btn-square-md"
  1402. style="background-color: lightpink;"></button>
  1403. <p style="margin-left: 14px;">Temporary Blocked</p>
  1404. </div>-->
  1405. </div>
  1406. </div>
  1407. </div>
  1408. <!-- Modal Footer -->
  1409. <div class="modal-footer">
  1410. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close
  1411. </button>
  1412. <button type="button" class="btn btn-primary" onclick="Reschedule()">Save
  1413. Changes
  1414. </button>
  1415. </div>
  1416. </div>
  1417. </div>
  1418. </div>
  1419. <!-- Reschedule OTP Verification Modal -->
  1420. <div class="modal fade" id="rescheduleOtpModal" tabindex="-1" role="dialog"
  1421. aria-labelledby="rescheduleOtpModalLabel" aria-hidden="true">
  1422. <div class="modal-dialog" role="document">
  1423. <div class="modal-content">
  1424. <div class="modal-header">
  1425. <h6 class="modal-title m-0" id="rescheduleOtpModalLabel">Reschedule Verification
  1426. </h6>
  1427. <button type="button" class="btn-close" data-bs-dismiss="modal"
  1428. aria-label="Close"></button>
  1429. </div>
  1430. <div class="modal-body">
  1431. <div class="row">
  1432. <div class="mb-3 text-center">
  1433. <img src="media/images/mobileotp.png" width="50%" alt="Mobileotp">
  1434. </div>
  1435. <div class="mb-0 text-center">
  1436. <h4>OTP Verification</h4>
  1437. <p class="text-mute">Enter the OTP sent to <b class="text-info"
  1438. id="rescheduleMobileTxt"></b></p>
  1439. <p class="text-danger" id="rescheduleOtpError"></p>
  1440. </div>
  1441. <div class="mb-3 text-center">
  1442. <div class="otp-input-box">
  1443. <input type="text" maxlength="1" class="otp-input" id="rescheduleOtp1"
  1444. required />
  1445. <input type="text" maxlength="1" class="otp-input" id="rescheduleOtp2"
  1446. required />
  1447. <input type="text" maxlength="1" class="otp-input" id="rescheduleOtp3"
  1448. required />
  1449. <input type="text" maxlength="1" class="otp-input" id="rescheduleOtp4"
  1450. required />
  1451. <input type="text" maxlength="1" class="otp-input" id="rescheduleOtp5"
  1452. required />
  1453. </div>
  1454. </div>
  1455. <div class="mb-3 text-center">
  1456. <div id="rescheduleResendContainer">
  1457. <p class="mb-0">Didn't receive OTP?</p>
  1458. <!-- <p class="mb-0 text-info" id="rescheduleResendLink">Please wait..<span
  1459. id="rescheduleCountdown">60</span>s</p> -->
  1460. <p class="mb-0 text-info">
  1461. <span id="rescheduleResendText">Please wait..</span>
  1462. <span id="rescheduleCountdown">60</span>s
  1463. </p>
  1464. </div>
  1465. </div>
  1466. </div>
  1467. </div>
  1468. <div class="modal-footer">
  1469. <button type="button" class="btn btn-secondary btn-sm"
  1470. data-bs-dismiss="modal">Close</button>
  1471. <button type="button" class="btn btn-primary btn-sm"
  1472. onclick="verifyRescheduleOtp()">Verify OTP</button>
  1473. </div>
  1474. </div>
  1475. </div>
  1476. </div>
  1477. <!-- Tracking Log Modal -->
  1478. <!-- Tracking Modal -->
  1479. <div class="modal fade" id="trackingModal" tabindex="-1" aria-labelledby="trackingModalLabel"
  1480. aria-hidden="true">
  1481. <div class="modal-dialog modal-lg">
  1482. <div class="modal-content">
  1483. <div class="modal-header">
  1484. <h4 class="modal-title">Booking Tracking</h4>
  1485. <button type="button" class="btn-close" data-bs-dismiss="modal"
  1486. aria-label="Close"></button>
  1487. </div>
  1488. <div class="modal-body">
  1489. <div class="tracking-container">
  1490. <ul id="trackingList" class="tracking-steps list-unstyled">
  1491. <!-- Steps will be dynamically appended here -->
  1492. </ul>
  1493. </div>
  1494. </div>
  1495. </div>
  1496. </div>
  1497. </div>
  1498. <!-- Modal -->
  1499. <div class="modal fade" id="uploadNocModal" tabindex="-1" aria-labelledby="uploadNocModalLabel"
  1500. aria-hidden="true">
  1501. <div class="modal-dialog">
  1502. <div class="modal-content">
  1503. <div class="modal-header">
  1504. <h5 class="modal-title" id="uploadNocModalLabel">Upload NOC</h5>
  1505. <button type="button" class="btn-close" data-bs-dismiss="modal"
  1506. aria-label="Close"></button>
  1507. </div>
  1508. <div class="modal-body">
  1509. <div class="mb-3">
  1510. <label for="nocFile" class="form-label">Select NOC File</label>
  1511. <input type="file" class="form-control nocfile" id="nocFile" name="nocFile"
  1512. required>
  1513. <input type="hidden" id="bookingssId" name="bookingssId">
  1514. </div>
  1515. </div>
  1516. <div class="modal-footer">
  1517. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close
  1518. </button>
  1519. <button type="button" class="btn btn-primary" id="submitNocButton">Submit</button>
  1520. </div>
  1521. </div>
  1522. </div>
  1523. </div>
  1524. <!-- Modal -->
  1525. <div class="modal fade" id="transactionHistoryModal" tabindex="-1"
  1526. aria-labelledby="transactionHistoryModalLabel" aria-hidden="true">
  1527. <div class="modal-dialog modal-lg" id="transactionmodel"> <!-- modal-lg makes it larger -->
  1528. <div class="modal-content">
  1529. <div class="modal-header">
  1530. <h5 class="modal-title" id="transactionHistoryModalLabel">Transaction History</h5>
  1531. <button type="button" class="btn-close" data-bs-dismiss="modal"
  1532. aria-label="Close"></button>
  1533. </div>
  1534. <div class="modal-body">
  1535. <!-- Scrollable Table -->
  1536. <div class="table-responsive"> <!-- Make the table scrollable if too large -->
  1537. <table class="table table-bordered" id="transactionTable">
  1538. <thead>
  1539. <tr>
  1540. <th>S.NO</th>
  1541. <th>Booking ID</th>
  1542. <th>Amount</th>
  1543. <th>Date</th>
  1544. <th>Transaction ID</th>
  1545. <th>Status</th>
  1546. </tr>
  1547. </thead>
  1548. <tbody>
  1549. <!-- Data will be populated dynamically here -->
  1550. </tbody>
  1551. </table>
  1552. </div>
  1553. <div class="table-responsive" id="refunddetails" style="display: none;">
  1554. <h2>Refund Details</h2>
  1555. <table class="table table-bordered" id="refunddetailsTable">
  1556. <thead>
  1557. <tr>
  1558. <th>S.NO</th>
  1559. <th>Booking ID</th>
  1560. <th>Amount</th>
  1561. <th>Date</th>
  1562. <th>Transaction ID</th>
  1563. <th>Refund Amount</th>
  1564. </tr>
  1565. </thead>
  1566. <tbody>
  1567. <!-- Data will be populated dynamically here -->
  1568. </tbody>
  1569. </table>
  1570. </div>
  1571. </div>
  1572. <div class="modal-footer">
  1573. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close
  1574. </button>
  1575. </div>
  1576. </div>
  1577. </div>
  1578. </div>
  1579. <footer th:replace="~{fragments/footer :: footer}"></footer>
  1580. </div>
  1581. </div>
  1582. </div>
  1583. <!--otp form-->
  1584. <div th:replace="~{fragments/loginreg :: div}"></div>
  1585. <!--otp form-->
  1586. <script src="js/html2pdf.bundle.min.js"></script>
  1587. <script th:replace="~{fragments/script :: script}"></script>
  1588. <script th:replace="~{fragments/logRegiOtpScript :: script}"></script>
  1589. <script type="text/javascript" src="https://www.paynimo.com/paynimocheckout/server/lib/checkout.js"></script>
  1590. <script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
  1591. <script src="https://cdn.datatables.net/buttons/2.4.1/js/dataTables.buttons.min.js"></script>
  1592. <script src="https://cdn.datatables.net/buttons/2.4.1/js/buttons.html5.min.js"></script>
  1593. <script type="text/javascript">
  1594. // Reschedule variables
  1595. var rescheduleBookingId = null;
  1596. var rescheduleStartDate = null;
  1597. var rescheduleEndDate = null;
  1598. var rescheduleMobileNumber = null;
  1599. var rescheduleHallId = null;
  1600. var rescheduleStartingSlot = null;
  1601. var rescheduleEndingSlot = null;
  1602. var rescheduleReason = null;
  1603. $(document).ready(function () {
  1604. $('#detailstable').DataTable({
  1605. responsive: true,
  1606. pageLength: 10,
  1607. ordering: true,
  1608. columnDefs: [{
  1609. targets: 'no-sort',
  1610. orderable: false
  1611. }],
  1612. dom: 'Bfrtip',
  1613. buttons: [
  1614. {
  1615. extend: 'excelHtml5',
  1616. text: 'Export to Excel',
  1617. className: 'btn btn-primary'
  1618. }
  1619. ]
  1620. });
  1621. });
  1622. $(document).ready(function () {
  1623. $('#submitNocButton').on('click', function (e) {
  1624. e.preventDefault();
  1625. // Get the form data
  1626. var formData = new FormData();
  1627. var fileInput = $('#nocFile')[0].files[0]; // Get the selected file
  1628. var bookingssId = $('#bookingssId').val(); // Get the bookingId
  1629. // Check if a file is selected
  1630. if (!fileInput) {
  1631. Swal.fire({
  1632. icon: 'warning',
  1633. title: 'No File Selected',
  1634. text: 'Please select a file to upload.',
  1635. });
  1636. return;
  1637. }
  1638. // Append file and bookingId to formData
  1639. formData.append('nocFile', fileInput);
  1640. formData.append('bookingssId', bookingssId);
  1641. // Perform Ajax request
  1642. $.ajax({
  1643. url: '/communityhall/user/api/uploaddocs', // API endpoint
  1644. type: 'POST',
  1645. data: formData,
  1646. contentType: false,
  1647. processData: false,
  1648. success: function (response) {
  1649. // Show success message and refresh the page
  1650. Swal.fire({
  1651. icon: 'success',
  1652. title: 'Success',
  1653. text: 'NOC uploaded successfully!',
  1654. }).then(() => {
  1655. $('#uploadNocModal').modal('hide'); // Close the modal
  1656. location.reload(); // Refresh the page
  1657. });
  1658. },
  1659. error: function (xhr, status, error) {
  1660. // Show error message
  1661. Swal.fire({
  1662. icon: 'error',
  1663. title: 'Upload Failed',
  1664. text: 'Failed to upload NOC: ' + error,
  1665. });
  1666. }
  1667. });
  1668. });
  1669. // Populate bookingId when opening the modal
  1670. $('#uploadNocModal').on('show.bs.modal', function (event) {
  1671. var button = $(event.relatedTarget); // Button that triggered the modal
  1672. var bookingId = button.data('booking-id'); // Extract bookingId from the button
  1673. $('#bookingssId').val(bookingId); // Set the bookingId in the hidden input field
  1674. });
  1675. });
  1676. // Function to track booking
  1677. function trackBooking(bookingId) {
  1678. $.ajax({
  1679. url: '/communityhall/user/api/trackBooking',
  1680. method: 'GET',
  1681. data: { bookingId: bookingId }, // Send booking ID to the server
  1682. success: function (data) {
  1683. // console.log("Received tracking data:", data);
  1684. // Clear the list initially before appending steps
  1685. $('#trackingList').empty();
  1686. if (Array.isArray(data) && data.length > 0) {
  1687. // Show the modal first
  1688. $('#trackingModal').modal('show');
  1689. // Create a Set to track seen statuses
  1690. const seenStatuses = new Set();
  1691. // Append steps one by one
  1692. data.forEach((event) => {
  1693. // Append each step if it hasn't been seen before
  1694. if (!seenStatuses.has(event.status)) {
  1695. seenStatuses.add(event.status); // Add status to Set
  1696. appendStep(event); // Call to append the event step
  1697. }
  1698. });
  1699. } else {
  1700. // Show a message when no tracking events are available
  1701. $('#trackingList').append('<li class="no-events">No tracking events available.</li>');
  1702. }
  1703. },
  1704. error: function (xhr, status, error) {
  1705. console.error("Failed to fetch booking details:", status, error);
  1706. alert('Failed to fetch booking details. Please try again later.');
  1707. }
  1708. });
  1709. }
  1710. function appendStep(event) {
  1711. const formattedDate = moment(event.dateTime).isValid()
  1712. ? moment(event.dateTime).format('MMM DD, YYYY, h:mm A') // Format date using Moment.js
  1713. : 'Invalid date';
  1714. const statusClass = getStatusClass(event.status); // Get CSS class for the status
  1715. const statusIcon = getStatusIcon(event.status); // Get icon for the status
  1716. // Create and append a step element for each event
  1717. const stepElement = `
  1718. <li class="tracking-step ${statusClass}">
  1719. <div class="step-icon">
  1720. <i class="fas ${statusIcon}"></i> <!-- Add the icon -->
  1721. </div>
  1722. <div class="step-content">
  1723. <h5>${event.description || 'No Description Available'}</h5> <!-- Event description -->
  1724. <p class="step-date">${formattedDate}</p> <!-- Formatted date -->
  1725. </div>
  1726. </li>
  1727. `;
  1728. // Append the element to the list
  1729. $('#trackingList').append(stepElement);
  1730. }
  1731. function getStatusClass(status) {
  1732. switch (status) {
  1733. case 'PAYMENT_SUCCESS':
  1734. case 'APPROVED':
  1735. case 'EVENT_COMPLETED':
  1736. case 'COMPLETED':
  1737. return 'completed'; // Returns 'completed' class for these statuses
  1738. case 'SETTLEMENT_RAISING':
  1739. return 'waiting';
  1740. case 'CANCELED':
  1741. return 'cancelled';
  1742. case 'REJECTED':
  1743. return 'rejected';
  1744. case 'GCC_BLOCKED':
  1745. return 'gcc-blocked';
  1746. default:
  1747. return 'pending'; // Default class if status is unknown
  1748. }
  1749. }
  1750. function getStatusIcon(status) {
  1751. switch (status) {
  1752. case 'PAYMENT_SUCCESS':
  1753. return 'fa-check-circle'; // Icon for payment success
  1754. case 'APPROVED':
  1755. return 'fa-thumbs-up';
  1756. case 'EVENT_COMPLETED':
  1757. return 'fa-calendar-check';
  1758. case 'CANCELED':
  1759. return 'fa-ban';
  1760. case 'REJECTED':
  1761. return 'fa-times-circle';
  1762. case 'GCC_BLOCKED':
  1763. return 'fa-lock';
  1764. default:
  1765. return 'fa-clock'; // Default icon for pending steps
  1766. }
  1767. }
  1768. function showFutureEvents() {
  1769. document.getElementById('futureEventsContainer').style.display = 'block';
  1770. }
  1771. function downloadAcknowledgment(event) {
  1772. event.preventDefault();
  1773. var bookingId = document.getElementById("booking_id").innerHTML;
  1774. var refId = document.getElementById("modalRefId").value;
  1775. // Redirect to the acknowledgment URL in the same tab
  1776. window.location.href = '/communityhall/user/acknowledgement?bookingId=' + encodeURIComponent(bookingId);
  1777. // var refId = document.getElementById("ref_" + bookingId).value;
  1778. console.log("Ref ID: " + refId);
  1779. window.location.href = '/communityhall/user/acknowledgement?ref_id=' + encodeURIComponent(refId);
  1780. }
  1781. function getTimeSlot(slotValue) {
  1782. var timeSlot;
  1783. var trimmedSlotValue = String(slotValue).trim(); // Convert to string and then trim
  1784. if (trimmedSlotValue === '1') {
  1785. timeSlot = 'Morning';
  1786. } else if (trimmedSlotValue === '2') {
  1787. timeSlot = 'Evening';
  1788. } else {
  1789. timeSlot = 'Unknown';
  1790. }
  1791. return timeSlot;
  1792. }
  1793. // function showBookingDetails(bookingId) {
  1794. function showBookingDetails(bookingId, refId) {
  1795. $.ajax({
  1796. url: '/communityhall/user/api/viewAllBookingDetails',
  1797. method: 'GET',
  1798. data: { bookingId: bookingId },
  1799. success: function (response) {
  1800. document.getElementById("td_userName").innerHTML = response.users.name;
  1801. document.getElementById("td_mobileNumber").innerHTML = response.users.mobileNo;
  1802. document.getElementById("td_usertype").innerHTML = response.users.usertype;
  1803. var userDetails = response.users;
  1804. var userDetailsString =
  1805. userDetails.doorNo + ", " +
  1806. userDetails.street + ", " +
  1807. userDetails.area + ", " +
  1808. userDetails.location + " ,Chennai- " +
  1809. userDetails.pinCode;
  1810. document.getElementById("td_useraddress").innerHTML = userDetailsString;
  1811. document.getElementById("td_hallName").innerHTML = response.hallDetails.hallName;
  1812. var hallDetails = response.hallDetails;
  1813. var hallDetailsString =
  1814. hallDetails.doorNo + ", " +
  1815. hallDetails.street + ", " +
  1816. hallDetails.area + ", " +
  1817. hallDetails.city + "- " +
  1818. hallDetails.pinCode;
  1819. document.getElementById("td_halladdress").innerHTML = hallDetailsString;
  1820. document.getElementById("td_caretakername").innerHTML = response.hallDetails.hallInchargeName;
  1821. document.getElementById("td_caretakermobileNumber").innerHTML = response.hallDetails.hallInchargeMobno;
  1822. document.getElementById("td_bookingDate").innerHTML = response.bookingDate;
  1823. document.getElementById("td_depositeAmount").innerHTML = parseFloat(response.depositAmount).toFixed(2);
  1824. document.getElementById("td_hallAmount").innerHTML = parseFloat(response.hallAmount).toFixed(2);
  1825. // Calculate GST and total amount
  1826. var gstAmount = (parseFloat(response.hallAmount) * (response.hallDetails.gst / 100)).toFixed(2);
  1827. var totalAmount = parseFloat(response.amountReceived).toFixed(2);
  1828. document.getElementById("td_gst").innerHTML = gstAmount;
  1829. document.getElementById("td_totalAmount").innerHTML = totalAmount;
  1830. document.getElementById("td_startDate").innerHTML = response.startDate;
  1831. document.getElementById("td_endDate").innerHTML = response.endDate;
  1832. document.getElementById("booking_id").innerHTML = response.bookingId;
  1833. function getTimeSlot(slotValue) {
  1834. var timeSlot;
  1835. var trimmedSlotValue = String(slotValue).trim(); // Convert to string and then trim
  1836. if (trimmedSlotValue === '1') {
  1837. timeSlot = 'Morning';
  1838. } else if (trimmedSlotValue === '2') {
  1839. timeSlot = 'Evening';
  1840. } else {
  1841. timeSlot = 'Unknown';
  1842. }
  1843. return timeSlot;
  1844. }
  1845. document.getElementById("td_startingSlot").innerHTML = getTimeSlot(response.startingSlot);
  1846. document.getElementById("td_endingSlot").innerHTML = getTimeSlot(response.endingSlot);
  1847. document.getElementById("bookingstatus_td").innerHTML = response.bookingStatus;
  1848. console.log("before comments user view history...");
  1849. console.log("Comments..." + response.comments);
  1850. if (response.bookingStatus === 'REJECTED' && response.comments) {
  1851. document.getElementById("rejectionreasondiv").style.display = "block";
  1852. const rejectionCell = document.getElementById("reasonforrejection");
  1853. rejectionCell.innerHTML = response.comments;
  1854. } else {
  1855. document.getElementById("rejectionreasondiv").style.display = "none";
  1856. document.getElementById("reasonforrejection").style.display = "none";
  1857. }
  1858. showReasonDocuments(response);
  1859. if (response.payments) {
  1860. document.getElementById("paymentsdetails").style.display = "block";
  1861. document.getElementById("td_transactionId").innerHTML = response.payments.transactionId;
  1862. document.getElementById("td_payamountReceived").innerHTML = response.payments.amountReceived;
  1863. document.getElementById("td_paymentStatus").innerHTML = response.payments.paymentStatus;
  1864. } else {
  1865. document.getElementById("paymentsdetails").style.display = "none";
  1866. }
  1867. if (response.ebDetails) {
  1868. document.getElementById("ebdetails").style.display = "block";
  1869. document.getElementById("td_EBNumber").innerHTML = response.hallDetails.ebNumber;
  1870. document.getElementById("td_startingReading").innerHTML = response.ebDetails.startingReading;
  1871. document.getElementById("td_endingReading").innerHTML = response.ebDetails.endingReading;
  1872. document.getElementById("td_usedunit").innerHTML = response.ebDetails.usedUnit;
  1873. document.getElementById("td_ebamountperunit").innerHTML = parseFloat(response.hallDetails.ebCostPerUnit).toFixed(2);
  1874. document.getElementById("td_electricityamount").innerHTML = parseFloat(response.ebDetails.ebAmount).toFixed(2);
  1875. } else {
  1876. document.getElementById("ebdetails").style.display = "none";
  1877. }
  1878. if (response.damageList && response.damageList.length > 0) {
  1879. document.getElementById("damagelist").style.display = "block";
  1880. } else {
  1881. document.getElementById("damagelist").style.display = "none";
  1882. }
  1883. if (response.settlement) {
  1884. document.getElementById("refunddetails").style.display = "block";
  1885. document.getElementById("td_depositeamountforrefund").innerHTML = parseFloat(response.depositAmount).toFixed(2);
  1886. document.getElementById("td_electricityamount").innerHTML = parseFloat(response.ebDetails.ebAmount).toFixed(2);
  1887. document.getElementById("td_ebAmount").innerHTML = parseFloat(response.ebDetails.ebAmount).toFixed(2);
  1888. document.getElementById("td_damage").innerHTML = parseFloat(response.settlement.damageAmount).toFixed(2);
  1889. var eb_amt = parseFloat(response.ebDetails.ebAmount).toFixed(2);
  1890. var deposit_amt = parseFloat(response.depositAmount).toFixed(2);
  1891. var tem_total = (deposit_amt - eb_amt).toFixed(2);
  1892. $("#td_settel_amt").html(tem_total);
  1893. } else {
  1894. document.getElementById("refunddetails").style.display = "none";
  1895. }
  1896. showDamageDetails(response);
  1897. if (response.bookingStatus === 'CANCELED' && ['WAITING', 'APPROVED', 'INITIATED'].includes(response.refundStatus)) {
  1898. document.getElementById("td_refundamount").innerHTML = `Your booking has been cancelled. Deposit amount of ₹ ${parseFloat(response.depositAmount).toFixed(2)} will be refund 3 to 15 Days`;
  1899. document.getElementById("refundamountDetails").style.display = "block";
  1900. document.getElementById("td_bookingStatus").innerHTML = response.bookingStatus;
  1901. document.getElementById("td_refundStatus").innerHTML = response.refundStatus;
  1902. } else if (response.bookingStatus === 'CANCELED' && response.refundStatus === 'COMPLETED') {
  1903. document.getElementById("td_refundamount").innerHTML = `Deposit amount of ₹ ${parseFloat(response.depositAmount).toFixed(2)} refunded successfully`;
  1904. document.getElementById("refundamountDetails").style.display = "block";
  1905. document.getElementById("td_bookingStatus").innerHTML = response.bookingStatus;
  1906. document.getElementById("td_refundStatus").innerHTML = response.refundStatus;
  1907. } else if (response.bookingStatus === 'REJECTED' && ['WAITING', 'APPROVED', 'INITIATED'].includes(response.refundStatus) && response.amountReceived == 0) {
  1908. document.getElementById("refundamountDetails").style.display = "none";
  1909. } else if (response.bookingStatus === 'REJECTED' && ['WAITING', 'APPROVED', 'INITIATED'].includes(response.refundStatus)) {
  1910. document.getElementById("td_refundamount").innerHTML = `Your booking has been Rejected by GCC. Full amount of ₹ ${parseFloat(response.amountReceived).toFixed(2)} will be refunded shortly`;
  1911. document.getElementById("refundamountDetails").style.display = "block";
  1912. document.getElementById("td_bookingStatus").innerHTML = response.bookingStatus;
  1913. document.getElementById("td_refundStatus").innerHTML = response.refundStatus;
  1914. } else if (response.bookingStatus === 'REJECTED' && response.refundStatus === 'COMPLETED') {
  1915. document.getElementById("td_refundamount").innerHTML = `Full amount of ₹${parseFloat(response.amountReceived).toFixed(2)} refunded successfully`;
  1916. document.getElementById("refundamountDetails").style.display = "block";
  1917. document.getElementById("td_bookingStatus").innerHTML = response.bookingStatus;
  1918. document.getElementById("td_refundStatus").innerHTML = response.refundStatus;
  1919. } else if (response.bookingStatus === 'REJECTED' && response.refundStatus === 'NA') {
  1920. document.getElementById("td_refundamount").innerHTML = `Your Booking has been rejected by GCC`;
  1921. document.getElementById("refundamountDetails").style.display = "block";
  1922. document.getElementById("td_bookingStatus").innerHTML = response.bookingStatus;
  1923. document.getElementById("td_refundStatus").innerHTML = response.refundStatus;
  1924. } else if (response.bookingStatus === 'GCC_BLOCKED' && ['WAITING', 'APPROVED', 'INITIATED'].includes(response.refundStatus)) {
  1925. document.getElementById("td_refundamount").innerHTML = `Your booking has been Blocked by GCC. Full amount of ₹ ${parseFloat(response.amountReceived).toFixed(2)} will be refunded shortly`;
  1926. document.getElementById("refundamountDetails").style.display = "block";
  1927. document.getElementById("td_bookingStatus").innerHTML = response.bookingStatus;
  1928. document.getElementById("td_refundStatus").innerHTML = response.refundStatus;
  1929. } else if (response.bookingStatus === 'GCC_BLOCKED' && response.refundStatus === 'COMPLETED') {
  1930. document.getElementById("td_refundamount").innerHTML = `Full amount of ₹${parseFloat(response.amountReceived).toFixed(2)} refunded successfully`;
  1931. document.getElementById("refundamountDetails").style.display = "block";
  1932. document.getElementById("td_bookingStatus").innerHTML = response.bookingStatus;
  1933. document.getElementById("td_refundStatus").innerHTML = response.refundStatus;
  1934. } /*else if(response.scheduleCount === 1){
  1935. document.getElementById("rescheduleDetails").style.display = "block";
  1936. document.getElementById("td_res_start_date").innerHTML = response.startDate;
  1937. document.getElementById("td_res_end_date").innerHTML = response.endDate;
  1938. document.getElementById("td_res_date").innerHTML = response.updatedDate;
  1939. }*/ else {
  1940. document.getElementById("refundamountDetails").style.display = "none";
  1941. }
  1942. // Show the modal
  1943. document.getElementById("modalBookingId").value = bookingId;
  1944. document.getElementById("modalRefId").value = refId;
  1945. $('#showBookingDetails').modal('show');
  1946. },
  1947. error: function () {
  1948. console.error("An error occurred while fetching booking details.");
  1949. }
  1950. });
  1951. }
  1952. function showDamageDetails(data) {
  1953. var damageFieldContainer = $('#damageDetails');
  1954. damageFieldContainer.empty();
  1955. // Create a div for table responsiveness
  1956. var tableResponsiveDiv = $('<div>').addClass('table-responsive').css({
  1957. 'margin-top': '-19px',
  1958. 'margin-left': '19px'
  1959. });
  1960. ;
  1961. // Create table with similar classes and styles to the modal table
  1962. var table = $('<table>').addClass('table table-bordered table-striped').css({
  1963. 'width': '97%',
  1964. 'border-color': 'black',
  1965. 'border-top-color': 'white',
  1966. 'width': ' 730px'
  1967. });
  1968. var thead = $('<thead>').addClass('thead-light');
  1969. var tbody = $('<tbody>');
  1970. // Create Damage Details header row
  1971. var headerRow = $('<tr>').appendTo(thead);
  1972. $('<th>').attr('colspan', '6').text('Damage Details (if any)').css({
  1973. 'padding': '0.45rem 0.45rem',
  1974. 'background-color': 'lightgrey',
  1975. 'font-weight': 'bold',
  1976. 'color': 'black',
  1977. }).appendTo(headerRow);
  1978. // Create table header row
  1979. var columnHeadersRow = $('<tr>').css('background-color', 'white').appendTo(thead);
  1980. $('<th>').text('S.No').css('padding', '0.45rem 0.45rem').appendTo(columnHeadersRow);
  1981. $('<th>').text('Asset Name').css('padding', '0.45rem 0.45rem').appendTo(columnHeadersRow);
  1982. $('<th>').text('Damage Img').css('padding', '0.45rem 0.45rem').appendTo(columnHeadersRow);
  1983. $('<th>').text('Cost').css('padding', '0.45rem 0.45rem').appendTo(columnHeadersRow);
  1984. $('<th>').text('Qty').css('padding', '0.45rem 0.45rem').appendTo(columnHeadersRow);
  1985. $('<th>').text('Amount').css('padding', '0.45rem 0.45rem').appendTo(columnHeadersRow);
  1986. var totalAmount = 0;
  1987. $.each(data.damageList, function (index, detail) {
  1988. var row = $('<tr>').appendTo(tbody);
  1989. $('<td>').text(index + 1).css('padding', '0.45rem 0.45rem').appendTo(row);
  1990. $('<td>').text(detail.assetName).css('padding', '0.45rem 0.45rem').appendTo(row);
  1991. var viewLink = $('<a>').attr('href', 'javascript:void(0)').text('View').on('click', function () {
  1992. showDamageImage(detail.damageImageUrl);
  1993. });
  1994. var assetamt = (detail.assetAmount / detail.quantity).toFixed(2);
  1995. $('<td>').css('padding', '0.45rem 0.45rem').append(viewLink).appendTo(row);
  1996. $('<td>').text(assetamt).css('padding', '0.45rem 0.45rem').appendTo(row);
  1997. $('<td>').text(detail.quantity).css('padding', '0.45rem 0.45rem').appendTo(row);
  1998. var amount = detail.assetAmount;
  1999. totalAmount += amount;
  2000. $('<td>').text(amount.toFixed(2)).css('padding', '0.45rem 0.45rem').appendTo(row);
  2001. $("#td_dam_amt").html(totalAmount.toFixed(2));
  2002. });
  2003. // Add row for total amount
  2004. var totalRow = $('<tr>').appendTo(tbody);
  2005. $('<td>').attr('colspan', '5').text('Total Amount').css('padding', '0.45rem 0.45rem; font-weight: bold; background-color: #f2f2f2').appendTo(totalRow);
  2006. $('<td>').text(totalAmount.toFixed(2)).css('padding', '0.45rem 0.45rem').appendTo(totalRow);
  2007. // Append the table elements to the container div
  2008. table.append(thead, tbody);
  2009. tableResponsiveDiv.append(table);
  2010. damageFieldContainer.append(tableResponsiveDiv);
  2011. var temp_total = parseFloat($("#td_settel_amt").html());
  2012. var settleAmount = temp_total - totalAmount;
  2013. if (settleAmount < 0) {
  2014. var pendingstatus = data.settlement.collectionStatus
  2015. $("#td_settel_amt").html(0.00);
  2016. $("#pendingcolumn").show();
  2017. $("#collectionstatuscolumn").show();
  2018. $('#td_collection_status').html(pendingstatus);
  2019. $("#td_pending_amt").html(Math.abs(settleAmount).toFixed(2));
  2020. $("#td_pending_amt").css("color", "red");
  2021. } else {
  2022. $("#td_settel_amt").html(settleAmount.toFixed(2));
  2023. $("#pendingcolumn").hide();
  2024. $("#collectionstatuscolumn").hide();
  2025. $("#td_settel_amt").css("color", "green"); // Set color to green for positive amounts
  2026. }
  2027. }
  2028. function showDamageImage(damageImageUrl) {
  2029. document.getElementById('filePreview').src = damageImageUrl;
  2030. $('#fileModal').modal('show');
  2031. }
  2032. function showchallonimage(challanImgLink) {
  2033. document.getElementById('filePreview').src = challanImgLink;
  2034. $('#fileModal').modal('show');
  2035. }
  2036. function showReasonDocuments(list) {
  2037. $.ajax({
  2038. type: "GET",
  2039. url: '/communityhall/api/officer/getReasonByName',
  2040. data: {
  2041. 'reasonName': list.reason
  2042. },
  2043. success: function (x) {
  2044. showReasonWithDocument(x, list);
  2045. }
  2046. });
  2047. }
  2048. // Display booking documents
  2049. function showReasonWithDocument(reasonData, list) {
  2050. var reasonDocumentData = reasonData.reasonDocumentMasterList;
  2051. var bookingDocumentsList = list.bookingDocumentsList;
  2052. const reasonFieldsContainer = $('#documents');
  2053. reasonFieldsContainer.empty();
  2054. // Create a responsive table container
  2055. var tableResponsiveDiv = $('<div>').addClass('table-responsive').css({
  2056. 'width': '729px',
  2057. 'border': '1px solid black'
  2058. });
  2059. // Create the table with Bootstrap classes and custom styles
  2060. var table = $('<table>').addClass('table table-bordered table-striped table-vcenter js-dataTable-responsive').css({
  2061. 'width': '100%',
  2062. 'height': 'auto',
  2063. 'border': '1px solid black'
  2064. });
  2065. // Create the table header (thead)
  2066. var thead = $('<thead>').appendTo(table);
  2067. var headerRow = $('<tr>').appendTo(thead);
  2068. $('<th>').attr('colspan', '3').text('Document Details').css({
  2069. 'color': 'black',
  2070. 'background-color': 'lightgrey',
  2071. 'padding': '0.45rem 0.45rem'
  2072. }).appendTo(headerRow);
  2073. // Create header row for columns
  2074. var columnHeadersRow = $('<tr>').appendTo(thead);
  2075. $('<th>').text('S.No').appendTo(columnHeadersRow);
  2076. $('<th>').text('Required Info').appendTo(columnHeadersRow);
  2077. $('<th>').text('Required Documents').appendTo(columnHeadersRow);
  2078. // Create the table body (tbody)
  2079. var tbody = $('<tbody>').appendTo(table);
  2080. // Iterate through the documents list and populate rows
  2081. for (var i = 0; i < bookingDocumentsList.length; i++) {
  2082. (function (index) {
  2083. var row = $('<tr>').appendTo(tbody);
  2084. $('<td>').text(index + 1).appendTo(row);
  2085. // Determine the text content for the second cell
  2086. var name = bookingDocumentsList[index].name ? bookingDocumentsList[index].name : ''; // Empty string if name is null or undefined
  2087. var fieldText = reasonDocumentData[index].fieldName;
  2088. var fullText = name ? fieldText + ': ' + name : fieldText; // Include colon only if name is not empty
  2089. $('<td>').text(fullText).appendTo(row);
  2090. // Create a link to view document image
  2091. var viewLink = $('<a>').attr('href', 'javascript:void(0)').text(reasonDocumentData[index].docFieldName).on('click', function () {
  2092. showDocumentImage(bookingDocumentsList[index].bookingDocUrl);
  2093. });
  2094. $('<td>').append(viewLink).appendTo(row);
  2095. })(i);
  2096. }
  2097. // Append table to the responsive container
  2098. tableResponsiveDiv.append(table);
  2099. // Append table to the container in the DOM
  2100. reasonFieldsContainer.append(tableResponsiveDiv);
  2101. }
  2102. function showDocumentImage(fileURL) {
  2103. openFileModal(fileURL);
  2104. }
  2105. // Event delegation for dynamically added elements
  2106. $(document).on('click', '.view-document', function () {
  2107. const fileURL = $(this).data('url');
  2108. openFileModal(fileURL);
  2109. });
  2110. function openFileModal(fileURL) {
  2111. $('#filePreview').attr('src', fileURL);
  2112. $('#fileModal').modal('show');
  2113. }
  2114. // For OTP input box
  2115. $('.otp-input').on('keyup', function (e) {
  2116. var $this = $(this);
  2117. if ($this.val().length === 1) {
  2118. $this.next('.otp-input').focus();
  2119. }
  2120. if ($this.val().length === 0) {
  2121. $this.prev('.otp-input').focus();
  2122. }
  2123. });
  2124. function cancelBooking(bookingId, mobileNo, bookingType) {
  2125. var mobileNum = mobileNo;
  2126. var bookingId = bookingId;
  2127. // Check if the booking type is OFFLINE
  2128. if (bookingType === "OFFLINE") {
  2129. Swal.fire({
  2130. title: 'Cancellation Not Available',
  2131. text: 'Cancellation is not available for offline bookings.',
  2132. icon: 'error'
  2133. });
  2134. } else {
  2135. Swal.fire({
  2136. title: 'Are you sure?',
  2137. text: 'Once canceled, this action can\'t be undo. Only the deposit Amount will be refunded within 3 to 15 days.',
  2138. icon: 'warning',
  2139. showCancelButton: true,
  2140. confirmButtonColor: '#3085d6',
  2141. cancelButtonColor: '#d33',
  2142. confirmButtonText: 'Yes, cancel it!',
  2143. cancelButtonText: 'Close',
  2144. }).then((result) => {
  2145. if (result.isConfirmed) {
  2146. // If user confirms, show OTP form
  2147. mobileNumberForCancel = mobileNum;
  2148. cancelBookingId = bookingId;
  2149. cancelBookingLogin = true;
  2150. sendOTP(mobileNum);
  2151. }
  2152. });
  2153. }
  2154. }
  2155. function resetRescheduleOTPSection() {
  2156. // Hide OTP section
  2157. var otpSection = document.getElementById("otpSection");
  2158. if (otpSection) {
  2159. otpSection.style.display = "none";
  2160. }
  2161. // Show reschedule button and hide verify button
  2162. var rescheduleBtn = document.getElementById("rescheduleBtn");
  2163. var verifyOtpBtn = document.getElementById("verifyOtpBtn");
  2164. if (rescheduleBtn) {
  2165. rescheduleBtn.style.display = "inline-block";
  2166. }
  2167. if (verifyOtpBtn) {
  2168. verifyOtpBtn.style.display = "none";
  2169. }
  2170. // Clear OTP input fields
  2171. for (let i = 1; i <= 6; i++) {
  2172. var otpField = document.getElementById("otp" + i);
  2173. if (otpField) {
  2174. otpField.value = "";
  2175. }
  2176. }
  2177. // Reset variables
  2178. rescheduleBookingId = null;
  2179. rescheduleStartDate = null;
  2180. rescheduleEndDate = null;
  2181. rescheduleMobileNumber = null;
  2182. rescheduleHallId = null;
  2183. rescheduleStartingSlot = null;
  2184. rescheduleEndingSlot = null;
  2185. rescheduleReason = null;
  2186. }
  2187. function openRescheduleModal(bookingId, startDate, endDate, noOfDays, hallId, startingSlot, endingSlot, reason) {
  2188. // Function to map slot values to their text representation
  2189. function getSlotText(slot) {
  2190. return slot === 1 ? 'Morning' : 'Evening';
  2191. }
  2192. // Populate modal inputs
  2193. const start = new Date(startDate);
  2194. const end = new Date(endDate);
  2195. const timeDiff = end - start;
  2196. // Convert time difference from milliseconds to days
  2197. const daysDiff = Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1;
  2198. // Set values for inputs
  2199. document.getElementById("bookingId").value = bookingId;
  2200. document.getElementById("startDateInput").value = startDate;
  2201. document.getElementById("endDateInput").value = endDate;
  2202. document.getElementById("noOfDaysInput").value = noOfDays;
  2203. document.getElementById("startingSlot").value = String(startingSlot);
  2204. document.getElementById("endingSlot").value = String(endingSlot);
  2205. document.getElementById("endingSlotHidden").value = String(endingSlot);
  2206. document.getElementById("daysDiff").value = daysDiff;
  2207. // Display slot text in the modal
  2208. document.getElementById("startDatetext").value = startDate;
  2209. // document.getElementById("startingSlotText").value = getSlotText(startingSlot);
  2210. // document.getElementById("endingSlotText").value = getSlotText(endingSlot);
  2211. // Store booking details for OTP verification
  2212. rescheduleBookingId = bookingId;
  2213. rescheduleStartDate = startDate;
  2214. rescheduleEndDate = endDate;
  2215. rescheduleHallId = hallId;
  2216. rescheduleStartingSlot = startingSlot;
  2217. rescheduleEndingSlot = endingSlot;
  2218. rescheduleReason = reason;
  2219. // Optionally, fetch and update calendar or availability based on hallId
  2220. getBookingCalendar(hallId, reason);
  2221. // Show the date change modal
  2222. $('#bookingRescheduleModal').modal('show');
  2223. }
  2224. function getBookingCalendar(hall_id, reason) {
  2225. // Make an AJAX call to fetch booking data
  2226. $.ajax({
  2227. type: 'GET',
  2228. url: '/communityhall/user/api/getPastData',
  2229. data: {
  2230. hall_id: hall_id
  2231. },
  2232. success: function (response) {
  2233. window.bookingResponse = {};
  2234. if (response && Array.isArray(response)) {
  2235. $("#startDateInput").datepicker("destroy");
  2236. for (var i = 0; i < response.length; i++) {
  2237. var dateString = datepickerFormat(response[i].bdate);
  2238. window.bookingResponse[dateString] = [response[i].morning_slot, response[i].evening_slot,
  2239. response[i].is_blocked, response[i].booking_status1, response[i].booking_status2];
  2240. }
  2241. initializeDatepickerWithColors(hall_id, reason);
  2242. if (response.length == 0) {
  2243. initializeDatepickerWithColors(hall_id, reason);
  2244. }
  2245. } else {
  2246. console.error('Invalid or empty response data.');
  2247. }
  2248. },
  2249. error: function (xhr, status, error) {
  2250. console.error('Error fetching hall details:', error);
  2251. }
  2252. });
  2253. }
  2254. function initializeDatepickerWithColors(hallId, reason) { // Confirm hallId is passed here
  2255. $("#datepicker-container").datepicker("destroy");
  2256. const serverDate = new Date($("#serverDate").val() + "T00:00:00")
  2257. // console.log(" view history Date:", serverDate);
  2258. const maxDate = new Date(serverDate);
  2259. maxDate.setMonth(maxDate.getMonth() + 6);
  2260. // console.log("View History: "+maxDate);
  2261. $("#startDateInput,#datepicker-container").datepicker({
  2262. dateFormat: "yy-mm-dd",
  2263. minDate: serverDate,
  2264. maxDate: maxDate,
  2265. beforeShowDay: function (eDate) {
  2266. const dateString = $.datepicker.formatDate("yy-mm-dd", eDate);
  2267. const bookingStatus = window.bookingResponse[dateString] || {};
  2268. // const currentDate = new Date();
  2269. serverDate.setHours(0, 0, 0, 0); // Normalize current date to midnight
  2270. eDate.setHours(0, 0, 0, 0); // Normalize selected date to midnight
  2271. // Logic for other dates
  2272. if (eDate < serverDate) {
  2273. return [false, "highlight-disabled", "Slot not Available"];
  2274. }
  2275. const isToday = eDate.getTime() === serverDate.getTime();
  2276. const currentHour = new Date().getHours();
  2277. const isBefore6AM = currentHour < 6;
  2278. const isAfter2PM = currentHour >= 14;
  2279. // Block 3-day logic for specific event types
  2280. // const today = new Date();
  2281. const blockedDate = new Date(serverDate);
  2282. blockedDate.setDate(serverDate.getDate() + 2);
  2283. const isThreeDayBlock = ["Commercial", "State Govt Event", "Central Govt Event"].includes(reason);
  2284. if (eDate <= blockedDate && isThreeDayBlock) {
  2285. return [false, "highlight-disabled", "Blocked due to event type"];
  2286. }
  2287. // Logic for currentdate
  2288. if (isToday) {
  2289. if (isBefore6AM) {
  2290. // Before 6 AM: Allow full-day booking or adjust based on booking status
  2291. return handleBookingStatus(bookingStatus, "Full Day Available");
  2292. } else if (isAfter2PM) {
  2293. // After 2 PM: Block all bookings
  2294. return handleAfter2PM(bookingStatus);
  2295. } else {
  2296. // Between 6 AM and 2 PM: Check status and disable morning slots
  2297. return handleMorningSlots(bookingStatus, isToday);
  2298. }
  2299. }
  2300. return handleBookingStatus(bookingStatus, "Slot Available");
  2301. },
  2302. });
  2303. $("#startDateInput").on("change", function () {
  2304. var selectedDate = $(this).val();
  2305. // var noOfDays = document.getElementById('noOfDaysInput').value;
  2306. var startingSlot = document.getElementById("startingSlot").value;
  2307. var endingSlot = document.getElementById("endingSlotHidden").value;
  2308. var noofdays = document.getElementById("noOfDaysInput").value;
  2309. updateEndDate(selectedDate, noofdays, startingSlot, endingSlot);
  2310. });
  2311. // ── Custom tooltip for calendar cells (handles pointer-events:none on .disabled) ──
  2312. // The <td> itself still receives mouse events even when its child has pointer-events:none.
  2313. // We read the title attribute that jQuery UI datepicker sets via beforeShowDay's 3rd return value.
  2314. if (!document.getElementById('dp-tooltip')) {
  2315. $('body').append('<div id="dp-tooltip"></div>');
  2316. }
  2317. $("#datepicker-container")
  2318. .off('mouseenter.dptt mouseleave.dptt mousemove.dptt', 'td[title]')
  2319. .on('mouseenter.dptt', 'td[title]', function (e) {
  2320. var tip = $(this).attr('title');
  2321. if (!tip) return;
  2322. $('#dp-tooltip').text(tip).css({
  2323. left: (e.clientX + 12) + 'px',
  2324. top: (e.clientY - 30) + 'px'
  2325. }).show();
  2326. })
  2327. .on('mousemove.dptt', 'td[title]', function (e) {
  2328. $('#dp-tooltip').css({
  2329. left: (e.clientX + 12) + 'px',
  2330. top: (e.clientY - 30) + 'px'
  2331. });
  2332. })
  2333. .on('mouseleave.dptt', 'td[title]', function () {
  2334. $('#dp-tooltip').hide();
  2335. });
  2336. }
  2337. function handleBookingStatus(bookingStatus, defaultMessage) {
  2338. if (bookingStatus[2] && bookingStatus[0] && !bookingStatus[1]) {
  2339. return [false, "highlight-yellow disabled", "GCC Blocked"];
  2340. } else if (bookingStatus[2] && bookingStatus[1] && !bookingStatus[0]) {
  2341. return [false, "highlight-violet disabled", "GCC Blocked"];
  2342. } else if (bookingStatus[2] && bookingStatus[1] && bookingStatus[0] && bookingStatus[3] != 'GCC_BLOCKED' && bookingStatus[4] != 'GCC_BLOCKED') {
  2343. return [false, "highlight-pink disabled", "GCC Blocked"];
  2344. } else if (bookingStatus[2] && bookingStatus[1] && bookingStatus[0] && bookingStatus[3] == 'GCC_BLOCKED' && bookingStatus[4] == 'GCC_BLOCKED') {
  2345. return [false, "highlight-blue disabled", "GCC Blocked"];
  2346. } else if (bookingStatus[2]) {
  2347. return [false, "highlight-blue disabled", "GCC Blocked"];
  2348. } else if (bookingStatus[0] && bookingStatus[1]) {
  2349. return [true, "highlight-pink disabled", "Slot Occupied"];
  2350. } else if (bookingStatus[0] && !bookingStatus[1]) {
  2351. return [true, "highlight-yellow", "Evening Slot Available"];
  2352. } else if (!bookingStatus[0] && bookingStatus[1]) {
  2353. return [true, "highlight-violet", "Only Morning Slot Available"];
  2354. }
  2355. return [true, "highlight-greens", defaultMessage];
  2356. }
  2357. // Helper function: Handles logic after 2 PM
  2358. function handleAfter2PM(bookingStatus) {
  2359. if (bookingStatus[2] && bookingStatus[0] && !bookingStatus[1]) {
  2360. return [true, "highlight-yellow disabled", "GCC Blocked"];
  2361. } else if (bookingStatus[2] && bookingStatus[1] && !bookingStatus[0]) {
  2362. return [true, "highlight-violet disabled", "GCC Blocked"];
  2363. } else if (bookingStatus[2] && bookingStatus[1] && bookingStatus[0] && bookingStatus[3] != 'GCC_BLOCKED' && bookingStatus[4] != 'GCC_BLOCKED') {
  2364. return [true, "highlight-pink disabled", "GCC Blocked"];
  2365. } else if (bookingStatus[2] && bookingStatus[1] && bookingStatus[0] && bookingStatus[3] == 'GCC_BLOCKED' && bookingStatus[4] == 'GCC_BLOCKED') {
  2366. return [true, "highlight-blue disabled", "GCC Blocked"];
  2367. } else if (bookingStatus[2]) {
  2368. return [true, "highlight-blue disabled", "GCC Blocked"];
  2369. } else if (bookingStatus[0] || bookingStatus[1]) {
  2370. return [true, "highlight-pink disabled", "Slot Occupied"];
  2371. }
  2372. return [false, "highlight-disabled", "Not Allowed to Book"];
  2373. }
  2374. // Helper function: Handles morning slots between 6 AM and 2 PM
  2375. function handleMorningSlots(bookingStatus, isToday) {
  2376. console.log("isToday....." + isToday);
  2377. if (bookingStatus[2] && bookingStatus[0] && !bookingStatus[1]) {
  2378. return [true, "highlight-yellow disabled", "GCC Blocked"];
  2379. } else if (bookingStatus[2] && bookingStatus[1] && !bookingStatus[0]) {
  2380. if (isToday) {
  2381. return [false, "highlight-disabled", "GCC Blocked"];
  2382. }
  2383. return [true, "highlight-violet disabled", "GCC Blocked"];
  2384. } else if (bookingStatus[2] && bookingStatus[1] && bookingStatus[0] && bookingStatus[3] != 'GCC_BLOCKED' && bookingStatus[4] != 'GCC_BLOCKED') {
  2385. return [true, "highlight-pink disabled", "GCC Blocked"];
  2386. } else if (bookingStatus[2] && bookingStatus[1] && bookingStatus[0] && bookingStatus[3] == 'GCC_BLOCKED' && bookingStatus[4] == 'GCC_BLOCKED') {
  2387. return [true, "highlight-blue disabled", "GCC Blocked"];
  2388. } else if (bookingStatus[2]) {
  2389. return [true, "highlight-blue disabled", "GCC Blocked"];
  2390. } else if (bookingStatus[0] && bookingStatus[1]) {
  2391. return [true, "highlight-pink disabled", "Slot Occupied"];
  2392. } else if (bookingStatus[0] && !bookingStatus[1]) {
  2393. return [true, "highlight-yellow", "Evening Slot Available"];
  2394. } else if (!bookingStatus[0] && bookingStatus[1]) {
  2395. return [false, "highlight-disabled", "Slot Occupied"];
  2396. }
  2397. return [true, "highlight-yellow", "Evening Slot Available"];
  2398. }
  2399. // Helper: returns true if the given date string is GCC-blocked
  2400. function isGCCBlockedDate(dateStr) {
  2401. var status = window.bookingResponse[dateStr] || [];
  2402. return (status[2] == true || status[2] == 1 ||
  2403. status[3] === 'GCC_BLOCKED' ||
  2404. status[4] === 'GCC_BLOCKED');
  2405. }
  2406. function updateEndDate(startDate, noofdays, startingSlot, endingSlot) {
  2407. if (startDate && noofdays !== undefined) {
  2408. var start = new Date(startDate);
  2409. var startFormatted = start.toISOString().split('T')[0];
  2410. var bookingStatus = window.bookingResponse[startFormatted] || [false, false];
  2411. var morningAvailable = !bookingStatus[0]; // false means available
  2412. var eveningAvailable = !bookingStatus[1]; // false means available
  2413. var isgccBlock = bookingStatus[2];
  2414. var bookingStatus1 = bookingStatus[3];
  2415. var bookingStatus2 = bookingStatus[4];
  2416. var endDate;
  2417. var isValid = true; // Flag to determine if all slots are available
  2418. // Convert noofdays to a number for accurate calculations
  2419. noofdays = parseFloat(noofdays);
  2420. // --- GCC Block checkpoint ---
  2421. // Block reschedule if the start date is GCC-blocked via any of the three status flags
  2422. if (isgccBlock == true || isgccBlock == 1 ||
  2423. bookingStatus1 === 'GCC_BLOCKED' ||
  2424. bookingStatus2 === 'GCC_BLOCKED') {
  2425. Swal.fire({
  2426. title: 'Date Not Available',
  2427. text: 'The selected start date is blocked by GCC. Please choose a different date.',
  2428. icon: 'warning',
  2429. confirmButtonText: 'OK'
  2430. });
  2431. document.getElementById('endDateInput').value = "";
  2432. return;
  2433. }
  2434. // --- End GCC Block checkpoint ---
  2435. // Handle slot availability and combinations
  2436. if (startingSlot === "2" && endingSlot === "2") { // Evening to Evening
  2437. //console.log("Handling Evening to Evening slot.");
  2438. if (noofdays === 0.5) {
  2439. if (eveningAvailable) {
  2440. endDate = new Date(start);
  2441. endDate.setDate(start.getDate() + Math.ceil(noofdays) - 1);
  2442. endDate = endDate.toISOString().split('T')[0];
  2443. document.getElementById('endDateInput').value = endDate;
  2444. //console.log("End Date (Evening to Evening):", endDate);
  2445. } else {
  2446. Swal.fire({
  2447. title: 'Evening Slot Not Available',
  2448. text: 'The evening slot is not available for the selected date range.',
  2449. icon: 'warning',
  2450. confirmButtonText: 'OK'
  2451. });
  2452. document.getElementById('endDateInput').value = "";
  2453. //console.log("Evening slot not available for", noofdays, "days.");
  2454. }
  2455. } else if (noofdays === 1.5) {
  2456. // Special handling for 2 days
  2457. let endDateCandidate = new Date(start);
  2458. endDateCandidate.setDate(start.getDate() + 1);
  2459. let endDateFormattedCandidate = endDateCandidate.toISOString().split('T')[0];
  2460. let endDateStatusCandidate = window.bookingResponse[endDateFormattedCandidate] || [false, false];
  2461. let morningAvailableOnEndDate = !endDateStatusCandidate[0]; // false means available
  2462. let eveningAvailableOnEndDate = !endDateStatusCandidate[1]; // false means available
  2463. if (eveningAvailable && morningAvailableOnEndDate && eveningAvailableOnEndDate) {
  2464. endDate = endDateCandidate.toISOString().split('T')[0];
  2465. // --- GCC Block check for end date ---
  2466. if (isGCCBlockedDate(endDate)) {
  2467. Swal.fire({
  2468. title: 'End Date Not Available',
  2469. text: 'The end date is blocked by GCC. Please choose a different start date.',
  2470. icon: 'warning',
  2471. confirmButtonText: 'OK'
  2472. });
  2473. document.getElementById('endDateInput').value = "";
  2474. } else {
  2475. document.getElementById('endDateInput').value = endDate;
  2476. }
  2477. //console.log("End Date (Morning to Evening with 2 days):", endDate);
  2478. } else {
  2479. Swal.fire({
  2480. title: 'Slot Not Available',
  2481. text: 'The Morning slots are not available for the selected date range.',
  2482. icon: 'warning',
  2483. confirmButtonText: 'OK'
  2484. });
  2485. document.getElementById('endDateInput').value = "";
  2486. //console.log("Morning or Evening slot not available for 2 days.");
  2487. }
  2488. } else {
  2489. //console.log("Unsupported duration for Evening to Evening slot.");
  2490. Swal.fire({
  2491. title: 'Invalid Selection',
  2492. text: 'The selected duration for the evening slot is not supported.',
  2493. icon: 'error',
  2494. confirmButtonText: 'OK'
  2495. });
  2496. document.getElementById('endDateInput').value = "";
  2497. }
  2498. } else if (startingSlot === "1" && endingSlot === "1") { // Morning to Morning
  2499. //console.log("Handling Morning to Morning slot.");
  2500. if (noofdays === 0.5) {
  2501. if (morningAvailable) {
  2502. endDate = new Date(start);
  2503. endDate.setDate(start.getDate() + Math.ceil(noofdays) - 1);
  2504. endDate = endDate.toISOString().split('T')[0];
  2505. document.getElementById('endDateInput').value = endDate;
  2506. //console.log("End Date (morning to morning):", endDate);
  2507. } else {
  2508. Swal.fire({
  2509. title: 'Morning Slot Not Available',
  2510. text: 'The Morning slot is not available for the selected date range.',
  2511. icon: 'warning',
  2512. confirmButtonText: 'OK'
  2513. });
  2514. document.getElementById('endDateInput').value = "";
  2515. //console.log("Evening slot not available for", noofdays, "days.");
  2516. }
  2517. } else if (noofdays === 1.5) {
  2518. // Special handling for 2 days
  2519. let endDateCandidate = new Date(start);
  2520. endDateCandidate.setDate(start.getDate() + 1);
  2521. let endDateFormattedCandidate = endDateCandidate.toISOString().split('T')[0];
  2522. let endDateStatusCandidate = window.bookingResponse[endDateFormattedCandidate] || [false, false];
  2523. let morningAvailableOnEndDate = !endDateStatusCandidate[0]; // false means available
  2524. let eveningAvailableOnEndDate = !endDateStatusCandidate[1]; // false means available
  2525. if (morningAvailable && eveningAvailable && morningAvailableOnEndDate) {
  2526. endDate = endDateCandidate.toISOString().split('T')[0];
  2527. // --- GCC Block check for end date ---
  2528. if (isGCCBlockedDate(endDate)) {
  2529. Swal.fire({
  2530. title: 'End Date Not Available',
  2531. text: 'The end date is blocked by GCC. Please choose a different start date.',
  2532. icon: 'warning',
  2533. confirmButtonText: 'OK'
  2534. });
  2535. document.getElementById('endDateInput').value = "";
  2536. } else {
  2537. document.getElementById('endDateInput').value = endDate;
  2538. }
  2539. //console.log("End Date (Morning to Evening with 2 days):", endDate);
  2540. } else {
  2541. Swal.fire({
  2542. title: 'Slot Not Available',
  2543. text: 'The evening slots are not available for the selected date range.',
  2544. icon: 'warning',
  2545. confirmButtonText: 'OK'
  2546. });
  2547. document.getElementById('endDateInput').value = "";
  2548. //console.log("Morning or Evening slot not available for 2 days.");
  2549. }
  2550. } else {
  2551. //console.log("Unsupported duration for Morning to Morning slot.");
  2552. Swal.fire({
  2553. title: 'Invalid Selection',
  2554. text: 'The selected duration for the morning slot is not supported.',
  2555. icon: 'error',
  2556. confirmButtonText: 'OK'
  2557. });
  2558. document.getElementById('endDateInput').value = "";
  2559. }
  2560. } else if (startingSlot === "1" && endingSlot === "2") { // Morning to Evening
  2561. //console.log("Handling Morning to Evening slot.");
  2562. if (noofdays === 1) {
  2563. if (morningAvailable && eveningAvailable) {
  2564. endDate = new Date(start);
  2565. endDate.setDate(start.getDate() + Math.ceil(noofdays) - 1);
  2566. endDate = endDate.toISOString().split('T')[0];
  2567. document.getElementById('endDateInput').value = endDate;
  2568. //console.log("End Date (Morning to Evening):", endDate);
  2569. } else {
  2570. Swal.fire({
  2571. title: ' Slot Not Available',
  2572. text: 'The Selected slot is not available for the selected date range.',
  2573. icon: 'warning',
  2574. confirmButtonText: 'OK'
  2575. });
  2576. document.getElementById('endDateInput').value = "";
  2577. //console.log("Evening slot not available for", noofdays, "days.");
  2578. }
  2579. } else if (noofdays === 2) {
  2580. // Special handling for 2 days
  2581. let endDateCandidate = new Date(start);
  2582. endDateCandidate.setDate(start.getDate() + 1);
  2583. let endDateFormattedCandidate = endDateCandidate.toISOString().split('T')[0];
  2584. let endDateStatusCandidate = window.bookingResponse[endDateFormattedCandidate] || [false, false];
  2585. let morningAvailableOnEndDate = !endDateStatusCandidate[0]; // false means available
  2586. let eveningAvailableOnEndDate = !endDateStatusCandidate[1]; // false means available
  2587. if (morningAvailable && eveningAvailable && morningAvailableOnEndDate && eveningAvailableOnEndDate) {
  2588. endDate = endDateCandidate.toISOString().split('T')[0];
  2589. // --- GCC Block check for end date ---
  2590. if (isGCCBlockedDate(endDate)) {
  2591. Swal.fire({
  2592. title: 'End Date Not Available',
  2593. text: 'The end date is blocked by GCC. Please choose a different start date.',
  2594. icon: 'warning',
  2595. confirmButtonText: 'OK'
  2596. });
  2597. document.getElementById('endDateInput').value = "";
  2598. } else {
  2599. document.getElementById('endDateInput').value = endDate;
  2600. }
  2601. //console.log("End Date (Morning to Evening with 2 days):", endDate);
  2602. } else {
  2603. Swal.fire({
  2604. title: 'Slot Not Available',
  2605. text: 'The morning and/or evening slots are not available for the selected date range.',
  2606. icon: 'warning',
  2607. confirmButtonText: 'OK'
  2608. });
  2609. document.getElementById('endDateInput').value = "";
  2610. //console.log("Morning or Evening slot not available for 2 days.");
  2611. }
  2612. } else {
  2613. //console.log("Unsupported duration for Morning to Evening slot.");
  2614. Swal.fire({
  2615. title: 'Invalid Selection',
  2616. text: 'The selected duration for the morning to evening slot is not supported.',
  2617. icon: 'error',
  2618. confirmButtonText: 'OK'
  2619. });
  2620. document.getElementById('endDateInput').value = "";
  2621. }
  2622. } else if (startingSlot === "2" && endingSlot === "1") { // Evening to Morning
  2623. //console.log("Handling Evening to Morning slot.");
  2624. if (noofdays === 1) {
  2625. if (eveningAvailable) { // Check if evening slot is available
  2626. let nextDay = new Date(start);
  2627. nextDay.setDate(start.getDate() + 1);
  2628. let nextDayFormatted = nextDay.toISOString().split('T')[0];
  2629. let nextDayStatus = window.bookingResponse[nextDayFormatted] || [false, false];
  2630. let nextDayMorningAvailable = !nextDayStatus[0]; // false means available
  2631. if (nextDayMorningAvailable) {
  2632. endDate = nextDay.toISOString().split('T')[0];
  2633. // --- GCC Block check for end date ---
  2634. if (isGCCBlockedDate(endDate)) {
  2635. Swal.fire({
  2636. title: 'End Date Not Available',
  2637. text: 'The end date is blocked by GCC. Please choose a different start date.',
  2638. icon: 'warning',
  2639. confirmButtonText: 'OK'
  2640. });
  2641. document.getElementById('endDateInput').value = "";
  2642. } else {
  2643. document.getElementById('endDateInput').value = endDate;
  2644. }
  2645. //console.log("End Date (Evening to Morning):", endDate);
  2646. } else {
  2647. Swal.fire({
  2648. title: 'Morning Slot Not Available',
  2649. text: 'The morning slot is not available for the next day.',
  2650. icon: 'warning',
  2651. confirmButtonText: 'OK'
  2652. });
  2653. document.getElementById('endDateInput').value = "";
  2654. //console.log("Morning slot not available for the next day.");
  2655. }
  2656. } else {
  2657. Swal.fire({
  2658. title: 'Evening Slot Not Available',
  2659. text: 'The evening slot is not available for the selected date.',
  2660. icon: 'warning',
  2661. confirmButtonText: 'OK'
  2662. });
  2663. document.getElementById('endDateInput').value = "";
  2664. //console.log("Evening slot not available for", startDate);
  2665. }
  2666. } else {
  2667. //console.log("Unsupported duration for Evening to Morning slot.");
  2668. Swal.fire({
  2669. title: 'Invalid Selection',
  2670. text: 'The selected duration for the evening to morning slot is not supported.',
  2671. icon: 'error',
  2672. confirmButtonText: 'OK'
  2673. });
  2674. document.getElementById('endDateInput').value = "";
  2675. }
  2676. } else {
  2677. //console.log("Unsupported slot combination or duration.");
  2678. Swal.fire({
  2679. title: 'Invalid Slot Combination',
  2680. text: 'The selected slot combination or duration is not supported.',
  2681. icon: 'error',
  2682. confirmButtonText: 'OK'
  2683. });
  2684. document.getElementById('endDateInput').value = "";
  2685. }
  2686. } else {
  2687. //console.log("Start Date or Number of Days not provided.");
  2688. Swal.fire({
  2689. title: 'Invalid Input',
  2690. text: 'Please provide a valid start date and number of days.',
  2691. icon: 'error',
  2692. confirmButtonText: 'OK'
  2693. });
  2694. document.getElementById('endDateInput').value = "";
  2695. }
  2696. }
  2697. function datepickerFormat(dateString) {
  2698. var dateObject = new Date(dateString);
  2699. var year = dateObject.getFullYear();
  2700. var month = (dateObject.getMonth() + 1).toString().padStart(2, "0");
  2701. var day = dateObject.getDate().toString().padStart(2, "0");
  2702. return `${year}-${month}-${day}`;
  2703. }
  2704. function printTables() {
  2705. // Get the printable content
  2706. var printableContent = document.getElementById('printableContent').innerHTML;
  2707. // Open a print window
  2708. var printWindow = window.open('', '', 'height=400,width=600');
  2709. // Write the printable content to the print window
  2710. printWindow.document.write('<html><head><title>Print</title></head><body>' + printableContent + '</body></html>');
  2711. // Close the print window after printing
  2712. printWindow.document.close();
  2713. printWindow.print();
  2714. printWindow.close();
  2715. }
  2716. function Reschedule() {
  2717. // --- Slot availability check for today's date ---
  2718. var startDate = document.getElementById("startDateInput").value;
  2719. var startingSlot = document.getElementById("startingSlot").value;
  2720. var endingSlot = document.getElementById("endingSlotHidden").value;
  2721. var todayDateStr = $("#serverDate").val();
  2722. var currentHour = new Date().getHours();
  2723. if (startDate === todayDateStr) {
  2724. // Morning slot (1) is NOT available after 6 AM
  2725. if (startingSlot === "1" && currentHour >= 6) {
  2726. Swal.fire({
  2727. icon: 'warning',
  2728. title: 'Morning Slot Not Available',
  2729. text: 'The Morning slot is not available for today as it is already past 6:00 AM. Please select a different date.',
  2730. showConfirmButton: true
  2731. });
  2732. return;
  2733. }
  2734. // Evening/Afternoon slot (2) is NOT available after 2 PM (14:00)
  2735. if (endingSlot === "2" && currentHour >= 14) {
  2736. Swal.fire({
  2737. icon: 'warning',
  2738. title: 'Afternoon Slot Not Available',
  2739. text: 'The Afternoon/Evening slot is not available for today as it is already past 2:00 PM. Please select a different date.',
  2740. showConfirmButton: true
  2741. });
  2742. return;
  2743. }
  2744. // After 2 PM: no slots available at all for today
  2745. if (currentHour >= 14) {
  2746. Swal.fire({
  2747. icon: 'warning',
  2748. title: 'No Slots Available',
  2749. text: 'No slots are available for today as it is already past 2:00 PM. Please select a future date.',
  2750. showConfirmButton: true
  2751. });
  2752. return;
  2753. }
  2754. }
  2755. // --- End slot availability check ---
  2756. // Get mobile number and show OTP modal for verification
  2757. $.ajax({
  2758. type: "GET",
  2759. url: '/communityhall/user/api/viewAllBookingDetails',
  2760. data: { bookingId: rescheduleBookingId },
  2761. success: function (response) {
  2762. rescheduleMobileNumber = response.users.mobileNo;
  2763. // Show mobile number in OTP modal
  2764. document.getElementById("rescheduleMobileTxt").textContent = rescheduleMobileNumber;
  2765. // Clear any previous OTP errors
  2766. document.getElementById("rescheduleOtpError").textContent = "";
  2767. // Clear OTP inputs
  2768. for (let i = 1; i <= 5; i++) {
  2769. document.getElementById("rescheduleOtp" + i).value = "";
  2770. }
  2771. // Close date change modal and show OTP modal
  2772. $('#bookingRescheduleModal').modal('hide');
  2773. $('#rescheduleOtpModal').modal('show');
  2774. // Send OTP immediately
  2775. sendRescheduleOTP(rescheduleMobileNumber);
  2776. },
  2777. error: function () {
  2778. Swal.fire({
  2779. icon: 'error',
  2780. title: 'Error',
  2781. text: 'Failed to get booking details. Please try again.',
  2782. showConfirmButton: true
  2783. });
  2784. }
  2785. });
  2786. }
  2787. var rescheduleTimer = null;
  2788. var RESCHEDULE_TIME = 60;
  2789. function sendRescheduleOTP(mobileNumber) {
  2790. $.ajax({
  2791. type: "GET",
  2792. url: "/communityhall/user/api/sendOTP",
  2793. data: {
  2794. mobileNo: mobileNumber,
  2795. purpose: "reschedule"
  2796. },
  2797. success: function (response) {
  2798. // Start countdown timer
  2799. startRescheduleCountdown();
  2800. },
  2801. error: function () {
  2802. Swal.fire({
  2803. icon: 'error',
  2804. title: 'Error',
  2805. text: 'Failed to send OTP. Please try again.',
  2806. showConfirmButton: true
  2807. });
  2808. }
  2809. });
  2810. }
  2811. // function startRescheduleCountdown() {
  2812. // var resendTimeout;
  2813. // var resendLink = $("#rescheduleResendLink");
  2814. // $("#rescheduleResendLink").html('<a href="#" id="rescheduleResendLink" class="text-info" onclick="return resendRescheduleOTP();">Resend OTP</a>');
  2815. // var countdown = $("#rescheduleCountdown");
  2816. // function startCountdown() {
  2817. // var timeleft = 60;
  2818. // countdown.text(timeleft);
  2819. // resendTimeout = setInterval(function () {
  2820. // timeleft--;
  2821. // countdown.text(timeleft);
  2822. // if (timeleft <= 0) {
  2823. // clearInterval(resendTimeout);
  2824. // $("#rescheduleResendLink").html('<a href="#" id="rescheduleResendLink" class="text-info" onclick="return sendRescheduleOTP(' + rescheduleMobileNumber + ');">Resend OTP</a>');
  2825. // }
  2826. // }, 1000);
  2827. // }
  2828. // startCountdown();
  2829. // }
  2830. function startRescheduleCountdown() {
  2831. clearInterval(rescheduleTimer); // prevent multiple timers
  2832. var timeLeft = RESCHEDULE_TIME;
  2833. $("#rescheduleResendText").text("Please wait..");
  2834. $("#rescheduleCountdown").text(timeLeft);
  2835. rescheduleTimer = setInterval(function () {
  2836. timeLeft--;
  2837. $("#rescheduleCountdown").text(timeLeft);
  2838. if (timeLeft <= 0) {
  2839. clearInterval(rescheduleTimer);
  2840. $("#rescheduleResendText").html(
  2841. '<a href="#" class="text-info" onclick="sendRescheduleOTP(' + rescheduleMobileNumber + '); return false;">Resend OTP</a>'
  2842. );
  2843. $("#rescheduleCountdown").text('');
  2844. }
  2845. }, 1000);
  2846. }
  2847. function resendRescheduleOTP() {
  2848. if (rescheduleMobileNumber) {
  2849. sendRescheduleOTP(rescheduleMobileNumber);
  2850. // Restart countdown timer after resending OTP
  2851. startRescheduleCountdown();
  2852. }
  2853. }
  2854. function verifyRescheduleOtp() {
  2855. // Get all the input fields with class `otp-input`
  2856. var otpInputs = $('.otp-input');
  2857. // Get the OTP value as a string
  2858. var otpValue = '';
  2859. otpInputs.each(function () {
  2860. otpValue += $(this).val();
  2861. });
  2862. if (otpValue.length !== 5) {
  2863. document.getElementById("rescheduleOtpError").textContent = "Please enter complete OTP";
  2864. return false;
  2865. }
  2866. // Verify OTP
  2867. $.ajax({
  2868. type: "GET",
  2869. url: "/communityhall/user/api/verifyofficialOTP",
  2870. data: {
  2871. otp: otpValue
  2872. },
  2873. dataType: 'text',
  2874. success: function (response) {
  2875. if (response.trim() === "Success") {
  2876. // OTP verified successfully, close OTP modal and proceed with reschedule
  2877. $('#rescheduleOtpModal').modal('hide');
  2878. validateDatesAndReschedule();
  2879. } else {
  2880. document.getElementById("rescheduleOtpError").textContent = "OTP is Incorrect!!!";
  2881. // Clear OTP inputs
  2882. for (let i = 1; i <= 5; i++) {
  2883. document.getElementById("rescheduleOtp" + i).value = "";
  2884. }
  2885. }
  2886. },
  2887. error: function () {
  2888. document.getElementById("rescheduleOtpError").textContent = "Error verifying OTP. Please try again.";
  2889. }
  2890. });
  2891. return false;
  2892. }
  2893. function proceedWithReschedule() {
  2894. // Debug: Log the data being sent
  2895. console.log('Reschedule data:', {
  2896. bookingId: rescheduleBookingId,
  2897. startDate: rescheduleStartDate,
  2898. endDate: rescheduleEndDate,
  2899. startingSlot: rescheduleStartingSlot,
  2900. endingSlot: rescheduleEndingSlot
  2901. });
  2902. $.ajax({
  2903. type: "POST",
  2904. url: "/communityhall/user/api/reschedule-dates",
  2905. data: {
  2906. bookingId: rescheduleBookingId,
  2907. startDate: rescheduleStartDate,
  2908. endDate: rescheduleEndDate,
  2909. startingSlot: rescheduleStartingSlot,
  2910. endingSlot: rescheduleEndingSlot
  2911. },
  2912. success: function (response) {
  2913. Swal.fire({
  2914. icon: 'success',
  2915. title: 'Success',
  2916. text: 'Booking rescheduled successfully!',
  2917. showConfirmButton: true
  2918. }).then((result) => {
  2919. if (result.isConfirmed) {
  2920. // Close modal and reload page
  2921. $('#bookingRescheduleModal').modal('hide');
  2922. location.reload();
  2923. }
  2924. });
  2925. },
  2926. error: function (xhr, status, error) {
  2927. console.error('Reschedule API Error:', {
  2928. status: xhr.status,
  2929. statusText: xhr.statusText,
  2930. responseText: xhr.responseText,
  2931. error: error
  2932. });
  2933. let errorMessage = 'Failed to reschedule booking. Please try again.';
  2934. if (xhr.responseText) {
  2935. try {
  2936. const errorData = JSON.parse(xhr.responseText);
  2937. errorMessage = errorData.message || errorData.error || errorMessage;
  2938. } catch (e) {
  2939. errorMessage = xhr.responseText || errorMessage;
  2940. }
  2941. }
  2942. Swal.fire({
  2943. icon: 'error',
  2944. title: 'Error',
  2945. text: errorMessage,
  2946. showConfirmButton: true
  2947. });
  2948. }
  2949. });
  2950. }
  2951. function validateDatesAndReschedule() {
  2952. // Retrieve values from modal inputs
  2953. var startDate = document.getElementById("startDateInput").value;
  2954. var endDate = document.getElementById("endDateInput").value;
  2955. var originalStartDate = document.getElementById("startDatetext").value;
  2956. var startingSlot = document.getElementById("startingSlot").value;
  2957. // var endingSlot = document.getElementById("endingSlot").value;
  2958. var endingSlot = document.getElementById("endingSlotHidden").value;
  2959. // Get today's date from server
  2960. var todayDateStr = $("#serverDate").val();
  2961. var currentHour = new Date().getHours();
  2962. // Debug: Log the retrieved dates
  2963. console.log('Retrieved dates:', {
  2964. startDate: startDate,
  2965. endDate: endDate,
  2966. originalStartDate: originalStartDate,
  2967. startingSlot: startingSlot,
  2968. endingSlot: endingSlot,
  2969. todayDateStr: todayDateStr,
  2970. currentHour: currentHour
  2971. });
  2972. // Check if the rescheduled start date is the same as the original booked start date
  2973. // if (startDate === originalStartDate) {
  2974. // Swal.fire({
  2975. // icon: 'warning',
  2976. // title: 'Warning',
  2977. // text: 'Your Rescheduled Start Date is the same as Your booking Start Date. Please change the date.',
  2978. // showConfirmButton: true
  2979. // });
  2980. // return;
  2981. // }
  2982. if (!endDate) {
  2983. Swal.fire({
  2984. icon: 'error',
  2985. title: 'Error',
  2986. text: 'End Date is Empty! Please check your Start Date',
  2987. showConfirmButton: true
  2988. });
  2989. return;
  2990. }
  2991. // --- Slot availability check for today's date ---
  2992. // If the new start date is today, validate slot against current time
  2993. if (startDate === todayDateStr) {
  2994. // Morning slot (1) is NOT available after 6 AM
  2995. if (startingSlot === "1" && currentHour >= 6) {
  2996. Swal.fire({
  2997. icon: 'warning',
  2998. title: 'Morning Slot Not Available',
  2999. text: 'The Morning slot is not available for today as it is already past 6:00 AM. Please select a different date or slot.',
  3000. showConfirmButton: true
  3001. });
  3002. return;
  3003. }
  3004. // Evening/Afternoon slot (2) is NOT available after 2 PM (14:00)
  3005. if (endingSlot === "2" && currentHour >= 14) {
  3006. Swal.fire({
  3007. icon: 'warning',
  3008. title: 'Afternoon Slot Not Available',
  3009. text: 'The Afternoon/Evening slot is not available for today as it is already past 2:00 PM. Please select a different date.',
  3010. showConfirmButton: true
  3011. });
  3012. return;
  3013. }
  3014. // After 2 PM: no slots available at all for today
  3015. if (currentHour >= 14) {
  3016. Swal.fire({
  3017. icon: 'warning',
  3018. title: 'No Slots Available',
  3019. text: 'No slots are available for today as it is already past 2:00 PM. Please select a future date.',
  3020. showConfirmButton: true
  3021. });
  3022. return;
  3023. }
  3024. }
  3025. // --- End slot availability check ---
  3026. // Store the validated dates
  3027. rescheduleStartDate = startDate;
  3028. rescheduleEndDate = endDate;
  3029. rescheduleStartingSlot = document.getElementById('startingSlot').value;
  3030. rescheduleEndingSlot = document.getElementById('endingSlotHidden').value;
  3031. // Debug: Log the final dates being sent
  3032. console.log('Final reschedule dates:', {
  3033. startDate: rescheduleStartDate,
  3034. endDate: rescheduleEndDate,
  3035. startingSlot: rescheduleStartingSlot,
  3036. endingSlot: rescheduleEndingSlot,
  3037. bookingId: rescheduleBookingId
  3038. });
  3039. proceedWithReschedule();
  3040. }
  3041. $(document).ready(function () {
  3042. // DataTables buttons configuration
  3043. var buttons = [
  3044. {
  3045. extend: 'pageLength',
  3046. className: 'btn btn-primary'
  3047. }
  3048. ];
  3049. $('#simpletable').DataTable({
  3050. dom: 'Bftip',
  3051. columnDefs: [
  3052. { targets: 'no-sort', orderable: false }
  3053. ],
  3054. lengthMenu: [
  3055. [5, 10, 20, 50, -1],
  3056. ['5 rows', '10 rows', '20 rows', '50 rows', 'Show all']
  3057. ],
  3058. scrollY: '50vh',
  3059. fixedColumns: {
  3060. left: 1,
  3061. right: 1
  3062. },
  3063. buttons: [buttons],
  3064. responsive: true,
  3065. searching: true, // Enable search
  3066. select: false,
  3067. processing: false,
  3068. });
  3069. $('#searchInput').on('keyup', function () {
  3070. dataTable.search(this.value).draw();
  3071. });
  3072. });
  3073. $(document).on('change', '.nocfile', function () {
  3074. validateFile(this);
  3075. });
  3076. function transactionHistory(userId) {
  3077. $.ajax({
  3078. type: "GET",
  3079. url: '/communityhall/user/api/getTransactionDetails',
  3080. data: { 'userId': userId },
  3081. success: function (data) {
  3082. // console.log("Full response:", data);
  3083. // console.log("Refund Details:", data.refundDetails);
  3084. const transactions = data.transactions || [];
  3085. const refundDetails = data.refundDetails || [];
  3086. populateTransactionTable(transactions);
  3087. populateRefundDetailsTable(refundDetails);
  3088. $('#transactionHistoryModal').modal('show'); // Show the modal
  3089. },
  3090. error: function (error) {
  3091. console.error("Error fetching transaction details", error);
  3092. }
  3093. });
  3094. }
  3095. function populateTransactionTable(transactions) {
  3096. const tableBody = $('#transactionTable tbody');
  3097. tableBody.empty(); // Clear any existing rows
  3098. transactions.forEach((transaction, index) => {
  3099. const paymentStatus = (transaction.statusCode === "0300" && transaction.response?.includes("success"))
  3100. ? "Success"
  3101. : "Payment Failed";
  3102. const row = `
  3103. <tr>
  3104. <td>${index + 1}</td>
  3105. <td>${transaction.bookingId}</td>
  3106. <td>${transaction.amount || '-'}</td>
  3107. <td>${transaction.date || '-'}</td>
  3108. <td>${transaction.txansactionId || '-'}</td>
  3109. <td>${paymentStatus}</td>
  3110. </tr>
  3111. `;
  3112. tableBody.append(row); // Append the row to the table body
  3113. });
  3114. }
  3115. function populateRefundDetailsTable(refundDetails) {
  3116. const refundTable = $('#refunddetails');
  3117. const tableBody = $('#refunddetailsTable tbody');
  3118. tableBody.empty(); // Clear any existing rows
  3119. if (refundDetails.length > 0) {
  3120. refundTable.show(); // Show the refund details table
  3121. refundDetails.forEach((refund, index) => {
  3122. const row = `
  3123. <tr>
  3124. <td>${index + 1}</td>
  3125. <td>${refund.bookingId}</td>
  3126. <td>${refund.amount}</td>
  3127. <td>${refund.date}</td>
  3128. <td>${refund.txansactionId}</td>
  3129. <td>${refund.refundAmount}</td>
  3130. </tr>
  3131. `;
  3132. tableBody.append(row);
  3133. });
  3134. } else {
  3135. refundTable.hide(); // Hide the refund details table
  3136. }
  3137. }
  3138. // Toggle Chat Box
  3139. function toggleChat() {
  3140. const chatBox = document.getElementById('chat-box');
  3141. chatBox.style.display = (chatBox.style.display === 'block') ? 'none' : 'block';
  3142. }
  3143. // Send Message
  3144. function sendMessage() {
  3145. const userInput = document.getElementById('userInput');
  3146. const message = userInput.value.trim();
  3147. if (message) {
  3148. // Create message element
  3149. const chatBody = document.getElementById('chat-body');
  3150. const userMessage = document.createElement('div');
  3151. userMessage.className = 'user-message';
  3152. userMessage.textContent = message;
  3153. chatBody.appendChild(userMessage);
  3154. chatBody.scrollTop = chatBody.scrollHeight; // Auto-scroll to bottom
  3155. // Send message to the server (Spring Boot API)
  3156. fetch('/communityhall/admin/api/send', {
  3157. method: 'POST',
  3158. headers: {
  3159. 'Content-Type': 'application/json',
  3160. },
  3161. body: JSON.stringify({ message }),
  3162. })
  3163. .then(response => response.json())
  3164. .then(data => {
  3165. // Add response message to chat
  3166. const responseMessage = document.createElement('div');
  3167. responseMessage.className = 'bot-message';
  3168. responseMessage.textContent = data.response;
  3169. chatBody.appendChild(responseMessage);
  3170. chatBody.scrollTop = chatBody.scrollHeight;
  3171. });
  3172. userInput.value = ''; // Clear input field
  3173. }
  3174. }
  3175. // ── Slot helper ──────────────────────────────────────────────────────
  3176. // Ending slot is deterministic: given (startSlot + noOfDays) there is
  3177. // exactly one valid ending slot. The user can only change Starting Slot;
  3178. // Ending Slot auto-fixes based on this table:
  3179. //
  3180. // noOfDays | start=1(Morning) → end | start=2(Afternoon) → end
  3181. // ---------|------------------------|-------------------------
  3182. // 0.5 | 1 (same slot, half-day) | 2 (same slot, half-day)
  3183. // 1 | 2 (6AM→10PM, full day) | 1 (2PM→next day 2PM)
  3184. // 1.5 | 1 (6AM→next day 2PM) | 2 (2PM→next day 10PM)
  3185. // 2 | 2 (6AM→day+1 10PM) | ❌ not allowed
  3186. function computeEndingSlot(startSlot, noOfDays) {
  3187. startSlot = String(startSlot);
  3188. noOfDays = parseFloat(noOfDays);
  3189. if (noOfDays === 0.5) return startSlot; // same slot, half-day
  3190. if (noOfDays === 1) return startSlot === "1" ? "2" : "1"; // flip: full-day
  3191. if (noOfDays === 1.5) return startSlot; // same slot, 1.5 days
  3192. if (noOfDays === 2) return startSlot === "1" ? "2" : null; // only morning valid for 2-day
  3193. return null;
  3194. }
  3195. // When user changes Starting Slot → auto-fix Ending Slot, re-validate end date
  3196. document.getElementById("startingSlot").addEventListener("change", function () {
  3197. var startSlot = this.value;
  3198. var noOfDays = parseFloat(document.getElementById("noOfDaysInput").value);
  3199. var endSlot = computeEndingSlot(startSlot, noOfDays);
  3200. // Guard: Afternoon start is not valid for 2-day booking
  3201. if (endSlot === null) {
  3202. Swal.fire({
  3203. icon: 'warning',
  3204. title: 'Slot Not Allowed',
  3205. text: 'Afternoon start is not supported for a ' + noOfDays + '-day booking. Reverting to the original slot.',
  3206. showConfirmButton: true
  3207. });
  3208. this.value = String(rescheduleStartingSlot);
  3209. return;
  3210. }
  3211. // Auto-fix the (disabled) ending slot display and its hidden mirror
  3212. document.getElementById("endingSlot").value = endSlot;
  3213. document.getElementById("endingSlotHidden").value = endSlot;
  3214. // Clear the computed end date — user must re-pick or it will re-compute
  3215. document.getElementById("endDateInput").value = "";
  3216. // If a start date is already selected, re-compute end date immediately
  3217. var startDate = document.getElementById("startDateInput").value;
  3218. if (startDate) {
  3219. updateEndDate(startDate, noOfDays, startSlot, endSlot);
  3220. }
  3221. });
  3222. // OTP input navigation for reschedule modal
  3223. $('.otp-input').on('keyup', function (e) {
  3224. var $this = $(this);
  3225. if ($this.val().length === 1) {
  3226. $this.next('.otp-input').focus();
  3227. }
  3228. if ($this.val().length === 0) {
  3229. $this.prev('.otp-input').focus();
  3230. }
  3231. });
  3232. // Clear OTP inputs when OTP modal is shown
  3233. $('#rescheduleOtpModal').on('shown.bs.modal', function () {
  3234. $('.otp-input').val('');
  3235. $('#rescheduleOtpError').text('');
  3236. });
  3237. </script>
  3238. </div>
  3239. </div>
  3240. </div>
  3241. </body>
  3242. </html>