PageSourceSearch

https://www.gurukrupabus.com/cms_builds/4516/gurukrupa-travels%C2%…/common/javascript/bookingConfirmPage.js

js gurukrupabus.com collected 2026-10-02 01:32:35 UTC 44,989 bytes, 1,251 lines download raw bytes

1// Booking Confirm Page Load Handler
2document.addEventListener("DOMContentLoaded", function () {
3  // Check if current URL contains /booking-confirm
4  if (
5    window.location.pathname.includes("/booking-confirm") ||
6    isTicketDetailsPage()
7  ) {
8    initBookingConfirmationPage();
9    initTicketDetailsPage();
10  }
11});
12
13function initBookingConfirmationPage() {
14  window.printTicketTemplate =
15    typeof print_ticket === "function" ? print_ticket() : "";
16  window.ticketDetail = null;
17  let params = getParamsData(window.location.search);
18  startLoading('[data-widget-id="print_ticket"]');
19  loadPrintTicket(params);
20}
21
22function initTicketDetailsPage() {
23  initModifyTicketModals();
24}
25
26function initModifyTicketModals() {
27  window.cancelTicketModal = new CustomModal({
28    header: cancelTicketHeader(),
29    body: `<div></div>`,
30    className: "modify-ticket-modal",
31  });
32  window.modifyTicketModal = new CustomModal({
33    header: "",
34    width: "800px",
35    showHeader: false,
36    body: `<div></div>`,
37    className: "modify-ticket-modal",
38  });
39}
40
41function modifyTicket() {
42  let { email = "", mobile = "" } =
43    window.ticketDetail?.onward?.passenger_details[0] || {};
44  let mobileNumber = mobile.split("-")[1] || mobile.split("-")[0] || "";
45  window.modifyTicketModal.setBody(
46    constructModifyTicketContent({ email, mobileNumber }),
47  );
48  window.modifyTicketModal.show();
49  let boardingPointOptions = [];
50  window.ticketDetail?.onward?.available_stages?.forEach((stages) => {
51    boardingPointOptions.push({
52      value: stages[1],
53      label: stages[0],
54    });
55  });
56  let droppingPointOptions = [];
57  window.ticketDetail?.onward?.available_droppoff_stages?.forEach((stages) => {
58    droppingPointOptions.push({
59      value: stages[1],
60      label: stages[0],
61    });
62  });
63  const modifyBoardingElement = document.getElementById("boardingPoint");
64  const modifyDroppingElement = document.getElementById("droppingPoint");
65
66  window.modifyVirtualBoardingElement = VirtualSelect.init({
67    ele: modifyBoardingElement,
68    options: boardingPointOptions,
69    hideClearButton: true,
70    dropboxWrapper: ".cms-modal-overlay",
71    popupDropboxBreakpoint: "200px",
72  });
73
74  window.modifyVirtualDroppingElement = VirtualSelect.init({
75    ele: modifyDroppingElement,
76    options: droppingPointOptions,
77    hideClearButton: true,
78    dropboxWrapper: ".cms-modal-overlay",
79    popupDropboxBreakpoint: "200px",
80  });
81  setTimeout(() => {
82    window.modifyVirtualBoardingElement.setValue(
83      window.ticketDetail?.onward?.boarding_details.stage_id.toString(),
84    );
85    window.modifyVirtualBoardingElement.$valueText.innerText =
86      boardingPointOptions.find(
87        (option) =>
88          option.value ===
89          window.ticketDetail?.onward?.boarding_details.stage_id,
90      )?.label || "";
91    window.modifyVirtualDroppingElement.setValue(
92      window.ticketDetail?.onward?.drop_off_details.stage_id.toString(),
93    );
94    window.modifyVirtualDroppingElement.$valueText.innerText =
95      droppingPointOptions.find(
96        (option) =>
97          option.value ===
98          window.ticketDetail?.onward?.drop_off_details.stage_id,
99      )?.label || "";
100  }, 100);
101
102  window.searchWidgetForm = new window.JustValidate(
103    ".modify-ticket-modal-form",
104  );
105
106  window.searchWidgetForm
107    .addField("#mobileNumber", [
108      {
109        rule: "required",
110        errorMessage: "Please enter mobile number",
111      },
112      {
113        rule: "minLength",
114        value: 10,
115        errorMessage: "Mobile number must be 10 digits",
116      },
117      {
118        rule: "maxLength",
119        value: 10,
120        errorMessage: "Mobile number must be 10 digits",
121      },
122    ])
123    .addField("#email", [
124      {
125        rule: "required",
126        errorMessage: "Please enter email",
127      },
128      {
129        rule: "email",
130        errorMessage: "Please enter a valid email address",
131      },
132    ])
133    .addField("#boardingPoint", [
134      {
135        rule: "required",
136        errorMessage: "Please select boarding point",
137      },
138    ])
139    .addField("#droppingPoint", [
140      {
141        rule: "required",
142        errorMessage: "Please select dropping point",
143      },
144    ]);
145
146  window.searchWidgetForm.onSuccess(async (event) => {
147    buttonLoading("#modify-ticket-submit-button");
148    updateTicketDetails();
149  });
150  window.searchWidgetForm.onFail((event) => {
151    buttonStopLoading("#modify-ticket-submit-button");
152  });
153}
154
155function updateTicketDetails() {
156  const data = {};
157  const ticket_number = window.ticketDetail.onward.ticket_number;
158  const phoneNumber = document.getElementById("mobileNumber").value;
159  data.query = "q15";
160  data.pnr_number = ticket_number;
161  data.phone_number = phoneNumber;
162  data.boarding_at = window.modifyVirtualBoardingElement.getValue();
163  data.country_code = "91";
164  data.email = document.getElementById("email").value;
165  data.dropping_at = window.modifyVirtualDroppingElement.getValue();
166
167  apiClient.post("/api/cms_booking_engine.json", data).then((res) => {
168    if (res.status === 200) {
169      if (res.data.code == 500) {
170        message.error(res.data.message);
171        buttonStopLoading("#modify-ticket-submit-button");
172      } else {
173        if (res.data != undefined && res.data.key != undefined) {
174          var url_data = `key=${res.data.key}`;
175        } else {
176          var url_data = `pnr_number=${ticket_number}&email=${phoneNumber}`;
177        }
178        buttonStopLoading("#modify-ticket-submit-button");
179        window.modifyTicketModal.hide();
180        setTimeout(() => {
181          message.success(
182            res.data.message ? res.data.message : "Ticket Updated Successfully",
183          );
184          setTimeout(() => {
185            window.location = `${window.location.origin}${window.location.pathname}?${url_data}`;
186          }, 1000);
187        }, 1000);
188      }
189      //window.location.reload();
190    } else {
191      buttonStopLoading("#modify-ticket-submit-button");
192      window.modifyTicketModal.hide();
193      setTimeout(() => {
194        message.error(res.data.message);
195      }, 1000);
196    }
197  });
198
199  // if (sysConfigurationModifyTicket) {
200  // }
201}
202
203function isTicketDetailsPage() {
204  return window.location.pathname.includes("/ticket-details"); //|| window.location.pathname.includes('/my-bookings');
205}
206
207async function loadPrintTicket(params = {}, cb = null) {
208  const state = window.store?.getState();
209  if (!state || !params) return;
210  const { operatorDetails } = state.config;
211  try {
212    const response = await apiClient.post("/api/cms_booking_engine.json", {
213      query: "q12",
214      ...params,
215    });
216    if (response.data.code === 419) {
217      message.error(
218        response.data.message ||
219          "Could not found this E-ticket. Please check the ticket number!",
220      );
221      setTimeout(() => {
222        window.location.href = "/manage-booking";
223      }, 2000);
224      return false;
225    }
226    if (response.status === 200 && response.data) {
227      const data = response.data;
228      window.ticketDetail = data || null;
229
230      if (cb && typeof cb === "function") {
231        cb();
232      }
233
234      let html = "";
235      html += constructTicketDetailsPageHeader();
236
237      html += renderTemplate(window.printTicketTemplate, {
238        logoUrl: window.logoUrl || "",
239        operator_address: operatorDetails.operator_address,
240        operator_work_number: operatorDetails.operator_work_number,
241        ...data,
242      });
243      //data-widget-id="print_ticket" append inside the div
244      const container = document.querySelector(
245        '[data-widget-id="print_ticket"]',
246      );
247      if (!container) {
248        return false;
249      }
250      document.querySelector('[data-widget-id="print_ticket"]').innerHTML =
251        html;
252      stopLoading('[data-widget-id="print_ticket"]');
253      const headerContentContainer = document.querySelector(
254        ".print_ticket-1-header-content-container",
255      );
256      if (isTicketDetailsPage()) {
257        if (
258          headerContentContainer &&
259          headerContentContainer.children.length > 0
260        ) {
261          headerContentContainer.children[0].style.display = "none";
262          headerContentContainer.children[1].style.display = "none";
263        }
264        document.getElementById("tracking_details_container").style.display =
265          "flex";
266      }
267    }
268  } catch (error) {
269    stopLoading('[data-widget-id="print_ticket"]');
270    console.error("Error fetching booking data:", error);
271  }
272}
273
274function printTicket() {
275  window.print();
276}
277
278function downloadTicket() {
279  if (!ticketDetail.onward.ticket_number) {
280    message.error("Ticket number not found!");
281    return;
282  }
283  let api_url = window.API_URL;
284  window.open(
285    `${api_url}/t_tickets/cms_download_pdf_ticket?pnr_number=${ticketDetail.onward.ticket_number}&is_new_cms=true`,
286    "_blank",
287  );
288}
289
290function constructTicketDetailsPageHeader() {
291  let actionList = window.ticketDetail.onward.is_eticket
292    ? [
293        {
294          label: "Print ticket",
295          onClick: "printTicket()",
296          is_visible: true,
297        },
298        {
299          label: "Download ticket",
300          onClick: "downloadTicket()",
301          is_visible: true,
302        },
303        {
304          label: "Prepone / postpone",
305          onClick: "cancelTicket(1)",
306          is_visible: window.ticketDetail?.is_pre_postpone_allowed,
307        },
308        {
309          label: "Modify ticket",
310          onClick: "modifyTicket()",
311          is_visible: window.ticketDetail?.is_update_allowed,
312        },
313        {
314          label: "Cancel ticket",
315          onClick: "cancelTicket(2)",
316          is_visible: window.ticketDetail?.is_cancellation_allowed,
317        },
318      ]
319    : [
320        {
321          label: "Print ticket",
322          onClick: "printTicket()",
323          is_visible: true,
324        },
325        {
326          label: "Modify ticket",
327          onClick: "modifyTicket()",
328          is_visible:
329            window.ticketDetail.sys_confinguration_modify_ticket &&
330            window.ticketDetail?.is_update_allowed,
331        },
332      ];
333  html = `
334              <div class="ticket-details-header_container">
335              <div class="ticket-details-header">
336                  <div class="title-section">
337                    Booking details
338                  </div>
339                  <div class="action-section">`;
340  actionList.forEach((action) => {
341    if (action.is_visible === false) return;
342    html += `<button class="modify-ticket-button" onclick="${action.onClick}">
343    ${action.label}
344    <img src="${window.domain}/common/assets/images/arrow_forward.svg" alt="arrow right" />
345    </button>`;
346  });
347  html += `</div>
348                </div>
349                </div>
350                `;
351  return html;
352}
353
354function cancelTicket(tabType) {
355  window.cancelTicketModal.setBody(cancelTicketBody(tabType));
356  window.cancelTicketModal.show();
357  let contentTemplate = "";
358  let params = getParamsData(window.location.search);
359  if (window.cancelTicketModal && tabType === 2) {
360    contentTemplate = cancelTicketContent();
361    const state = window.store?.getState();
362    const { user } = state?.user || {};
363    document.getElementById("modify-ticket-body-content").innerHTML =
364      renderTemplate(contentTemplate, {
365        ...window.ticketDetail.onward,
366        is_coupon_allowed: window.ticketDetail.is_coupon_allowed,
367        is_cash_credit: window.ticketDetail.is_cash_credit,
368        is_guest_user: !user,
369      });
370    if (params.is_from_my_booking !== "true") {
371      document.querySelector(
372        'input[name="refund_type"][value="' +
373          (window.ticketDetail.onward.is_coupon_allowed &&
374          !window.ticketDetail.onward.wallet_booking &&
375          !window.ticketDetail.onward.default_cash_credit
376            ? "true"
377            : "false") +
378          '"]',
379      ).checked = true;
380    }
381    //#cancel-ticket-button
382    document.getElementById("cancel-ticket-button").style.display = "flex";
383    document.getElementById("pre-postPone-button").style.display = "none";
384  } else if (window.cancelTicketModal && tabType === 1) {
385    contentTemplate = prePostPoneTicketContent();
386    document.getElementById("modify-ticket-body-content").innerHTML =
387      renderTemplate(contentTemplate, {
388        ...window.ticketDetail.onward,
389        reschedule_percentage:
390          window.ticketDetail.reschedule_percentage > 0 &&
391          typeof window.ticketDetail.reschedule_percentage === "number"
392            ? `${window.ticketDetail.reschedule_percentage.toString()}%`
393            : "₹0",
394      });
395    initPrePostPoneDatePicker();
396    //#pre-postPone-button
397    document.getElementById("cancel-ticket-button").style.display = "none";
398    document.getElementById("pre-postPone-button").style.display = "flex";
399  }
400}
401
402function initPrePostPoneDatePicker() {
403  let prePostPoneDatePicker = null;
404  const newTravelDateInput = document.getElementById("newTravelDate");
405  const travelDate = window.ticketDetail.onward.travel_date;
406  prePostPoneDatePicker = flatpickr("#newTravelDate", {
407    altInput: true,
408    altFormat: "j F Y",
409    dateFormat: "d/m/Y", // Changed to match original '"24/12/2025"' format
410    minDate: "today",
411    allowInput: true,
412    clickOpens: true,
413    altInputClass: "flatpickr-input", // Custom class for input
414    disableMobile: "true",
415    onReady: function (selectedDates, dateStr, instance) {
416      // Get the alternate input (the visible one) instead of the original hidden input
417      const altInput = instance.altInput;
418
419      if (altInput) {
420        const wrapper = document.createElement("div");
421        wrapper.className = "PrePostPone-datepicker-wrapper";
422        wrapper.style.cssText = `
423            position: relative;
424            display: flex;
425            align-items: center;
426            width: 100%;
427          `;
428
429        // Insert wrapper before the alternate input
430        document.querySelector(".PrePostPone-datepicker-wrapper")?.remove(); // Remove any existing wrapper
431        altInput.parentNode.insertBefore(wrapper, altInput);
432
433        // Move alternate input into wrapper
434        wrapper.appendChild(altInput);
435
436        // Create calendar icon
437        const calendarIcon = document.createElement("img");
438        calendarIcon.className = "calendar-icon";
439        calendarIcon.src = `${window.domain}/common/assets/images/calendar_today.svg`;
440        calendarIcon.alt = "Calendar Icon";
441        calendarIcon.style.cssText = `
442            position: absolute;
443            right: 0px;
444            margin-right: 16px;
445            top: 50%;
446            transform: translateY(-50%);
447            width: 20px;
448            height: 20px;
449            cursor: pointer;
450            z-index: 1;
451          `;
452
453        // Add click event to icon to open calendar
454        calendarIcon.addEventListener("click", function (e) {
455          e.preventDefault();
456          instance.open();
457        });
458
459        wrapper.appendChild(calendarIcon);
460      }
461    },
462    onClose: function (selectedDates, dateStr, instance) {
463      if (!dateStr) {
464        document
465          .getElementById("newTravelDate")
466          .classList.add("placeholder-active");
467        document
468          .getElementById("newTravelDate")
469          .setAttribute("placeholder", "Onward Date");
470      }
471    },
472  });
473}
474
475function cancelTicketHeader() {
476  const html = String.raw;
477  const htmlContent = html`<div class="modify-ticket-header">
478    <div class="icon-container">
479      <svg
480        width="24"
481        height="24"
482        viewBox="0 0 24 24"
483        fill="none"
484        xmlns="http://www.w3.org/2000/svg"
485      >
486        <path
487          d="M20 3H19V1H17V3H7V1H5V3H4C2.9 3 2 3.9 2 5V21C2 22.1 2.9 23 4 23H20C21.1 23 22 22.1 22 21V5C22 3.9 21.1 3 20 3ZM20 21H4V10H20V21ZM20 8H4V5H20V8Z"
488          fill="#FF4800"
489        />
490      </svg>
491    </div>
492    <div class="text-container">
493      <div class="title">Prepone/ postpone ticket</div>
494      <div class="description">You have a FlexiTicket</div>
495    </div>
496  </div>`;
497  return htmlContent;
498}
499
500function cancelTicketBody(tabType) {
501  let html = "";
502  html += `<div class="modify-ticket-body">`;
503  html += `<div class="modify-ticket-body-description">You have a FlexiTicket</div>`;
504  html += cancelTicketTabs(tabType);
505  html += `<div class="modify-ticket-body-content" id="modify-ticket-body-content">`;
506  html += `</div>`;
507  html += `</div>`;
508  return html;
509}
510
511function cancelTicketTabs(tabType) {
512  const refund_percentage =
513    100 - window.ticketDetail.onward.cancellation_percentage;
514  const id_reschedule_percentage =
515    window.ticketDetail.reschedule_percentage > 0 &&
516    typeof window.ticketDetail.reschedule_percentage === "number";
517  let html = "";
518  html += `<div class="modify-ticket-tabs" id="modify-ticket-tabs">`;
519  html += `<div class="modify-ticket-tab" onclick="cancelTicketTabContent(1)">`;
520  html += `<div class="tab-form-container">`;
521  html += `<input type="radio" name="modify-ticket-tab" id="change-date-tab" ${tabType === 1 ? "checked" : ""} />`;
522  html += `<div class="tab-label">`;
523  html += `<div class="tab-title">Prepone / postpone${!id_reschedule_percentage ? ' for <span class="highlight">FREE</span>' : ""}</div>`;
524  html += `<div class="tab-description">Subject to seat availability</div>`;
525  html += `</div>`;
526  html += `</div>`;
527  html += `<div class="tab-action-button-container"><button class="tab-action-button" id="pre-postPone-button" onclick="showTicketTabContent(1)">Date change ${!id_reschedule_percentage ? "for free" : ""}</button></div>`;
528  html += `</div>`;
529  html += `<div class="modify-ticket-tab" onclick="cancelTicketTabContent(2)">`;
530  html += `<div class="tab-form-container">`;
531  html += `<input type="radio" name="modify-ticket-tab" id="cancel-ticket-tab" ${tabType === 2 ? "checked" : ""} />`;
532  html += `<div class="tab-label">`;
533  html += `<div class="tab-title">Cancel ticket</div>`;
534  html += `<div class="tab-description">${refund_percentage || 0}% of total fare will be refunded</div>`;
535  html += `</div>`;
536  html += `</div>`;
537  html += `<div class="tab-action-button-container"><button class="tab-action-button" id="cancel-ticket-button" onclick="showTicketTabContent(2)">Review and cancel</button></div>`;
538  html += `</div>`;
539  html += `</div>`;
540  return html;
541}
542
543function showTicketTabContent(tabType) {
544  this.event.stopPropagation();
545  window.cancelTicketModal.hideHeader();
546  document.getElementById("modify-ticket-tabs").style.display = "none";
547  document.getElementById("modify-ticket-body-content").style.display = "flex";
548}
549
550function cancelTicketTabContent(tabType) {
551  // stop propagation to avoid triggering parent onclick
552  this.event.stopPropagation();
553  if (tabType === 1) {
554    window.cancelTicketModal.setBody(cancelTicketBody(tabType));
555    contentTemplate = prePostPoneTicketContent();
556    document.getElementById("modify-ticket-body-content").innerHTML =
557      renderTemplate(contentTemplate, {
558        ...window.ticketDetail.onward,
559        reschedule_percentage:
560          window.ticketDetail.reschedule_percentage > 0 &&
561          typeof window.ticketDetail.reschedule_percentage === "number"
562            ? `${window.ticketDetail.reschedule_percentage.toString()}%`
563            : "₹0",
564      });
565    initPrePostPoneDatePicker();
566    //#pre-postPone-button
567    document.getElementById("cancel-ticket-button").style.display = "none";
568    document.getElementById("pre-postPone-button").style.display = "flex";
569  } else if (tabType === 2) {
570    window.cancelTicketModal.setBody(cancelTicketBody(tabType));
571    contentTemplate = cancelTicketContent();
572    const state = window.store?.getState();
573    const { user } = state?.user || {};
574    document.getElementById("modify-ticket-body-content").innerHTML =
575      renderTemplate(contentTemplate, {
576        ...window.ticketDetail.onward,
577        is_guest_user: !user,
578      });
579
580    //refund_type set value to true if isCoupon is true else false
581    if (document.querySelector('input[name="refund_type"]')) {
582      document.querySelector(
583        'input[name="refund_type"][value="' +
584          (window.ticketDetail.onward.is_coupon_allowed &&
585          !window.ticketDetail.onward.wallet_booking &&
586          !window.ticketDetail.onward.default_cash_credit
587            ? "true"
588            : "false") +
589          '"]',
590      ).checked = true;
591    }
592    document.getElementById("cancel-ticket-button").style.display = "flex";
593    document.getElementById("pre-postPone-button").style.display = "none";
594  }
595}
596
597function showTabHeader() {
598  window.cancelTicketModal.showHeader();
599  document.getElementById("modify-ticket-tabs").style.display = "flex";
600  document.getElementById("modify-ticket-body-content").style.display = "none";
601}
602
603function cancelTicketContent() {
604  const html = String.raw;
605  const htmlContent = html`
606    <div class="mobile-cancel-ticket-header" onclick="showTabHeader()">
607      <svg
608        width="24"
609        height="24"
610        viewBox="0 0 24 24"
611        fill="none"
612        xmlns="http://www.w3.org/2000/svg"
613      >
614        <path
615          d="M20 11H7.83L13.42 5.41L12 4L4 12L12 20L13.41 18.59L7.83 13H20V11Z"
616          fill="black"
617        />
618      </svg>
619      Cancellation
620    </div>
621    <div class="cancel-ticket-modal-header">
622      <div class="cancel-ticket-modal-journey-container">
623        <div class="cancel-ticket-modal-journey-separator-container-mobile">
624          <div class="cancel-ticket-modal-journey-separator-dot"></div>
625          <div class="cancel-ticket-modal-journey-separator"></div>
626          <div class="cancel-ticket-modal-journey-separator-dot"></div>
627        </div>
628        <div class="cancel-ticket-modal-journey-details">
629          <div class="cancel-ticket-modal-journey-point">
630            <div class="cancel-ticket-modal-journey-time-date-container">
631              <div class="cancel-ticket-modal-journey-time">{{dep_time}}</div>
632              <div class="cancel-ticket-modal-journey-date">
633                {{dayjs(travel_date, 'DD/MM/YYYY').format('dddd D MMMM YYYY')}}
634              </div>
635            </div>
636            <div class="cancel-ticket-modal-journey-city">From {{origin}}</div>
637          </div>
638          <div class="cancel-ticket-modal-journey-duration-container">
639            <div class="cancel-ticket-modal-journey-separator-dot"></div>
640            <div class="cancel-ticket-modal-journey-separator"></div>
641            <div class="cancel-ticket-modal-journey-duration">{{duration}}</div>
642            <div class="cancel-ticket-modal-journey-separator"></div>
643            <div class="cancel-ticket-modal-journey-separator-dot"></div>
644          </div>
645          <div class="cancel-ticket-modal-journey-point">
646            <div class="cancel-ticket-modal-journey-time-date-container">
647              <div class="cancel-ticket-modal-journey-time">{{arr_time}}</div>
648              <div class="cancel-ticket-modal-journey-date">
649                {{dayjs(arr_date, 'DD/MM/YYYY').format('dddd D MMMM YYYY')}}
650              </div>
651            </div>
652            <div class="cancel-ticket-modal-journey-city">
653              To {{destination}}
654            </div>
655          </div>
656        </div>
657      </div>
658    </div>
659    <div class="cancel-ticket-modal-pnr-date-container">
660      <div class="cancel-ticket-modal-pnr">
661        PNR:
662        <span class="cancel-ticket-modal-pnr-text">{{ticket_number}}</span>
663      </div>
664      <div class="cancel-ticket-modal-pnr">
665        Booked on:
666        <span class="cancel-ticket-modal-pnr-text"
667          >{{dayjs(booked_date, 'YYYY-MM-DD').format('D MMMM YYYY')}}</span
668        >
669      </div>
670    </div>
671    <div class="cancel-ticket-modal-passenger-info">
672      <div class="cancel-ticket-modal-passenger-info-header">
673        Select passengers
674      </div>
675      <div class="cancel-ticket-modal-passenger-list">
676        {{#each passenger_details}}
677        <div class="cancel-ticket-modal-passenger-item">
678          <div class="cancel-ticket-modal-passenger-item-info">
679            <input
680              type="checkbox"
681              id="passenger-{{seat_number}}"
682              name="passenger-{{seat_number}}"
683              class="cancel-ticket-modal-passenger-checkbox"
684              value="{{seat_number}}"
685            />
686            <div class="cancel-ticket-modal-passenger-name-age">
687              <div class="cancel-ticket-modal-passenger-name">{{name}}</div>
688              <div class="cancel-ticket-modal-passenger-age">
689                {{gender}} , {{age}} years
690              </div>
691            </div>
692          </div>
693          <div class="cancel-ticket-modal-passenger-item-info">
694            <div class="cancel-ticket-modal-passenger-seat-number">
695              {{seat_number}}
696            </div>
697          </div>
698        </div>
699        {{/each}}
700      </div>
701    </div>
702    {{#if wallet_booking == false || wallet_booking == 'false'}}
703    <div class="cancel-ticket-modal-cancellation-typeContainer">
704      <div class="cancel-ticket-modal-cancellation-type-title">
705        Cancellation refund as :
706      </div>
707      <div class="cancel-ticket-modal-cancellation-type-list">
708        {{#if is_coupon_allowed}}
709        <label
710          class="cancel-ticket-modal-cancellation-type-item"
711          for="refund-wallet"
712        >
713          <input
714            type="radio"
715            id="Coupon-refund"
716            name="refund_type"
717            value="true"
718          />
719          Coupon
720        </label>
721        {{/if}} {{#if is_cash_credit}}
722        <label
723          class="cancel-ticket-modal-cancellation-type-item"
724          for="refund-to-source"
725        >
726          <input
727            type="radio"
728            id="refund-to-source"
729            name="refund_type"
730            value="false"
731          />
732          Refund to source
733        </label>
734        {{/if}}
735      </div>
736    </div>
737    {{/if}}
738    <div class="cancel-ticket-modal-passenger-info-footer">
739      <button
740        class="ticket-modal-passenger-info-footer-button"
741        onclick="reviewRefundDetails()"
742        id="review-refund-button"
743      >
744        Review refund details
745      </button>
746    </div>
747  `;
748
749  return htmlContent;
750}
751
752function prePostPoneTicketContent() {
753  const html = String.raw;
754  let htmlContent = html`
755    <div class="pre-postpone-ticket-modal-content">
756      <div class="pre-postpone-ticket-modal-body">
757        <div class="pre-postpone-ticket-body-form-content">
758          <div class="pre-postpone-ticket-form-group">
759            <label for="newTravelDate">Select new travel date</label>
760          </div>
761          <div class="pre-postpone-ticket-form-input-container">
762            <div class="pre-postpone-ticket-form-input-wrapper">
763              <input
764                type="text"
765                id="newTravelDate"
766                name="newTravelDate"
767                placeholder="Enter date of journey"
768                required
769              />
770            </div>
771            <div class="pre-postpone-ticket-form-description-label">
772              Date change charges :
773              <div id="date-change-charges">{{reschedule_percentage}}</div>
774            </div>
775          </div>
776        </div>
777        <div class="pre-postpone-ticket-info-container">
778          <div class="pre-postpone-ticket-info-content">
779            <div class="pre-postpone-ticket-info-header">
780              <div class="pre-postpone-ticket-info-header-title">
781                You are changing travel date
782              </div>
783              <div class="pre-postpone-ticket-info-header-subtitle">
784                for following passenger
785              </div>
786            </div>
787            <div class="pre-postpone-ticket-info-passenger-list">
788              {{#each passenger_details}}
789              <div class="pre-postpone-ticket-info-passenger-item">
790                <div class="pre-postpone-ticket-info-passenger-name">
791                  {{name}}
792                </div>
793                <div class="pre-postpone-ticket-info-passenger-seat-number">
794                  {{title}},{{age}} years - Seat No: {{seat_number}}
795                </div>
796              </div>
797              {{/each}}
798            </div>
799          </div>
800          <div class="pre-postpone-ticket-info-footer">
801            Note: Once you change the date for this ticket, you will not be able
802            to cancel or change date again.
803          </div>
804        </div>
805      </div>
806      <div class="pre-postpone-ticket-modal-footer">
807        <button
808          class="pre-postpone-ticket-modal-footer-button"
809          onclick="prePostPone()"
810          id="pre-postpone-button"
811        >
812          Select service
813        </button>
814      </div>
815    </div>
816  `;
817  return htmlContent;
818}
819
820async function reviewRefundDetails() {
821  buttonLoading("#review-refund-button");
822  const selectedPassengers = Array.from(
823    document.querySelectorAll(
824      ".cancel-ticket-modal-passenger-checkbox:checked",
825    ),
826  ).map((checkbox) => checkbox.value);
827  if (selectedPassengers.length === 0) {
828    message.error("Please select at least one passenger to cancel the ticket.");
829    buttonStopLoading("#review-refund-button");
830    return;
831  }
832  let is_partial_cancelled =
833    window.ticketDetail.onward.passenger_details.length !==
834    selectedPassengers.length;
835  // Proceed with reviewing refund details for selected passengers
836  let contact_details =
837    window.ticketDetail.onward.email || window.ticketDetail.onward.phone || "";
838  // user selected refund type
839
840  const refundType = document.querySelector(
841    'input[name="refund_type"]:checked',
842  )?.value;
843  try {
844    const { data } = await apiClient.post("api/do_cancel_ticket.json", {
845      partial_cancellation: is_partial_cancelled,
846      ticket_number: window.ticketDetail.onward.ticket_number,
847      contact_details: contact_details,
848      travel_date: window.ticketDetail.onward.travel_date,
849      seat_numbers: selectedPassengers.join(","),
850    });
851    if (data.code === 411) {
852      window.cancelTicketModal.hide();
853      buttonStopLoading("#review-refund-button");
854      setTimeout(() => {
855        message.error(
856          data.message ||
857            "Unable to process cancellation. Please try again later.",
858        );
859      }, 500);
860      return;
861    } else if (data) {
862      buttonStopLoading("#review-refund-button");
863      contentTemplate = cancelTicketConfirmContent();
864      document.getElementById("modify-ticket-body-content").innerHTML =
865        renderTemplate(contentTemplate, {
866          ...data,
867          refund_amount: data.refund_amount.toString(),
868          total_fare: data.total_fare.toString(),
869          total_cancellation_charge: data.total_cancellation_charge.toString(),
870          cancellation_percentage: data.cancellation_percentage.toString(),
871          refundType: refundType,
872          cancellation_policies:
873            window.ticketDetail?.onward?.cancellation_policies,
874        });
875    }
876  } catch (error) {
877    buttonStopLoading("#review-refund-button");
878    console.error("Error reviewing refund details:", error);
879  }
880}
881
882function toggleCancellationPolicyList() {
883  const policyListContainer = document.querySelector(
884    ".cancel-ticket-confirmation-modal .cancel-ticket-policy-list-container",
885  );
886  const subtitle = document.querySelector(
887    ".cancel-ticket-confirmation-modal .cancel-ticket-confirmation-refund-subtitle",
888  );
889  if (policyListContainer) {
890    policyListContainer.classList.toggle("active");
891  }
892  if (subtitle) {
893    subtitle.classList.toggle("active");
894  }
895}
896
897function cancelTicketConfirmContent() {
898  const html = String.raw;
899  let htmlContent = html` <div
900      class="mobile-cancel-ticket-header"
901      onclick="cancelTicket(2); showTicketTabContent(2);"
902    >
903      <svg
904        width="24"
905        height="24"
906        viewBox="0 0 24 24"
907        fill="none"
908        xmlns="http://www.w3.org/2000/svg"
909      >
910        <path
911          d="M20 11H7.83L13.42 5.41L12 4L4 12L12 20L13.41 18.59L7.83 13H20V11Z"
912          fill="black"
913        />
914      </svg>
915      Review refund details
916    </div>
917    <div class="cancel-ticket-confirmation-modal">
918      <div class="cancel-ticket-confirmation-refund-seat-container">
919        <div class="cancel-ticket-confirmation-refund-container">
920          <div class="cancel-ticket-confirmation-refund-title-container">
921            <div class="cancel-ticket-confirmation-refund-title">
922              Total refund amount
923            </div>
924            {{#if cancellation_policies && cancellation_policies.length > 0}}
925            <div
926              class="cancel-ticket-confirmation-refund-subtitle"
927              onclick="toggleCancellationPolicyList()"
928            >
929              View cancellation policy
930              <div class="cancellation-policy-icon">
931                <svg
932                  width="20"
933                  height="20"
934                  viewBox="0 0 20 20"
935                  fill="none"
936                  xmlns="http://www.w3.org/2000/svg"
937                >
938                  <path
939                    d="M14.1293 6.25C14.4787 6.25 14.6731 6.65427 14.4548 6.92708L10.3215 12.0931C10.1547 12.3016 9.83811 12.3015 9.67129 12.0931L5.53799 6.92708C5.31974 6.65427 5.51414 6.25 5.86351 6.25L14.1293 6.25Z"
940                    fill="white"
941                  />
942                </svg>
943              </div>
944            </div>
945            {{else}}
946            <a
947              class="cancel-ticket-confirmation-refund-subtitle"
948              href="cancellation-policy"
949              target="_blank"
950            >
951              View cancellation policy
952            </a>
953            {{/if}}
954          </div>
955          <div class="cancel-ticket-confirmation-refund-amount">
956            ₹ {{refund_amount}}
957          </div>
958        </div>
959        <div class="cancel-ticket-policy-list-container">
960          {{#each cancellation_policies}}
961          <div class="cancel-ticket-policy-item">
962            Between {{time_limit_from}} to {{time_limit_to}} from the station
963            departure time: {{percent}} % Cancellation Charges
964          </div>
965          {{/each}}
966        </div>
967        <div class="cancel-ticket-confirmation-seat-container">
968          <div class="cancel-ticket-confirmation-seat-title">
969            Seat to be cancelled :
970            <span class="cancel-ticket-confirmation-seat-number">
971              <input
972                type="hidden"
973                id="cancel-seat-numbers"
974                value="{{seat_nos}}"
975              />
976              {{seat_nos}}
977            </span>
978          </div>
979        </div>
980      </div>
981      <div class="cancel-ticket-modal-refund-info">
982        <div class="cancel-ticket-modal-refund-info-header">Refund breakup</div>
983        <div class="cancel-ticket-modal-refund-info-list">
984          <div class="cancel-ticket-modal-refund-info-item">
985            <div class="cancel-ticket-modal-refund-info-item-label">
986              Amount paid
987            </div>
988            <div class="cancel-ticket-modal-refund-info-item-value highlight">
989              ₹ {{total_fare}}
990            </div>
991          </div>
992          <div class="cancel-ticket-modal-refund-info-item">
993            <div class="cancel-ticket-modal-refund-info-item-label">
994              Cancellation Charge
995            </div>
996            <div class="cancel-ticket-modal-refund-info-item-value">
997              ₹ {{total_cancellation_charge}}
998            </div>
999          </div>
1000          <div class="cancel-ticket-modal-refund-info-item">
1001            <div class="cancel-ticket-modal-refund-info-item-label">
1002              Cancellation Percentage
1003            </div>
1004            <div class="cancel-ticket-modal-refund-info-item-value">
1005              {{cancellation_percentage}}%
1006            </div>
1007          </div>
1008          <div class="cancel-ticket-modal-refund-info-item-separator"></div>
1009          <div class="cancel-ticket-modal-refund-info-item">
1010            <div class="cancel-ticket-modal-refund-info-item-label">
1011              Total refundable amount
1012            </div>
1013            <div class="cancel-ticket-modal-refund-info-item-value highlight">
1014              ₹ {{refund_amount}}
1015            </div>
1016          </div>
1017        </div>
1018      </div>
1019    </div>
1020    <div class="cancel-ticket-modal-passenger-info-footer">
1021      <input type="hidden" id="refund-type" value="{{refundType}}" />
1022      <button
1023        class="ticket-modal-passenger-info-footer-button"
1024        onclick="confirmCancellation()"
1025        id="confirm-cancel-button"
1026      >
1027        Confirm cancellation
1028      </button>
1029    </div>`;
1030  return htmlContent;
1031}
1032
1033async function confirmCancellation() {
1034  buttonLoading("#confirm-cancel-button");
1035  let seat_numbers = document.getElementById("cancel-seat-numbers").value;
1036  //remove the extra spaces
1037  seat_numbers = seat_numbers
1038    .split(",")
1039    .map((seat) => seat.trim())
1040    .join(",");
1041  let is_partial_cancelled =
1042    window.ticketDetail.onward.passenger_details.length !==
1043    seat_numbers.split(",").length;
1044  const refundType =
1045    document.getElementById("refund-type")?.value == "true" ? true : false;
1046  try {
1047    const { data } = await apiClient.post("api/cms_booking_engine.json", {
1048      query: is_partial_cancelled ? "q14" : "q13",
1049      ticket_number: window.ticketDetail.onward.ticket_number,
1050      contact_details:
1051        window.ticketDetail.onward.email ||
1052        window.ticketDetail.onward.phone ||
1053        "",
1054      travel_date: window.ticketDetail.onward.travel_date,
1055      seat_numbers: seat_numbers,
1056      refund_type: window.ticketDetail.onward.wallet_booking
1057        ? "3"
1058        : refundType
1059          ? "1"
1060          : "2",
1061    });
1062    if (data) {
1063      buttonStopLoading("#confirm-cancel-button");
1064      window.cancelTicketModal.hide();
1065      if (data.code === 489 || data.code === "489") {
1066        message.error(data.message);
1067        return false;
1068      }
1069      setTimeout(() => {
1070        message.success(
1071          "Your ticket has been successfully cancelled. Refund will be processed shortly.",
1072        );
1073        const state = window.store?.getState();
1074        const { user } = state?.user || {};
1075        setTimeout(() => {
1076          if (user) {
1077            if (is_partial_cancelled) {
1078              window.location.reload();
1079            } else {
1080              locationRedirect("/my-bookings");
1081            }
1082          } else {
1083            if (is_partial_cancelled) {
1084              window.location.reload();
1085            } else {
1086              locationRedirect("/manage-booking");
1087            }
1088          }
1089        }, 1000);
1090      }, 1000);
1091      // Optionally, refresh the ticket details or update the UI accordingly
1092    }
1093  } catch (error) {
1094    buttonStopLoading("#confirm-cancel-button");
1095    console.error("Error confirming cancellation:", error);
1096  }
1097}
1098
1099function constructModifyTicketContent({ email = "", mobileNumber = "" }) {
1100  const html = String.raw;
1101  let htmlContent = html`
1102    <form class="modify-ticket-modal-form">
1103      <div class="modify-ticket-modal-header">
1104        <div class="modify-ticket-modal-title">
1105          <div
1106            class="modify-ticket-modal-title-icon"
1107            onclick="window.modifyTicketModal.hide()"
1108          >
1109            <img
1110              src="${window.domain}/common/assets/images/arrow_back.svg"
1111              alt="Modify Ticket Icon"
1112            />
1113          </div>
1114          <div class="modify-ticket-modal-title-text">Modify ticket</div>
1115        </div>
1116        <div class="modify-ticket-modal-description">
1117          <ul>
1118            <li>You can change Boarding Address and Mobile No.</li>
1119            <li>
1120              After the Modification, please take the Print of the Ticket.
1121            </li>
1122          </ul>
1123        </div>
1124      </div>
1125      <div class="modify-ticket-modal-body">
1126        <div class="modify_ticket_form_group_wrapper">
1127          <div class="modify_ticket_form_group">
1128            <label for="mobileNumber">PHONE NUMBER</label>
1129            <div class="mobile_number_input_container">
1130              <div class="country_code_prefix">+91</div>
1131              <div class="mobile_number_input_wrapper">
1132                <input
1133                  type="text"
1134                  id="mobileNumber"
1135                  name="mobileNumber"
1136                  placeholder="Enter mobile number"
1137                  oninput="this.value = replaceStringWithEmpty(this.value)"
1138                  minlength="10"
1139                  maxlength="10"
1140                  value="${mobileNumber}"
1141                />
1142              </div>
1143            </div>
1144          </div>
1145          <div class="modify_ticket_form_group">
1146            <label for="email">EMAIL</label>
1147            <input
1148              type="text"
1149              id="email"
1150              name="email"
1151              placeholder="Enter email"
1152              value="${email}"
1153            />
1154          </div>
1155        </div>
1156        <div class="modify_ticket_form_group_wrapper">
1157          <div class="modify_ticket_form_group">
1158            <label for="boardingPoint">BOARDING Point</label>
1159            <div
1160              type="text"
1161              id="boardingPoint"
1162              name="boardingPoint"
1163              placeholder="Enter boarding point"
1164            ></div>
1165          </div>
1166          <div class="modify_ticket_form_group">
1167            <label for="droppingPoint">DROPPING Point</label>
1168            <div
1169              type="text"
1170              id="droppingPoint"
1171              name="droppingPoint"
1172              placeholder="Enter dropping point"
1173            ></div>
1174          </div>
1175        </div>
1176      </div>
1177      <div class="modify-ticket-modal-footer">
1178        <button
1179          id="modify-ticket-submit-button"
1180          class="modify-ticket-modal-footer-button-confirm"
1181          onclick="updateModifyTicket()"
1182        >
1183          Update ticket
1184        </button>
1185      </div>
1186    </form>
1187  `;
1188  return htmlContent;
1189}
1190
1191async function prePostPone() {
1192  buttonLoading("#pre-postpone-button");
1193  try {
1194    const newTravelDate = document.getElementById("newTravelDate").value;
1195    if (!newTravelDate) {
1196      buttonStopLoading("#pre-postpone-button");
1197      message.error("Please select new travel date");
1198      return;
1199    }
1200    const response = await apiClient.post("/api/do_cancel_ticket.json", {
1201      partial_cancellation: false,
1202      ticket_number: window.ticketDetail.onward.ticket_number,
1203      contact_details: window.ticketDetail.onward.phone,
1204      travel_date: window.ticketDetail.onward.travel_date,
1205      pre_post_open_type: "pre_post",
1206      pre_post_now: true,
1207      pre_post_date: newTravelDate,
1208    });
1209    if (response.data.ticket_no) {
1210      const res = await apiClient.post("/api/cms_booking_engine.json", {
1211        query: "q16",
1212        ticket_number: response.data.ticket_no,
1213        pre_post_open_type: "pre_post",
1214        pre_post_now: true,
1215        pre_post_date: newTravelDate,
1216      });
1217      if (res.status === 200 && res.data) {
1218        window.cancelTicketModal.hide();
1219        message.success(
1220          `${res.data.refund_mode}, refund amount ${res.data.refund_amount} will be processed shortly.`,
1221        );
1222        setTimeout(() => {
1223          let url = res.data.url_path;
1224          window.location.href = res.data.url_path;
1225        }, 1000);
1226      } else {
1227        window.cancelTicketModal.hide();
1228        buttonStopLoading("#pre-postpone-button");
1229        setTimeout(() => {
1230          message.error(
1231            res.data.message ||
1232              "Could not process date change. Please try again later.",
1233          );
1234        }, timeout);
1235      }
1236    } else {
1237      window.cancelTicketModal.hide();
1238      buttonStopLoading("#pre-postpone-button");
1239      setTimeout(() => {
1240        message.error(
1241          response.data.message ||
1242            "Could not process date change. Please try again later.",
1243        );
1244      }, 1000);
1245    }
1246  } catch (error) {
1247    buttonStopLoading("#pre-postpone-button");
1248    console.error("Error in prePostPone:", error);
1249  }
1250  //search-results.html?from=16&fromCity=Bangalore&to=1938&toCity=Hyderabad&depart=2025-12-25&pre_postpone=true&res_id=322598
1251}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.