PageSourceSearch

https://www.plrtravels.com/assets/js/scripts.js?v=1790225720

js plrtravels.com collected 2026-10-02 01:39:42 UTC 265,223 bytes, 8,122 lines download raw bytes

1$(function () {
2	// initSidebar();
3	initSearchWidget();
4	initPWA();
5
6	$(document).ajaxError(function (event, jqxhr, settings, thrownError) {
7		jqxhr.status === 401 && logout(); // Unauthorized
8		settings.dataType === 'json' && settings.success({ status: 0, errorDesc: thrownError || 'An Unknown Error Occurred' });
9	});
10
11	window.onerror = function (message, source, lineno, colno, error) {
12		$.post('user/log-client-err', {
13			error: error.stack,
14			pathname: location.pathname
15		});
16	};
17
18	$('.previous-day').on('click', function (e) {
19		trackEvent('Previous Day', 'click', 'Previous Day');
20	});
21	$('.next-day').on('click', function (e) {
22		trackEvent('Next Day', 'click', 'Next Day');
23	});
24	$('.swap-icon').on('click', function (e) {
25		trackEvent('Station Swap', 'click', 'Station Swapping');
26	});
27
28
29	$('.payment-slider').slick({
30		arrows: false,
31		autoplay: true,
32		dots: true,
33		autoplaySpeed: 3000,
34		speed: 3000,
35		cssEase: 'linear',
36		slidesToShow: 1,
37		slidesToScroll: 1,
38		responsive: [
39			{
40				breakpoint: 1024,
41				settings: {
42					slidesToShow: 1,
43					slidesToScroll: 1
44				}
45			}
46		]
47	});
48});
49
50let isLoadingBusMap = false;
51let connectingSelected = false;
52
53var connDetails = new Array();
54var triggerConnEle = $();
55
56var tripStageCode = new Array();
57var tripDate = new Array();
58var fromStation = new Array();
59var toStation = new Array();
60var fromStationName = new Array();
61var toStationName = new Array();
62
63var busmapp = new Array();
64var previousTrip = null;
65
66var discountCoupon = [];
67
68var currencySymbol = '';
69
70var regConnTrip = initOrResetRegConnTrip();
71function initOrResetRegConnTrip() {
72	return {
73		"PREVIOUS_M_TRIP": null,
74		"CURRENT_M_TRIP": null,
75		"TRIP_SET": new Set(),
76		"AVAILABLE_SEAT": 0,
77		"PASSENGER_COUNT": 0,
78		"SEAT_COUNT": 0,
79		"CURRENT_SEQ": 0,
80		"PREVIOUS_SEQ": 0,
81		"SEQ_COMPLETED": -1,
82		"SEQ_STATUS": "BOARDING", // [BOARDING , CONNECTING ,DROPPING]
83		"TOTAL_SEQ": 1,
84		"SEQUENCE_TRIP_CODE": new Array(),
85		"SEQUENCE_TRIP_NAME": new Array(),
86		"SEQUENCE_TRIP_F_T_D_AMOUNT": new Map(),
87		"TRIP_FARE": new Array(),
88		/**
89		 * @description use to auto filling passenger detail except SEQ_STATUS BOARDING 
90		 */
91		"PASSENGER_DETAILS": {
92			"NAME": new Array(),
93			"AGE": new Array(),
94			"GENDER": new Array(),
95		},
96		/**
97		 * @template 
98		 * common for ticket booking at trips(mapped to connecting trips)
99		 * @field
100		 * common fields : emailaddress, phonebooking, freeservice, phone ,additionalAttributes , etc...(relevant like those)
101		 * orderDetails : detail for booking ticket in a trip
102		 * additionalAttributes : extra details for booking ticket
103		 * @var orderDetails - It holds array of sampleTripDetail,
104		 * which has to be done at final process before ajax/api request for blocking
105		 */
106		"TKT_BLK_BOOK_DETAILS": {
107			'emailaddress': "",
108			'phonebooking': 0,
109			'freeservice': 0,
110			'phone': "",
111			/**
112			 * @description holds array of sampleTripDetail
113			 */
114			'orderDetails': new Array(),
115			/**
116			 * @requires  TRIP_CONNECT - required connecting service code - master code
117			 * @description  except TRIP_CONNECT remaining fields are optional/based on booking process
118			 * @field ALTERNATE_MOBILE, INCLUSIVE_GST, GST_IN, GST_TRADE_NAME, GST_EMAIL , etc...
119			 */
120			'additionalAttributes': {
121				"TRIP_CONNECT": ''
122			}
123
124		},
125	};
126}
127
128
129/**
130 * @template - for ticket detail format
131 */
132var sampleTicketDetail = {
133	'name': '',
134	'age': 0,
135	'gender': '',
136	'fare': 0,
137	'seatname': '',
138	'code': ''
139};
140/**
141 * @template - for COMMON_DETAILS.orderDetails  array element
142 * @field
143 * tripCode ,travelDate - code and date of trip mapped to connecting trip
144 * journeyType - CN (connection type  there is not OW and RT in this)
145 * fromStation, boardingPoint, toStation, droppingPoint - trip's respective station and its point
146 * ticketDetails - contains array of sampleTicketDetail obj
147*/
148var sampleTripDetail = {
149	'tripCode': '',
150	'travelDate': '',
151	'journeyType': 'CN',// for Connection type
152	'fromStation': '',
153	'fromStationName': '',
154	'boardingPoint': '',
155	'boardingPointName': '',
156	'toStation': '',
157	'toStationName': '',
158	'droppingPoint': '',
159	'droppingPointName': '',
160	'bus': {},
161	'ticketDetails': new Array(),
162};
163
164var sampleBusDetails = {
165	'busName': '',
166	'busDisplayName': '',
167	'busType': '',
168	'fromStationTime': '',
169	'toStationTime': '',
170	'schedule': {
171		'code': '',
172		'name': '',
173		'serviceNumber': '',
174		'displayName': '',
175	}
176
177};
178
179function isObjectEmpty(obj) {
180	return Object.keys(obj).length === 0;
181}
182
183(function ($) {
184	_alert = function (node, settings) {
185		return node.finish()
186			.off('detach')
187			.html('<div class="alert alert-' + settings.type + ' alert-dismissible fade show" role="alert">\n\
188						<button aria-label="Close" class="close" data-dismiss="alert" type="button">\n\
189							<span aria-hidden="true"> x</span>\n\
190						</button>\n\
191						<strong>' + settings.title + '</strong>&emsp;' + settings.message +
192				'</div>')
193			.delay(settings.delay)
194			.queue(function () {
195				$(this).children('.alert').last().alert('close');
196			})
197			.children('.alert').last().on('close.bs.alert', function () {
198				$(this).trigger('detach');
199			});
200	};
201
202	$.fn.danger = function (options) {
203		var settings = $.extend({
204			type: 'danger',
205			title: '<i class="fa fa-exclamation-triangle fa-lg" aria-hidden="true"></i>',
206			message: 'Please fillout the necessary fields.',
207			delay: 5000
208		}, (typeof options === 'string') ? { message: options } : options);
209
210		return _alert(this, settings);
211	};
212
213	$.fn.timeExceed = function (options) {
214		var settings = $.extend({
215			type: 'danger',
216			title: '<i class="fa fa-exclamation-triangle fa-lg" aria-hidden="true"></i>',
217			message: 'OTP limit exceeded. Kindly use an alternate number.',
218			delay: 5000
219		}, (typeof options === 'string') ? { message: options } : options);
220
221		return _alert(this, settings);
222	};
223
224	$.fn.success = function (options) {
225		var settings = $.extend({
226			type: 'success',
227			title: '<i class="fa fa-check fa-lg" aria-hidden="true"></i>',
228			message: 'Your request has been completed Successfully.',
229			delay: 3000
230		}, (typeof options === 'string') ? { message: options } : options);
231
232		return _alert(this, settings);
233	};
234
235	$.fn.emailmobile = function (options) {
236		var settings = $.extend({
237			type: 'danger',
238			title: '<i class="fa fa-exclamation-triangle fa-lg" aria-hidden="true"></i>',
239			message: 'Invalid Email / Mobile number.',
240			delay: 5000
241		}, (typeof options === 'string') ? { message: options } : options);
242
243		return _alert(this, settings);
244	};
245
246	$.fn.invalidTicket = function (options) {
247		var settings = $.extend({
248			type: 'danger',
249			title: '<i class="fa fa-exclamation-triangle fa-lg" aria-hidden="true"></i>',
250			message: 'Invalid Access',
251			delay: 5000
252		}, (typeof options === 'string') ? { message: options } : options);
253
254		return _alert(this, settings);
255	};
256}(jQuery));
257
258(function ($) {
259	$.cookie = function (key, value, milliseconds, path = '/') {
260		if (!value) {
261			var keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)');
262			return keyValue ? keyValue[2] : null;
263		}
264		var expires = new Date();
265		expires.setTime(expires.getTime() + milliseconds);
266		document.cookie = key + '=' + value + ';expires=' + expires.toUTCString() + '; path=' + path;
267	};
268}(jQuery));
269
270(function ($) {
271	if (location.pathname !== '/') return;
272
273	$.ajax({
274		type: 'POST',
275		url: 'banners',
276		dataType: 'json',
277		success: function (result) {
278			if (result.status != 1 || (result.data.length == 0 && result.announcement.length == 0)) return;
279
280			let banners = [];
281			let bannersAnnounce = [];
282
283			if (Array.isArray(result.data)) {
284				banners = result.data.map(url => ({ src: url }));
285			}
286
287			if (Array.isArray(result.announcement)) {
288				bannersAnnounce = result.announcement.map(item => ({
289					src: item.url,
290					caption: `<a class="fancybox-caption" href="${item.redirectUrl}" data-redirect-url="${item.redirectUrl}" target="_blank"></a>`
291				}));
292			}
293
294			let bannerData = [...bannersAnnounce, ...banners];
295
296			Fancybox.show(bannerData, {
297				Thumbs: false,
298				Toolbar: false,
299
300				Image: {
301					zoom: false,
302					click: false,
303					wheel: 'slide'
304				},
305			});
306			setTimeout(() => {
307				document.addEventListener('click', (event) => {
308					if (event.target.closest('.carousel__button.is-close')) {
309						return;
310					}
311
312					if (event.target.closest('.fancybox__content')) {
313						handleRedirect();
314					}
315				});
316
317				function handleRedirect() {
318					const selectedSlide = document.querySelector('.fancybox__slide.is-selected');
319					if (selectedSlide) {
320						let redirectUrl = selectedSlide.querySelector('a.fancybox-caption')?.getAttribute('data-redirect-url');
321
322						if (!redirectUrl) return;
323
324						if (!/^https?:\/\//i.test(redirectUrl)) {
325							redirectUrl = 'https://' + redirectUrl;
326						}
327
328						if (isValidURL(redirectUrl)) {
329							window.open(redirectUrl, '_blank');
330						}
331					}
332				}
333
334				function isValidURL(url) {
335					try {
336						new URL(url);
337						return true;
338					} catch (_) {
339						return false;
340					}
341				}
342
343			}, 1000);
344		}
345	});
346}(jQuery));
347
348var totalTripCount = 0;
349var totalAvailableSeatCount = 0;
350
351Selectize.define('search_on_focus', function () {
352	var self = this;
353
354	self.on('dropdown_open', function () {
355		self.clear(true);
356	});
357
358	self.on('blur', function () {
359		if (self.getValue() == '') {
360			self.setValue(self.lastValidValue, true);
361		}
362	});
363
364	self.on('item_add', function (value) {
365		if (self.lastValidValue != value) {
366			self.lastValidValue = value;
367		}
368	});
369});
370
371const validate = {
372	isEmail: function (email) {
373		let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
374		return re.test(email);
375	},
376	isMobile: function (mobile) {
377		let re = /^[6-9]\d{9}$/;
378		return re.test(mobile);
379	},
380	isGSTIN: function (GSTIN) {
381		let re = /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$/;
382		return re.test(GSTIN);
383	}
384};
385
386function cleanString(string = '') {
387	return string.replace(/[^a-zA-Z0-9-]/g, '').toLowerCase();
388}
389
390function percentageOf(percent, total) {
391	return (percent / 100) * total;
392}
393
394function logout() {
395	location.href = 'user/logout';
396}
397
398function initSidebar() {
399	var slideout = new Slideout({
400		panel: document.getElementById('panel'),
401		menu: document.getElementById('menu'),
402		padding: 256,
403		tolerance: 70,
404		easing: 'cubic-bezier(.32,2,.55,.27)'
405	});
406
407	$('.toggle-button').on('click', function () {
408		slideout.toggle(); s
409	});
410}
411
412var renderFromStations;
413var renderToStations;
414var fromselectize
415var toselectize
416
417function initSearchWidget() {
418	if (!$('#search-form').length) {
419		return;
420	}
421	$('#search-form').on('submit', initSearch);
422
423	const SELECTIZEOPTIONS = {
424		valueField: 'code',
425		labelField: 'name',
426		searchField: ['name'],
427		sortField: ['name'],
428		closeAfterSelect: true,
429		copyClassesToDropdown: false,
430		optgroups: [
431			{ label: 'TOP STATIONS', value: 'TOP' },
432			{ label: 'ALL STATIONS', value: 'ALL' }
433		],
434		plugins: ['search_on_focus']
435	};
436
437	var $fromselect = $('#search-from-station').selectize(SELECTIZEOPTIONS);
438	var $toselect = $('#search-to-station').selectize(SELECTIZEOPTIONS);
439
440	fromselectize = $fromselect.prop('selectize');
441	toselectize = $toselect.prop('selectize');
442
443	fromselectize.settings.placeholder = 'Select From City';
444	toselectize.settings.placeholder = 'Select To City';
445	fromselectize.updatePlaceholder();
446	toselectize.updatePlaceholder();
447
448	const DATEPICKEROPTIONS = {
449		format: 'D, d M',
450		startDate: '0d',
451		endDate: '+90d',
452		weekStart: 1,
453		daysOfWeekHighlighted: '0,6',
454		maxViewMode: 'days',
455		autoclose: true,
456		todayHighlight: true,
457		templates: {
458			leftArrow: '<i class="fas fa-chevron-left"></i>',
459			rightArrow: '<i class="fas fa-chevron-right"></i>'
460		}
461	};
462
463	var $onwardpicker = $('#search-onward-date').datepicker(DATEPICKEROPTIONS);
464	var $returnpicker = $('#search-return-date').datepicker(DATEPICKEROPTIONS);
465
466	$onwardpicker
467		.datepicker('setDate', moment().toDate())
468		.on('changeDate', function (e) {
469			$returnpicker.datepicker('setDate', null);
470			$returnpicker.datepicker('setStartDate', moment(e.date).toDate());
471		});
472
473	$('[data-datebtn]').on('click', function () {
474		var days = $(this).data('datebtn');
475		$onwardpicker.datepicker('setDate', moment().add(days, 'days').toDate());
476		initSearch();
477	});
478
479	$onwardpicker.attr('placeholder', 'Journey Date').prop('autocomplete', 'off');
480	$returnpicker.attr('placeholder', 'Return Date').prop('autocomplete', 'off');
481
482	var routes = $('#routes-data:hidden').data('value');
483
484	var mapStationsOptions = function (routeList, optgroup) {
485		var stationList = [];
486
487		$.each(routeList || [], function (i, station) {
488			station.optgroup = optgroup;
489			stationList.push(station)
490		});
491
492		return stationList;
493	};
494
495	renderFromStations = function () {
496		toselectize.setValue('');
497
498		fromselectize.clearOptions();
499		fromselectize.addOption(mapStationsOptions(routes.topRoute, 'TOP'));
500		fromselectize.addOption(mapStationsOptions(routes.route, 'ALL'));
501	};
502
503	renderToStations = function () {
504		var fromStationCode = fromselectize.getValue();
505		var toStationCode = toselectize.getValue();
506		var route = routes.route[fromStationCode];
507
508		toselectize.setValue('', true);
509		toselectize.clearOptions();
510		if (!route) return;
511
512		var topRoutes = routes.route[fromStationCode].topRoutesList;
513		var toRoutes = routes.route[fromStationCode].toRoutesList;
514
515		toselectize.addOption(mapStationsOptions(topRoutes, 'TOP'));
516		toselectize.addOption(mapStationsOptions(toRoutes, 'ALL'));
517		toselectize.setValue((topRoutes[toStationCode] || toRoutes[toStationCode] || { code: '' }).code, true);
518	};
519
520	renderFromStations();
521	renderToStations();
522
523	$fromselect.on('change', function () {
524		toselectize.focus();
525		renderToStations();
526	});
527
528	$toselect.on('change', function () {
529		$onwardpicker.focus();
530	});
531
532	var $swapbtn = $('#search-swap-icon');
533	$swapbtn.find('a').addBack().attr('tabindex', '-1');
534
535	$swapbtn.on('click', function () {
536		var fromStationCode = fromselectize.getValue();
537		var toStationCode = toselectize.getValue();
538
539		// clear search
540		if (!toStationCode || !fromStationCode) {
541			fromselectize.setValue('', true);
542			toselectize.setValue('', true);
543			return;
544		}
545
546		var emptyObj = { code: '' };
547
548		// set from station
549		var toRouteObj = routes.route[toStationCode] || emptyObj;
550		fromselectize.setValue(toRouteObj.code, true);
551		renderToStations();
552
553		// set to station
554		var fromRouteObj = toRouteObj.toRoutesList[fromStationCode] || toRouteObj.topRoutesList[fromStationCode] || emptyObj;
555		toselectize.setValue(fromRouteObj.code, true);
556	});
557
558	// apply recent search
559	var recentSearch = $('#recent-search-data:hidden').data('value');
560
561	if (recentSearch) {
562		let [fromStationCode, toStationCode, onwardDate] = recentSearch || [];
563
564		fromselectize.setValue(fromStationCode, true);
565		renderToStations();
566		toselectize.setValue(toStationCode, true);
567		$onwardpicker.datepicker('setDate', moment(onwardDate, 'YYYY-MM-DD').toDate());
568	}
569
570	// fill only in SRP
571	var returnDate = $returnpicker.data('date');
572	if (returnDate) {
573		$returnpicker.datepicker('setDate', moment(returnDate, 'YYYY-MM-DD').toDate());
574	}
575
576	$(document).ready(function () {
577		$('a[data-toggle="modal"][data-target="#otp-login"]').on('click', function () {
578			genCaptcha();
579		});
580	});
581}
582document.addEventListener('wheel', function (e) {
583	if (e.target.closest('.selectize-dropdown') || e.target.closest('.selectize-input')) {
584		e.stopPropagation();
585	}
586}, {
587	passive: false
588});
589function filterStations() {
590	var value = event.target.value || '';
591	value = value.trim().toLowerCase();
592	$('#stations-list .station').toggleClass('d-none', value !== '');
593	$('#stations-list .station[data-station*="' + value + '"]').removeClass('d-none');
594}
595
596function initSearch() {
597	event && event.preventDefault();
598
599	var query = {};
600	query.fromStationCode = $('#search-from-station').val();
601	query.fromStationName = $('#search-from-station :selected').text();
602	query.toStationCode = $('#search-to-station').val();
603	query.toStationName = $('#search-to-station :selected').text();
604
605	if (!query.fromStationCode) {
606		fromselectize.focus();
607		// renderFromStations();
608		return false;
609	}
610
611	if (!query.toStationCode) {
612		toselectize.focus();
613		// renderToStations();
614		return false;
615	}
616
617	var $onwardpicker = $('#search-onward-date');
618	var onwardDate = moment($onwardpicker.datepicker('getDate'));
619	query.onwardDate = onwardDate.format('YYYY-MM-DD');
620	if (!onwardDate.isValid()) {
621		query.onwardDate = moment().format('YYYY-MM-DD');
622		$onwardpicker.datepicker('setDate', moment().toDate());
623	}
624
625	var $returnpicker = $('#search-return-date');
626	var returnDate = moment($returnpicker.datepicker('getDate'))
627	if (returnDate.isValid()) {
628		query.returnDate = returnDate.format('YYYY-MM-DD');
629	}
630
631	$('#search-btn')
632		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Searching...')
633		.prop('disabled', true);
634
635	location.href = buildSearchUrl(query);
636}
637
638function buildSearchUrl(params) {
639	let fromStationName = encodeURIComponent(cleanString(params.fromStationName));
640	let toStationName = encodeURIComponent(cleanString(params.toStationName));
641
642	let query = {}
643	query.fromStationCode = params.fromStationCode;
644	query.toStationCode = params.toStationCode;
645	query.onwardDate = params.onwardDate;
646
647	if (params.returnDate) query.returnDate = params.returnDate;
648	if (params.searchType) query.searchType = params.searchType;
649	if (params.reschedule) query.reschedule = params.reschedule;
650
651	return 'search/' + fromStationName + '-to-' + toStationName + '?' + $.param(query);
652}
653
654function initTripSearch(data) {
655	// $('#trip-list-container').html('<div class="p-5 text-center">Loading...</div>');
656	$('.loading').removeClass('d-none');
657	data.tripCode = null;
658	$.ajax({
659		type: 'POST',
660		url: 'search/search-list',
661		data: data,
662		dataType: 'json',
663		success: function (result) {
664			var $tripContents = $('#trip-list-conn-container');
665			var $tripContent = $('#trip-list-container');
666			forLoadingHtml();
667			let tottrip = 0
668
669			if (result.data == '' || result.data == null) {
670				$('#trip-list-container').danger({
671					message: 'Sorry! data not found',
672					delay: 100000
673				});
674			} else if (result.data.conn || result.data.reg) {
675				isConnecting = true;
676				listViewConnMaster(data, result.data.conn, $tripContents);
677				connDetails = result.data.conn;
678				tottrip = result.data.conn ? result.data.conn.length : 0;
679
680
681				if (result.data.reg) {
682					isConnecting = false;
683					renderTripList(result.data.reg);
684					tottrip += result.data.reg[0].tripLength;
685				}
686
687				$('.conn-total-trip-count-div').removeClass('d-none');
688				$('.conn-total-trip-count').html('<img src="assets/images/search/buscount.svg" alt="Bus Icon"> Showing ' + tottrip + ' Trips on this routes');
689
690			} else {
691				$('#trip-list-container').danger({
692					message: result.errorDesc,
693					delay: 100000
694				});
695			}
696		}
697	});
698}
699
700function groupPunctualityByDate(punctualityList, fromStationCode, toStationCode) {
701	var grouped = {};
702
703	$.each(punctualityList, function (i, item) {
704		if (!item.tripDate) {
705			return;
706		}
707
708		if (!grouped[item.tripDate]) {
709			grouped[item.tripDate] = { departure: null, arrival: null, records: [] };
710		}
711
712		grouped[item.tripDate].records.push(item);
713	});
714
715	$.each(grouped, function (date, data) {
716		$.each(data.records, function (i, item) {
717			if (fromStationCode && item.stationCode === fromStationCode) {
718				data.departure = item;
719			}
720			if (toStationCode && item.stationCode === toStationCode) {
721				data.arrival = item;
722			}
723		});
724
725		if (!data.departure || !data.arrival) {
726			var uniqueStations = [];
727			$.each(data.records, function (i, item) {
728				var exists = uniqueStations.some(function (s) {
729					return s.stationCode === item.stationCode;
730				});
731				if (!exists) {
732					uniqueStations.push(item);
733				}
734			});
735
736			if (!data.departure && uniqueStations.length) {
737				data.departure = uniqueStations[0];
738			}
739			if (!data.arrival && uniqueStations.length > 1) {
740				data.arrival = uniqueStations[uniqueStations.length - 1];
741			}
742		}
743	});
744
745	return grouped;
746}
747
748function formatPunctualityDelay(minutes) {
749	// calculate the actual no of hours
750	/* if (minutes >= 60) {
751	 	return Math.floor(minutes / 60) + 'hr Delay';
752	}*/
753	// static hour seat if delay is more than 60 minutes
754	if (minutes > 60) {
755		return '1 hr Delay';
756	}
757	return minutes + 'm Delay';
758}
759
760function renderPunctualityStatus(item) {
761	if (!item) {
762		return '<span class="punctuality-na">-</span>';
763	}
764
765	if (item.onTime == 1 || item.delayMinutes == 0) {
766		return '<i class="fas fa-check punctuality-check"></i>';
767	}
768
769	var delayClass = item.delayMinutes >= 60 ? 'punctuality-delay-red' : 'punctuality-delay-orange';
770	return '<span class="' + delayClass + '">' + formatPunctualityDelay(item.delayMinutes) + '</span>';
771}
772
773function renderPunctuality(punctualityList, tripDate, fromStationCode, toStationCode) {
774	if (!punctualityList || !punctualityList.length) {
775		return '';
776	}
777
778	var total = punctualityList.length;
779	var onTimeCount = 0;
780	$.each(punctualityList, function (i, item) {
781		if (item.onTime == 1) {
782			onTimeCount++;
783		}
784	});
785
786	var percentage = Math.round((onTimeCount / total) * 100);
787	var colorClass = 'punctuality-red';
788	if (percentage >= 81) {
789		colorClass = 'punctuality-green';
790	} else if (percentage >= 60) {
791		colorClass = 'punctuality-orange';
792	}
793
794	var grouped = groupPunctualityByDate(punctualityList, fromStationCode, toStationCode);
795	var sortedDates = Object.keys(grouped).sort(function (a, b) {
796		return moment(a).valueOf() - moment(b).valueOf();
797	});
798
799	if (sortedDates.length > 7) {
800		sortedDates = sortedDates.slice(-7);
801	}
802
803	var dotsHtml = '';
804	var popoverRows = '';
805
806	$.each(sortedDates, function (i, dateKey) {
807		var dayData = grouped[dateKey];
808		var dayOnTime = true;
809
810		$.each(dayData.records, function (j, item) {
811			if (item.onTime != 1) {
812				dayOnTime = false;
813			}
814		});
815
816		var dotClass = dayOnTime ? 'punctuality-dot-on' : 'punctuality-dot-delay';
817		dotsHtml += '<span class="punctuality-dot ' + dotClass + '"></span>';
818
819		popoverRows += '<tr>' +
820			'<td class="punctuality-date">' + moment(dateKey).format('ddd, DD - MMM') + '</td>' +
821			'<td class="punctuality-status">' + renderPunctualityStatus(dayData.departure) + '</td>' +
822			'<td class="punctuality-status">' + renderPunctualityStatus(dayData.arrival) + '</td>' +
823			'</tr>';
824	});
825
826	var popoverHtml = '<div class="punctuality-popover">' +
827		'<table class="punctuality-popover-table">' +
828		'<thead><tr>' +
829		'<th>Last 7 Days Reliability</th>' +
830		'<th>Departure Time</th>' +
831		'<th>Arrival Time</th>' +
832		'</tr></thead>' +
833		'<tbody>' + popoverRows + '</tbody>' +
834		'</table>' +
835		'</div>';
836
837	return '<div class="trip-punctuality-wrap">' +
838		'<span class="trip-punctuality-badge ' + colorClass + '">' + percentage + '% On - Time</span>' +
839		'<div class="trip-punctuality-dots-wrap">' +
840		'<span class="trip-punctuality-dots">' + dotsHtml + '</span>' +
841		popoverHtml +
842		'</div>' +
843		'</div>';
844}
845
846function renderTripList(trips = []) {
847	var $tripcont = $('#trip-list-container');
848	var template = $('#template-trip-list').html();
849	var onwardsTag = ' <small>Starts From</small>';
850	var perSeat = 'Per Seat from';
851
852	var filterData = {};
853	filterData.boardingPointsMap = new Map();
854	filterData.droppingPointsMap = new Map();
855	filterData.busOperatorsMap = new Map();
856	filterData.amenitiesMap = new Map();
857
858	// var namespaceProfile = {};
859	// var currencyFormat = '';
860
861	totalTripCount = 0;
862	$.each(trips, function (i, tripss) {
863
864		// namespaceProfile = tripss.namespaceProfile;
865		totalTripCount = tripss.triplist.length;
866
867		// if (namespaceProfile && namespaceProfile.currencyCode == 'NPR') {
868		// 	currencyFormat = 'NRs.';
869		// } else {
870		// 	currencyFormat = '<i class="fas fa-sm fa-rupee-sign"></i> ';
871		// }
872
873		$.each(tripss.triplist, function (i, trip) {
874			totalAvailableSeatCount += trip.computed.availableSeatCount;
875			if (trip.tripStatus.code !== 'TPO') {
876				return;
877			}
878
879			// filter data mapping
880			$.each(trip.fromStation.stationPoint || [], function (k, bp) {
881				filterData.boardingPointsMap.set(bp.code, bp);
882			});
883
884			$.each(trip.toStation.stationPoint || [], function (k, dp) {
885				filterData.droppingPointsMap.set(dp.code, dp);
886			});
887
888			$.each(trip.amenities || [], function (k, am) {
889				filterData.amenitiesMap.set(am.code, am);
890			});
891
892			if (trip.operator) {
893				filterData.busOperatorsMap.set(trip.operator.code, trip.operator);
894			}
895
896			var $tpl = $(template);
897
898			// stage fare
899			var stageFares = [];
900			var discountFares = [];
901			var fareWithAvailableSeats = [];
902			$.each(trip.stageFare || [], function (i, stage) {
903				if (stage.availableSeatCount > 0) {
904					stageFares.push(stage.fare);
905					fareWithAvailableSeats.push(stage.fare);
906				} else {
907					stageFares.push(stage.fare);
908				} // un cammand for fare issue 22/11/24
909				discountFares.push(stage.discountFare || 0);
910			});
911			var minFareSource = fareWithAvailableSeats.length > 0 ? fareWithAvailableSeats : stageFares;
912
913			var minFare = Math.min.apply(null, minFareSource);
914			var minDiscountFare = Math.min.apply(null, discountFares);
915
916			var offer = Math.round(minDiscountFare / minFare * 100);
917
918			// amenities
919			var amenities = [];
920			$.each(trip.amenities || [], function (i, amenity) {
921				amenities.push('<span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span>');
922			});
923
924			// via routes
925			var viaStations = [];
926			var viaStationslide = [];
927			$.each(trip.viaStations || [], function (i, via) {
928				viaStations.push(via.name);
929				if (via.name.length > 15) {
930					let viaroutecutstring = via.name.substring(0, 15) + '...';
931					viaStationslide.push(viaroutecutstring);
932				} else {
933					viaStationslide.push(via.name);
934				}
935			});
936
937			// badges
938			var badges = [];
939			if (new String(trip.bus.categoryCode).split('|').includes('CC01')) {
940				badges.push('<span class="badge badge-primary" title="Air Conditioned Bus">AC</span>');
941			}
942
943			// templating
944			$tpl.attr('id', 'trip-' + trip.tripCode);
945			$tpl.find('.trip-bustype').html(trip.schedule.displayName.length > 15 ? trip.schedule.displayName : trip.bus.busType);
946			$tpl.find('.trip-badges').html(badges.join(''));
947
948			$tpl.find('.trip-offer-amount').html(minDiscountFare)
949			$tpl.find('.trip-offer-ribbon').toggleClass('d-none', !minDiscountFare);
950
951			$tpl.find('.trip-offer').toggleClass('d-none', !minDiscountFare);
952			$tpl.find('.hl-off-percent').html(offer + '%');
953
954			offerNumber = getofferDesignNumber();
955
956			if (offerNumber == 1) {
957				$tpl.find('.trip-offer').addClass('offer-1');
958				$tpl.find('.offer-icon').html('<img src="assets/images/search/offer-symbol-1.svg" alt="Rating User icon" class="">');
959				if (minDiscountFare > 0)
960					$tpl.find('.fare-margin').removeClass('fare-margin');
961			} else if (offerNumber == 2) {
962				$tpl.find('.trip-offer').addClass('offer-2');
963				$tpl.find('.offer-icon').html('<img src="assets/images/search/offer-symbol-2.svg" alt="Rating User icon" class="">');
964				$tpl.find('.hl-off-percent').addClass('offer-colour');
965				if (minDiscountFare > 0)
966					$tpl.find('.fare-margin').removeClass('fare-margin');
967			} else if (offerNumber == 3) {
968				$tpl.find('.trip-offer').addClass('offer-3');
969				$tpl.find('.offer-icon').html('<img src="assets/images/search/offer-symbol-2.svg" alt="Rating User icon" class="">');
970				$tpl.find('.hl-off-percent').addClass('offer-colour');
971				if (minDiscountFare > 0)
972					$tpl.find('.fare-margin').removeClass('fare-margin');
973			}
974
975			currencySymbol = trip.currencySymbol;
976
977			$tpl.find('.trip-fare').html(trip.currencySymbol + (minFare - minDiscountFare));
978			$tpl.find('.trip-onwards').html(stageFares.length > 1 && onwardsTag);
979			$tpl.find('.trip-perseat-from').html(stageFares.length > 1 && perSeat);
980			$tpl.find('.trip-fare-original').html(trip.currencySymbol + minFare).toggleClass('d-none', !minDiscountFare);
981			$tpl.find('.trip-starttime').html(moment(trip.fromStation.dateTime).format('hh:mm A'));
982			$tpl.find('.trip-endtime').html(moment(trip.toStation.dateTime).format('hh:mm A'));
983			$tpl.find('.trip-startdate').html(moment(trip.fromStation.dateTime).format('DD MMM'));
984			$tpl.find('.trip-enddate').html(moment(trip.toStation.dateTime).format('DD MMM'));
985			$tpl.find('.trip-startday').html(moment(trip.fromStation.dateTime).format('ddd'));
986			$tpl.find('.trip-endday').html(moment(trip.toStation.dateTime).format('ddd'));
987			$tpl.find('.trip-duration').html(trip.travelTime + ' hrs');
988			$tpl.find('.trip-seatsavail').attr('title', 'Total ' + trip.bus.totalSeatCount + ' Seats').html(trip.computed.availableSeatCount);
989			$tpl.find('.trip-via').html(viaStations.join(', '));
990			$tpl.find('.trip-amenities').html(amenities.join(''));
991			$tpl.find('.trip-reststop-count').html(trip.travelStopCount);
992			$tpl.find('[data-triptab="RESTSTOPS"]').toggleClass('d-none', !trip.travelStopCount);
993			$tpl.find('.rest-stop').toggleClass('d-none', !trip.travelStopCount);
994
995			if (amenities.length == 0) {
996				$tpl.find('[data-triptab="AMENITIES"]').addClass('d-none')
997			}
998
999			if (trip.computed.availableSeatCount === 0) {
1000				$tpl.find('.trip-seatsavail').parent().hide();
1001				$tpl.find('.trip-viewbusmap').html('Sold Out').removeClass('btn-primary').addClass('btn-danger').css({ 'padding': '4px 15px' });
1002				$tpl.find('.trip-viewbusmap, .tripinfo-container').addClass('no-map');
1003			} else {
1004				$tpl.find('.trip-viewbusmap').html(trip.computed.availableSeatCount + ' Seats')
1005			}
1006
1007			$tpl.find('.COPYtooltip').attr('id', 'COPYtooltip-' + trip.tripCode);
1008
1009			$.each(trip.fromStation.stationPoint || [], function (k, bp) {
1010				$tpl.find('.trip-fromstationpoint').html(bp.name);
1011				return false;
1012			});
1013
1014			$.each((trip.toStation.stationPoint || []).reverse(), function (k, dp) {
1015				$tpl.find('.trip-tostationpoint').html(dp.name);
1016				return false;
1017			});
1018
1019			//bus image profile 
1020			if (trip.busImageDetails && trip.busImageDetails.PROFILE && trip.busImageDetails.PROFILE.length > 0) {
1021				const imageUrl = trip.busImageDetails.PROFILE[0].imageUrlSlugs;
1022				$tpl.find('.bus-profile').css('background-image', 'url(' + imageUrl + ')');
1023			} else {
1024				$tpl.find('.bus-profile').addClass('d-none');
1025			}
1026
1027			$tpl.find('[data-triptab="BUSPHOTOS"]').toggleClass('d-none', !trip.busImageDetails.GALLERY);
1028			$tpl.find('.bus-gallery').toggleClass('d-none', !trip.busImageDetails.GALLERY);
1029
1030			var currentStationIndex = 0;
1031			var $viaRoutesContainer = $tpl.find('.all-via-routes');
1032			$viaRoutesContainer.html('<span class="">' + viaStationslide[currentStationIndex] + '</span>');
1033			$viaRoutesContainer.addClass('show');
1034			setInterval(function () {
1035				if (currentStationIndex >= viaStationslide.length) {
1036					currentStationIndex = 0;
1037				}
1038				$viaRoutesContainer.removeClass('show');
1039				$viaRoutesContainer.html('<span class="">' + viaStationslide[currentStationIndex] + '</span>');
1040				setTimeout(function () {
1041					$viaRoutesContainer.addClass('show');
1042				}, 100);
1043				currentStationIndex++;
1044			}, 3000);
1045
1046
1047			//journey status
1048			var currentDate = new Date(); // current date
1049			var year = currentDate.getFullYear();
1050			var month = ('0' + (currentDate.getMonth() + 1)).slice(-2);
1051			var day = ('0' + currentDate.getDate()).slice(-2);
1052
1053			var hours = ('0' + currentDate.getHours()).slice(-2);
1054			var minutes = ('0' + currentDate.getMinutes()).slice(-2);
1055			var seconds = ('0' + currentDate.getSeconds()).slice(-2);
1056
1057			var formattedDate = year + '-' + month + '-' + day; // date only
1058			var formattedDateTime = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds; // date time
1059			var formattedDateTimeObj = new Date(formattedDateTime); // current date time
1060
1061			// from station
1062			var fromDateTime = Object.values(trip.fromStation.stationPoint)[0];
1063			if (fromDateTime && fromDateTime.dateTime) {
1064				var fromDateTimeObj = new Date(fromDateTime.dateTime); // from station point date time
1065			}
1066
1067			var timeDifference = formattedDateTimeObj - fromDateTimeObj;
1068			var timeDifferenceInSeconds = Math.floor(timeDifference / 1000);
1069			var timeDifferenceInMinutes = Math.floor(timeDifferenceInSeconds / 60);
1070
1071			var absoluteTimeDifferenceInMinutes = Math.abs(timeDifferenceInMinutes); // minutes
1072			var absoluteTimeDifference = Math.abs(timeDifference); // hours
1073
1074			var timeDifferenceHours = Math.round(absoluteTimeDifference / (1000 * 60 * 60));
1075
1076			// to station 
1077			var toStationPoint = Object.values(trip.toStation.stationPoint);
1078			var toDateTime = toStationPoint[toStationPoint.length - 1];
1079
1080			if (toStationPoint.length > 0 && toStationPoint && toDateTime.dateTime) {
1081				var toDateTimeObj = new Date(toDateTime.dateTime); // to station point date time
1082			}
1083
1084			var formattedTravelDate = new Date(trip.travelDate);
1085			var formatTravelDate = formattedTravelDate.toISOString().split('T')[0]; // travel date
1086
1087			if (formattedDateTimeObj > fromDateTimeObj) {
1088				if (trip.tripStatus.code == "TCA" || (trip.tripStatus.code == "TPC" && trip.bookedSeatCount == 0)) {
1089					$tpl.find('#bus-status').removeClass('d-none').addClass('mt-35');
1090				} else {
1091					$tpl.find('#bus-status').removeClass('d-none').addClass('in-journey').html('In Journey');
1092				}
1093			} else if (timeDifferenceHours == 0) {
1094				if (trip.tripStatus.code == "TCA" || (trip.tripStatus.code == "TPC" && trip.bookedSeatCount == 0)) {
1095					$tpl.find('#bus-status').removeClass('d-none').addClass('mt-35');
1096				} else {
1097					$tpl.find('#bus-status').removeClass('d-none').addClass('hg-g').html('Depart in ' + absoluteTimeDifferenceInMinutes + ' Mins');
1098				}
1099			} else if (formattedDateTimeObj < fromDateTimeObj) {
1100				if (trip.tripStatus.code == "TCA" || (trip.tripStatus.code == "TPC" && trip.bookedSeatCount == 0)) {
1101					$tpl.find('#bus-status').removeClass('d-none').addClass('mt-35');
1102				} else {
1103					$tpl.find('#bus-status').removeClass('d-none').addClass('hg-g').html('Depart in ' + timeDifferenceHours + ' Hrs');
1104				}
1105			}
1106
1107			if (formatTravelDate == formattedDate) {
1108				$tpl.find('#bus-status').removeClass('d-none');
1109			} else {
1110				$tpl.find('#bus-status').addClass('d-none');
1111			}
1112
1113			// comingFrom-station
1114			var fromStationFirstBoarding = Object.values(trip.fromStation.stationPoint)[0];
1115
1116			if (fromStationFirstBoarding.name.length > 13) {
1117				let stationName = fromStationFirstBoarding.name.substring(0, 13) + '...';
1118				if (formattedDateTimeObj > fromDateTimeObj) {
1119					$tpl.find('.comingFrom-station').html('Coming from ' + stationName);
1120				} else {
1121					$tpl.find('.comingFrom-station').html('Starting from ' + stationName);
1122				}
1123			} else {
1124				if (formattedDateTimeObj > fromDateTimeObj) {
1125					$tpl.find('.comingFrom-station').html('Coming from ' + fromStationFirstBoarding.name);
1126				} else {
1127					$tpl.find('.comingFrom-station').html('Starting from ' + fromStationFirstBoarding.name);
1128				}
1129			}
1130
1131			if (trip.tripInfo.registrationNumber != '') {
1132				$tpl.find('.vehicle-number').removeClass('d-none');
1133				$tpl.find('.veh-register-no').html(trip.tripInfo.registrationNumber);
1134			}
1135
1136
1137			if (trip.singleSeats != 0) {
1138				$tpl.find('.single-seat-details').removeClass('d-none');
1139				$tpl.find('.single-seat').html(trip.singleSeats + ' Single');
1140			}
1141
1142			if (trip.windowSeats != 0) {
1143				$tpl.find('.window-seat-details').removeClass('d-none');
1144				$tpl.find('.window-seat').html(trip.windowSeats + ' Window');
1145			}
1146
1147			if (trip.femaleBookedSeats != 0) {
1148				$tpl.find('.female-seat-details').removeClass('d-none');
1149				$tpl.find('.female-seat').html(trip.femaleBookedSeats + ' Female');
1150			}
1151			
1152
1153			$tpl.find('.boardingpoint-count').html(trip.fromStation.stationPoint.length);
1154			$tpl.find('.droppingpoint-count').html(trip.toStation.stationPoint.length);
1155
1156			if (isPM(trip.fromStation.dateTime)) {
1157				$tpl.find('.travelTime').html('<img class="mr_2" src="assets/images/search/night-time.svg" width="17px" height= "17px">' + trip.travelTime + ' hrs');
1158			} else {
1159				$tpl.find('.travelTime').html('<img class="mr_2" src="assets/images/search/day-time.svg" width="17px" height= "17px">' + trip.travelTime + ' hrs');
1160			}			
1161
1162			var punctualityHtml = renderPunctuality(trip.punctualityList, trip.travelDate, trip.fromStation.code, trip.toStation.code);
1163			$tpl.find('.trip-punctuality').html(punctualityHtml).toggleClass('d-none', !punctualityHtml);
1164
1165			// lower
1166			var lower = renderBusSeatsV4({
1167				layer: 1,
1168				matrix: trip.lmatrix,
1169				seatStatus: trip.seatStatus
1170			});
1171
1172			$tpl.find('.mini-lower-layer-seats').html(lower);
1173
1174			// upper
1175			if (trip.umatrix) {
1176				var upper = renderBusSeatsV4({
1177					layer: 2,
1178					matrix: trip.umatrix,
1179					seatStatus: trip.seatStatus
1180				});
1181
1182				$tpl.find('.mini-upper-layer-seats').html(upper);
1183				$tpl.find('.mini-upper-layer, .mini-layer-name').removeClass('d-none');
1184			}
1185
1186			// busmap
1187			// $tpl.find('.trip-viewbusmap').on('click', function (e) {
1188			// 	if (isLoadingBusMap) return;
1189
1190			// 	if (!$(e.target).is('.boardingpoint-count, .droppingpoint-count')) {
1191			// 	!$(this).hasClass('no-map') && initBusMap(trip);
1192			// 	} else {
1193			// 		renderTripTab('STATIONPOINTS', trip);
1194			// 	}
1195			// });
1196
1197			// var scrollInProgress = false;
1198			$tpl.find('.tripinfo-container').on('click', function (e) {
1199
1200				$('#trip-' + trip.tripCode).find('.trip-tabs-content').removeClass('busgallery-background');
1201
1202				var tripElement = $('#trip-' + trip.tripCode);
1203				if (tripElement.length && !$(this).hasClass('no-map') &&
1204					!$(e.target).is('.share-link') &&
1205					!$(e.target).closest('.trip-punctuality-wrap').length &&
1206					!$(e.target).is('.boardingpoint-count') &&
1207					!$(e.target).is('.droppingpoint-count') &&
1208					!$(e.target).hasClass('rest-stop') &&
1209					!$(e.target).hasClass('via-routes') &&
1210					!$(e.target).hasClass('bus-gallery') &&
1211					!$(e.target).hasClass('bus-profile')) {
1212
1213					$('html, body').animate({
1214						scrollTop: tripElement.offset().top - 60
1215					}, 1000, 'swing', function () {
1216						tripElement.find('.trip-tab-content').slideToggle(300);
1217						$('.trip-tab-content').not(tripElement.find('.trip-tab-content')).slideUp(300);
1218					});
1219				}
1220
1221				if (isLoadingBusMap) return;
1222				if ($(e.target).closest('.trip-tabs').length > 0) {
1223					return;
1224				}
1225
1226				if ($(e.target).is('.share-link')) {
1227					generateSharingLink(trip);
1228					trackEvent('Share Trip', 'click', 'Share Link');
1229					return;
1230				}
1231
1232				if ($(e.target).closest('.trip-punctuality-wrap').length) {
1233					return;
1234				}
1235
1236				if ($(e.target).is('.boardingpoint-count, .droppingpoint-count')) {
1237					renderTripTab('STATIONPOINTS', trip);
1238					trackEvent('Trip Info', 'click', 'STATIONPOINTS');
1239					return;
1240				}
1241
1242				if ($(e.target).hasClass('rest-stop')) {
1243					renderTripTab('RESTSTOPS', trip);
1244					trackEvent('Trip Info', 'click', 'RESTSTOPS');
1245					return;
1246				}
1247
1248				if ($(e.target).hasClass('bus-gallery') || $(e.target).hasClass('bus-profile')) {
1249					$('#trip-' + trip.tripCode).find('.trip-tabs-content').addClass('busgallery-background');
1250					renderTripTab('BUSPHOTOS', trip);
1251					trackEvent('Trip Info', 'click', 'BUSPHOTOS');
1252					return;
1253				}
1254
1255				if ($(e.target).hasClass('via-routes')) {
1256					renderTripTab('VIAROUTES', trip);
1257					trackEvent('Trip Info', 'click', 'VIAROUTES');
1258					return;
1259				}
1260
1261				if (!$(this).hasClass('no-map')) {
1262					$(this).find('.trip-viewbusmap').html('Hide seats');
1263					initBusMap(trip, 'reg');
1264				}
1265			});
1266
1267			// tabs
1268			$tpl.find('[data-triptab]').on('click', function (e) {
1269				var tab = $(e.target).data('triptab');
1270				renderTripTab(tab, trip);
1271				trackEvent('Trip Info', 'click', tab);
1272			});
1273
1274			// ordering
1275			$tpl
1276				.attr('data-departure', moment(trip.fromStation.dateTime).valueOf())
1277				.attr('data-availability', trip.availableSeatCount)
1278				.attr('data-fare', minFare);
1279
1280			// tooltips
1281			$tpl.find('[data-toggle="tooltip"]').tooltip({
1282				container: $tripcont,
1283				html: true,
1284				placement: 'top',
1285				boundary: 'viewport',
1286			});
1287
1288			// append
1289			$tripcont.append($tpl);
1290		});
1291	});
1292
1293	// trip seat card
1294	// $('#trip-seats-card').toggleClass('d-none');
1295	$('.total-trip-count').html('<img src="assets/images/search/buscount.svg" alt="Bus Icon"> Showing ' + trips.length + ' Buses on this route');
1296	$('.total-seat-count').html('<b>' + totalAvailableSeatCount + '</b> Seats Available');
1297
1298	$('#trip-empty-container').toggleClass('d-none', !!trips.length);
1299	$('#trip-list-filter').toggleClass('invisible', trips.length < 2);
1300
1301	// sort trip list
1302	sortTripList();
1303
1304	// filter trip list
1305	renderTripFilter(filterData, trips);
1306	openSharedTrip();
1307}
1308
1309function renderTripTab(tab, trip) {
1310	// if (isConnecting) {
1311	// 	var $tabcont = $('#cmTrip-' + trip.tripCode).find('.info-cont');
1312	// // } else {
1313		var $tabcont = $('#trip-' + trip.tripCode).find('.trip-tabs-content');
1314	// }
1315
1316
1317	if ($tabcont.find('[data-tabcontent=' + tab + ']').length) {
1318		resetTripList(trip);
1319		return;
1320	}
1321	resetTripList(trip);
1322
1323	$('#trip-' + trip.tripCode).find('[data-triptab=' + tab + ']').addClass('font-weight-bold');
1324	$tabcont.html('<div class="text-center">Loading...</div>');
1325
1326	switch (tab) {
1327		case 'AMENITIES':
1328			var $amenities = $('<div/>').addClass('row').attr('data-tabcontent', tab);
1329			$.each(trip.amenities || [], function (i, amenity) {
1330				$amenities.append('<div class="col-6 py-2"><span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span> <span>' + amenity.name + '</span></div>');
1331			});
1332			$tabcont.html($amenities);
1333			break;
1334
1335		case 'RESCHEDULE':
1336			var $rescheduleInstructions = $('<div/>').addClass('reschedule-list');
1337			$rescheduleInstructions.append('<b>Reschedule Instructions:</b>');
1338			$rescheduleInstructions.append('<ul class="pL-15">' +
1339				'<li>Rescheduling will be subject to availability of seats.</li>' +
1340				'<li>Rescheduled (both new & old) tickets not allowed cancel or reschedule further.</li>' +
1341				'<li>Reschedule fee and fare difference (If new ticket amount is higher than old ticket) should be paid by customer.</li>' +
1342				'<li>No amount will be refunded, if the new ticket you book is of lower amount than the previous booking.</li>' +
1343				'<li>Upon successful transaction, you will receive new ticket and same passenger(s) should travel with new ticket.</li>' +
1344				'<li>Ticket once transferred cannot transferred or cancelled again. ( Applicable for Both Postpone or Prepone )</li>' +
1345				'</ul>');
1346			$tabcont.html($rescheduleInstructions);
1347			break;
1348
1349		case 'STATIONPOINTS':
1350			var template = $('#template-station-point').html();
1351			var $stationpoints = $('<div/>').addClass('row').addClass('m-0').attr('data-tabcontent', tab);
1352
1353			var $frompoints = $('<div/>').addClass('col-md-6');
1354			$frompoints.append('<h6>Boarding Points</h6>');
1355
1356			var lastdate = {};
1357			$.each(trip.fromStation.stationPoint || [], function (i, station) {
1358				var $sp = $(template);
1359				var date = moment(station.dateTime).format('ddd, DD MMM')
1360				if (!lastdate[date]) {
1361					lastdate[date] = date;
1362					$frompoints.append('<div class="bpdp-bg p-1 px-3">' + date + '</div>');
1363				}
1364				$sp.find('.sp-time').html(moment(station.dateTime).format('hh:mm A'));
1365				$sp.find('.sp-name').html(station.name);
1366				$.each(station.amenities || [], function (i, amenity) {
1367					$sp.find('.sp-amenities').append('<span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span>');
1368				});
1369				$sp.appendTo($frompoints);
1370			});
1371
1372			var $topoints = $('<div/>').addClass('col-md-6 border-left');
1373			$topoints.append('<h6>Dropping Points</h6>');
1374
1375			var lastdate = {};
1376			var toStationPoints = trip.toStation.stationPoint || [];
1377
1378			toStationPoints.sort(function (a, b) {
1379				return moment(a.dateTime).unix() - moment(b.dateTime).unix();
1380			});
1381
1382			$.each(toStationPoints, function (i, station) {
1383				var $sp = $(template);
1384				var date = moment(station.dateTime).format('ddd, DD MMM')
1385				if (!lastdate[date]) {
1386					lastdate[date] = date;
1387					$topoints.append('<div class="bpdp-bg p-1 px-3">' + date + '</div>');
1388				}
1389				$sp.find('.sp-time').html(moment(station.dateTime).format('hh:mm A'));
1390				$sp.find('.sp-name').html(station.name);
1391				$.each(station.amenities || [], function (i, amenity) {
1392					$sp.find('.sp-amenities').append('<span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span>');
1393				});
1394				$sp.appendTo($topoints);
1395			});
1396
1397			$stationpoints.append($frompoints).append($topoints);
1398			$tabcont.html($stationpoints);
1399
1400			$tabcont.find('[data-toggle="tooltip"]').tooltip({
1401				container: $tabcont,
1402				html: true,
1403				placement: 'top',
1404				boundary: 'viewport',
1405			});
1406			break;
1407
1408		case 'CANCELTERMS':
1409			var data = {};
1410			data.tripCode = trip.tripCode;
1411			data.fromStationCode = trip.fromStation.code;
1412			data.toStationCode = trip.toStation.code;
1413			data.travelDate = trip.travelDate;
1414
1415			$.ajax({
1416				type: 'POST',
1417				url: 'search/cancellation-terms',
1418				data: data,
1419				dataType: 'json',
1420				success: function (result) {
1421					if (result.status == 1) {
1422						var template = $('#template-cancellation-policy').html();
1423						var $terms = $('<div/>').attr('data-tabcontent', tab).append(template);
1424						var $tbody = $terms.find('tbody');
1425						$.each(result.data.policyList || [], function (i, policy) {
1426							var $tr = $('<tr/>');
1427							$('<td/>').html(policy.term).appendTo($tr);
1428							$('<td/>').html(policy.deductionAmountTxt + ' (' + policy.chargesTxt + ')').appendTo($tr);
1429							$('<td/>').html(policy.refundAmountTxt).appendTo($tr);
1430							$tr.appendTo($tbody);
1431						});
1432						$tabcont.html($terms);
1433					} else {
1434						$tabcont.danger({ message: result.errorDesc, delay: 10e6 });
1435					}
1436				}
1437			});
1438			break;
1439
1440		case 'RESTSTOPS':
1441			var data = {};
1442			data.tripCode = trip.tripCode;
1443			data.fromStationCode = trip.fromStation.code;
1444			data.toStationCode = trip.toStation.code;
1445			$.ajax({
1446				type: 'POST',
1447				url: 'search/rest-stops',
1448				data: data,
1449				dataType: 'json',
1450				success: function (result) {
1451					if (result.status == 1) {
1452						var template = $('#template-rest-stops').html();
1453						var $reststops = $('<div/>').addClass('row m-0').attr('data-tabcontent', tab);
1454						$.each(result.data || [], function (i, stop) {
1455							var $reststop = $(template);
1456							$reststop.find('.time').text(moment(stop.travelStopTime).format('hh:mm A'));
1457							$reststop.find('.name').text(stop.name);
1458							$reststop.find('.location').attr('href', 'https://maps.google.com?q=' + encodeURIComponent(stop.latitude + ',' + stop.longitude));
1459							$reststop.find('.duration').text(stop.minutes);
1460							$reststop.find('.restroom').text(stop.restRoom);
1461
1462							var $remarks = $.trim(stop.remarks).split('\n').filter(Boolean).map(r => $('<div />').text(r));
1463							$reststop.find('.remarks').html($remarks);
1464							$reststop.find('.remarks-panel').toggleClass('d-none', $remarks.length == 0);
1465
1466							$.each(stop.amenities || [], function (i, amenity) {
1467								$reststop.find('.amenities').append('<div class="badge badge-secondary font-weight-normal mr-1">' + amenity + '</div>');
1468							});
1469
1470							$reststops.append($reststop);
1471						});
1472						$tabcont.html('<h6 class="rest-stopH">Rest Stops</h6>');
1473						$tabcont.append($reststops);
1474					}
1475					else {
1476						$tabcont.danger({ message: result.errorDesc, delay: 10e6 });
1477					}
1478				}
1479			});
1480			break;
1481
1482		case 'VIAROUTES':
1483			var data = {};
1484			data.tripCode = trip.tripCode;
1485			$.ajax({
1486				type: 'POST',
1487				url: 'search/stage-details',
1488				data: data,
1489				dataType: 'json',
1490				success: function (result) {
1491					if (result.status == 1) {
1492						var $viastation = $('<div/>').addClass('row').addClass('m-0').attr('data-tabcontent', tab);
1493
1494						var $stations = $('<div/>').addClass('col-md-6 via-panel');
1495						$stations.append('<h6>Via Stations</h6>');
1496
1497						var lastdate = {};
1498						$.each(result.data || [], function (i, station) {
1499							var date = moment(station.fromStation.dateTime).format('ddd, DD MMM')
1500							if (!lastdate[date]) {
1501								lastdate[date] = date;
1502								$stations.append('<div class="bpdp-bg p-1 px-3">' + date + '</div>');
1503							}
1504							$stations.append('<div class="row bpdp-icon"><div class="col"><b>' + moment(station.fromStation.dateTime).format('hh:mm A') + '</b> - ' + station.fromStation.name + '</div></div>');
1505						});
1506
1507						var $map = $('<div/>').addClass('col-md-6');
1508						$map.append('<div id="via-map"></div>');
1509
1510						$viastation.append($stations).append($map);
1511						$tabcont.html($viastation);
1512
1513						initViaRouteMap(result.data);
1514					} else {
1515						$tabcont.danger({ message: result.errorDesc, delay: 10e6 });
1516					}
1517				}
1518			});
1519			break;
1520
1521		case 'BUSPHOTOS':
1522			const images = trip.busImageDetails.GALLERY ?? [];
1523			const $slider = $('<div/>').attr('data-tabcontent', tab).addClass('image-slider');
1524
1525			images.forEach((image) => {
1526				const imgElement = `<div class="slick-slide">
1527								<img class="bus-image-new" src="${image.imageUrlSlug}
1527" alt="Bus Image" 
1528									onerror="this.style.display='none';" />
1529							</div>`;
1530				$slider.append(imgElement);
1531			});
1532			$tabcont.html($slider).hide().slideDown(300);
1533			$slider.before('<div class="sslick-arrow slick-prev"><i class="fa fa-chevron-left"></i></div>');
1534			$slider.after('<div class="sslick-arrow slick-next"><i class="fa fa-chevron-right"></i></div>');
1535			initImageSlider($slider);
1536
1537			break;
1538		default:
1539			break;
1540	}
1541}
1542
1543function renderTripFilter(filterData, trips) {
1544	var template = $('#template-custom-checkbox').html();
1545
1546	var $bplist = $('#filter-bp-list');
1547	filterData.boardingPointsMap.forEach(function (bp) {
1548		var $cb = $(template);
1549		$cb.attr('data-name', bp.name.toLowerCase());
1550		$cb.find('input').attr('id', 'bp-cb-' + bp.code).attr('value', bp.code).addClass('filter-bp-cb');
1551		$cb.find('label').attr('for', 'bp-cb-' + bp.code).html(bp.name);
1552
1553		$bplist.append($cb);
1554	});
1555	$bplist.closest('.filter-section').find('.badge-count').html(filterData.boardingPointsMap.size);
1556
1557	var $dplist = $('#filter-dp-list');
1558	filterData.droppingPointsMap.forEach(function (dp) {
1559		var $cb = $(template);
1560		$cb.attr('data-name', dp.name.toLowerCase());
1561		$cb.find('input').attr('id', 'dp-cb-' + dp.code).attr('value', dp.code).addClass('filter-dp-cb');
1562		$cb.find('label').attr('for', 'dp-cb-' + dp.code).html(dp.name);
1563
1564		$dplist.append($cb);
1565	});
1566	$dplist.closest('.filter-section').find('.badge-count').html(filterData.droppingPointsMap.size);
1567
1568	var $bolist = $('#filter-bo-list');
1569	filterData.busOperatorsMap.forEach(function (bo) {
1570		var $cb = $(template);
1571		$cb.attr('data-name', bo.name.toLowerCase());
1572		$cb.find('input').attr('id', 'bo-cb-' + bo.code).attr('value', bo.code).addClass('filter-bo-cb');
1573		$cb.find('label').attr('for', 'bo-cb-' + bo.code).html(bo.name);
1574
1575		$bolist.append($cb);
1576	});
1577	$bolist.closest('.filter-section').toggleClass('d-none', filterData.busOperatorsMap.size < 2)
1578		.find('.badge-count').html(filterData.busOperatorsMap.size);
1579
1580	var $amlist = $('#filter-am-list');
1581	filterData.amenitiesMap.forEach(function (am) {
1582		var $cb = $(template);
1583		$cb.attr('data-name', am.name.toLowerCase());
1584		$cb.find('input').attr('id', 'am-cb-' + am.code).attr('value', am.code).addClass('filter-am-cb');
1585		$cb.find('label').attr('for', 'am-cb-' + am.code).html(am.name);
1586
1587		$amlist.append($cb);
1588	});
1589	$amlist.closest('.filter-section').toggleClass('d-none', filterData.amenitiesMap.size < 2)
1590		.find('.badge-count').html(filterData.amenitiesMap.size);
1591
1592	// Events
1593	$('#trip-filter-panel').on('change', function (e) {
1594		applyTripListFilter(trips);
1595	});
1596
1597	const TRIPFILTER_HASH = '#tripfilter';
1598	$('#trip-filter-modal').on('show.bs.modal', function () {
1599		location.hash = TRIPFILTER_HASH;
1600	}).on('hide.bs.modal', function () {
1601		location.hash === TRIPFILTER_HASH && history.back();
1602	});
1603	$(window).on('hashchange', function () {
1604		switch (location.hash) {
1605			case TRIPFILTER_HASH:
1606				showFilterTripList();
1607				break;
1608			default:
1609				hideFilterTripList();
1610		}
1611	});
1612
1613	$('#trip-filter-panel .filter-search').on('input', function (e) {
1614		var value = e.target.value || '';
1615		value = value.trim().toLowerCase();
1616
1617		var $list = $(e.target).closest('.filter-section').find('.filter-cb-list');
1618		$list.find('.custom-checkbox').toggleClass('d-none', value !== '');
1619		$list.find('[data-name*="' + value + '"]').removeClass('d-none');
1620	});
1621}
1622
1623function showFilterTripList() {
1624	resetTripList();
1625	$('#trip-filter-modal').modal('show');
1626}
1627
1628function hideFilterTripList() {
1629	$('#trip-filter-modal').modal('hide');
1630}
1631
1632function resetTripListFilter() {
1633	$('.trip-filter-toggle .active').removeClass('active');
1634	$('#trip-filter-panel :checkbox').prop('checked', false);
1635	$('.trip-infos.d-none').removeClass('d-none');
1636	$('#trip-empty-container').html('').removeClass('p-3');
1637	$('#trip-filter-modal').modal('hide');
1638}
1639
1640function applyTripListFilter(trips = []) {
1641	var filterCount = $('#trip-filter-panel :checkbox:checked').length;
1642
1643	var $allTrips = $('.trip-infos');
1644	if (!filterCount) {
1645		$allTrips.removeClass('d-none');
1646		$('#trip-empty-container').toggleClass('d-none', !!$allTrips.filter(':visible').length);
1647		$('#trip-filter-modal').modal('hide');
1648		return;
1649	}
1650	$allTrips.addClass('d-none');
1651
1652	const DAYSERVICE = $('.departure-time-cb[value="DAY"]').is(':checked');
1653	const NIGHTSERVICE = $('.departure-time-cb[value="NIGHT"]').is(':checked');
1654	const EVENINGSERVICE = $('.departure-time-cb[value="EVEDAYAFTERFIVE"]').is(':checked');
1655	const LATESERVICE = $('.departure-time-cb[value="TENAFTERNIGHT"]').is(':checked');
1656
1657	const BUSCLIMATELIST = $('.bus-type-cb[data-category="CLIMATE"]:checked').map((k, v) => v.value).get();
1658	const BUSCLIMATEREGEX = new RegExp(BUSCLIMATELIST.join('|'));
1659
1660	const BUSTYPELIST = $('.bus-type-cb[data-category="SEATTYPE"]:checked').map((k, v) => v.value).get();
1661	const BUSTYPEREGEX = new RegExp(BUSTYPELIST.join('|'));
1662
1663	const BOARDINGLIST = $('.filter-bp-cb:checked').map((k, v) => v.value).get();
1664	const DROPPINGLIST = $('.filter-dp-cb:checked').map((k, v) => v.value).get();
1665	const OPERATORLIST = $('.filter-bo-cb:checked').map((k, v) => v.value).get();
1666	const AMENITYLIST = $('.filter-am-cb:checked').map((k, v) => v.value).get();
1667
1668
1669	$.each(trips, function (i, trip) {
1670		$.each(trip.triplist, function (i, tripss) {
1671
1672			const $trip = $('#trip-' + tripss.tripCode);
1673
1674			const DAYSTART = moment(tripss.travelDate + ' 06:00:00');
1675			const NIGHTSTART = moment(tripss.travelDate + ' 18:00:00');
1676			const EVENINGSTART = moment(tripss.travelDate + ' 17:00:00');
1677			const LATESTART = moment(tripss.travelDate + ' 22:00:00');
1678			const STARTTIME = moment(tripss.fromStation.dateTime);
1679
1680			if (DAYSERVICE && NIGHTSERVICE && EVENINGSERVICE && LATESERVICE) {
1681			} else {
1682				if (DAYSERVICE) {
1683					trackEvent('Trip Filter', 'click', 'DAYSERVICE');
1684					// Before 10 AM (up to 10 AM)
1685					const DAYEND = moment(tripss.travelDate + ' 10:00:00');
1686					if (!STARTTIME.isBefore(DAYEND)) {
1687						return;
1688					}
1689				}
1690
1691				if (NIGHTSERVICE) {
1692					trackEvent('Trip Filter', 'click', 'NIGHTSERVICE');
1693					// 10 AM to 5 PM
1694					const NIGHTEND = moment(tripss.travelDate + ' 17:00:00');
1695					if (!STARTTIME.isBetween(NIGHTSTART, NIGHTEND)) {
1696						return;
1697					}
1698				}
1699
1700				if (EVENINGSERVICE) {
1701					trackEvent('Trip Filter', 'click', 'EVENINGSERVICE');
1702					// 5 PM to 10 PM
1703					const EVENINGEND = moment(tripss.travelDate + ' 22:00:00');
1704					if (!STARTTIME.isBetween(EVENINGSTART, EVENINGEND)) {
1705						return;
1706					}
1707				}
1708
1709				if (LATESERVICE) {
1710					trackEvent('Trip Filter', 'click', 'LATESERVICE');
1711					// After 10 PM
1712					if (!STARTTIME.isAfter(LATESTART)) {
1713						return;
1714					}
1715				}
1716			}
1717
1718			if ((BUSCLIMATELIST.length && !BUSCLIMATEREGEX.test(tripss.bus.categoryCode)) ||
1719				(BUSTYPELIST.length && !BUSTYPEREGEX.test(tripss.bus.categoryCode))) {
1720				trackEvent('Bus Type', 'click', 'Bus Type Filter');
1721				return;
1722			}
1723			if (BOARDINGLIST.length) {
1724
1725				trackEvent('Trip Filter', 'click', 'BOARDING');
1726				$.each(tripss.fromStation.stationPoint || [], function (k, sp) {
1727					if (BOARDINGLIST.includes(sp.code)) {
1728						$trip.removeClass('d-none');
1729						return false;
1730					}
1731				});
1732			}
1733			if (DROPPINGLIST.length) {
1734				trackEvent('Trip Filter', 'click', 'DROPPING');
1735				$.each(tripss.toStation.stationPoint || [], function (k, sp) {
1736					if (DROPPINGLIST.includes(sp.code)) {
1737						$trip.removeClass('d-none');
1738						return false;
1739					}
1740				});
1741			}
1742			if (OPERATORLIST.length) {
1743				trackEvent('Trip Filter', 'click', 'OPERATOR');
1744				if (tripss.operator && OPERATORLIST.includes(tripss.operator.code)) {
1745					$trip.removeClass('d-none');
1746				}
1747			}
1748			if (AMENITYLIST.length) {
1749				trackEvent('Trip Filter', 'click', 'AMENITY');
1750				$.each(tripss.amenities || [], function (k, am) {
1751					if (AMENITYLIST.includes(am.code)) {
1752						$trip.removeClass('d-none');
1753						return false;
1754					}
1755				});
1756			}
1757
1758			$trip.removeClass('d-none');
1759		});
1760	});
1761
1762	$('#trip-empty-container').toggleClass('d-none', !!$allTrips.filter(':visible').length);
1763
1764	$('#trip-filter-modal').modal('hide');
1765}
1766
1767function sortTripList(orderby = 'departure', ordertype = 'asc') {
1768	var $tripcont = $('#trip-list-container');
1769
1770	var $tripinfo = $tripcont.find('.trip-infos').sort(function (a, b) {
1771		return $(b).data(orderby) < $(a).data(orderby) ? 1 : -1;
1772	});
1773
1774	if (ordertype == 'desc') {
1775		$tripinfo = $tripinfo.get().reverse();
1776	}
1777
1778	$tripcont.append($tripinfo);
1779
1780	$('#trip-list-header').on('click', function (e) {
1781		trackEvent('Trip Sorting', 'click', orderby);
1782	});
1783
1784	$('#trip-list-header').toggleClass('d-none', $tripinfo.length < 2);
1785}
1786
1787// Returns availableSeatCount regardless of whether the trip object uses the
1788// regular shape (`trip.computed.availableSeatCount`) or the connecting-trip
1789// shape (`trip.availableSeatCount`).
1790function getTripAvailableSeatCount(trip) {
1791	if (!trip) return 0;
1792	if (trip.computed && typeof trip.computed.availableSeatCount !== 'undefined') {
1793		return trip.computed.availableSeatCount;
1794	}
1795	if (typeof trip.availableSeatCount !== 'undefined') {
1796		return trip.availableSeatCount;
1797	}
1798	return 0;
1799}
1800
1801function initBusMap(trip, type) {
1802	var $busmapcont = $('#trip-' + trip.tripCode).find('.trip-tabs-content');
1803
1804	var $tripinfo = $('#trip-' + trip.tripCode).find('.tripinfo-container');
1805
1806	$('.tripinfo-container').find('.minibusfilter').removeClass('minibusfilter');
1807
1808	if ($busmapcont.find('.busmap-container').length) {
1809		$tripinfo.find('.trip-viewbusmap').html(getTripAvailableSeatCount(trip) + ' Seats');
1810		resetTripList(trip);
1811		return;
1812	}
1813	isLoadingBusMap = true;
1814	resetTripList(trip);
1815
1816	var data = {};
1817	data.tripCode = trip.tripCode;
1818	data.fromStationCode = trip.fromStation.code;
1819	data.toStationCode = trip.toStation.code;
1820	data.travelDate = trip.travelDate;
1821
1822	$busmapcont.html('<div class="text-center">Loading...</div>');
1823
1824	if (type == 'conn') { // in case of connecting need to pass master schedule code
1825		data.isConnecting = isConnecting;
1826		data.connScheduleCode = $busmapcont.closest('.c-m-trip-infos').attr('data-schedule-code-master');
1827	}
1828
1829	$.ajax({
1830		type: 'POST',
1831		url: 'search/busmap',
1832		data: data,
1833		dataType: 'json',
1834		success: function (result) {
1835			if (result.status == 1) {
1836
1837				type == 'conn' ? renderBusMapConn(result.data, isConnecting = true) : renderBusMap(result.data);
1838				isLoadingBusMap = false;
1839				connectingSelected = false;
1840
1841				busmapp = result.data;
1842				var res = result.data
1843				var terms = '';
1844
1845				var servicenotes = '';
1846				if (res.terms && res.terms['service_notes']) {
1847					servicenotes += '<h6>Service Notes</h6><ul style="font-size: 12px;line-height: 17px;">';
1848					$.each(res.terms['service_notes'], function (k, val) {
1849						servicenotes += '<li>' + val.name + '</li>'
1850					});
1851					servicenotes += '</ul>'
1852				}
1853
1854				$('#schedule-service-terms').html(servicenotes);
1855
1856				if (res.terms && res.terms['travel_policy']) {
1857					terms += '<ul class="travel-policy">'
1858					$.each(res.terms['travel_policy'], function (k, val) {
1859						terms += '<li>' + val.name + '</li>'
1860					});
1861					terms += '</ul>';
1862				}
1863
1864				$('#schedule-travel-terms').html(terms);
1865
1866				if (res.terms && !(res.terms.length > 0)) {
1867					$('.travel-info-card').addClass('d-none');
1868				}
1869
1870				$('#trip-' + trip.tripCode).find('#minibusmap').addClass('minibusfilter');
1871				previousTrip = trip;
1872			} else {
1873				$busmapcont.danger(result.errorDesc);
1874				isLoadingBusMap = false;
1875			}
1876		}
1877	});
1878}
1879
1880function resetTripList(trip) {
1881	$('.trip-tabs-content').empty();
1882	$('.trip-tabs [data-triptab].font-weight-bold').removeClass('font-weight-bold');
1883	$('#selected-seat-footer').addClass('d-none');
1884	$('#trip-' + trip.tripCode).find('#minibusmap').removeClass('minibusfilter');
1885	if (previousTrip) {
1886		$('#trip-' + previousTrip.tripCode).find('.tripinfo-container').find('.trip-viewbusmap').html(getTripAvailableSeatCount(previousTrip) + ' Seats');
1887		previousTrip = null;
1888	}
1889}
1890
1891function renderBusMap(busmap) {
1892	var template = $('#template-busmap-cont').html();
1893	var $tpl = $(template);
1894
1895	// lower
1896	var lower = renderBusSeats({
1897		layer: 1,
1898		matrix: busmap.lmatrix,
1899		seatStatus: busmap.seatStatus
1900	});
1901
1902	$tpl.find('.lower-layer-seats').html(lower);
1903
1904	// upper
1905	if (busmap.umatrix) {
1906		var upper = renderBusSeats({
1907			layer: 2,
1908			matrix: busmap.umatrix,
1909			seatStatus: busmap.seatStatus
1910		});
1911
1912		$tpl.find('.upper-layer-seats').html(upper);
1913		$tpl.find('.upper-layer, .layer-name').removeClass('d-none');
1914	}
1915
1916
1917	var uniqueFares = {};
1918	$.each(busmap.seatStatus, function (i, seat) {
1919		if ($.inArray(seat.status.code, ['BO', 'BL', 'AO', 'BL', 'TBL', 'QS', 'PBL']) == -1) {
1920			uniqueFares[seat.fare] = (uniqueFares[seat.fare] || 0) + 1;
1921		}
1922	});
1923
1924	if (Object.keys(uniqueFares).length > 1) {
1925		$tpl.find('#seat-layout-fare-filter').removeClass('d-none');
1926		$.each(uniqueFares, function (fare, count) {
1927			$tpl.find('#seat-layout-fare-filter').append('<label class="btn btn-outline-secondary button-all btn-sm fare-labels">' +
1928				'<input type="radio" name="fare-filter" value="' + fare + '" autocomplete="off"><span class="fare-tabs">'+ currencySymbol + '<b>' + fare + '</b> <small>(' + count + ')</small> </span>' +
1929				'</label>');
1930		});
1931	}
1932
1933	// append
1934	$('#trip-' + busmap.busmap.tripCode).find('.trip-tabs-content').html($tpl);
1935
1936	var $busmap = $('#trip-' + busmap.busmap.tripCode).find('.busmap-layers');
1937
1938	// select event
1939	$busmap.on('click', '.seat-select-visibility', function () {
1940		if ($(this).hasClass('seat-disabled')) {
1941			return;
1942		}
1943
1944		const searchInfo = getSearchInfo();
1945		var $selected = $busmap.find('.seat-selected');
1946
1947		if (searchInfo.reschedule > 0 && $selected.length >= searchInfo.reschedule) {
1948			$(this).removeClass('seat-selected');
1949			$(this).removeClass('seater-selected');
1950			$(this).removeClass('sleeper-selected');
1951			return;
1952		}
1953
1954		if ($(this).hasClass('SLEEPER')) {
1955			$(this).toggleClass('seat-selected');
1956			$(this).toggleClass('sleeper-selected');
1957		}
1958
1959		if ($(this).hasClass('SEATER')) {
1960			$(this).toggleClass('seat-selected');
1961			$(this).toggleClass('seater-selected');
1962		}
1963
1964		$selected = $busmap.find('.seat-selected');
1965
1966		if ($selected.length == 0) {
1967			zeroSeat();
1968		} else if ($selected.length < 6) {
1969			// $('#selected-seat-panel').removeClass('d-none');
1970			// $('#schedule-travel-terms').addClass('d-none');
1971		}
1972		// $('#selected-seat-panel, #schedule-travel-terms').toggleClass('d-none', $selected.length == 0);
1973
1974		if ($selected.length > 0) {
1975			$("#booking-card").removeClass("d-none");
1976			$(".select-info-card").addClass("d-none");
1977		}
1978
1979		// validation
1980		if ($selected.length > 6) {
1981			$(this).removeClass('seat-selected');
1982			$(this).removeClass('seater-selected');
1983			$(this).removeClass('sleeper-selected');
1984			alert('Maximum no.of seats allowed is 6');
1985			return false;
1986		}
1987
1988		calculateSeatFare(busmap);
1989	});
1990
1991	$('#seat-layout-fare-filter input[name="fare-filter"]').on('change', function () {
1992		$busmap.find('.seat-disabled').removeClass('seat-disabled');
1993		$busmap.find('.seat-selected').removeClass('seat-selected');
1994		$busmap.find('.seater-selected').removeClass('seater-selected');
1995		$busmap.find('.sleeper-selected').removeClass('sleeper-selected');
1996
1997		var fareFilter = this.value;
1998		if (fareFilter == 'ALL') {
1999			return;
2000		}
2001		$busmap.find('.seat-select-visibility:not([data-fare="' + fareFilter + '"])').toggleClass('seat-disabled', this.checked)
2002	});
2003
2004	var spTemplate = $('#template-stationpoint-list').html();
2005
2006	var spItems = function (item, escape) {
2007		var $tpl = $('<b/>');
2008		$('<span/>').html(moment(escape(item.dateTime)).format('hh:mm A')).appendTo($tpl);
2009		$('<span class="ml-4"/>').html(escape(item.name)).appendTo($tpl);
2010
2011		return $tpl;
2012	}
2013
2014	var spOptions = function (item, escape) {
2015		var $tpl = $(spTemplate);
2016		$tpl.find('.sp-name').html(escape(item.name));
2017		$tpl.find('.sp-date').html(moment(escape(item.dateTime)).format('ddd DD MMM'));
2018		$tpl.find('.sp-time').html(moment(escape(item.dateTime)).format('hh:mm A'));
2019		$tpl.find('.sp-landmark').html(escape(item.landmark));
2020		$.each(item.amenities || [], function (i, amenity) {
2021			$tpl.find('.sp-amenities').append('<span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span>');
2022		});
2023
2024		return $tpl;
2025	}
2026
2027	$('#boarding-point-list').selectize({
2028		placeholder: 'Select Boarding Point',
2029		valueField: 'code',
2030		labelField: 'name',
2031		searchField: ['name', 'landmark'],
2032		options: busmap.busmap.fromStation.stationPoint || [],
2033		render: {
2034			item: spItems,
2035			option: spOptions,
2036		},
2037		onChange: function (value) {
2038			let station = this.options[value];
2039			if (!station) return;
2040			let address = Array.from(new Set([station.name, station.address, station.landmark].filter(
2040Boolean))).join(', ');
2041			$('#boarding-point-address').html('<div class="bg-light p-2">' + address + '</div>');
2042
2043			calculateSeatFare(busmap);
2044
2045			var droppingSelectize = $('#dropping-point-list').data('selectize');
2046			droppingSelectize.focus();
2047		}
2048	});
2049
2050	$('#dropping-point-list').selectize({
2051		placeholder: 'Select Dropping Point',
2052		valueField: 'code',
2053		labelField: 'name',
2054		searchField: ['name', 'landmark'],
2055		options: busmap.busmap.toStation.stationPoint || [],
2056		render: {
2057			item: spItems,
2058			option: spOptions,
2059		},
2060		onChange: function (value) {
2061			let station = this.options[value];
2062			if (!station) return;
2063			let address = Array.from(new Set([station.name, station.address, station.landmark].filter(Boolean))).join(', ');
2064			$('#dropping-point-address').html('<div class="bg-light p-2">' + address + '</div>');
2065
2066			calculateSeatFare(busmap);
2067		}
2068	});
2069
2070	$('.boarding-point-title').on('click', function () {
2071		boardingTab();
2072	});
2073
2074	$('.dropping-point-title').on('click', function () {
2075		droppingTab();
2076	});
2077
2078	$.each(busmap.busmap.fromStation.stationPoint, function (i, seat) {
2079		const radioButton = $("<input>", {
2080			type: "radio",
2081			id: `boarding-point-${i}`,
2082			name: "boarding-point",
2083			value: seat.code,
2084		});
2085
2086		// name
2087		const boardingName = $("<div class='boarding-name'>");
2088		boardingName.text(seat.name);
2089
2090		const dateTime = new Date(seat.dateTime.replace(' ', 'T'));
2091		const formattedBpTime = dateTime.toLocaleString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
2092
2093		// time
2094		const boardingTime = $("<div class='boarding-time'>");
2095		boardingTime.text(formattedBpTime);
2096
2097		// address
2098		const addressDiv = $("<div class='row m-0'>");
2099		const address = $("<div class='bpaddress'>");
2100		const addresscontent = Array.from(new Set([seat.name, seat.address, seat.landmark].filter(Boolean))).join(', ');
2101		address.text(addresscontent);
2102		addressDiv.append(address);
2103
2104		const boardingSelDiv = $("<div class='boarding-card'>");
2105		boardingSelDiv.append(radioButton, boardingName, boardingTime, addressDiv);
2106
2107		const boardingAddressCard = $("<div class='boarding-address-card'>");
2108		boardingAddressCard.append(addressDiv);
2109
2110		const amenityDiv = $("<div class='row m-0 bpamenity'>");
2111		const amneity_card = $("<div class='boarding-amenity'>");
2112
2113		const boardingAmenityCard = $("<div class='boarding-amenity-card'>");
2114		$.each(seat.amenities || [], function (i, amenity) {
2115			amneity_card.append('<div class="boarding-amenity-inner"><span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span> <span class="amenity-name">' + amenity.name + '</span></div>');
2116		});
2117		amenityDiv.append(amneity_card);
2118
2119		if (seat.amenities.length > 0)
2120			boardingAmenityCard.append(amenityDiv);
2121
2122		const boardingInner = $("<div class='boarding-inner'>");
2123		boardingInner.append(boardingSelDiv, boardingAddressCard, boardingAmenityCard);
2124		$('.boarding-point-list-inner').append(boardingInner);
2125	});
2126
2127	$(".boarding-inner").on("click", function () {
2128		const radioButton = $(this).find("input[type='radio'][name='boarding-point']");
2129		radioButton.prop("checked", true).addClass('checked');
2130
2131		calculateSeatFare(busmap);
2132
2133		selectedBP = $(this).find("input[type='radio'][name='boarding-point']").val();
2134
2135		$.each(busmap.busmap.fromStation.stationPoint, function (i, val) {
2136			if (val.code == selectedBP) {
2137
2138				const dateTime = new Date(val.dateTime.replace(' ', 'T'));
2139				const formattedBpTime = dateTime.toLocaleString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
2140
2141				$('.boarding-point-name').html(val.name);
2142				$('.boarding-point-time').html(formattedBpTime);
2143				$('.boarding-address-details').html(Array.from(new Set([val.name, val.address, val.landmark].filter(Boolean))).join(', '));
2144			}
2145		});
2146
2147		droppingChange();
2148	});
2149
2150	$.each(busmap.busmap.toStation.stationPoint, function (i, seat) {
2151		const radioButton = $("<input>", {
2152			type: "radio",
2153			id: `dropping-point-${i}`,
2154			name: "dropping-point",
2155			value: seat.code,
2156		});
2157
2158		// name
2159		const droppingName = $("<div class='dropping-name'>");
2160		droppingName.text(seat.name);
2161
2162		const dateTime = new Date(seat.dateTime.replace(' ', 'T'));
2163		const formattedDpTime = dateTime.toLocaleString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
2164
2165		// time
2166		const droppingTime = $("<div class='dropping-time'>");
2167		droppingTime.text(formattedDpTime);
2168
2169		// address
2170		const dpaddressDiv = $("<div class='row m-0'>");
2171		const dpaddress = $("<div class='bpaddress'>");
2172		const dpaddresscontent = Array.from(new Set([seat.name, seat.address, seat.landmark].filter(Boolean))).join(', ');
2173		dpaddress.text(dpaddresscontent);
2174		dpaddressDiv.append(dpaddress);
2175
2176		const droppingSelDiv = $("<div class='dropping-card'>");
2177		droppingSelDiv.append(radioButton, droppingName, droppingTime, dpaddressDiv);
2178
2179		const droppingAddressCard = $("<div class='dropping-address-card'>");
2180		droppingAddressCard.append(dpaddressDiv);
2181
2182
2183		const dpamenityDiv = $("<div class='row m-0 dpamenity'>");
2184		const dpamneity_card = $("<div class='dropping-amenity'>");
2185
2186		const droppingAmenityCard = $("<div class='dropping-amenity-card'>");
2187		$.each(seat.amenities || [], function (i, amenity) {
2188			dpamneity_card.append('<div class="dropping-amenity-inner"><span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span> <span class="amenity-name">' + amenity.name + '</span></div>');
2189		});
2190		dpamenityDiv.append(dpamneity_card);
2191
2192		if (seat.amenities.length > 0)
2193			droppingAmenityCard.append(dpamenityDiv);
2194
2195		// $(".dropping-inner").append(droppingSelDiv, droppingAddressCard, droppingAmenityCard);
2196
2197		const droppingInner = $("<div class='dropping-inner'>");
2198		droppingInner.append(droppingSelDiv, droppingAddressCard, droppingAmenityCard);
2199		$('.dropping-point-list-inner').append(droppingInner);
2200	});
2201
2202	$(".dropping-inner").on("click", function () {
2203		const radioButton = $(this).find("input[type='radio'][name='dropping-point']");
2204		radioButton.prop("checked", true).addClass('checked');
2205		calculateSeatFare(busmap);
2206
2207		selectedDP = $(this).find("input[type='radio'][name='dropping-point']").val();
2208
2209		$.each(busmap.busmap.toStation.stationPoint, function (i, val) {
2210			if (val.code == selectedDP) {
2211
2212				const dateTime = new Date(val.dateTime.replace(' ', 'T'));
2213				const formattedDpTime = dateTime.toLocaleString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
2214
2215				$('.dropping-point-name').html(val.name);
2216				$('.dropping-point-time').html(formattedDpTime);
2217				$('.dropping-address-details').html(Array.from(new Set([val.name, val.address, val.landmark].filter(Boolean))).join(', '));
2218			}
2219		});
2220
2221		boardingDroppingSelected();
2222
2223	});
2224
2225	var onclickNext = function () {
2226		const SEARCHINFO = getSearchInfo();
2227		const BOOKINGDATA = getBookingData(busmap);
2228
2229		if (!$('input[name="boarding-point"]:checked').val() || !$('input[name="dropping-point"]:checked').val()) {
2230			// alert('Please select Boarding and Dropping points');
2231
2232			$('.bpdpSelecting').addClass('inValid-shadow');
2233
2234			setTimeout(function () {
2235				$('.bpdpSelecting').removeClass('inValid-shadow');
2236			}, 2000);
2237
2238			return;
2239		}
2240
2241		if (SEARCHINFO.reschedule > 0 && BOOKINGDATA.seatDetails.length != SEARCHINFO.reschedule) {
2242			alert(SEARCHINFO.reschedule + ' seats need to be selected');
2243			return;
2244		}
2245
2246		$('#selected-seat-next')
2247			.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Please Wait...')
2248			.attr('disabled', true);
2249
2250
2251		if (SEARCHINFO.returnDate != '' && SEARCHINFO.searchType != 2) { // return trip
2252			var onwardData = BOOKINGDATA;
2253
2254			sessionStorage.setItem('BOOKINGDATA', JSON.stringify({ onwardData }));
2255
2256			var query = {};
2257			query.fromStationCode = onwardData.toStation.code;
2258			query.fromStationName = encodeURIComponent(cleanString(onwardData.toStation.name));
2259			query.toStationCode = onwardData.fromStation.code;
2260			query.toStationName = encodeURIComponent(cleanString(onwardData.fromStation.name));
2261			query.onwardDate = SEARCHINFO.onwardDate;
2262			query.returnDate = SEARCHINFO.returnDate;
2263			query.searchType = 2;
2264
2265			location.href = buildSearchUrl(query);
2266		} else { // onward trip
2267			var bookingData = sessionStorage.getItem('BOOKINGDATA');
2268			bookingData = JSON.parse(bookingData) || {};
2269			if (SEARCHINFO.searchType == 2) {
2270				bookingData.returnData = BOOKINGDATA;
2271			} else {
2272				bookingData.onwardData = BOOKINGDATA;
2273			}
2274			sessionStorage.setItem('BOOKINGDATA', JSON.stringify(bookingData));
2275			let reschedule = SEARCHINFO.reschedule > 0;
2276			gotoPassengerDetails(reschedule);
2277		}
2278	};
2279
2280
2281	$('.boarding-point-change').on('click', function () {
2282		showBoardingDropping('board');
2283	});
2284	$('.dropping-point-change').on('click', function () {
2285		showBoardingDropping('drop');
2286	});
2287
2288	$('#selected-seat-next').off('click').on('click', onclickNext);
2289}
2290
2291function renderBusMapConn(busmap, isConnecting) {
2292	var template = $('#template-busmap-cont').html();
2293	var $tpl = $(template);
2294
2295	tripStageCode = busmap.busmap.tripCode;
2296	tripDate = busmap.busmap.fromStation.dateTime;
2297	fromStation = busmap.busmap.fromStation.code;
2298	toStation = busmap.busmap.toStation.code;
2299	fromStationName = busmap.busmap.fromStation.name;
2300	toStationName = busmap.busmap.toStation.name;
2301	// lower
2302	var lower = renderBusSeats({
2303		layer: 1,
2304		matrix: busmap.lmatrix,
2305		seatStatus: busmap.seatStatus
2306	});
2307
2308	$tpl.find('.lower-layer-seats').html(lower);
2309
2310	// upper
2311	if (busmap.umatrix) {
2312		var upper = renderBusSeats({
2313			layer: 2,
2314			matrix: busmap.umatrix,
2315			seatStatus: busmap.seatStatus
2316		});
2317
2318		$tpl.find('.upper-layer-seats').html(upper);
2319		$tpl.find('.upper-layer, .layer-name').removeClass('d-none');
2320	}
2321
2322
2323	var uniqueFares = {};
2324	$.each(busmap.seatStatus, function (i, seat) {
2325		if ($.inArray(seat.status.code, ['BO', 'BL', 'AO', 'BL', 'TBL', 'QS', 'PBL']) == -1) {
2326			uniqueFares[seat.fare] = (uniqueFares[seat.fare] || 0) + 1;
2327		}
2328	});
2329
2330	if (Object.keys(uniqueFares).length > 1) {
2331		$tpl.find('#seat-layout-fare-filter').removeClass('d-none');
2332		$.each(uniqueFares, function (fare, count) {
2333			$tpl.find('#seat-layout-fare-filter').append('<label class="btn btn-outline-secondary button-all btn-sm fare-labels">' +
2334				'<input type="radio" name="fare-filter" value="' + fare + '" autocomplete="off"><span class="fare-tabs">'+ currencySymbol + '<b>' + fare + '</b> <small>(' + count + ')</small> </span>' +
2335				'</label>');
2336		});
2337	}
2338
2339	// append
2340	$('#trip-' + busmap.busmap.tripCode).find('.trip-tabs-content').html($tpl);
2341
2342	var $busmap = $('#trip-' + busmap.busmap.tripCode).find('.busmap-layers');
2343
2344	$('.bpdpHeight').addClass('d-none');
2345	$(".connecting-content").removeClass("d-none");
2346	$('#selected-seat-next').html('next');
2347
2348	// select event
2349	$busmap.on('click', '.seat-select-visibility', function () {
2350
2351		if ($(this).hasClass('seat-disabled')) {
2352			return;
2353		}
2354
2355		if (connectingSelected) {
2356			return;
2357		}
2358
2359		const searchInfo = getSearchInfo();
2360		var $selected = $busmap.find('.seat-selected');
2361
2362		if (regConnTrip.SEQ_STATUS !== 'BOARDING' && regConnTrip.CURRENT_SEQ !== 0 && regConnTrip.CURRENT_M_TRIP == null) {
2363			if (regConnTrip.SEAT_COUNT >= $selected.length) {
2364				alert("You cannot select more than " + regConnTrip.PASSENGER_COUNT + " seats.");
2365				$(this).removeClass('seat-selected');
2366				$(this).removeClass('seater-selected');
2367				$(this).removeClass('sleeper-selected');
2368				return;
2369			}
2370		}
2371
2372		if (searchInfo.reschedule > 0 && $selected.length >= searchInfo.reschedule) {
2373			$(this).removeClass('seat-selected');
2374			$(this).removeClass('seater-selected');
2375			$(this).removeClass('sleeper-selected');
2376			return;
2377		}
2378
2379
2380		if (regConnTrip.SEAT_COUNT > 0 && $selected.length >= regConnTrip.SEAT_COUNT) {
2381			// forseatSelectZero();
2382			$(this).removeClass('seat-selected');
2383			$(this).removeClass('seater-selected');
2384			$(this).removeClass('sleeper-selected');
2385			return;
2386		}
2387
2388
2389		if ($(this).hasClass('SLEEPER')) {
2390			$(this).toggleClass('seat-selected');
2391			$(this).toggleClass('sleeper-selected');
2392		}
2393
2394		if ($(this).hasClass('SEATER')) {
2395			$(this).toggleClass('seat-selected');
2396			$(this).toggleClass('seater-selected');
2397		}
2398
2399		if (isConnecting) {
2400			const $busMapCnt = $('#trip-' + busmap.busmap.tripCode).find('.trip-conn-tabs-content');
2401
2402			//based on the sequence of connecting trip  flow  work
2403			// info-cont
2404			const $seqLi = $('#trip-' + busmap.busmap.tripCode).closest('.info-cont').find('.conn-stations').find(`input[name^="station_"][data-tripSequence="${regConnTrip.CURRENT_SEQ}"]`).closest('.closestdiv')
2405			$busMapCnt.find('.boarding-point-divider').addClass('d-none'); // for befor click the seat
2406			$busMapCnt.find('.dropping-point-list-card').addClass('d-none');
2407			$busMapCnt.find('.dropping-point-title').addClass('d-none');
2408			$busMapCnt.find(".connecting-content").removeClass("d-none");
2409			$busMapCnt.find('#conn-from-station-name').val($seqLi.attr('data-from-station-name'));
2410			$busMapCnt.find('#conn-to-station-name').val($seqLi.attr('data-to-station-name'));
2411
2412
2413			// hided uncomanit
2414			// $busMapCnt.find('#remarks').closest('.clear_fix_both').addClass('d-none');
2415			// $busMapCnt.find('table.table').addClass('d-none');
2416
2417			switch (regConnTrip.SEQ_STATUS) {
2418				case 'BOARDING':
2419					// $busMapCnt.find('.pno-seg').removeClass('col-sm-4').addClass('col-sm-6');
2420					// $busMapCnt.find('.bp-seg').removeClass('col-sm-4').addClass('col-sm-6');
2421					// $busMapCnt.find('.station-area-filter').removeClass('hide');                      
2422					// $busMapCnt.find('.alt-mobileno-lbl').removeClass('hide');
2423					// $busMapCnt.find('#alt-mobileno').removeClass('hide');
2424					$busMapCnt.find('#conn-dropping-point').val($seqLi.attr('data-dp-point'));
2425					$busMapCnt.find('#conn-dropping-point-name').val($seqLi.attr('data-dp-point-name'));
2426					// $busMapCnt.find('.connecting-content').addClass('d-none');
2427					$busMapCnt.find('.bpdpHeight').removeClass('d-none');
2428					$busMapCnt.find('.bpdpHeight').css('height', ' 450px');
2429
2430					$busMapCnt.find('#from-state-name').val(busmap.busmap.fromStation.state.name);
2431					$busMapCnt.find('#from-state').val(busmap.busmap.fromStation.state.code);
2432					$busMapCnt.find('#from-city-name').val(busmap.busmap.fromStation.name);
2433					$busMapCnt.find('#from-city').val(busmap.busmap.fromStation.code);
2434
2435
2436					$("#booking-card").removeClass("d-none");
2437					$(".select-info-card").addClass("d-none");
2438					$(".bpdpHeight").removeClass("d-none");
2439					$(".connecting-content").addClass("d-none");
2440
2441					break;
2442				case 'CONNECTING':
2443					$busMapCnt.find('#conn-bording-point').val($seqLi.attr('data-bp-point'));
2444					$busMapCnt.find('#conn-bording-point-name').val($seqLi.attr('data-bp-point-name'));
2445					$busMapCnt.find('#conn-dropping-point').val($seqLi.attr('data-dp-point'));
2446					$busMapCnt.find('#conn-dropping-point-name').val($seqLi.attr('data-dp-point-name'));
2447					// $busMapCnt.find('.bpdpHeight').css('height', ' 350px');
2448					$busMapCnt.find('.connecting-content').removeClass('d-none');
2449					$busMapCnt.find('.bpdpHeight').addClass('d-none');
2450					$(".select-info-card").addClass("d-none");
2451					$("#booking-card").removeClass("d-none");
2452					// $busMapCnt.find('.num-bp-dp-cnt').addClass('hide');
2453
2454					break;
2455				case 'DROPPING':
2456					$busMapCnt.find('#conn-bording-point').val($seqLi.attr('data-bp-point'));
2457					$busMapCnt.find('#conn-bording-point-name').val($seqLi.attr('data-bp-point-name'));
2458					// $busMapCnt.find('.pno-seg').addClass('hide');
2459					$busMapCnt.find('.boarding-point-list-card, .boarding-point-title').addClass('d-none');
2460					$busMapCnt.find('.dropping-point-list-card').removeClass('d-none');// hide for except last sequence
2461					$busMapCnt.find('.dropping-point-title').removeClass('d-none');// hide for except last sequence
2462					$busMapCnt.find('.dropping-point-title').addClass('boardingdroppingbold');
2463					$busMapCnt.find('.dropping-design').removeClass('d-none');
2464					$busMapCnt.find('.bpdpHeight').removeClass('d-none');
2465					$busMapCnt.find('.bpdpHeight').css('height', ' 450px');
2466					$("#booking-card").removeClass("d-none");
2467					$(".select-info-card").addClass("d-none");
2468					$(".bpdpHeight").removeClass("d-none");
2469					$(".connecting-content").addClass("d-none");
2470					break;
2471			}
2472
2473		}
2474		$selected = $busmap.find('.seat-selected');
2475
2476		if ($selected.length == 0) {
2477			zeroSeat();
2478		} else if ($selected.length < 6) {
2479			// $('#selected-seat-panel').removeClass('d-none');
2480			// $('#schedule-travel-terms').addClass('d-none');
2481		}
2482		// $('#selected-seat-panel, #schedule-travel-terms').toggleClass('d-none', $selected.length == 0);
2483
2484		// 	if ($selected.length > 0) {
2485		// 	$("#booking-card").removeClass("d-none");
2486		//	$(".select-info-card").addClass("d-none");
2487		// 	$(".bpdpHeight").removeClass("d-none");
2488		// 	$(".connecting-content").addClass("d-none");
2489		// 	}
2490
2491
2492		// validation
2493		if ($selected.length > 6) {
2494			$(this).removeClass('seat-selected');
2495			$(this).removeClass('seater-selected');
2496			$(this).removeClass('sleeper-selected');
2497			alert('Maximum no.of seats allowed is 6');
2498			return false;
2499		}
2500
2501		calculateSeatFare(busmap);
2502
2503	});
2504
2505	$('#seat-layout-fare-filter input[name="fare-filter"]').on('change', function () {
2506		$busmap.find('.seat-disabled').removeClass('seat-disabled');
2507		$busmap.find('.seat-selected').removeClass('seat-selected');
2508		$busmap.find('.seater-selected').removeClass('seater-selected');
2509		$busmap.find('.sleeper-selected').removeClass('sleeper-selected');
2510
2511		var fareFilter = this.value;
2512		if (fareFilter == 'ALL') {
2513			return;
2514		}
2515		$busmap.find('.seat-select-visibility:not([data-fare="' + fareFilter + '"])').toggleClass('seat-disabled', this.checked)
2516	});
2517
2518	var spTemplate = $('#template-stationpoint-list').html();
2519
2520	var spItems = function (item, escape) {
2521		var $tpl = $('<b/>');
2522		$('<span/>').html(moment(escape(item.dateTime)).format('hh:mm A')).appendTo($tpl);
2523		$('<span class="ml-4"/>').html(escape(item.name)).appendTo($tpl);
2524
2525		return $tpl;
2526	}
2527
2528	var spOptions = function (item, escape) {
2529		var $tpl = $(spTemplate);
2530		$tpl.find('.sp-name').html(escape(item.name));
2531		$tpl.find('.sp-date').html(moment(escape(item.dateTime)).format('ddd DD MMM'));
2532		$tpl.find('.sp-time').html(moment(escape(item.dateTime)).format('hh:mm A'));
2533		$tpl.find('.sp-landmark').html(escape(item.landmark));
2534		$.each(item.amenities || [], function (i, amenity) {
2535			$tpl.find('.sp-amenities').append('<span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span>');
2536		});
2537
2538		return $tpl;
2539	}
2540
2541	$('#boarding-point-list').selectize({
2542		placeholder: 'Select Boarding Point',
2543		valueField: 'code',
2544		labelField: 'name',
2545		searchField: ['name', 'landmark'],
2546		options: busmap.busmap.fromStation.stationPoint || [],
2547		render: {
2548			item: spItems,
2549			option: spOptions,
2550		},
2551		onChange: function (value) {
2552			let station = this.options[value];
2553			if (!station) return;
2554			let address = Array.from(new Set([station.name, station.address, station.landmark].filter(Boolean))).join(', ');
2555			$('#boarding-point-address').html('<div class="bg-light p-2">' + address + '</div>');
2556
2557			calculateSeatFare(busmap);
2558
2559			var droppingSelectize = $('#dropping-point-list').data('selectize');
2560			droppingSelectize.focus();
2561		}
2562	});
2563
2564	$('#dropping-point-list').selectize({
2565		placeholder: 'Select Dropping Point',
2566		valueField: 'code',
2567		labelField: 'name',
2568		searchField: ['name', 'landmark'],
2569		options: busmap.busmap.toStation.stationPoint || [],
2570		render: {
2571			item: spItems,
2572			option: spOptions,
2573		},
2574		onChange: function (value) {
2575			let station = this.options[value];
2576			if (!station) return;
2577			let address = Array.from(new Set([station.name, station.address, station.landmark].filter(Boolean))).join(', ');
2578			$('#dropping-point-address').html('<div class="bg-light p-2">' + address + '</div>');
2579
2580			calculateSeatFare(busmap);
2581		}
2582	});
2583
2584	$('.boarding-point-title').on('click', function () {
2585		boardingTab();
2586	});
2587
2588	$('.dropping-point-title').on('click', function () {
2589		droppingTab();
2590	});
2591
2592	$.each(busmap.busmap.fromStation.stationPoint, function (i, seat) {
2593		const radioButton = $("<input>", {
2594			type: "radio",
2595			id: `boarding-point-${i}`,
2596			name: "boarding-point",
2597			value: seat.code,
2598		});
2599
2600		// name
2601		const boardingName = $("<div class='boarding-name'>");
2602		boardingName.text(seat.name);
2603
2604		const dateTime = new Date(seat.dateTime.replace(' ', 'T'));
2605		const formattedBpTime = dateTime.toLocaleString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
2606
2607		// time
2608		const boardingTime = $("<div class='boarding-time'>");
2609		boardingTime.text(formattedBpTime);
2610
2611		// address
2612		const addressDiv = $("<div class='row m-0'>");
2613		const address = $("<div class='bpaddress'>");
2614		const addresscontent = Array.from(new Set([seat.name, seat.address, seat.landmark].filter(Boolean))).join(', ');
2615		address.text(addresscontent);
2616		addressDiv.append(address);
2617
2618		const boardingSelDiv = $("<div class='boarding-card'>");
2619		boardingSelDiv.append(radioButton, boardingName, boardingTime, addressDiv);
2620
2621		const boardingAddressCard = $("<div class='boarding-address-card'>");
2622		boardingAddressCard.append(addressDiv);
2623
2624		const amenityDiv = $("<div class='row m-0 bpamenity'>");
2625		const amneity_card = $("<div class='boarding-amenity'>");
2626
2627		const boardingAmenityCard = $("<div class='boarding-amenity-card'>");
2628		$.each(seat.amenities || [], function (i, amenity) {
2629			amneity_card.append('<div class="boarding-amenity-inner"><span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span> <span class="amenity-name">' + amenity.name + '</span></div>');
2630		});
2631		amenityDiv.append(amneity_card);
2632
2633		if (seat.amenities.length > 0)
2634			boardingAmenityCard.append(amenityDiv);
2635
2636		const boardingInner = $("<div class='boarding-inner'>");
2637		boardingInner.append(boardingSelDiv, boardingAddressCard, boardingAmenityCard);
2638		$('.boarding-point-list-inner').append(boardingInner);
2639	});
2640
2641	$(".boarding-inner").on("click", function () {
2642		const radioButton = $(this).find("input[type='radio'][name='boarding-point']");
2643		radioButton.prop("checked", true).addClass('checked');
2644
2645		calculateSeatFare(busmap);
2646
2647		selectedBP = $(this).find("input[type='radio'][name='boarding-point']").val();
2648
2649		$.each(busmap.busmap.fromStation.stationPoint, function (i, val) {
2650			if (val.code == selectedBP) {
2651
2652				const dateTime = new Date(val.dateTime.replace(' ', 'T'));
2653				const formattedBpTime = dateTime.toLocaleString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
2654
2655				$('.boarding-point-name').html(val.name);
2656				$('.boarding-point-time').html(formattedBpTime);
2657				$('.boarding-address-details').html(Array.from(new Set([val.name, val.address, val.landmark].filter(Boolean))).join(', '));
2658			}
2659		});
2660
2661		// droppingChange();
2662	});
2663
2664	$.each(busmap.busmap.toStation.stationPoint, function (i, seat) {
2665		const radioButton = $("<input>", {
2666			type: "radio",
2667			id: `dropping-point-${i}`,
2668			name: "dropping-point",
2669			value: seat.code,
2670		});
2671
2672		// name
2673		const droppingName = $("<div class='dropping-name'>");
2674		droppingName.text(seat.name);
2675
2676		const dateTime = new Date(seat.dateTime.replace(' ', 'T'));
2677		const formattedDpTime = dateTime.toLocaleString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
2678
2679		// time
2680		const droppingTime = $("<div class='dropping-time'>");
2681		droppingTime.text(formattedDpTime);
2682
2683		// address
2684		const dpaddressDiv = $("<div class='row m-0'>");
2685		const dpaddress = $("<div class='bpaddress'>");
2686		const dpaddresscontent = Array.from(new Set([seat.name, seat.address, seat.landmark].filter(Boolean))).join(', ');
2687		dpaddress.text(dpaddresscontent);
2688		dpaddressDiv.append(dpaddress);
2689
2690		const droppingSelDiv = $("<div class='dropping-card'>");
2691		droppingSelDiv.append(radioButton, droppingName, droppingTime, dpaddressDiv);
2692
2693		const droppingAddressCard = $("<div class='dropping-address-card'>");
2694		droppingAddressCard.append(dpaddressDiv);
2695
2696
2697		const dpamenityDiv = $("<div class='row m-0 dpamenity'>");
2698		const dpamneity_card = $("<div class='dropping-amenity'>");
2699
2700		const droppingAmenityCard = $("<div class='dropping-amenity-card'>");
2701		$.each(seat.amenities || [], function (i, amenity) {
2702			dpamneity_card.append('<div class="dropping-amenity-inner"><span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span> <span class="amenity-name">' + amenity.name + '</span></div>');
2703		});
2704		dpamenityDiv.append(dpamneity_card);
2705
2706		if (seat.amenities.length > 0)
2707			droppingAmenityCard.append(dpamenityDiv);
2708
2709		// $(".dropping-inner").append(droppingSelDiv, droppingAddressCard, droppingAmenityCard);
2710
2711		const droppingInner = $("<div class='dropping-inner'>");
2712		droppingInner.append(droppingSelDiv, droppingAddressCard, droppingAmenityCard);
2713		$('.dropping-point-list-inner').append(droppingInner);
2714	});
2715
2716	$(".dropping-inner").on("click", function () {
2717		const radioButton = $(this).find("input[type='radio'][name='dropping-point']");
2718		radioButton.prop("checked", true).addClass('checked');
2719		calculateSeatFare(busmap);
2720
2721		selectedDP = $(this).find("input[type='radio'][name='dropping-point']").val();
2722
2723		$.each(busmap.busmap.toStation.stationPoint, function (i, val) {
2724			if (val.code == selectedDP) {
2725
2726				const dateTime = new Date(val.dateTime.replace(' ', 'T'));
2727				const formattedDpTime = dateTime.toLocaleString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
2728
2729				$('.dropping-point-name').html(val.name);
2730				$('.dropping-point-time').html(formattedDpTime);
2731				$('.dropping-address-details').html(Array.from(new Set([val.name, val.address, val.landmark].filter(Boolean))).join(', '));
2732			}
2733		});
2734
2735		boardingDroppingSelected();
2736
2737	});
2738
2739	var onclickNext = function () {
2740		const SEARCHINFO = getSearchInfo();
2741		const BOOKINGDATA = getConnBookingData(busmap);
2742
2743		if (!$('input[name="boarding-point"]:checked').val() || !$('input[name="dropping-point"]:checked').val()) {
2744			// alert('Please select Boarding and Dropping points');
2745
2746			$('.bpdpSelecting').addClass('inValid-shadow');
2747
2748			setTimeout(function () {
2749				$('.bpdpSelecting').removeClass('inValid-shadow');
2750			}, 2000);
2751
2752			return;
2753		}
2754
2755		if (SEARCHINFO.reschedule > 0 && BOOKINGDATA.seatDetails.length != SEARCHINFO.reschedule) {
2756			alert(SEARCHINFO.reschedule + ' seats need to be selected');
2757			return;
2758		}
2759
2760		$('#selected-seat-next')
2761			.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Please Wait...')
2762			.attr('disabled', true);
2763
2764
2765		if (SEARCHINFO.returnDate != '' && SEARCHINFO.searchType != 2) { // return trip
2766			var onwardData = BOOKINGDATA;
2767
2768			sessionStorage.setItem('BOOKINGDATA', JSON.stringify({ onwardData }));
2769
2770			var query = {};
2771			query.fromStationCode = onwardData.toStation.code;
2772			query.fromStationName = encodeURIComponent(cleanString(onwardData.toStation.name));
2773			query.toStationCode = onwardData.fromStation.code;
2774			query.toStationName = encodeURIComponent(cleanString(onwardData.fromStation.name));
2775			query.onwardDate = SEARCHINFO.onwardDate;
2776			query.returnDate = SEARCHINFO.returnDate;
2777			query.searchType = 2;
2778
2779			location.href = buildSearchUrl(query);
2780		} else { // onward trip
2781			var bookingData = sessionStorage.getItem('BOOKINGDATA');
2782			bookingData = JSON.parse(bookingData) || {};
2783			if (SEARCHINFO.searchType == 2) {
2784				bookingData.returnData = BOOKINGDATA;
2785			} else {
2786				bookingData.onwardData = BOOKINGDATA;
2787			}
2788			sessionStorage.setItem('BOOKINGDATA', JSON.stringify(bookingData));
2789			let reschedule = SEARCHINFO.reschedule > 0;
2790			gotoPassengerDetails(reschedule);
2791		}
2792	};
2793
2794	$('.boarding-point-change').on('click', function () {
2795		showBoardingDropping('board');
2796	});
2797	$('.dropping-point-change').on('click', function () {
2798		showBoardingDropping('drop');
2799	});
2800	initConnBook(busmap);
2801	// $('#selected-seat-next').off('click').on('click', initConnBook());
2802}
2803
2804function initConnBook(busmap) {
2805	var $busmap = $('#trip-' + busmap.busmap.tripCode);
2806	$busmap.find('#selected-seat-next').on('click', function () {
2807
2808		let tripDetails = {};
2809		let noErr = true;
2810		var connetSchedule = '';
2811
2812		switch (regConnTrip.SEQ_STATUS) {
2813			case 'BOARDING':
2814				noErr = boardingValidation();
2815				if (!noErr) {
2816					return;
2817				}
2818
2819				connetSchedule = getConnCommonDetails();
2820				getConnCommonDetails();
2821				tripDetails = getTripDetails();
2822				break;
2823			case 'CONNECTING':
2824				noErr = connectingPtErrValidator();
2825				if (!noErr) {
2826					return;
2827				}
2828
2829				tripDetails = getTripDetails();
2830				break;
2831			case 'DROPPING':
2832				noErr = droppingValidation();
2833				if (!noErr) {
2834					return;
2835				}
2836				tripDetails = getTripDetails();
2837				break;
2838		}
2839		connectingContinue(tripDetails, $busmap, connetSchedule);
2840	})
2841
2842	function getConnCommonDetails() {
2843		// regConnTrip.TKT_BLK_BOOK_DETAILS.emailaddress = session_email;
2844		// regConnTrip.TKT_BLK_BOOK_DETAILS.phone = $busmap.find('#mobileno').val();
2845		// regConnTrip.TKT_BLK_BOOK_DETAILS.phonebooking = $busmap.find('input[name="phoneBooking"]').is(":checked") == true ? 1 : 0;
2846		// regConnTrip.TKT_BLK_BOOK_DETAILS.freeservice = $busmap.find('input[name="chkfreeservice"]').is(":checked") == true ? 1 : 0;
2847		regConnTrip.TKT_BLK_BOOK_DETAILS.additionalAttributes.TRIP_CONNECT = $busmap.closest('.c-m-trip-infos').attr('data-schedule-code-master');
2848	}
2849
2850	function getTripDetails() {
2851		let tripDetails = { ...sampleTripDetail };
2852
2853		tripDetails.tripCode = tripStageCode;
2854		tripDetails.travelDate = tripDate;
2855		tripDetails.fromStation = fromStation;
2856		tripDetails.toStation = toStation;
2857		tripDetails.fromStationName = fromStationName;
2858		tripDetails.toStationName = toStationName;
2859		// tripDetails.fromStationName = $busmap.find('#conn-from-station-name').val();
2860		// tripDetails.toStationName = $busmap.find('#conn-to-station-name').val();
2861		var $selected = $busmap.find('.seat-selected'); // seat count
2862
2863
2864		switch (regConnTrip.SEQ_STATUS) {
2865			case 'BOARDING':
2866				tripDetails.boardingPoint = $busmap.find('input[name="boarding-point"]:checked').val();
2867				tripDetails.boardingPointName = $busmap.find('input[name="boarding-point"]:checked').closest('.boarding-card').find('.boarding-name').text();
2868				// tripDetails.boardingPointName = $busmap.find('#conn-bording-point-name').val();
2869				tripDetails.droppingPoint = $busmap.find('#conn-dropping-point').val();
2870				tripDetails.droppingPointName = $busmap.find('#conn-dropping-point-name').val();
2871
2872				tripDetails.city = $busmap.find('#from-city-name').val();
2873				tripDetails.cityCode = $busmap.find('#from-city').val();
2874				tripDetails.state = $busmap.find('#from-state-name').val();
2875				tripDetails.stateCode = $busmap.find('#from-state').val();
2876
2877				// set only once 
2878				// regConnTrip.PASSENGER_DETAILS.NAME = $busmap.find('input[name="name"]').serializeArray();
2879				// regConnTrip.PASSENGER_DETAILS.AGE = $busmap.find('input[name="age"]').serializeArray();
2880				// regConnTrip.PASSENGER_DETAILS.GENDER = $busmap.find('.gen').seri
2880alizeObject();
2881				regConnTrip.PASSENGER_COUNT = $selected.length;
2882				// set only once 
2883				break;
2884			case 'CONNECTING':
2885				// tripDetails.boardingPoint = $busmap.find('#conn-bording-point').val();
2886				tripDetails.boardingPoint = $busmap.find('#conn-bording-point').val();
2887				tripDetails.boardingPointName = $busmap.find('#conn-bording-point-name').val();
2888				// tripDetails.boardingPointName = $busmap.find('#conn-bording-point-name').val();
2889				tripDetails.droppingPoint = $busmap.find('#conn-dropping-point').val();
2890				tripDetails.droppingPointName = $busmap.find('#conn-dropping-point-name').val();
2891				break;
2892			case 'DROPPING':
2893				tripDetails.boardingPoint = $busmap.find('#conn-bording-point').val();
2894				tripDetails.boardingPointName = $busmap.find('#conn-bording-point-name').val();
2895				// tripDetails.droppingPoint = $busmap.find('#dropping-point').val();
2896				// tripDetails.droppingPointName = $busmap.find('#conn-dropping-point-name').val();
2897				tripDetails.droppingPoint = $busmap.find('input[name="dropping-point"]:checked').val();
2898				tripDetails.droppingPointName = $busmap.find('input[name="dropping-point"]:checked').closest('.dropping-card').find('.dropping-name').text();
2899				break;
2900		}
2901
2902		tripDetails.ticketDetails = getTicketDetails();
2903		tripDetails.bus = getBusDetails();
2904
2905		return tripDetails;
2906	}
2907
2908	function getTicketDetails() {
2909		let tripTotFare = 0;
2910		let seats = [];
2911		$('#trip-' + busmap.busmap.tripCode).find('.busmap-layers .seat-selected').each(function (i, seat) {
2912			var $seat = $(seat);
2913
2914			var seatCode = $seat.data('code');
2915			var seatDetail = busmap.seatDetails[seatCode];
2916			seatDetail.seatCode = seatCode;
2917			seats.push(seatDetail);
2918		});
2919
2920		if (regConnTrip.CURRENT_SEQ == 0) {
2921			regConnTrip.SEAT_COUNT = seats.length;
2922		}
2923
2924		// $('.seats-' + id).each(function () {
2925		//     let seat = { ...sampleTicketDetail };
2926		//     const seatElement = $(this);
2927
2928		//     seat.name = $.trim(seatElement.find('input[name="name"]').val());
2929		//     seat.age = $.trim(seatElement.find('input[name="age"]').val());
2930		//     seat.gender = seatElement.find('.gen:checked').val();
2931		//     seat.fare = parseFloat(seatElement.attr('data-fare'));
2932		//     // seat.discount = seatElement.attr('data-discount');//  not added in SAMPLE_TICKET_DETAIL
2933		//     seat.seatname = seatElement.attr('data-name');
2934		//     seat.code = seatElement.attr('data-code');
2935
2936		//     // proof check
2937		//     const prooftype = $.trim(seatElement.find('select[name="proof-type"]').val());
2938		//     const proofcode = $.trim(seatElement.find('input[name="proof-code"]').val());
2939
2940		//     if (prooftype && proofcode) {
2941		//         // seat.idProof = `${prooftype} - ${proofcode}`; //not added in SAMPLE_TICKET_DETAIL
2942		//     }
2943
2944		//     tripTotFare += seat.fare;
2945		//     seats.push(seat);
2946		// });
2947
2948		// regConnTrip.TRIP_FARE.splice(regConnTrip.CURRENT_SEQ, 0, tripTotFare);// set trip total fare with respective sequence
2949		return seats;
2950	}
2951
2952	function getBusDetails() {
2953		const _bus = busmap.busmap;
2954
2955		// let busDetail = { ...sampleBusDetails };
2956		let busDetail = JSON.parse(JSON.stringify(sampleBusDetails));
2957
2958		busDetail.busName = _bus.bus.name;
2959		busDetail.busDisplayName = _bus.bus.displayName;
2960		busDetail.busType = _bus.bus.busType;
2961		busDetail.fromStationTime = _bus.fromStation.dateTime;
2962		busDetail.toStationTime = _bus.toStation.dateTime;
2963		busDetail.schedule.code = _bus.schedule.code;
2964		busDetail.schedule.name = _bus.schedule.name;
2965		busDetail.schedule.serviceNumber = _bus.schedule.serviceNumber;
2966		busDetail.schedule.displayName = _bus.schedule.displayName;
2967
2968		return busDetail;
2969	}
2970
2971	function boardingValidation() {
2972		let boardingVal = $('input[name="boarding-point"]:checked').val();
2973		if (boardingVal == undefined || boardingVal == '') {
2974			$('.bpdpSelecting').addClass('inValid-shadow');
2975
2976			setTimeout(function () {
2977				$('.bpdpSelecting').removeClass('inValid-shadow');
2978			}, 2000);
2979
2980			return false;
2981		} else {
2982			return true;
2983		}
2984	}
2985
2986	function droppingValidation() {
2987		if (!isPassengerCountMatchwithBoardingCount()) return false;
2988
2989		let droppingVal = $('input[name="dropping-point"]:checked').val();
2990		if (droppingVal == undefined || droppingVal == '') {
2991			$('.bpdpSelecting').addClass('inValid-shadow');
2992
2993			setTimeout(function () {
2994				$('.bpdpSelecting').removeClass('inValid-shadow');
2995			}, 2000);
2996
2997			return false;
2998		} else {
2999			return true;
3000		}
3001	}
3002
3003
3004	function isPassengerCountMatchwithBoardingCount() {
3005		let count = $('#trip-' + busmap.busmap.tripCode).find('.seat-selected').length;
3006		if (count < regConnTrip.PASSENGER_COUNT) {
3007			alert("You cannot select less than " + regConnTrip.SEAT_COUNT + " seats.");
3008			return false;
3009		}
3010		return true;
3011	}
3012
3013	function connectingPtErrValidator() {
3014		if (!isPassengerCountMatchwithBoardingCount()) return false;
3015		return true;
3016	}
3017
3018}
3019
3020function connectingContinue(tripDetails, busmap, connetSchedule) {
3021
3022	const $busmap = busmap;
3023	const $masterTrip = $busmap.closest('.c-m-trip-infos');
3024
3025	// Initialize if no current trip is set
3026	if (regConnTrip.CURRENT_M_TRIP === null) {
3027		regConnTrip.CURRENT_M_TRIP = $masterTrip.attr('data-trip-code');
3028		regConnTrip.PREVIOUS_M_TRIP = regConnTrip.CURRENT_M_TRIP;
3029		regConnTrip.SEQUENCE_TRIP_NAME = $masterTrip.attr('data-conn-t-stations').split(',')
3030		regConnTrip.AVAILABLE_SEAT = Number($masterTrip.attr('data-available-seat-count'));// type case to number
3031		regConnTrip.TOTAL_SEQ = ($masterTrip.attr('data-total-sequence') - 1);//to match with index number
3032	} else {
3033		regConnTrip.CURRENT_M_TRIP = $masterTrip.attr('data-trip-code');
3034	}
3035
3036	// If the trip is being changed
3037	if (regConnTrip.CURRENT_M_TRIP !== regConnTrip.PREVIOUS_M_TRIP) {
3038		if (confirm("Are you sure you want to change Trip?")) {
3039			regConnTrip = initOrResetRegConnTrip(); // Reset the trip
3040			return; // Stop execution
3041		}
3042	}
3043
3044	// validate trip is added or not
3045	function isTripRoutDefined(tripDetails) {
3046		let isDefined = false;
3047
3048		const trip = regConnTrip.TKT_BLK_BOOK_DETAILS.orderDetails.filter(o => o.tripCode === tripDetails.tripCode)
3049		if (trip && !isObjectEmpty(trip) &&
3050			tripDetails.fromStation === trip.fromStation &&
3051			tripDetails.boardingPoint === trip.boardingPoint &&
3052			tripDetails.toStation === trip.toStation &&
3053			tripDetails.droppingPoint === trip.droppingPoint) {
3054			isDefined = true;
3055		}
3056
3057		return isDefined;
3058	}
3059
3060	if (isTripRoutDefined(tripDetails)) {
3061		if (confirm("Are you sure you want to change Bus?")) {
3062			// regConnTrip.TRIP_FARE.splice(regConnTrip.CURRENT_SEQ, 0, tripTotFare);// set trip total fare with respective sequence
3063			regConnTrip.TKT_BLK_BOOK_DETAILS.orderDetails.splice(regConnTrip.CURRENT_SEQ, 1, tripDetails);
3064			// regConnTrip.TRIP_MAP.set(tripDetails.tripCode, tripDetails);// update the map with new tripDetails
3065			showBookDetailAgainstTripSequence();
3066
3067			return; // If the user confirms, stop the execution
3068		}
3069	}
3070
3071	// ok
3072	function showBookDetailAgainstTripSequence() {
3073		const $disDom = $masterTrip.find(`input[name^="station_"][data-tripSequence="${regConnTrip.CURRENT_SEQ}"]`).closest('li').find('.stationCollapseCtrlC');
3074		const fetchDataForTripDetais = () => {
3075			return {
3076				"SeatName": $('#seats-container .seat-list').html(),
3077				"SeatFares": $('#seats-fare-container .seat-fare').html(),
3078				"Discount": $('#discount-container .discount').html(),
3079				"Tax": $('#service-container .total-service').html(),
3080				"Payable": $('.payable .fare').html(),
3081			}
3082		}
3083		let details = fetchDataForTripDetais();
3084		regConnTrip.SEQUENCE_TRIP_F_T_D_AMOUNT.set(tripDetails.tripCode, details);
3085
3086		$disDom.find('.seat-name').html(details.SeatName);
3087		$disDom.find('.raw-fare').html(details.SeatFares);
3088		$disDom.find('.discount').html(details.Discount);
3089		$disDom.find('.tax').html(details.Tax);
3090		$disDom.find('.payable-fare').html(details.Payable);
3091
3092	}
3093
3094	// Add the new trip if it's not already added
3095	if (!regConnTrip.TRIP_SET.has(tripDetails.tripCode)) {
3096		regConnTrip.TRIP_SET.add(tripDetails.tripCode); // Add the tripCode to the set
3097		regConnTrip.TKT_BLK_BOOK_DETAILS.orderDetails.splice(regConnTrip.CURRENT_SEQ, 0, tripDetails);
3098		regConnTrip.SEQUENCE_TRIP_CODE.splice(regConnTrip.CURRENT_SEQ, 0, tripDetails.tripCode); // Insert the trip code at the correct sequence
3099		showBookDetailAgainstTripSequence();//ok
3100	} else {
3101		alert("Not allowed to modify passenger ticket details");
3102	}
3103
3104	// which means final step is reached ==> (regConnTrip.CURRENT_SEQ === regConnTrip.TOTAL_SEQ)
3105	if (regConnTrip.SEQ_STATUS === 'DROPPING') {
3106		connectTripDetais(connetSchedule);
3107		return;
3108	} else {
3109		const $input = $masterTrip.find(`input[name^="station_"][data-tripSequence="${regConnTrip.CURRENT_SEQ + 1}"]`);
3110		if ($input.length > 0) {
3111			$input.prop('checked', true).trigger('change'); // Trigger the change event for that input
3112		}
3113	}
3114}
3115
3116function getEmergencyExitClass(seatStatus, layer, row, matrix, seatTypeMap) {
3117	var aboveRow = row - 1;
3118	var hasSleeper = false;
3119	var hasSeater = false;
3120
3121	if (aboveRow >= matrix.rowmin) {
3122		for (var col = matrix.colmin; col <= matrix.colmax; col++) {
3123			var pos = '' + layer + aboveRow + col;
3124			var info = seatStatus[pos];
3125
3126			if (info && seatTypeMap[info.seatType]) {
3127				var category = seatTypeMap[info.seatType].category;
3128				if (category === 'SLEEPER') hasSleeper = true;
3129				if (category === 'SEATER') hasSeater = true;
3130			}
3131		}
3132	}
3133
3134	if (hasSeater && !hasSleeper) {
3135		return 'emergency-exit-seater-filer';
3136	}
3137
3138	return 'emergency-exit-sleeper-filer';
3139}
3140
3141function renderBusSeats(obj) {
3142	// var seatGenderClass = {
3143	// 	"M": "seat-booked-gents", // Booked for Male
3144	// 	"F": "seat-booked-ladies" // Booked for Female
3145	// };
3146	var seatStatusClass = {
3147		"AM": "seat-select-visibility seat-available-gents", // Available male
3148		"AF": "seat-select-visibility seat-available-ladies", // Available female
3149		"AY": "seat-select-visibility seat-available-you", // Allocated for You
3150		"AL": "seat-select-visibility", // Available
3151		"BO": "seat-booked", // Booked
3152		"BM": "seat-booked-gents", // Booked for Male
3153		"BF": "seat-booked-ladies", // Booked for Female
3154		"AO": "seat-booked-gents", // Booked
3155		"UK": "seat-booked-gents", // Booked
3156		"TBL": "seat-booked-gents", // Blocked
3157		"PBL": "seat-booked-gents", // Booked
3158		"BL": "seat-booked-gents", // Blocked
3159		"SDBL": "seat-blocked-socialdis" // Blocked
3160	};
3161	var seatType = {
3162		// seater
3163		"SS": { name: "Semi Sleeper", class: "seat-lay-search", category: "SEATER" },
3164		"SSS": { name: "Single Semi Sleeper", class: "seat-lay-search", category: "SEATER" },
3165		"ST": { name: "Seater", class: "seat-lay-search", category: "SEATER" },
3166		"SST": { name: "Single Seater", class: "seat-lay-search", category: "SEATER" },
3167		"PB": { name: "Pushback", class: "seat-lay-search", category: "SEATER" },
3168		"PTY": { name: "Pantry", class: "seat-lay-search", category: "PANTRY" },
3169		"WST": { name: "Window Seat", class: "seat-lay-search", category: "SEATER" },
3170		"BKST": { name: "Back Seat", class: "seat-lay-search", category: "SEATER" },
3171		"PBST": { name: "Pushback Seat", class: "seat-lay-search", category: "SEATER" },
3172
3173		// sleeper
3174		"SL": { name: "Sleeper", class: "sleeper-lay-search", category: "SLEEPER" },
3175		"USL": { name: "Upper Sleeper", class: "sleeper-lay-search", category: "SLEEPER" },
3176		"LSL": { name: "Lower Sleeper", class: "sleeper-lay-search", category: "SLEEPER" },
3177		"SUSL": { name: "Single Upper Sleeper", class: "sleeper-lay-search", category: "SLEEPER" },
3178		"SLSL": { name: "Single Lower Sleeper", class: "sleeper-lay-search", category: "SLEEPER" },
3179		"WSL": { name: "Window Sleeper", class: "sleeper-lay-search", category: "SLEEPER" },
3180
3181		// restroom
3182		"RRM": { name: "Rest Room", class: "restroom-sleeper-filer", category: "RESTROOM" },
3183		"FRS": { name: "Free Space", class: "restroom-sleeper-filer", category: "EMPTY" },
3184		"EME": { name: "Emergency Exit", class: "emergency-exit-filer", category: "EMERGENCYEXIT" },
3185	};
3186
3187	// shorthand
3188	var layer = obj.layer;
3189	var matrix = obj.matrix;
3190	var seatStatus = obj.seatStatus;
3191
3192	// flags
3193	var isSleeperSeatFound = false;
3194	var isSeaterFound = false;
3195
3196	// return array
3197	var allSeatNodes = [];
3198	var emptySeatNodes = [];
3199
3200	// construct seats row and col wise
3201	for (var row = matrix.rowmin; row <= matrix.rowmax; row++) {
3202		var rowSeatFound = false;
3203		var hasDefinedSeats = false; // Track if the row has any defined seats
3204		var lastDefinedCol = matrix.colmin - 1; // Track the last column with a defined seat
3205
3206		var definedSeatsInRow = [];
3207		for (var col = matrix.colmin; col <= matrix.colmax; col++) {
3208			var pos = '' + layer + row + col;
3209			if (seatStatus[pos]) {
3210				definedSeatsInRow.push(col);
3211			}
3212		}
3213		for (var col = matrix.colmin; col <= matrix.colmax; col++) {
3214
3215			// position
3216			var pos = '' + layer + row + col;
3217
3218			// position seat details
3219			var seatinfo = seatStatus[pos];
3220
3221			// seat div
3222			var $seat = $('<div/>');
3223
3224			// empty seat
3225			if (!seatinfo) {
3226
3227				if (rowSeatFound && isSleeperSeatFound) {
3228					var isBetweenDefinedSeats = false;
3229					for (var i = 0; i < definedSeatsInRow.length - 1; i++) {
3230						if (col >
3230 definedSeatsInRow[i] && col < definedSeatsInRow[i + 1]) {
3231							isBetweenDefinedSeats = true;
3232							break;
3233						}
3234					}
3235					if (!isBetweenDefinedSeats) {
3236						continue;
3237					}
3238				}
3239
3240				$seat.html('&nbsp;');
3241
3242				emptySeatNodes.push($seat.get(0));
3243				allSeatNodes.push($seat.get(0));
3244				continue;
3245			}
3246			hasDefinedSeats = true;
3247			lastDefinedCol = col;
3248
3249			$.each(allSeatNodes, function () {
3250				var $this = $(this);
3251				var $container = $this.closest('.busmap-card');
3252				$container.addClass('busmap-card-' + layer);
3253			});
3254
3255			$eme = '';
3256
3257			if (seatinfo.emergencyExitDoor !== 'NA') {
3258				$eme = '<span class="emergengcy-' + seatinfo.emergencyExitDoor + '-filer"></span>';
3259			}
3260
3261			var seatTypeClass = seatType[seatinfo.seatType] ? seatType[seatinfo.seatType].class : null;
3262			if (seatinfo.seatType === 'EME') {
3263				seatTypeClass = getEmergencyExitClass(seatStatus, layer, row, matrix, seatType);
3264			}
3265
3266			$seat
3267				.addClass(seatTypeClass) // seat type class
3268				.addClass(seatStatusClass[seatinfo.status.code]) // seat status class
3269				// .addClass(seatGenderClass[seatinfo.genderstatus.code]) // seat gender class
3270				.addClass(seatType[seatinfo.seatType].category) // seat category
3271				.attr('data-code', seatinfo.code)
3272				.attr('data-fare', seatinfo.fare)
3273				.attr('data-discount', seatinfo.discountFare)
3274				.attr('data-service', seatinfo.serviceTax)
3275				.attr('data-seattype', seatinfo.status.code)
3276				.html(seatinfo.seatName+$eme) // seat name
3277
3278			
3279
3280			if (seatinfo.status.code === "BO" && seatinfo.genderstatus.code === "M") {
3281				$seat.addClass("seat-booked-gents");
3282			} else if (seatinfo.status.code === "BO" && seatinfo.genderstatus.code === "F") {
3283				$seat.addClass("seat-booked-ladies");
3284			}
3285
3286			if (seatinfo.status.code === "BL" && seatinfo.genderstatus.code === "M") {
3287				$seat.addClass("seat-booked-gents");
3288			} else if (seatinfo.status.code === "BL" && seatinfo.genderstatus.code === "F") {
3289				$seat.removeClass("seat-booked-gents");
3290				$seat.addClass("seat-booked-ladies");
3291			}
3292
3293			// for quota seats
3294			if ((seatinfo.status.code === "QS") && seatinfo.genderstatus.code === "M") {
3295				$seat.addClass("seat-booked-gents");
3296			} else if ((seatinfo.status.code === "QS") && seatinfo.genderstatus.code === "F") {
3297				$seat.removeClass("seat-booked-gents");
3298				$seat.addClass("seat-booked-ladies");
3299			}
3300
3301			if (seatinfo.status.code === '') {
3302				$seat.addClass('seat-select-visibility');
3303			}
3304
3305			if (seatType[seatinfo.seatType]) {
3306				if (seatType[seatinfo.seatType].category === 'SLEEPER') isSleeperSeatFound = true;
3307				if (seatType[seatinfo.seatType].category === 'SEATER') isSeaterFound = true;
3308			}
3309
3310			// vertical layout
3311			if (seatinfo.orientation == 1) {
3312				$seat.addClass('vertical-seat');
3313			}
3314
3315			// rest Room
3316			if (seatinfo.seatType == 'RRM') {
3317				var $restroom = $('<div/>').addClass('restroom-lay').attr('title', seatType[seatinfo.seatType].name);
3318				$seat.removeClass(seatStatusClass[seatinfo.status.code]).html($restroom);
3319			}
3320
3321			// free space
3322			if (seatinfo.seatType == 'FRS') {
3323				$seat.removeClass(seatStatusClass[seatinfo.status.code]).empty();
3324			}
3325			
3326			// emergency exit
3327			if (seatinfo.seatType == 'EME') {
3328				var $emeCard = $('<div/>').addClass('emergency-lay').attr('title', seatType[seatinfo.seatType].name);
3329				$seat.removeClass(seatStatusClass[seatinfo.status.code]).html($emeCard).append($eme);
3330			}
3331
3332			// tooltip
3333			var toolipTitle = function () {
3334				if (['RRM', 'PTY', 'EME'].includes(seatinfo.seatType)) {
3335					return '<small>' + seatType[seatinfo.seatType].name + '</small>';
3336				}
3337
3338				if (['AM', 'AF', 'AL', 'AY'].includes(seatinfo.status.code)) {
3339					var seattype = seatType[seatinfo.seatType] ? seatType[seatinfo.seatType].name : '';
3340					var fare = currencySymbol + seatinfo.fare;
3341					var status = seatinfo.status.code == 'AF' ? 'Available for Female' : 'Available';
3342					return '<small>' + seattype + ' - ' + fare + '<br/>' + status + '</small>';
3343				}
3344
3345				return '<small>Booked</small>';
3346			}
3347
3348			$seat.tooltip({
3349				container: '.busmap-container',
3350				html: true,
3351				placement: 'top',
3352				boundary: 'viewport',
3353				title: toolipTitle()
3354			});
3355
3356			rowSeatFound = true;
3357			allSeatNodes.push($seat.get(0));
3358		}
3359
3360		var $clearfix = $('<div/>').addClass('clearfix');
3361		allSeatNodes.push($clearfix.get(0));
3362	}
3363
3364	if (isSeaterFound) {
3365		$(emptySeatNodes).addClass('seat-lay-search');
3366	} else if (isSleeperSeatFound) {
3367		$(emptySeatNodes).addClass('sleeper-lay-search');
3368	}
3369
3370	return allSeatNodes;
3371}
3372
3373function calculateSeatFare(busmap) {
3374	var reschedule = +getQueryParametersFromURL();
3375	var $busmap = $('#trip-' + busmap.busmap.tripCode).find('.busmap-layers');
3376	var $selected = $busmap.find('.seat-selected');
3377	var seatCount = $selected.length;
3378
3379	var fare = 0;
3380	var gst = 0;
3381	var discount = 0;
3382	var seatnames = [];
3383	var totalfare = 0;
3384
3385	$selected.each(function (i, seat) {
3386		var $seat = $(seat);
3387
3388		var seatCode = $seat.data('code');
3389		var seatDetails = busmap.seatDetails[seatCode];
3390
3391		seatnames.push(seatDetails.seatName);
3392		if (Number(seatDetails.fare)) { // base fare
3393			fare += seatDetails.fare;
3394		}
3395		if (Number(seatDetails.serviceTax)) { // service tax
3396			gst += seatDetails.serviceTax;
3397		}
3398		if (Number(seatDetails.discountFare)) { // discount
3399			discount += seatDetails.discountFare;
3400		}
3401	});
3402
3403	// Boarding Fare
3404	var boardingFare = 0;
3405	// var selectedBoarding = $('#boarding-point-list').val();
3406	var selectedBoarding = $('input[name="boarding-point"]:checked').val();
3407	$.each(busmap.busmap.fromStation.stationPoint || [], function (i, boarding) {
3408		if (boarding.code == selectedBoarding && Number(boarding.fare) > 0) {
3409			boardingFare = Number(boarding.fare) * seatCount;
3410			return false;
3411		}
3412	});
3413
3414	// Dropping Fare
3415	var droppingFare = 0;
3416	// var selectedDropping = $('#dropping-point-list').val();
3417	var selectedDropping = $('input[name="dropping-point"]:checked').val();
3418	$.each(busmap.busmap.toStation.stationPoint || [], function (i, dropping) {
3419		if (dropping.code == selectedDropping && Number(dropping.fare) > 0) {
3420			droppingFare = Number(dropping.fare) * seatCount;
3421			return false;
3422		}
3423	});
3424
3425	if (reschedule > 0) {
3426		totalfare = fare + boardingFare + droppingFare - discount;
3427		// GST
3428		if (gst > 0) {
3429			const GSTPERCENTAGE = 5;
3430			gst = percentageOf(GSTPERCENTAGE, totalfare);
3431			totalfare += gst;
3432		}
3433
3434		// footer
3435		$('#selected-seat-name').html(seatnames.join(', '));
3436		$('#selected-seat-fare').html(Number(fare).toFixed(2));
3437
3438		if (Number(gst) > 0) {
3439			$('#selected-seat-gst').removeClass('d-none');
3440			$('#selected-seat-gst').html(Number(gst).toFixed(2));
3441		}
3442		$('#selected-seat-discount-title').addClass('d-none');
3443
3444		// if (Number(discount) > 0) {
3445		// 	$('#selected-seat-discount').removeClass('d-none');
3446		// 	$('#selected-seat-discount').html(Number(discount).toFixed(2));
3447		// }
3448
3449		// $('#selected-seat-discount').html(Number(discount).toFixed(2))
3450		// .closest('.row').toggleClass('d-none', !Boolean(discount));
3451	} else {
3452		// Total Fare
3453		totalfare = fare + boardingFare + droppingFare - discount;
3454
3455		// GST
3456		if (gst > 0) {
3457			const GSTPERCENT = 5;
3458			gst = percentageOf(GSTPERCENT, totalfare);
3459			totalfare += gst;
3460		}
3461
3462		// footer
3463		$('#selected-seat-name').html(seatnames.join(', '));
3464		$('#selected-seat-fare').html(Number(fare).toFixed(2));
3465
3466		if (Number(gst) > 0) {
3467			$('#selected-seat-gst').removeClass('d-none');
3468			$('#selected-seat-gst').html(Number(gst).toFixed(2));
3469		}
3470
3471		if (Number(discount) > 0) {
3472			$('#selected-seat-discount').removeClass('d-none');
3473			$('#selected-seat-discount').html(Number(discount).toFixed(2));
3474		}
3475
3476		$('#selected-seat-discount').html(Number(discount).toFixed(2))
3477			.closest('.row').toggleClass('d-none', !Boolean(discount));
3478	}
3479
3480	$('#selected-seat-pickupcharges').html(Number(boardingFare).toFixed(2))
3481		.closest('.row').toggleClass('d-none', !Boolean(boardingFare));
3482	$('#selected-seat-droppingcharges').html(Number(droppingFare).toFixed(2))
3483		.closest('.row').toggleClass('d-none', !Boolean(droppingFare));
3484	$('#selected-seat-gst').html(Number(gst).toFixed(2))
3485		.closest('.row').toggleClass('d-none', !Boolean(gst));
3486	// $('#selected-seat-discount').html(Number(discount).toFixed(2))
3487	// 	.closest('.row').toggleClass('d-none', !Boolean(discount));
3488	$('#selected-seat-total').html(Number(totalfare).toFixed(2));
3489
3490	var overallAmountTooltipContent = "";
3491	overallAmountTooltipContent += "Fare: " + currencySymbol + Number(fare).toFixed(2) + "<br>";
3492	if (Number(gst) > 0) {
3493		overallAmountTooltipContent += "Service Tax (GST): " + currencySymbol + Number(gst).toFixed(2) + "<br>";
3494	}
3495
3496	if (Number(discount) > 0) {
3497		overallAmountTooltipContent += "Discount: " + currencySymbol + Number(discount).toFixed(2) + "<br>";
3498	}
3499
3500	if (Number(boardingFare) > 0) {
3501		overallAmountTooltipContent += "Boarding Fare: " + currencySymbol + Number(boardingFare).toFixed(2) + "<br>";
3502	}
3503
3504	if (Number(droppingFare) > 0) {
3505		overallAmountTooltipContent += "Dropping Fare: " + currencySymbol + Number(droppingFare).toFixed(2) + "<br>";
3506	}
3507	overallAmountTooltipContent += "Total Fare: " + currencySymbol + Number(totalfare).toFixed(2) + "<br>";
3508
3509	$('.overall-amount-details .overall-amount-tooltip').html(overallAmountTooltipContent);
3510
3511	// $('#toggle-seat-fareinfo')
3512	// 	.toggleClass('d-none', (gst > 0 && discount > 0))
3513	// 	.on('click', function () {
3514	// 		$(this).remove();
3515	// 		$('#selected-seat-fareinfo').removeClass('d-none');
3516	// 	});
3517}
3518
3519function getQueryParametersFromURL() {
3520	var currentURL = location.href;
3521	var urlParts = currentURL.split('?');
3522
3523	if (urlParts.length === 2) {
3524		var queryParams = urlParts[1];
3525		var paramPairs = queryParams.split('&');
3526
3527		var paramObject = {};
3528		for (var i = 0; i < paramPairs.length; i++) {
3529			var pair = paramPairs[i].split('=');
3530			if (pair.length === 2) {
3531				var key = decodeURIComponent(pair[0]);
3532				var value = decodeURIComponent(pair[1]);
3533				paramObject[key] = value;
3534			}
3535		}
3536
3537		return paramObject.reschedule;
3538	} else {
3539		return null;
3540	}
3541}
3542
3543function getBookingData(tripinfo) {
3544	// shorthand
3545	var busmap = tripinfo.busmap;
3546
3547	var data = {};
3548	data.tripCode = busmap.tripCode;
3549	data.tripStageCode = busmap.tripStageCode;
3550	data.fromStation = {};
3551	data.fromStation.code = busmap.fromStation.code;
3552	data.fromStation.name = busmap.fromStation.name;
3553	data.fromStation.dateTime = busmap.fromStation.dateTime;
3554	data.toStation = {};
3555	data.toStation.code = busmap.toStation.code;
3556	data.toStation.name = busmap.toStation.name;
3557	data.toStation.dateTime = busmap.toStation.dateTime;
3558	data.bus = {};
3559	data.bus.code = busmap.bus.code;
3560	data.bus.categoryCode = busmap.bus.categoryCode;
3561	data.bus.busType = busmap.bus.busType;
3562	data.discountList = busmap.discountList;
3563	data.schedule = {};
3564	data.schedule.code = busmap.schedule.code;
3565	data.city = busmap.fromStation.name;
3566	data.state = busmap.fromStation.state.name;
3567	data.cityCode = busmap.fromStation.code;
3568	data.stateCode = busmap.fromStation.state.code;
3569
3570	data.terms = tripinfo.terms || [];
3571
3572	data.fromStation.stationPoint = {}; // boarding point
3573	// var selectedBoarding = $('#boarding-point-list').val();
3574	var selectedBoarding = $('input[name="boarding-point"]:checked').val();
3575	$.each(busmap.fromStation.stationPoint || [], function (i, boarding) {
3576		if (boarding.code == selectedBoarding) {
3577			data.fromStation.stationPoint.code = boarding.code;
3578			data.fromStation.stationPoint.name = boarding.name;
3579			data.fromStation.stationPoint.dateTime = boarding.dateTime;
3580			data.fromStation.stationPoint.fare = Number(boarding.fare) || 0;
3581			return false;
3582		}
3583	});
3584
3585	data.toStation.stationPoint = {}; // dropping point
3586	// var selectedDropping = $('#dropping-point-list').val();
3587	var selectedDropping = $('input[name="dropping-point"]:checked').val();
3588	$.each(busmap.toStation.stationPoint || [], function (i, dropping) {
3589		if (dropping.code == selectedDropping) {
3590			data.toStation.stationPoint.code = dropping.code;
3591			data.toStation.stationPoint.name = dropping.name;
3592			data.toStation.stationPoint.dateTime = dropping.dateTime;
3593			data.toStation.stationPoint.fare = Number(dropping.fare) || 0;
3594			return false;
3595		}
3596	});
3597
3598	data.seatDetails = []; // seats
3599	$('#trip-' + data.tripCode).find('.busmap-layers .seat-selected').each(function (i, seat) {
3600		var $seat = $(seat);
3601
3602		var seatCode = $seat.data('code');
3603		var seatDetail = tripinfo.seatDetails[seatCode];
3604		seatDetail.seatCode = seatCode;
3605		data.seatDetails.push(seatDetail);
3606	});
3607
3608	return data;
3609}
3610
3611function gotoPassengerDetails(reschedule = false) {
3612	var bookingData = sessionStorage.getItem('BOOKINGDATA');
3613	sessionStorage.removeItem('BOOKINGDATA');
3614
3615	if (!bookingData) {
3616		return;
3617	}
3618
3619	// submit form
3620	$('#form-seats-data').val(bookingData);
3621	$('#form-seats').attr('action', reschedule ? 'reschedule/passenger-info' : 'passenger-info').submit();
3622}
3623
3624function autofillPassInfo() {
3625	var data = {};
3626	data.mobileNumber = $('#pass-mobile').val().trim();
3627	data.seatCount = $('.pass-info').length;
3628
3629	if (!validate.isMobile(data.mobileNumber)) {
3630		return;
3631	}
3632	if ($('#pass-mobile').data('oldvalue') == data.mobileNumber) {
3633		return;
3634	}
3635
3636	$('#pass-mobile').data('oldvalue', data.mobileNumber);
3637
3638	$.ajax({
3639		type: 'POST',
3640		url: 'passenger-info/autofill-info',
3641		data: data,
3642		dataType: 'json',
3643		success: function (result) {
3644			if (result.status == 1) {
3645				var ticketDetails = result.data.ticketDetails;
3646				$('#pass-email').val(result.data.passegerEmailId);
3647				$('.pass-info').each(function (i) {
3648					if (i >= ticketDetails.length) return false;
3649					$this = $(this);
3650
3651					$this.find('.pass-name').val(ticketDetails[i].passengerName);
3652					$this.find('.pass-age').val(ticketDetails[i].passengerAge);
3653					$this.find('.pass-gender[value="' + ticketDetails[i].passengerGendar + '"]:not(:disabled)').prop('checked', true);
3654				});
3655			}
3656		}
3657	});
3658}
3659
3660function toggleRequestInvoice() {
3661	$('.gst-field').toggleClass('d-none');
3662	$('#pass-gstemail').val($('#pass-email').val());
3663}
3664
3665function toggleAllPassInfo() {
3666	var state = $('#all-pass-details').is(':checked');
3667
3668	$('#onward-trip, #return-trip')
3669		.find('.pass-info:not(:first)')
3670		.find('.pass-name, .pass-age, .seat-name')
3671		.toggleClass('d-none', !state);
3672}
3673
3674function toggleConnRequestInvoice() {
3675	$('.gst-field').slideToggle('slow');
3676	$('#pass-gstemail').val($('#pass-email').val());
3677}
3678
3679function calculateTicketFare(offerData) {
3680	var { onwardData, returnData, rescheduleData } = getPassengerTicketData();
3681	var addonCharges = getAddonCharges();
3682
3683	var femaleDiscount;
3684	$.each(onwardData.discountList || [], function (i, discount) {
3685		if (discount.femaleDiscountFlag) {
3686			femaleDiscount = discount;
3687		}
3688	});
3689
3690	var onwardfare = 0;
3691	var returnfare = 0;
3692	var boardingfare = 0;
3693	var droppingfare = 0;
3694	var gst = 0;
3695	var discount = 0;
3696
3697	var faredifference = 0;
3698
3699	var onwardSeatCount = onwardData.seatDetails.length;
3700	$.each(onwardData.seatDetails || [], function (i, seat) {
3701		onwardfare += seat.fare;
3702		gst += seat.serviceTax;
3703		discount += seat.discountFare;
3704
3705		if (femaleDiscount) {
3706			var gender = $('.onward-trip [data-code="' + seat.seatCode + '"]').find('.pass-gender:checked').val();
3707
3708			if (gender === 'F') {
3709				discount += (femaleDiscount.percentageFlag)
3710					? percentageOf(femaleDiscount.discountValue, seat.fare)
3711					: femaleDiscount.discountValue;
3712			}
3713		}
3714	});
3715
3716	if (onwardData.fromStation.stationPoint && Number(onwardData.fromStation.stationPoint.fare) > 0) {
3717		boardingfare += Number(onwardData.fromStation.stationPoint.fare) * onwardSeatCount;
3718	}
3719
3720	if (onwardData.toStation.stationPoint && Number(onwardData.toStation.stationPoint.fare) > 0) {
3721		droppingfare += Number(onwardData.toStation.stationPoint.fare) * onwardSeatCount;
3722	}
3723
3724	if (returnData) {
3725		var returnSeatCount = returnData.seatDetails.length;
3726		$.each(returnData.seatDetails || [], function (i, seat) {
3727			returnfare += seat.fare;
3728			gst += seat.serviceTax;
3729			discount += seat.discountFare;
3730		});
3731
3732		if (returnData.fromStation.stationPoint && Number(returnData.fromStation.stationPoint.fare) > 0) {
3733			boardingfare += Number(returnData.fromStation.stationPoint.fare) * returnSeatCount;
3734		}
3735		if (returnData.toStation.stationPoint && Number(returnData.toStation.stationPoint.fare) > 0) {
3736			droppingfare += Number(returnData.toStation.stationPoint.fare) * returnSeatCount;
3737		}
3738	}
3739
3740	$('#apply-offer-help').html('');
3741	if (offerData) {
3742		var offerValue = (offerData.percentageFlag) ? percentageOf(offerData.value, fare) : offerData.value;
3743		var offerAmount = Math.max((offerData.maxvalue || 0), offerValue);
3744
3745		$('#apply-offer-help').html('A discount of ' + currencySymbol + Number(offerAmount).toFixed(2) + ' has been applied');
3746		discount += offerAmount;
3747	}
3748
3749	var totalfare = onwardfare + returnfare + boardingfare + droppingfare - discount;
3750
3751	if (gst > 0) {
3752		const GSTPERCENT = 5;
3753		gst = percentageOf(GSTPERCENT, totalfare);
3754		totalfare += gst;
3755	}
3756
3757	if (rescheduleData) {
3758		faredifference = Math.max(0, totalfare - rescheduleData.totalPaid + discount);
3759		totalfare = faredifference + rescheduleData.reschedulableAmount;
3760	}
3761
3762	var gogreen = $('#gogreen-addon-cb').is(':checked');
3763	if (addonCharges.GOGREEN && gogreen) {
3764		totalfare += addonCharges.GOGREEN;
3765	}
3766
3767	var pgcharges = 0;
3768	var pgchargepercent = Number($('input[name="payment-options"]:checked').data('pgcharges')) || 0;
3769	if (pgchargepercent > 0) {
3770		pgcharges = percentageOf(pgchargepercent, totalfare);
3771		totalfare += pgcharges;
3772	}
3773
3774	// totalfare = Math.round(totalfare);
3775
3776	$faretable = $('#pass-fare-details').empty();
3777
3778	if (rescheduleData) {
3779		if (faredifference > 0) {
3780			$faretable.append(buildFareRow('NEWTICKET', onwardfare));
3781			// $faretable.append(buildFareRow('DISCOUNT', discount));
3782			$faretable.append(buildFareRow('GST', gst));
3783			$faretable.append(buildFareRow('OLDTICKET', rescheduleData.totalPaid));
3784			$faretable.append(emptyFareRow('<div class="border-top" />'));
3785			$faretable.append(buildFareRow('FAREDIFF', faredifference));
3786		}
3787		$faretable.append(buildFareRow('RESCHARGE', rescheduleData.reschedulableAmount));
3788		$faretable.append(buildFareRow('PGCHARGE', pgcharges));
3789	} else {
3790		$faretable.append(buildFareRow(returnfare ? 'ONWARD' : 'BASEFARE', onwardfare));
3791		$faretable.append(buildFareRow('RETURN', returnfare));
3792		$faretable.append(buildFareRow('PICKUP', boardingfare));
3793		$faretable.append(buildFareRow('DROPPING', droppingfare));
3794		$faretable.append(buildFareRow('DISCOUNT', discount));
3795		$faretable.append(buildFareRow('GST', gst));
3796		$faretable.append(buildFareRow('PGCHARGE', pgcharges));
3797		if (gogreen) {
3798			$faretable.append(buildFareRow('GOGREEN', addonCharges.GOGREEN));
3799		}
3800	}
3801	$faretable.append(emptyFareRow());
3802	$faretable.append(buildFareRow('TOTAL', totalfare));
3803
3804	if (totalfare == 0) {
3805		$('#pg-accordion, #pg-redirect-hint').addClass('d-none');
3806		$('#block-ticket-btn').html('Continue');
3807	}
3808}
3809
3810function buildFareRow(code, value) {
3811	var entities = {
3812		'BASEFARE': { name: 'Ticket Fare', type: 'Cr', class: 'ticket-fare-tr' },
3813		'ONWARD': { name: 'Onward Ticket Fare', type: 'Cr', class: '' },
3814		'RETURN': { name: 'Return Ticket Fare', type: 'Cr', class: '' },
3815		'PICKUP': { name: 'Pickup Charges', type: 'Cr', class: '' },
3816		'DROPPING': { name: 'Dropping Charges', type: 'Cr', class: '' },
3817		'DISCOUNT': { name: 'Discount', type: 'Dr', class: '' },
3818		'GST': { name: 'GST', type: 'Cr', class: '' },
3819		'PGCHARGE': { name: 'Payment Gateway Charges', type: 'Cr', class: '' },
3820		'GOGREEN': { name: 'Go Green', type: 'Cr', class: 'text-success' },
3821		'NEWTICKET': { name: 'New Ticket Fare', type: 'Cr', class: '' },
3822		'OLDTICKET': { name: 'Old Ticket Fare', type: 'Dr', class: '' },
3823		'FAREDIFF': { name: 'Fare Difference', type: 'Cr', class: '' },
3824		'RESCHARGE': { name: 'Reschedule Charges', type: 'Cr', class: '', allowZero: true },
3825		'TOTAL': { name: 'Total Fare', type: 'NA', class: 'total-fare-tr', allowZero: true },
3826		'GRANDTOTAL': { name: 'Grand Total', type: 'NA', class: 'total-fare-tr', allowZero: true },
3827		'ONWFARE': { name: 'Onward Bus Fare', type: 'Cr', class: '' },
3828		'BUSFARE': { name: 'Bus Fare', type: 'Cr', class: '' },
3829		'ONWDISCOUNT': { name: 'Discount', type: 'Ar', class: '' },
3830		'ONWGST': { name: 'Tax', type: 'Cr', class: '' },
3831		'ONWTOTAL': { name: 'Total Fare', type: 'NA', class: 'total-fare-tr' },
3832		'RETFARE': { name: 'Return Bus Fare', type: 'Cr', class: '' },
3833		'RETDISCOUNT': { name: 'Discount', type: 'Ar', class: '' },
3834		'RETGST': { name: 'Tax', type: 'Cr', class: '' },
3835		'RETTOTAL': { name: 'Total Fare', type: 'NA', class: 'total-fare-tr' },
3836		'HOTELFARE': { name: 'Room Fare', type: 'Cr', class: 'hotel-fare' },
3837		'HOTELPERSONFARE': { name: 'Extra Person Fare', type: 'Cr', class: 'hotel-person-fare' },
3838		'HOTELDISCOUNT': { name: 'Discount', type: 'Ar', class: 'hotel-discount' },
3839		'HOTELGST': { name: 'Tax', type: 'Cr', class: 'hotel-gst' },
3840		'HOTELTOTAL': { name: 'Total Hotel Fare', type: 'NA', class: 'hotel-total' },
3841		'OVRTOTAL': { name: 'Total Bus Fare', type: 'NA', class: '' },
3842		'TOTALDISCOUNT': { name: 'Total Discount Fare', type: 'NA', class: '' },
3843		'TAXTOTAL': { name: 'Tax', type: 'NA', class: '' },
3844	};
3845
3846	if (!entities[code] || (!entities[code].allowZero && Number(value) <= 0)) {
3847		return null;
3848	}
3849
3850	var $tr = $('<tr />').addClass(entities[code].class);
3851	$('<td />').addClass('text-left').addClass(entities[code].class).addClass('fare-clr').text(entities[code].name).appendTo($tr);
3852	$('<td />').addClass('text-right').addClass(entities[code].class).html('<i class="fa fa-rupee-sign fa-fw"></i> ' + (entities[code].type == 'Dr' ? '-' : '') + Number(value).toFixed(2)).appendTo($tr);
3853
3854	return $tr;
3855}
3856
3857function emptyFareRow(content) {
3858	var $tr = $('<tr />');
3859	$('<td colspan="2"/>').html(content).appendTo($tr);
3860
3861	return $tr;
3862}
3863
3864function processTicketData(ticketData, type) {
3865	$('#pass-alert').html('');
3866
3867	var data = {};
3868	data.mobileNumber = $('#pass-mobile').val().trim();
3869	data.emailId = $('#pass-email').val().trim();
3870	data.offerDiscountCode = $('#pass-offercode').val().trim();
3871	data.gatewayPartner = {};
3872	data.gatewayPartner.code = $('input[name="payment-options"]:checked').val() || '';
3873	data.orderDetails = [];
3874	data.addexOrder = []; // addex array
3875
3876	var err = 0;
3877	if (!validate.isMobile(data.mobileNumber)) {
3878		$('#pass-mobile').addClass('is-invalid');
3879		err++;
3880	}
3881	if (!validate.isEmail(data.emailId)) {
3882		$('#pass-email').addClass('is-invalid');
3883		err++;
3884	}
3885	if (!type) {
3886		if ($('input[name="payment-options"]').length && data.gatewayPartner.code == '') {
3887			$('input[name="payment-options"]').addClass('is-invalid');
3888			err++;
3889		}
3890	}
3891
3892	// autofill first seat name
3893	var allPassDetails = $('#all-pass-details').is(':checked');
3894	if (!allPassDetails) {
3895		$('#onward-trip, #return-trip').find('.pass-info:first').each(function () {
3896			var $firstseat = $(this);
3897			var $hiddenseats = $firstseat.siblings('.pass-info');
3898
3899			$hiddenseats.find('.pass-name').val($firstseat.find('.pass-name').val());
3900			$hiddenseats.find('.pass-age').val($firstseat.find('.pass-age').val());
3901		});
3902	}
3903
3904	var { onwardData, returnData, hotelData } = ticketData;
3905
3906	var addonCharges = getAddonCharges();
3907
3908	var onwardTicket = {};
3909	onwardTicket.journeyType = 'OW';
3910	onwardTicket.tripCode = onwardData.tripCode;
3911	onwardTicket.fromStation = {};
3912	onwardTicket.fromStation.code = onwardData.fromStation.code;
3913	onwardTicket.toStation = {};
3914	onwardTicket.toStation.code = onwardData.toStation.code;
3915	onwardTicket.boardingPoint = onwardData.fromStation.stationPoint;
3916	onwardTicket.droppingPoint = onwardData.toStation.stationPoint;
3917	onwardTicket.travelDate = moment(onwardData.fromStation.dateTime).format('YYYY-MM-DD');
3918	onwardTicket.ticketDetails = [];
3919	$.each(onwardData.seatDetails || [], function (i, seatDetail) {
3920		var $seat = $('#onward-trip .pass-info[data-code="' + seatDetail.seatCode + '"]')
3921
3922		var seat = {};
3923		seat.seatCode = seatDetail.seatCode;
3924		seat.seatName = seatDetail.seatName;
3925		seat.seatFare = seatDetail.fare;
3926		seat.passengerName = $seat.find('.pass-name').val().trim();
3927		seat.passengerAge = $seat.find('.pass-age').val().trim();
3928		seat.passengerGendar = $seat.find('.pass-gender:checked').val() || '';
3929		onwardTicket.ticketDetails.push(seat);
3930
3931		if (seat.passengerName == '') {
3932			$seat.find('.pass-name').addClass('is-invalid');
3933			err++;
3934		}
3935		if (seat.passengerAge == '') {
3936			$seat.find('.pass-age').addClass('is-invalid');
3937			err++;
3938		}
3939		if (seat.passengerGendar == '') {
3940			$seat.find('.pass-gender').addClass('is-invalid');
3941			err++;
3942		}
3943	});
3944
3945	data.orderDetails.push(onwardTicket);
3946
3947	if (returnData) {
3948		var returnTicket = {};
3949		returnTicket.journeyType = 'RT';
3950		returnTicket.tripCode = returnData.tripCode;
3951		returnTicket.fromStation = {};
3952		returnTicket.fromStation.code = returnData.fromStation.code;
3953		returnTicket.toStation = {};
3954		returnTicket.toStation.code = returnData.toStation.code;
3955		returnTicket.boardingPoint = returnData.fromStation.stationPoint;
3956		returnTicket.droppingPoint = returnData.toStation.stationPoint;
3957		returnTicket.travelDate = moment(returnData.fromStation.dateTime).format('YYYY-MM-DD');
3958		returnTicket.ticketDetails = [];
3959		$.each(returnData.seatDetails || [], function (i, seatDetail) {
3960			var $seat = $('#return-trip .pass-info[data-code="' + seatDetail.seatCode + '"]')
3961
3962			var seat = {};
3963			seat.seatCode = seatDetail.seatCode;
3964			seat.seatName = seatDetail.seatName;
3965			seat.seatFare = seatDetail.fare;
3966			seat.passengerName = $seat.find('.pass-name').val().trim();
3967			seat.passengerAge = $seat.find('.pass-age').val().trim();
3968			seat.passengerGendar = $seat.find('.pass-gender:checked').val() || '';
3969			returnTicket.ticketDetails.push(seat);
3970
3971			if (seat.passengerName == '') {
3972				$seat.find('.pass-name').addClass('is-invalid');
3973				err++;
3974			}
3975			if (seat.passengerAge == '') {
3976				$seat.find('.pass-age').addClass('is-invalid');
3977				err++;
3978			}
3979			if (seat.passengerGendar == '') {
3980				$seat.find('.pass-gender').addClass('is-invalid');
3981				err++;
3982			}
3983		});
3984
3985		data.orderDetails.push(returnTicket);
3986	}
3987
3988	if (hotelData && $('.hotel-details-card').hasClass('selected')) {
3989
3990		var addonHotel = {};
3991		var addonCode = $('.hotel-details-card.selected').data('addon-code');
3992		var hotelDetails = $.each(hotelData || [], function (i, hotel) {
3993			return addonCode == hotel.code
3994		});
3995		const currentDate = new Date();
3996
3997		addonHotel.orderDate = formatHotelDate(onwardData.toStation.dateTime);
3998		addonHotel.transactionDate = formatHotelDate(currentDate);
3999
4000		addonHotel.serviceType = {};
4001		addonHotel.serviceType.code = $('.hotel-details-card.selected').data('addon-service-code');
4002
4003		addonHotel.addon = {};
4004		addonHotel.addon.code = addonCode;
4005		addonHotel.addon.criteriaCode = $('.hotel-details-card.selected').data('addon-criteria-code');
4006		addonHotel.inventoryCode = $('.hotel-details-card.selected').data('addon-inv-code');
4007
4008		addonHotel.orderDetails = {};
4009		addonHotel.orderDetails.checkIn = $('.hotel-details-card.selected').data('addon-c-in');
4010		addonHotel.orderDetails.checkOut = $('.hotel-details-card.selected').data('addon-c-out');
4011		addonHotel.orderDetails.personCount = onwardData.seatDetails.length;
4012
4013		var roomCount = $('.hotel-details-card.selected').find('.hotel-rooms-number').text();
4014		var personcount = $('.hotel-details-card.selected').find('.hotel-person-number').text();
4015		addonHotel.orderDetails.addonCount = convertToNumber(roomCount);
4016		addonHotel.orderDetails.extraPersonCount = convertToNumber(personcount);
4017
4018		var custname = '';
4019		$('#onward-trip, #return-trip').find('.pass-info:first').each(function () {
4020			var $firstseat = $(this);
4021			custname = $firstseat.find('.pass-name').val().trim();
4022		});
4023		addonHotel.customerName = custname;
4024		addonHotel.customerMobileNumber = $('#pass-mobile').val().trim();
4025		addonHotel.activeFlag = 1;
4026		addonHotel.ticketAmount = $('#ticket-amount').val();
4027
4028		data.addexOrder.push(addonHotel);
4029	}
4030
4031	data.additionalAttributes = {};
4032	data.additionalAttributes.WHATSAPP_NOTIFICATION_FLAG = $('input[name="whatsapp-flag"]:checked').length === 0 ? 1 : 0;
4033	data.additionalAttributes.CITY_CODE = $('#pass-city').data('code');
4034	data.additionalAttributes.STATE_CODE = $('#pass-state').data('code');
4035	var alternateMobileNo = $('#pass-mobile-alt').val().trim();
4036	if (validate.isMobile(alternateMobileNo)) {
4037		data.additionalAttributes.ALTERNATE_MOBILE = alternateMobileNo;
4038	}
4039
4040	if ($('#pass-gst-invoice').is(':checked')) {
4041		data.additionalAttributes.GST_IN = $('#pass-gstin').val().trim();
4042		data.additionalAttributes.GST_TRADE_NAME = $('#pass-gsttrade').val().trim();
4043		data.additionalAttributes.GST_EMAIL = $('#pass-gstemail').val().trim();
4044
4045		if (!validate.isGSTIN(data.additionalAttributes.GST_IN)) {
4046			$('#pass-gstin').addClass('is-invalid');
4047			err++;
4048		}
4049		if (data.additionalAttributes.GST_TRADE_NAME == '') {
4050			$('#pass-gsttrade').addClass('is-invalid');
4051			err++;
4052		}
4053		if (!validate.isEmail(data.additionalAttributes.GST_EMAIL)) {
4054			$('#pass-gstemail').addClass('is-invalid');
4055			err++;
4056		}
4057	}
4058
4059	var gogreen = $('#gogreen-addon-cb').is(':checked');
4060	if (gogreen && addonCharges.GOGREEN) {
4061		data.additionalAttributes.GO_GREEN = addonCharges.GOGREEN;
4062	}
4063
4064	if (err) {
4065		$('#pass-alert').danger().on('detach', function () {
4066			$('.is-invalid').removeClass('is-invalid');
4067		});
4068		return false;
4069	}
4070
4071	return data;
4072}
4073
4074function validateOffer(ticketData, type) {
4075
4076	if (type == 'CONN') {
4077		var data = processConnTicketData(ticketData);
4078	} else {
4079		var data = processTicketData(ticketData, 'addon');
4080	}
4081
4082	if (!data || !data.offerDiscountCode) {
4083		// calculateTicketFare();
4084		if (type == 'CONN') {
4085			connCalculation();
4086		} else {
4087			newTicketCalculation();
4088		}
4089		return;
4090	}
4091
4092	$('#apply-offer-help').html('');
4093	$('#apply-offer-btn')
4094		.prop('disabled', true)
4095		.html('Apply');
4096
4097	$.ajax({
4098		type: 'POST',
4099		url: 'passenger-info/validate-offer',
4100		data: data,
4101		dataType: 'json',
4102		success: function (result) {
4103			$('#apply-offer-btn').prop('disabled', false).html('Apply');
4104			if (result.status == 1) {
4105				// calculateTicketFare(result.data);
4106				if (type == 'CONN') {
4107					connCalculation(result.data);
4108				} else {
4109					newTicketCalculation(result.data);
4110				}
4111
4112				$('#apply-offer-help')
4113					.removeClass('text-danger')
4114					.addClass('text-success');
4115			} else {
4116				$('#apply-offer-help')
4117					.addClass('text-danger')
4118					.removeClass('text-success')
4119					.html(result.errorDesc);
4120			}
4121		}
4122	});
4123}
4124
4125
4126function processConnTicketData(ticketData) {
4127	$('#pass-alert').html('');
4128
4129	var data = {};
4130	data.mobileNumber = $('#pass-mobile').val().trim();
4131	data.emailId = $('#pass-email').val().trim();
4132	data.offerDiscountCode = '';
4133	data.gatewayPartner = {};
4134	data.gatewayPartner.code = $('input[name="payment-options"]:checked').val() || '';
4135	data.city = $('#pass-city').val().trim();
4136	data.state = $('#pass-state').val().trim();
4137
4138	data.addexOrder = []; // addex array
4139
4140	var err = 0;
4141	if (!validate.isMobile(data.mobileNumber)) {
4142		$('#pass-mobile').addClass('is-invalid');
4143		err++;
4144	}
4145	if (!validate.isEmail(data.emailId)) {
4146		$('#pass-email').addClass('is-invalid');
4147		err++;
4148	}
4149	if ($('input[name="payment-options"]').length && data.gatewayPartner.code == '') {
4150		$('input[name="payment-options"]').addClass('is-invalid');
4151		err++;
4152	}
4153
4154	data.additionalAttributes = {};
4155	data.additionalAttributes.WHATSAPP_NOTIFICATION_FLAG = $('input[name="whatsapp-flag"]:checked').length === 0 ? 1 : 0;
4156	data.additionalAttributes.CITY_CODE = $('#pass-city').data('code');
4157	data.additionalAttributes.STATE_CODE = $('#pass-state').data('code');
4158	data.additionalAttributes.TRIP_CONNECT = $('#conn-schedule-code').val();
4159	var alternateMobileNo = $('#pass-mobile-alt').val().trim();
4160	if (validate.isMobile(alternateMobileNo)) {
4161		data.additionalAttributes.ALTERNATE_MOBILE = alternateMobileNo;
4162	}
4163
4164	if ($('#pass-gst-invoice').is(':checked')) {
4165		data.additionalAttributes.GST_IN = $('#pass-gstin').val().trim();
4166		data.additionalAttributes.GST_TRADE_NAME = $('#pass-gsttrade').val().trim();
4167		data.additionalAttributes.GST_EMAIL = $('#pass-gstemail').val().trim();
4168
4169		if (!validate.isGSTIN(data.additionalAttributes.GST_IN)) {
4170			$('#pass-gstin').addClass('is-invalid');
4171			err++;
4172		}
4173		if (data.additionalAttributes.GST_TRADE_NAME == '') {
4174			$('#pass-gsttrade').addClass('is-invalid');
4175			err++;
4176		}
4177		if (!validate.isEmail(data.additionalAttributes.GST_EMAIL)) {
4178			$('#pass-gstemail').addClass('is-invalid');
4179			err++;
4180		}
4181	}
4182
4183	const lastEleOfOrderDetails = ticketData.connectOrderDetails[ticketData.connectOrderDetails.length - 1];
4184	if (ticketData.hotelData && $('.hotel-details-card').hasClass('selected')) {
4185
4186		var addonHotel = {};
4187		var addonCode = $('.hotel-details-card.selected').data('addon-code');
4188		// var hotelDetails = $.each(hotelData || [], function (i, hotel) {
4189		// 	return addonCode == hotel.code
4190		// });
4191		const currentDate = new Date();
4192
4193		addonHotel.orderDate = formatHotelDate(lastEleOfOrderDetails.bus.toStationTime);
4194		addonHotel.transactionDate = formatHotelDate(currentDate);
4195
4196		addonHotel.serviceType = {};
4197		addonHotel.serviceType.code = $('.hotel-details-card.selected').data('addon-service-code');
4198
4199		addonHotel.addon = {};
4200		addonHotel.addon.code = addonCode;
4201		addonHotel.addon.criteriaCode = $('.hotel-details-card.selected').data('addon-criteria-code');
4202		addonHotel.inventoryCode = $('.hotel-details-card.selected').data('addon-inv-code');
4203
4204		addonHotel.orderDetails = {};
4205		addonHotel.orderDetails.checkIn = $('.hotel-details-card.selected').data('addon-c-in');
4206		addonHotel.orderDetails.checkOut = $('.hotel-details-card.selected').data('addon-c-out');
4207		addonHotel.orderDetails.personCount = lastEleOfOrderDetails.ticketDetails.length;
4208
4209		var roomCount = $('.hotel-details-card.selected').find('.hotel-rooms-number').text();
4210		var personcount = $('.hotel-details-card.selected').find('.hotel-person-number').text();
4211		addonHotel.orderDetails.addonCount = convertToNumber(roomCount);
4212		addonHotel.orderDetails.extraPersonCount = convertToNumber(personcount);
4213
4214		var custname = '';
4215		$('#connecting-trip').find('.pass-info:first').each(function () {
4216			var $firstseat = $(this);
4217			custname = $firstseat.find('.pass-name').val().trim();
4218		});
4219		addonHotel.customerName = custname;
4220		addonHotel.customerMobileNumber = $('#pass-mobile').val().trim();
4221		addonHotel.activeFlag = 1;
4222		addonHotel.ticketAmount = $('#conn-ticket-amount').val();
4223
4224		data.addexOrder.push(addonHotel);
4225	}
4226
4227	data.orderDetails = transformConnTicketDataArray(ticketData.connectOrderDetails);
4228
4229	// var allPassDetails = $('#all-pass-details').is(':checked');
4230	// if (allPassDetails) {
4231	// 	// If the checkbox is checked, fill all pass-name fields with the name from the first seat
4232	// 	var firstSeatName = $('#connecting-trip').find('.pass-info:first .pass-name').val().trim();
4233	// 	$('#connecting-trip').find('.pass-name').val(firstSeatName);
4234	// } else {
4235	// 	// If the checkbox is not checked, only fill the siblings of the first seat
4236	// 	$('#connecting-trip').find('.pass-info:first').each(function () {
4237	// 		var $firstseat = $(this);
4238	// 		var $hiddenseats = $firstseat.siblings('.pass-info');
4239
4240	// 		$hiddenseats.find('.pass-name').val($firstseat.find('.pass-name').val());
4241	// 		$hiddenseats.find('.pass-age').val($firstseat.find('.pass-age').val());
4242	// 	});
4243	// }
4244
4245	// var ticketDetailsLength = lastEleOfOrderDetails.ticketDetails.length;
4246	// if (ticketDetailsLength > 0) {
4247	// 	var firstSeatName = $('#connecting-trip').find('.pass-info:first .pass-name').val().trim();
4248	// 	for (var i = 0; i < ticketDetailsLength; i++) {
4249	// 		$('#connecting-trip').find('.pass-name').eq(i).val(firstSeatName);
4250	// 	}
4251	// }
4252
4253	$('#connecting-trip').find('.pass-name').each(function () {
4254		if ($(this).val().trim() === '') {
4255			$(this).addClass('is-invalid');
4256			err++;
4257		}
4258	});
4259
4260	$('#connecting-trip').find('.pass-age').each(function () {
4261		if ($(this).val().trim() === '') {
4262			$(this).addClass('is-invalid');
4263			err++;
4264		}
4265	});
4266
4267	$('#connecting-trip').find('.pass-info').each(function () {
4268		var $genderInputs = $(this).find('.pass-gender');
4269		if (!$genderInputs.is(':checked')) {
4270			$genderInputs.addClass('is-invalid');
4271			err++;
4272		}
4273	});
4274
4275	if (err) {
4276		$('#pass-alert').danger().on('detach', function () {
4277			$('.is-invalid').removeClass('is-invalid');
4278		});
4279		return false;
4280	}
4281
4282	return data;
4283}
4284
4285function transformConnTicketDataArray(dataArray) {
4286	let transformedArray = dataArray.map(conndata => {
4287
4288		let transformedData = {
4289			tripCode: conndata.tripCode || '',
4290			travelDate: conndata.travelDate || '',
4291			journeyType: conndata.journeyType || '',
4292			fromStation: {
4293				code: conndata.fromStation || '',
4294				name: conndata.fromStationName || '',
4295			},
4296			boardingPoint: {
4297				code: conndata.boardingPoint || '',
4298				name: conndata.boardingPointName || '',
4299			},
4300			toStation: {
4301				code: conndata.toStation || '',
4302				name: conndata.toStationName || '',
4303			},
4304			droppingPoint: {
4305				code: conndata.droppingPoint || '',
4306				name: conndata.droppingPointName || '',
4307			},
4308			ticketDetails: []
4309		};
4310
4311		conndata.ticketDetails.forEach(ticket => {
4312			let transformedTicketDetail = {
4313				seatCode: ticket.seatCode || '',
4314				passengerGendar: ticket.passengerGendar || '',
4315				passengerName: ticket.passengerName || '',
4316				passengerAge: ticket.passengerAge || '',
4317				seatFare: ticket.fare || 0,
4318				seatName: ticket.seatName || '',
4319				idProof: null
4320			};
4321
4322			const $passInfoBlock = $('#connecting-trip').find(`.pass-info[data-code="${ticket.seatCode}"]`);
4323			const passengerName = $passInfoBlock.find('.pass-name').val().trim();
4324			const passengerAge = $passInfoBlock.find('.pass-age').val().trim();
4325			const passengerGender = $passInfoBlock.find('.pass-gender:checked').val();
4326
4327			transformedTicketDetail.passengerName = passengerName;
4328			transformedTicketDetail.passengerAge = passengerAge;
4329			transformedTicketDetail.passengerGendar = passengerGender;
4330
4331			transformedData.ticketDetails.push(transformedTicketDetail);
4332		});
4333
4334		return transformedData;
4335	});
4336
4337	return transformedArray;
4338}
4339
4340function initBlockSeats(ticketData) {
4341	var data = processTicketData(ticketData);
4342
4343	if (!$('#pass-terms').is(':checked')) {
4344		$('#pass-terms').addClass('is-invalid');
4345		return;
4346	}
4347
4348	if (!data) {
4349		return;
4350	}
4351
4352	$('#block-ticket-btn')
4353		.prop('disabled', true)
4354		.html(
4355			'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> ' +
4356			'Please wait...'
4357		);
4358
4359	$.ajax({
4360		type: 'POST',
4361		url: 'passenger-info/block-seats',
4362		data: data,
4363		dataType: 'json',
4364		success: function (result) {
4365			if (result.status == 1) {
4366				if (result.data.paymentGatewayProcessFlag) {
4367					if (result.data.gatewayCode == 'RAZORPAY') {
4368						var options = result.data.gatewayInputDetails;
4369						options.image = 'assets/images/logo.png';
4370						options.theme = {};
4371						options.theme.color = getComputedStyle(document.documentElement).getPropertyValue('--theme-primary-color').trim();
4372						options.modal = {};
4373						options.modal.escape = false;
4374						options.modal.confirm_close = true;
4375						options.modal.ondismiss = function () {
4376							location.href = 'passenger-info/payment-response?orderCode=' + result.data.code;
4377						};
4378						var rzp1 = new Razorpay(options);
4379						rzp1.open();
4380						return
4381					}
4382
4383					var formControl = '';
4384					$.each(result.data.gatewayInputDetails || [], function (rekey, reval) {
4385						formControl += '<input name="' + rekey + '" id="' + rekey + '" value="' + reval + '" />';
4386					});
4387					$('body').append('<form action="' + result.data.paymentRequestUrl + '" name="frm_payment" id="frm_payment" method="post" style="display:none;">' + formControl + '</form>');
4388					$('#frm_payment').submit();
4389				} else {
4390					location.href = 'passenger-info/payment-response?orderCode=' + result.data.code;
4391				}
4392			} else {
4393				$('#pass-alert').danger(result.errorDesc);
4394			}
4395			$('#block-ticket-btn').prop('disabled', false).html('Continue');
4396		}
4397	});
4398}
4399
4400function doAgentLogin(event) {
4401	event.preventDefault();
4402
4403	var data = {
4404		username: $('#agent-login-username').val().trim(),
4405		password: $('#agent-login-password').val().trim()
4406	};
4407
4408	var err = 0;
4409
4410	if (data.username === '') {
4411		$('#agent-login-username').addClass('is-invalid');
4412		err++;
4413	}
4414
4415	if (data.password.length < 6) {
4416		$('#agent-login-password').addClass('is-invalid');
4417		err++;
4418	}
4419
4420	if (err) {
4421		$('#agent-login-alert').danger().on('detach', function () {
4422			$('#agent-login-form .is-invalid').removeClass('is-invalid');
4423		});
4424		return;
4425	}
4426
4427	$('#agent-login-btn').html('Loading...').attr('disabled', true);
4428
4429	$.ajax({
4430		type: 'POST',
4431		url: 'user/authenticate',
4432		data: data,
4433		dataType: 'json',
4434		success: function (result) {
4435			$('#agent-login-btn').text('Get Details').attr('disabled', false);
4436
4437			if (result && result.status == 1) {
4438				let groupCode = result.data?.group?.code || null;
4439
4440				let profileGroup = result?.otpVerifyGroup || [];
4441				let profileGroupCode = profileGroup[0]?.code || null;
4442
4443				let matchFound = true; // default to true
4444
4445				let groupMatch = false; // default to false
4446                groupMatch = profileGroup.some(group => group.code === groupCode);
4447 
4448                if (groupCode && profileGroupCode) {
4449                    if (groupMatch) {
4450                        matchFound = false; // if same, set to false
4451                    }
4452                }
4453
4454				if (matchFound) {
4455
4456					const operatorCode = $('#op').val() || '';	
4457					if (operatorCode !== 'jbconnect') {
4458						window.open('user/dashboard', '_blank');
4459					}
4460					$('#agent-login-alert').success({
4461						message: 'Login success',
4462						delay: 1500
4463					}).on('detach', function () {
4464						location.replace('');
4465					});
4466
4467					$('#otp-section-two').hide();
4468					$('#otp-verify-btn').hide();
4469					$('#otp-verifyed-btn').hide();
4470				} else {
4471					generateOtpLogin(); // fallback if group mismatch
4472				}
4473
4474			} else {
4475				// Show login error if status is not 1 or data is invalid
4476				let errorMsg = result?.errorDesc || 'Login failed';
4477				$('#agent-login-alert').html('<div class="alert alert-danger">' + errorMsg + '</div>').show();
4478			}
4479		},
4480	});
4481}
4482
4483function generateOtpLogin() {
4484	var data = {};
4485	$.ajax({
4486		type: 'POST',
4487		url: 'user/generate-otp',
4488		data: data,
4489		dataType: 'json',
4490		success: function (response) {
4491			if (response.status == 1) {
4492				$('#otp-section-two').show();
4493				$('#otp-verify-btn').show();
4494				$('#otp-verifyed-btn').hide();
4495				$('#agent-login-btn').hide();
4496				$('#agent-login-otps').val('');
4497				$('#agent-login-username').prop('readonly', true);
4498				$('#agent-login-password').prop('readonly', true);
4499				$('#agent-login-alert').html('<div class="alert alert-danger">' + (response.message || 'Failed to generate OTP') + '</div>').hide();
4500				// window.authToken = authToken;
4501			} else {
4502				$('#otp-verify-btn').hide();
4503				$('#otp-verifyed-btn').show();
4504				$('#otp-section-two').show();
4505				$('#agent-login-btn').hide();
4506			}
4507		}
4508	});
4509}
4510
4511function verifyOtpNumber() {
4512
4513	var data = {};
4514	data.otpNumber = $('#agent-login-otps').val().trim();
4515	var err = 0;
4516
4517	if (data.otpNumber.length < 6) {
4518		$('#agent-login-otps').addClass('is-invalid');
4519		err++;
4520	}
4521
4522	if (err > 0) {
4523		$('#agent-login-alert').html('<div class="alert alert-danger">Please enter the 6-digit OTP.</div>').show();
4524		return;
4525	}
4526
4527	$('#otp-verify-btn')
4528		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Verifying...')
4529		.attr('disabled', true);
4530
4531	$.ajax({
4532		type: 'POST',
4533		url: 'user/verifynumber',
4534		data: data,
4535		dataType: 'json',
4536		success: function (result) {
4537
4538			$('#otp-verify-btn').text('Verify OTP').attr('disabled', false);
4539			if (result.status == 1) {
4540				window.open('user/dashboard', '_blank');
4541				$('#agent-login-alert').success({
4542					message: 'Login success',
4543					delay: 1500
4544				}).on('detach', function () {
4545					location.replace('');
4546				});
4547
4548				$('#otp-section-two').hide();
4549				$('#otp-verify-btn').hide();
4550				$('#otp-verifyed-btn').hide();
4551
4552
4553			} else {
4554				$('#agent-login-alert').html('<div class="alert alert-danger">' + (result.errorDesc || 'OTP verification failed') + '</div>').show();
4555			}
4556		}
4557	});
4558}
4559
4560function verifyedUserNumber() {
4561	var data = {};
4562	data.otpNumber = $('#agent-login-otps').val().trim();
4563
4564	var err = 0;
4565
4566	if (data.otpNumber.length < 6) {
4567		$('#agent-login-otps').addClass('is-invalid');
4568		err++;
4569	}
4570
4571	if (err > 0) {
4572		$('#agent-login-alert').html('<div class="alert alert-danger">Please enter the 6-digit OTP.</div>').show();
4573		return;
4574	}
4575
4576	$('#otp-verify-btn')
4577		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Verifying...')
4578		.attr('disabled', true);
4579
4580	$.ajax({
4581		type: 'POST',
4582		url: 'user/verify-user-number',
4583		data: data,
4584		dataType: 'json',
4585		success: function (result) {
4586			$('#otp-verifyed-btn').text('Verify OTP').attr('disabled', false);
4587			if (result.status == 1) {
4588				window.open('user/dashboard', '_blank');
4589				$('#agent-login-alert').success({
4590					message: 'Login success',
4591					delay: 1500
4592				}).on('detach', function () {
4593					location.replace('');
4594				});
4595
4596				$('#otp-section-two').hide();
4597				$('#otp-verify-btn').hide();
4598				$('#otp-verifyed-btn').hide();
4599			} else {
4600				$('#agent-login-alert').html('<div class="alert alert-danger">' + (result.errorDesc || 'OTP verification failed') + '</div>').show();
4601			}
4602		}
4603	});
4604}
4605
4606function toggleSearchBar() {
4607	$(event.target).closest('header')
4608		.find('.topbar, .searchbar').toggleClass('d-none')
4609		.find('.search-input:visible').focus();
4610}
4611
4612function filterBranches() {
4613	var value = event.target.value || '';
4614	value = value.trim().toLowerCase();
4615	$('.state, .branch').toggleClass('d-none', value !== '');
4616	$('.branch[data-branch*="' + value + '"]').removeClass('d-none');
4617}
4618
4619function filterStationPoints() {
4620	var value = event.target.value || '';
4621	value = value.trim().toLowerCase();
4622	$('.station, .stationpoint').toggleClass('d-none', value !== '');
4623	$('.stationpoint[data-stationpoint*="' + value + '"]').removeClass('d-none');
4624}
4625
4626function clearSearch(selector) {
4627	$(selector).val('').trigger('keyup');
4628}
4629
4630function sendFeedback() {
4631	event && event.preventDefault();
4632
4633	var data = {},
4634		err = 0;
4635	data.name = $('#feedback-name').val().trim();
4636	data.mobile = $('#feedback-mobile').val().trim();
4637	data.email = $('#feedback-email').val().trim();
4638	data.comments = $('#feedback-comments').val().trim();
4639	data.ticketCode = $('#feedback-pnr:hidden').val().trim();
4640
4641	if (data.name === '') {
4642		$('#feedback-name').addClass('is-invalid');
4643		err++;
4644	}
4645	if (!validate.isMobile(data.mobile)) {
4646		$('#feedback-mobile').addClass('is-invalid');
4647		err++;
4648	}
4649	if (!validate.isEmail(data.email)) {
4650		$('#feedback-email').addClass('is-invalid');
4651		err++;
4652	}
4653	if (data.comments === '') {
4654		$('#feedback-comments').addClass('is-invalid');
4655		err++;
4656	}
4657
4658	if (err) {
4659		$('#feedback-alert').danger().on('detach', function () {
4660			$('#feedback-form .is-invalid').removeClass('is-invalid');
4661		});
4662		return;
4663	}
4664
4665	$('#feedback-btn').text('Submitting...').attr('disabled', true);
4666
4667	$.ajax({
4668		type: 'POST',
4669		url: 'feedback/send-feedback',
4670		data: data,
4671		dataType: 'json',
4672		success: function (result) {
4673			$('#feedback-btn').text('Feedback').attr('disabled', false);
4674			if (result.status == 1) {
4675				$('#feedback-alert').success().on('detach', function () {
4676					location.reload();
4677				});
4678			} else {
4679				$('#feedback-alert').danger(result.errorDesc);
4680			}
4681		}
4682	});
4683
4684}
4685
4686function getTicketDetailsPrint() {
4687	event && event.preventDefault();
4688
4689	$('#print-ticket-cont, #print-ticket-alert').html('');
4690
4691	var data = {};
4692	data.ticketCode = $('#print-ticket-pnr').val().trim();
4693
4694	if (data.ticketCode == '') {
4695		$('#print-ticket-pnr').addClass('is-invalid');
4696		$('#print-ticket-alert').danger().on('detach', function () {
4697			$('#print-ticket-form .is-invalid').removeClass('is-invalid');
4698		});
4699		return;
4700	}
4701
4702	$('#print-ticket-btn')
4703		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
4704		.attr('disabled', true);
4705
4706	$.ajax({
4707		type: 'POST',
4708		url: 'print-ticket/get-ticket-details',
4709		data: data,
4710		dataType: 'json',
4711		success: function (result) {
4712			if (result.status == 1) {
4713				$('#print-ticket-btn').text('Get Details').attr('disabled', false);
4714				$('#print-ticket-cont').html(result.data);
4715			} else {
4716				$('#print-ticket-alert').invalidTicket({ message: result['errorDesc'] }).on('detach', function () {
4717					$('#print-ticket-pnr .is-invalid').removeClass('is-invalid');
4718				});
4719				$('#print-ticket-btn').text('Get Details').attr('disabled', false);
4720			}
4721		}
4722	});
4723
4724}
4725
4726function sendTicketSMS() {
4727	event && event.preventDefault();
4728
4729	$('#print-ticket-cont, #print-ticket-alert').html('');
4730
4731	var data = {};
4732	data.ticketCode = $('#print-ticket-pnr').val().trim();
4733
4734	if (data.ticketCode == '') {
4735		$('#print-ticket-pnr').addClass('is-invalid');
4736		$('#print-ticket-alert').danger().on('detach', function () {
4737			$('#print-ticket-form .is-invalid').removeClass('is-invalid');
4738		});
4739		return;
4740	}
4741
4742	$('#sms-ticket-btn')
4743		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Sending...')
4744		.attr('disabled', true);
4745
4746	$.ajax({
4747		type: 'POST',
4748		url: 'print-ticket/send-ticket-sms',
4749		data: data,
4750		dataType: 'json',
4751		success: function (result) {
4752			$('#sms-ticket-btn').text('Send SMS').attr('disabled', false);
4753
4754			if (result.status == 1) {
4755				$('#print-ticket-alert').success('SMS has been sent successfully');
4756			} else {
4757				$('#print-ticket-alert').danger(result.errorDesc);
4758			}
4759		}
4760	});
4761
4762}
4763
4764function getTrackingDetails() {
4765	event && event.preventDefault();
4766
4767	$('#ticket-tracking-cont, #ticket-tracking-alert').html('');
4768
4769	var data = {};
4770	data.ticketCode = $('#ticket-tracking-pnr').val().trim();
4771	data.type = 1; // for html return;
4772
4773	if (data.ticketCode == '') {
4774		$('#ticket-tracking-pnr').addClass('is-invalid');
4775		$('#ticket-tracking-alert').danger().on('detach', function () {
4776			$('#ticket-tracking-form .is-invalid').removeClass('is-invalid');
4777		});
4778		return;
4779	}
4780
4781	$('#ticket-tracking-btn')
4782		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
4783		.attr('disabled', true);
4784
4785	$.ajax({
4786		type: 'POST',
4787		url: 'track-my-bus/get-tracking-details',
4788		data: data,
4789		dataType: 'html',
4790		success: function (result) {
4791			$('#ticket-tracking-btn').text('Get Details').attr('disabled', false);
4792			$('#ticket-tracking-cont').html(result);
4793		}
4794	});
4795
4796}
4797
4798function getCancelDetails() {
4799	event && event.preventDefault();
4800
4801	$('#cancel-ticket-cont, #cancel-ticket-alert').html('');
4802
4803	var data = {},
4804		err = 0;
4805	data.ticketCode = $('#cancel-ticket-pnr').val().trim();
4806	data.emailId = $('#cancel-ticket-email').val().trim();
4807
4808	if (data.ticketCode == '') {
4809		$('#cancel-ticket-pnr').addClass('is-invalid');
4810		err++;
4811	}
4812
4813	if (err) {
4814		$('#cancel-ticket-pnr').addClass('is-invalid');
4815		$('#cancel-ticket-alert').danger().on('detach', function () {
4816			$('#cancel-ticket-form .is-invalid').removeClass('is-invalid');
4817		});
4818		return;
4819	}
4820
4821	$('#cancel-ticket-btn')
4822		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
4823		.attr('disabled', true);
4824
4825	$.ajax({
4826		type: 'POST',
4827		url: 'cancel-ticket/get-cancel-details',
4828		data: data,
4829		dataType: 'html',
4830		success: function (result) {
4831			$('#cancel-ticket-btn').text('Get Details').attr('disabled', false);
4832			$('#cancel-ticket-cont').html(result);
4833		}
4834	});
4835
4836}
4837
4838function getTicketRefundDetails() {
4839	event && event.preventDefault();
4840
4841	$('#ticket-refund-status-cont, #ticket-refund-status-alert').html('');
4842
4843	var data = {};
4844	data.ticketCode = $('#ticket-refund-status-pnr').val().trim();
4845
4846	if (data.ticketCode == '') {
4847		$('#ticket-refund-status-pnr').addClass('is-invalid');
4848		$('#ticket-refund-status-alert').danger().on('detach', function () {
4849			$('#ticket-refund-status-form .is-invalid').removeClass('is-invalid');
4850		});
4851		return;
4852	}
4853
4854	$('#ticket-refund-status-btn')
4855		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
4856		.attr('disabled', true);
4857
4858	$.ajax({
4859		type: 'POST',
4860		url: 'ticket-refund-status/get-refund-ticket-details',
4861		data: data,
4862		dataType: 'html',
4863		success: function (result) {
4864			$('#ticket-refund-status-btn').text('Get Details').attr('disabled', false);
4865			$('#ticket-refund-status-cont').html(result);
4866		}
4867	});
4868
4869}
4870
4871function doCancelTicket() {
4872	if (!confirm('Do you want to cancel the selected seats?')) {
4873		return;
4874	}
4875
4876	var data = {};
4877	data.ticketCode = $('#cancel-pnr:hidden').val().trim();
4878	data.emailId = $('#cancel-email:hidden').val().trim();
4879	data.mobileNumber = $('#cancel-mobile:hidden').val().trim();
4880	data.seatCodeList = $('.cancel-ticket-cb:checked').map(function (i, cb) {
4881		return $(cb).data('code');
4882	}).get().join(',');
4883
4884	if (data.seatCodeList == '') {
4885		alert('Please select atleast one seat');
4886		return;
4887	}
4888
4889	var regularSeatList = $('#cancel-seat-list:hidden').val().trim();
4890	var connSeatList = $('#cancel-conn-seat-list:hidden').val().trim();
4891
4892	// Split strings []
4893	var selectedSeats = data.seatCodeList.split(',').filter(Boolean);
4894	var existingSeats = connSeatList.split(',').filter(Boolean);
4895
4896	// remove duplicates
4897	var combinedSeats = [...new Set([...selectedSeats, ...existingSeats])];
4898
4899	data.seatCodeList = combinedSeats.length > 1 ? combinedSeats.join(',') : combinedSeats[0] || '';
4900
4901	$('#confirm-cancel-btn')
4902		.prop('disabled', true)
4903		.html(
4904			'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> ' +
4905			'Cancelling...'
4906		);
4907
4908	$.ajax({
4909		type: 'POST',
4910		url: 'cancel-ticket/confirm-cancel',
4911		data: data,
4912		dataType: 'json',
4913		success: function (result) {
4914			$('#confirm-cancel-btn').prop('disabled', false).html('Cancel');
4915			if (result.status == 1) {
4916				$('#confirm-cancel-alert').success().on('detach', function () {
4917					location.reload();
4918				});
4919			} else {
4920				$('#confirm-cancel-alert').danger(result.errorDesc);
4921			}
4922		}
4923	});
4924}
4925
4926
4927async function sendOTP() {
4928	var data = {},err = 0;
4929	data.mobileNumber = $('#otp-login-mobile').val().trim();
4930
4931	if (!validate.isMobile(data.mobileNumber)) {
4932		$('#otp-login-mobile').addClass('is-invalid');
4933		err++;
4934	}
4935
4936    var captchaInput = $('#captchaCode').val().trim();
4937    if (!captchaInput) {
4938        $('#captchaCode').addClass('is-invalid');
4939        $('#otp-login-alert').danger().on('detach', function () {
4940			$('#captchaCode .is-invalid').removeClass('is-invalid');
4941		});
4942		err++;
4943    }
4944
4945	if (err) {
4946		$('#otp-login-alert').danger().on('detach', function () {
4947			$('#mobile-section .is-invalid').removeClass('is-invalid');
4948			$('#captchaCode .is-invalid').removeClass('is-invalid');
4949		});
4950		return;
4951	}
4952
4953	// Captcha is verified server-side within send-otp; send it in the payload.
4954	data.captacha = captchaInput;
4955
4956	$('#otp-login-alert').html('');
4957	$('#send-otp-btn')
4958		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Sending...')
4959		.attr('disabled', true);
4960
4961	$.ajax({
4962		type: 'POST',
4963		url: 'user/sending-otp',
4964		data: data,
4965		dataType: 'json',
4966		success: function (result) {
4967			$('#send-otp-btn').prop('disabled', false).html('Submit');
4968			if (result.status == 1) {
4969				subscribeWebOTP();
4970				$('#otp-login-alert').success();
4971				$('#mobile-section').addClass('d-none');
4972				$('#otp-section').removeClass('d-none');
4973			} else {
4974				genCaptcha(); // reset on failure
4975				$('#otp-login-alert').danger(result.errorDesc);
4976			}
4977		},
4978		error: function () {
4979			$('#send-otp-btn').prop('disabled', false).html('Submit');
4980			genCaptcha();
4981		}
4982	});
4983}
4984
4985
4986function validateOTP() {
4987	var data = {},
4988		err = 0;
4989	data.mobileNumber = $('#otp-login-mobile').val().trim();
4990	data.otpNumber = $('#otp-login-pin').val().trim();
4991
4992	if (data.otpNumber == '') {
4993		$('#otp-login-pin').addClass('is-invalid');
4994		err++;
4995	}
4996
4997	if (err) {
4998		$('#otp-login-validate-alert').danger().on('detach', function () {
4999			$('#otp-section .is-invalid').removeClass('is-invalid');
5000		});
5001		return;
5002	}
5003
5004	$('#otp-login-validate-alert').html('');
5005	$('#validate-otp-btn')
5006		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Validating...')
5007		.attr('disabled', true);
5008
5009	$.ajax({
5010		type: 'POST',
5011		url: 'user/validate-otp',
5012		data: data,
5013		dataType: 'json',
5014		success: function (result) {
5015			if (result.status == 1) {
5016				$('#otp-login-validate-alert').success();
5017
5018				location.href = '';
5019			} else if (result.status == 2) {
5020				$('#otp-login-validate-alert').success();
5021
5022				$('#otp-section').addClass('d-none');
5023				$('#register-section').removeClass('d-none');
5024			} else {
5025				$('#otp-login-validate-alert').danger(result.errorDesc);
5026				$('#validate-otp-btn').prop('disabled', false).html('Submit');
5027			}
5028		}
5029	});
5030}
5031
5032function registerUser() {
5033	var data = {},
5034		err = 0;
5035	data.name = $('#otp-register-fname').val().trim();
5036	data.lastname = $('#otp-register-lname').val().trim();
5037	data.email = $('#otp-register-email').val().trim();
5038	data.mobile = $('#otp-login-mobile').val().trim();
5039
5040	if (data.name == '') {
5041		$('#otp-register-fname').addClass('is-invalid');
5042		err++;
5043	}
5044	if (!validate.isEmail(data.email)) {
5045		$('#otp-register-fname').addClass('is-invalid');
5046		err++;
5047	}
5048
5049	if (err) {
5050		$('#otp-login-register-alert').danger().on('detach', function () {
5051			$('#register-section .is-invalid').removeClass('is-invalid');
5052		});
5053		return;
5054	}
5055
5056	$('#otp-login-register-alert').html('');
5057	$('#otp-register-btn')
5058		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Submitting...')
5059		.attr('disabled', true);
5060
5061	$.ajax({
5062		type: 'POST',
5063		url: 'user/update-profile',
5064		data: data,
5065		dataType: 'json',
5066		success: function (result) {
5067			$('#otp-register-btn').prop('disabled', false).html('Submit');
5068			if (result.status == 1) {
5069				$('#otp-login-register-alert').success();
5070
5071				location.href = '';
5072			} else {
5073				$('#otp-login-register-alert').danger(result.errorDesc);
5074			}
5075		}
5076	});
5077}
5078
5079function subscribeWebOTP() {
5080	if (!window.OTPCredential) return;
5081
5082	const input = document.querySelector('#otp-login-pin');
5083	const button = document.querySelector('#validate-otp-btn');
5084	if (!input || !button) return;
5085
5086	const ac = new AbortController();
5087	button.addEventListener('click', e => {
5088		ac.abort();
5089	});
5090
5091	navigator.credentials.get({
5092		otp: { transport: ['sms'] },
5093		signal: ac.signal
5094	}).then(otp => {
5095		input.value = otp.code;
5096		button.click();
5097	}).catch(err => {
5098		console.log(err);
5099	});
5100}
5101
5102function initPWA() {
5103	if ('serviceWorker' in navigator) {
5104		try {
5105			navigator.serviceWorker.register('serviceWorker.js');
5106		} catch (error) {
5107			console.log('Service Worker Registration Failed');
5108		}
5109	}
5110}
5111
5112function formatMobileNo(event) {
5113	if (!event.target) return;
5114	var value = event.target.value || '';
5115	value = value.replace(/[^0-9]/g, '');
5116	if (value.length > 0 && /^[6-9]/.test(value)) {
5117		event.target.value = value.substring(0, 10);
5118	} else {
5119		event.target.value = '';
5120	}
5121}
5122
5123function formatName(event) {
5124	if (!event.target) return;
5125	var value = event.target.value || '';
5126	value = value.replace(/[^a-zA-Z\s]/g, '');
5127	event.target.value = value;
5128}
5129
5130function formatAge(event) {
5131	if (!event.target) return;
5132	var value = event.target.value || '';
5133	value = value.replace(/[^0-9]/g, '');
5134	event.target.value = value;
5135}
5136
5137function manageTicket() {
5138	event && event.preventDefault();
5139
5140	$('#manage-ticket-cont, #manage-ticket-alert').html('');
5141
5142	var data = {},
5143		err = 0;
5144	error = 0;
5145	data.ticketCode = $('#manage-ticket-pnr').val().trim();
5146
5147	var inputData = $('#manage-ticket-email-mobile').val().trim();
5148
5149	if (validate.isMobile(inputData)) {
5150		data.mobileNumber = inputData;
5151	} else if (validate.isEmail(inputData)) {
5152		data.emailId = inputData;
5153	} else {
5154		$('#manage-ticket-email-mobile').addClass('is-invalid');
5155		err++;
5156	}
5157
5158	var opreation = $('[name="manage-ticket-radio"]:checked').val();
5159
5160	if (data.ticketCode == '') {
5161		$('#manage-ticket-pnr').addClass('is-invalid');
5162		error++;
5163		err--;
5164	}
5165
5166	if (err) {
5167		$('#manage-ticket-alert').emailmobile().on('detach', function () {
5168			$('#manage-ticket-form .is-invalid').removeClass('is-invalid');
5169		});
5170		return;
5171	}
5172
5173	if (error) {
5174		$('#manage-ticket-alert').danger().on('detach', function () {
5175			$('#manage-ticket-form .is-invalid').removeClass('is-invalid');
5176		});
5177		return;
5178	}
5179
5180	$('#manage-ticket-btn')
5181		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
5182		.attr('disabled', true);
5183
5184	const url = {};
5185	url['PRINT'] = 'print-ticket/get-ticket-details';
5186	url['DOWNLOAD'] = 'print-ticket/get-ticket-details';
5187	url['SMS'] = 'print-ticket/send-ticket-sms';
5188	url['CANCEL'] = 'cancel-ticket/get-cancel-details';
5189	url['BOARDING'] = 'modify-ticket/boardingpoint-modify-details';
5190	url['TRACK'] = 'track-my-bus/get-tracking-details';
5191	url['RESCHEDULE'] = 'reschedule/get-reschedule-details';
5192	url['INVOICE'] = 'modify-ticket/ticket-invoice-details';
5193	url['REFUND'] = 'ticket-refund-status/get-refund-ticket-details';
5194
5195	switch (opreation) {
5196		case 'PRINT':
5197		case 'DOWNLOAD':
5198		case 'CANCEL':
5199		case 'BOARDING':
5200		case 'TRACK':
5201		case 'RESCHEDULE':
5202		case 'INVOICE':
5203		case 'REFUND':
5204			$.ajax({
5205				type: 'POST',
5206				url: url[opreation],
5207				data: data,
5208				dataType: 'json',
5209				success: function (result) {
5210					if (result.status == 1) {
5211						$('#manage-ticket-form-cont').addClass('d-none');
5212						$('#manage-ticket-body-cont').removeClass('d-none');
5213						$('#manage-ticket-body').html(result.data);
5214
5215						// Check if the element #print-tiket-return-pnr exists
5216						// if ($('#print-tiket-return-pnr').length) {
5217						// 	$('#manage-ticket-return').removeClass('d-none');
5218						// 	$('#manage-ticket-onward').removeClass('d-none');
5219						// 	const returnPnr = $('#print-tiket-return-pnr').val();
5220						// } else {
5221						// 	$('#manage-ticket-return').addClass('d-none');
5222						// 	$('#manage-ticket-onward').addClass('d-none');
5223						// }
5224					} else {
5225						$('#manage-ticket-alert').invalidTicket({ message: result['errorDesc'] }).on('detach', function () {
5226							$('#manage-ticket-form .is-invalid').removeClass('is-invalid');
5227						});
5228						$('#manage-ticket-btn').text('Next').attr('disabled', false);
5229					}
5230				}
5231			});
5232			break;
5233		case 'SMS':
5234			$.ajax({
5235				type: 'POST',
5236				url: url[opreation],
5237				data: data,
5238				dataType: 'json',
5239				success: function (result) {
5240					$('#manage-ticket-btn').text('Next').attr('disabled', false);
5241
5242					if (result.status == 1) {
5243						$('#manage-ticket-alert').success('SMS has been sent successfully');
5244					} else {
5245						$('#manage-ticket-alert').danger(result.errorDesc);
5246					}
5247				}
5248			});
5249			break;
5250	}
5251
5252}
5253
5254function manageTicketBack() {
5255	$('.onward-ticket').addClass('d-none');
5256	$('.return-ticket').addClass('d-none');
5257	$('#manage-ticket-btn').text('Next').attr('disabled', false);
5258	$('#manage-ticket-form-cont').removeClass('d-none');
5259	$('#manage-ticket-body-cont').addClass('d-none');
5260}
5261
5262function modifyMobileNumer() {
5263	event && event.preventDefault();
5264
5265	$('#modify-ticket-cont, #modify-ticket-alert').html('');
5266
5267	var data = {},
5268		err = 0;
5269	data.ticketCode = $('#modify-ticket-pnr').val().trim();
5270	data.emailId = $('#modify-ticket-email').val().trim();
5271
5272	if (data.ticketCode == '') {
5273		$('#modify-ticket-pnr').addClass('is-invalid');
5274		err++;
5275	}
5276
5277	if (!validate.isEmail(data.emailId)) {
5278		$('#modify-ticket-email').addClass('is-invalid');
5279		err++;
5280	}
5281
5282	if (err) {
5283		$('#modify-ticket-pnr').addClass('is-invalid');
5284		$('#modify-ticket-alert').danger().on('detach', function () {
5285			$('#modify-ticket-form .is-invalid').removeClass('is-invalid');
5286		});
5287		return;
5288	}
5289
5290	$('#modify-mobile-btn')
5291		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
5292		.attr('disabled', true);
5293
5294	$.ajax({
5295		type: 'POST',
5296		url: 'modify-ticket/mobileno-modify-details',
5297		data: data,
5298		dataType: 'html',
5299		success: function (result) {
5300			$('#modify-ticket-form-cont').addClass('d-none');
5301			$('#modify-ticket-body-cont').removeClass('d-none');
5302			$('#modify-ticket-body').html(result);
5303		}
5304	});
5305}
5306
5307function updateMobileNo() {
5308	var data = {},
5309		err = 0;
5310	data.ticketCode = $('#manage-ticket-pnr').val().trim();
5311	data.emailId = $('#manage-ticket-email-mobile').val().trim();
5312	data.oldMobileNumber = $('#modify-mobile-oldno').val().trim();
5313	data.newMobileNumber = $('#modify-mobile-newno').val().trim();
5314
5315	if (!validate.isMobile(data.newMobileNumber)) {
5316		$('#modify-mobile-newno').addClass('is-invalid');
5317		err++;
5318	}
5319
5320	if (err) {
5321		$('#modify-mobile-alert').danger().on('detach', function () {
5322			$('#register-section .is-invalid').removeClass('is-invalid');
5323		});
5324		return;
5325	}
5326
5327	$('#modify-mobile-alert').html('');
5328	$('#update-mobile-btn')
5329		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Updating...')
5330		.attr('disabled', true);
5331
5332	$.ajax({
5333		type: 'POST',
5334		url: 'modify-ticket/update-mobile-no',
5335		data: data,
5336		dataType: 'json',
5337		success: function (result) {
5338			$('#update-mobile-btn').prop('disabled', false).html('Save Mobile Number');
5339			if (result.status == 1) {
5340				$('#modify-mobile-alert').success('New mobile number has been updated. <a href="print-ticket?pnr=' + data.ticketCode + '">View Ticket Details</a>');
5341			} else {
5342				$('#modify-mobile-alert').danger(result.errorDesc);
5343			}
5344		}
5345	});
5346}
5347
5348function modifyTicketBack() {
5349	$('#modify-boarding-btn').text('Edit Boarding Point').attr('disabled', false);
5350	$('#modify-mobile-btn').text('Edit Mobile Number').attr('disabled', false);
5351	$('#modify-ticket-form-cont').removeClass('d-none');
5352	$('#modify-ticket-body-cont').addClass('d-none');
5353}
5354
5355function modifyBoardingPoint() {
5356	event && event.preventDefault();
5357
5358	$('#modify-ticket-cont, #modify-ticket-alert').html('');
5359
5360	var data = {},
5361		err = 0;
5362	data.ticketCode = $('#modify-ticket-pnr').val().trim();
5363	data.emailId = $('#modify-ticket-email').val().trim();
5364
5365	if (data.ticketCode == '') {
5366		$('#modify-ticket-pnr').addClass('is-invalid');
5367		err++;
5368	}
5369
5370	if (!validate.isEmail(data.emailId)) {
5371		$('#modify-ticket-email').addClass('is-invalid');
5372		err++;
5373	}
5374
5375	if (err) {
5376		$('#modify-ticket-pnr').addClass('is-invalid');
5377		$('#modify-ticket-alert').danger().on('detach', function () {
5378			$('#modify-ticket-form .is-invalid').removeClass('is-invalid');
5379		});
5380		return;
5381	}
5382
5383	$('#modify-boarding-btn')
5384		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
5385		.attr('disabled', true);
5386
5387	$.ajax({
5388		type: 'POST',
5389		url: 'modify-ticket/boardingpoint-modify-details',
5390		data: data,
5391		dataType: 'html',
5392		success: function (result) {
5393			$('#modify-ticket-form-cont').addClass('d-none');
5394			$('#modify-ticket-body-cont').removeClass('d-none');
5395			$('#modify-ticket-body').html(result);
5396		}
5397	});
5398}
5399
5400function updateBoardingPoint() {
5401	var data = {},
5402		err = 0;
5403	data.ticketCode = $('#manage-ticket-pnr').val().trim();
5404	data.emailId = $('#manage-ticket-email-mobile').val().trim();
5405	data.oldBoardingPointCode = $('#modify-boardingpoint-old').val().trim();
5406	data.newBoardingPointCode = $('#modify-boardingpoint-new').val().trim();
5407
5408	if (data.newBoardingPointCode == '') {
5409		$('#modify-boardingpoint-new').addClass('is-invalid');
5410		err++;
5411	}
5412
5413	if (err) {
5414		$('#modify-boarding-alert').danger().on('detach', function () {
5415			$('#register-section .is-invalid').removeClass('is-invalid');
5416		});
5417		return;
5418	}
5419
5420	$('#modify-boarding-alert').html('');
5421	$('#update-boarding-btn')
5422		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Updating...')
5423		.attr('disabled', true);
5424
5425	$.ajax({
5426		type: 'POST',
5427		url: 'modify-ticket/update-boarding-point',
5428		data: data,
5429		dataType: 'json',
5430		success: function (result) {
5431			$('#update-boarding-btn').prop('disabled', false).html('Save Boarding Number');
5432			if (result.status == 1) {
5433				$('#modify-boarding-alert').success('New boarding number has been updated. <a href="print-ticket?pnr=' + data.ticketCode + '">View Ticket Details</a>');
5434			} else {
5435				$('#modify-boarding-alert').danger(result.errorDesc);
5436			}
5437		}
5438	});
5439}
5440
5441function updateInvoiceDetails() {
5442	var data = {},
5443		err = 0;
5444	data.gstin = $('#invoice-gstin').val().trim();
5445	data.tradeName = $('#invoice-tradename').val().trim();
5446	data.ticketCode = $('#manage-ticket-pnr').val().trim();
5447
5448	if (!validate.isGSTIN(data.gstin)) {
5449		$('#invoice-gstin').addClass('is-invalid');
5450		err++;
5451	}
5452
5453	if (data.tradeName == '') {
5454		$('#invoice-tradename').addClass('is-invalid');
5455		err++;
5456	}
5457
5458	if (err) {
5459		$('#invoice-details-alert').danger().on('detach', function () {
5460			$('#invoice-details-panel .is-invalid').removeClass('is-invalid');
5461		});
5462		return;
5463	}
5464
5465	$('#invoice-details-alert').html('');
5466	$('#update-invoice-btn')
5467		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Updating...')
5468		.attr('disabled', true);
5469
5470	$.ajax({
5471		type: 'POST',
5472		url: 'modify-ticket/update-ticket-invoice',
5473		data: data,
5474		dataType: 'json',
5475		success: function (result) {
5476			$('#update-invoice-btn').prop('disabled', false).html('Save Invoice Details');
5477			if (result.status == 1) {
5478				manageTicket();
5479				$('#invoice-details-alert').success();
5480			} else {
5481				$('#invoice-details-alert').danger(result.errorDesc);
5482			}
5483		}
5484	});
5485}
5486
5487function getCancellationPolicy(tripCode, fromStationCode, toStationCode, travelDate) {
5488	var data = {};
5489	data.tripCode = tripCode;
5490	data.fromStationCode = fromStationCode;
5491	data.toStationCode = toStationCode;
5492	data.travelDate = travelDate;
5493
5494	$('#cancel-policy-cont').html('<div class="h5 p-5 text-center">Loading...</div>');
5495
5496	$.ajax({
5497		type: 'POST',
5498		url: 'search/cancellation-terms',
5499		data: data,
5500		dataType: 'json',
5501		success: function (result) {
5502			if (result.status == 1) {
5503				var template = $('#template-cancellation-policy').html();
5504				var $terms = $(template);
5505				var $tbody = $terms.find('tbody');
5506				$.each(result.data.policyList || [], function (i, policy) {
5507					var $tr = $('<tr/>');
5508					$('<td/>').html(policy.term).appendTo($tr);
5509					$('<td/>').html(policy.deductionAmountTxt + ' (' + policy.chargesTxt + ')').appendTo($tr);
5510					$('<td/>').html(policy.refundAmountTxt).appendTo($tr);
5511					$tr.appendTo($tbody);
5512				});
5513				$('#cancel-policy-cont').html($terms);
5514			} else {
5515				$('#cancel-policy-cont').danger({ message: result.errorDesc, delay: 10e6 });
5516			}
5517		}
5518	});
5519}
5520
5521function gotoPrintPage() {
5522	var data = {};
5523	data.pnr = $('#print-tkt-pnr').val().trim();
5524
5525	if (!data.pnr) {
5526		$('#print-tkt-pnr').addClass('is-invalid');
5527		return;
5528	}
5529	location.href = 'print-ticket?' + $.param(data);
5530}
5531
5532function gotoTrackPage() {
5533	var data = {};
5534	data.pnr = $('#track-bus-pnr').val().trim();
5535
5536	if (!data.pnr) {
5537		$('#track-bus-pnr').addClass('is-invalid');
5538		return;
5539	}
5540	location.href = 'track-my-bus?' + $.param(data);
5541}
5542
5543function getRescheduleDetails() {
5544	event && event.preventDefault();
5545
5546	$('#reschedule-ticket-cont, #reschedule-ticket-alert').html('');
5547
5548	var data = {},
5549		err = 0;
5550	data.ticketCode = $('#reschedule-ticket-pnr').val().trim();
5551
5552	if (data.ticketCode == '') {
5553		$('#reschedule-ticket-pnr').addClass('is-invalid');
5554		err++;
5555	}
5556
5557	var inputData = $('#reschedule-ticket-email-mobile').val().trim();
5558
5559	if (validate.isMobile(inputData)) {
5560		data.mobileNumber = inputData;
5561	} else if (validate.isEmail(inputData)) {
5562		data.emailId = inputData;
5563	} else {
5564		$('#reschedule-ticket-email-mobile').addClass('is-invalid');
5565		err++;
5566	}
5567
5568	if (err) {
5569		$('#reschedule-ticket-pnr').addClass('is-invalid');
5570		$('#reschedule-ticket-alert').danger().on('detach', function () {
5571			$('#reschedule-ticket-form .is-invalid').removeClass('is-invalid');
5572		});
5573		return;
5574	}
5575
5576	$('#reschedule-ticket-btn')
5577		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
5578		.attr('disabled', true);
5579
5580	$.ajax({
5581		type: 'POST',
5582		url: 'reschedule/get-reschedule-details',
5583		data: data,
5584		dataType: 'html',
5585		success: function (result) {
5586			$('#reschedule-ticket-btn').text('Get Details').attr('disabled', false);
5587			$('#reschedule-ticket-cont').html(result);
5588		}
5589	});
5590}
5591
5592function initRescheduleSeats() {
5593	var { onwardData, returnData } = getPassengerTicketData();
5594
5595	var data = {};
5596	data.transferBoardingPoint = {};
5597	data.transferBoardingPoint.code = onwardData.fromStation.stationPoint.code;
5598	data.transferDroppingPoint = {};
5599	data.transferDroppingPoint.code = onwardData.toStation.stationPoint.code;
5600	data.captureFareDifferece = true;
5601	data.captureTransferCharge = true;
5602	data.notificationFlag = false;
5603	data.paymentPartnerCode = $("input[name='payment-options']:checked").val();
5604	data.transferTripStageCode = onwardData.tripStageCode;
5605	data.transferTripCode = onwardData.tripCode;
5606	data.ticketCode = $('#reschedule-ticket-code').val();
5607	data.myAccountFlag = false;
5608	data.transferFromStation = {};
5609	data.transferFromStation.code = onwardData.fromStation.code;
5610	data.transferToStation = {};
5611	data.transferToStation.code = onwardData.toStation.code;
5612	data.transferTravelDate = moment(onwardData.fromStation.dateTime).format('YYYY-MM-DD');
5613	data.seatCode = [];
5614	data.transferSeatCode = [];
5615	$('#onward-trip .pass-info').each(function () {
5616		data.seatCode.push($(this).data('oldseatcode'));
5617		data.transferSeatCode.push($(this).data('code'));
5618	});
5619
5620	var err = 0;
5621	if ($('input[name="payment-options"]').length && data.paymentPartnerCode == '') {
5622		$('input[name="payment-options"]').addClass('is-invalid');
5623		err++;
5624	}
5625
5626	if (!$('#pass-terms').is(':checked')) {
5627		$('#pass-terms').addClass('is-invalid');
5628		err++;
5629	}
5630
5631	if (err) {
5632		$('#pass-alert').danger().on('detach', function () {
5633			$('.is-invalid').removeClass('is-invalid');
5634		});
5635		return false;
5636	}
5637
5638	$('#block-ticket-btn')
5639		.prop('disabled', true)
5640		.html(
5641			'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> ' +
5642			'Please wait...'
5643		);
5644
5645	$.ajax({
5646		type: 'POST',
5647		url: 'reschedule/block-seats',
5648		data: data,
5649		dataType: 'json',
5650		success: function (result) {
5651			if (result.status == 1) {
5652				if (result.data.paymentGatewayProcessFlag) {
5653					if (result.data.gatewayCode == 'RAZORPAY') {
5654						var options = result.data.gatewayInputDetails;
5655						options.image = 'assets/images/logo.png';
5656						options.theme = {};
5657						options.theme.color = getComputedStyle(document.documentElement).getPropertyValue('--theme-primay-color');
5658						options.modal = {};
5659						options.modal.escape = false;
5660						options.modal.confirm_close = true;
5661						options.modal.ondismiss = function () {
5662							location.href = 'reschedule/payment-response?orderCode=' + result.data.code;
5663						};
5664						var rzp1 = new Razorpay(options);
5665						rzp1.open();
5666						return
5667					}
5668
5669					var formControl = '';
5670					$.each(result.data.gatewayInputDetails || [], function (rekey, reval) {
5671						formControl += '<input name="' + rekey + '" id="' + rekey + '" value="' + reval + '" />';
5672					});
5673					$('body').append('<form action="' + result.data.paymentRequestUrl + '" name="frm_payment" id="frm_payment" method="post" style="display:none;">' + formControl + '</form>');
5674					$('#frm_payment').submit();
5675				} else {
5676					location.href = 'reschedule/payment-response?orderCode=' + result.data.code;
5677				}
5678			} else {
5679				$('#pass-alert').danger(result.errorDesc);
5680			}
5681			$('#block-ticket-btn').prop('disabled', false).html('Continue');
5682		}
5683	});
5684}
5685
5686function scrollToTop() {
5687	window.scrollTo({ top: 0, behavior: 'smooth' });
5688}
5689
5690function countUp(selector, options = {}) {
5691	function formatNumberWithSuffix(value) {
5692		if (value >= 1e7) return (value / 1e7).toFixed(1).replace(/\.0$/, '') + 'Cr'; // Crore
5693		if (value >= 1e5) return (value / 1e5).toFixed(1).replace(/\.0$/, '') + 'L';  // Lakh
5694		if (value >= 1e9) return (value / 1e9).toFixed(1).replace(/\.0$/, '') + 'b';
5695		if (value >= 1e6) return (value / 1e6).toFixed(1).replace(/\.0$/, '') + 'm';
5696		if (value >= 1e3) return (value / 1e3).toFixed(1).replace(/\.0$/, '') + 'k';
5697		return value.toString();
5698	}
5699
5700	function onIntersection(entries) {
5701		entries.forEach(entry => {
5702			if (!entry.isIntersecting) return;
5703			observer.unobserve(entry.target);
5704
5705			const defaults = {
5706				duration: 1000,
5707				easing: 'swing',
5708				step: function () {
5709					const val = Math.ceil(this.counter);
5710					this.textContent = formatNumberWithSuffix(val);
5711				},
5712				complete: function () {
5713					const target = $(this).data('target');
5714					this.textContent = formatNumberWithSuffix(target);
5715				}
5716			};
5717
5718			const settings = $.extend(true, defaults, options);
5719
5720			$(entry.target).prop('counter', 0).animate({
5721				counter: $(entry.target).data('target')
5722			}, settings);
5723		});
5724	}
5725
5726	const observer = new IntersectionObserver(onIntersection, { threshold: 1 });
5727	document.querySelectorAll(selector).forEach(el => observer.observe(el));
5728}
5729
5730function initViaRouteMap(stations) {
5731	var map = L.map('via-map', { attributionControl: false }).setView([20.5937, 78.9629], 5);
5732
5733	L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
5734
5735	var markerLayer = L.featureGroup();
5736	$.each(stations || [], function (i, station) {
5737		$.each(station.fromStation.stationPoint || [], function (i, point) {
5738			L.marker([point.latitude, point.longitude])
5739				.bindPopup('<b>' + point.name + '</b> : ' + moment(point.dateTime).format('hh:mm A') + '<br/>' + point.landmark)
5740				.addTo(markerLayer);
5741		});
5742	});
5743
5744	markerLayer.addTo(map);
5745	map.fitBounds(markerLayer.getBounds());
5746}
5747
5748function retryPayment(tc) {
5749	var data = {};
5750
5751	$('#retry-payment-btn')
5752		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
5753		.attr('disabled', true);
5754
5755	$.ajax({
5756		type: 'POST',
5757		url: 'passenger-info/payment-info',
5758		data: data,
5759		dataType: 'json',
5760		success: function (res) {
5761			// $('#retry-payment-btn').text('Get Details').attr('disabled', false);
5762			location.href = 'passenger-info/payment-info?orderCode=' + tc;
5763		}
5764	});
5765}
5766
5767// function to make the whatsapp qr code to visible / hidden
5768$(".wa-float-icon").hover(function () {
5769	$(".wt-qr_code").stop(true, true).fadeToggle(600);
5770});
5771
5772// whatsapp qr code
5773window.addEventListener("load", function() {
5774		document.querySelectorAll(".whatsapp").forEach(function(el) {
5775
5776			// Step 1: Show after small delay
5777			setTimeout(function() {
5778				el.classList.add("show-on-load");
5779
5780				// Step 2: Hide after 1 second
5781				setTimeout(function() {
5782					el.classList.remove("show-on-load");
5783				}, 1000);
5784
5785			}, 200);
5786
5787		});
5788	});
5789function isPM(time) {
5790	var timeParts = time.split(' ');
5791	var timeHourPart = timeParts[1].split(':')[0];
5792	var hours = parseInt(timeHourPart);
5793
5794	return hours >= 12 && hours < 24;
5795}
5796
5797function renderBusSeatsV4(obj) {
5798	var seatGenderClass = {
5799		"M": "seat-booked-gents", // Booked for Male
5800		"F": "seat-booked-ladies" // Booked for Female
5801	};
5802	var seatStatusClass = {
5803		"AM": "seat-select-visibilitys seat-available-gents", // Available male
5804		"AF": "seat-select-visibilitys seat-available-ladies", // Available female
5805		"AY": "seat-select-visibilitys seat-available-you", // Allocated for You
5806		"AL": "seat-select-visibilitys", // Available
5807		"BO": "seat-booked", // Booked
5808		"BM": "seat-booked-gents", // Booked for Male
5809		"BF": "seat-booked-ladies", // Booked for Female
5810		"AO": "seat-booked-gents", // Booked
5811		"UK": "seat-booked-gents", // Booked
5812		"TBL": "seat-booked-gents", // Blocked
5813		"PBL": "seat-booked-gents", // Booked
5814		"BL": "seat-booked-gents", // Blocked
5815		"SDBL": "seat-blocked-socialdis" // Blocked
5816	};
5817
5818	var seatType = {
5819		// seater
5820		"SS": { name: "Semi Sleeper", class: "seat-lay-searchs", category: "SEATER" },
5821		"SSS": { name: "Single Semi Sleeper", class: "seat-lay-searchs", category: "SEATER" },
5822		"ST": { name: "Seater", class: "seat-lay-searchs", category: "SEATER" },
5823		"SST": { name: "Single Seater", class: "seat-lay-searchs", category: "SEATER" },
5824		"PB": { name: "Pushback", class: "seat-lay-searchs", category: "SEATER" },
5825		"PTY": { name: "Pantry", class: "seat-lay-searchs", category: "PANTRY" },
5826		"WST": { name: "Window Seat", class: "seat-lay-searchs", category: "SEATER" },
5827		"BKST": { name: "Back Seat", class: "seat-lay-searchs", category: "SEATER" },
5828		"PBST": { name: "Pushback Seat", class: "seat-lay-searchs", category: "SEATER" },
5829
5830		// sleeper
5831		"SL": { name: "Sleeper", class: "sleeper-lay-searchs", category: "SLEEPER" },
5832		"USL": { name: "Upper Sleeper", class: "sleeper-lay-searchs", category: "SLEEPER" },
5833		"LSL": { name: "Lower Sleeper", class: "sleeper-lay-searchs", category: "SLEEPER" },
5834		"SUSL": { name: "Single Upper Sleeper", class: "sleeper-lay-searchs", category: "SLEEPER" },
5835		"SLSL": { name: "Single Lower Sleeper", class: "sleeper-lay-searchs", category: "SLEEPER" },
5836		"WSL": { name: "Window Sleeper", class: "sleeper-lay-searchs", category: "SLEEPER" },
5837
5838		// restroom
5839		"RRM": { name: "Rest Room", class: "restroom-sleeper-filer", category: "RESTROOM" },
5840		"FRS": { name: "Free Space", class: "restroom-sleeper-filer", category: "EMPTY" },
5841		"EME": { name: "Emergency Exit", class: "emergency-exit-filer", category: "EMERGENCYEXIT" },
5842	};
5843
5844	// shorthand
5845	var layer = obj.layer;
5846	var matrix = obj.matrix;
5847	var seatStatus = obj.seatStatus;
5848
5849	// flags
5850	var isSleeperSeatFound = false;
5851	var isSeaterFound = false;
5852
5853	// return array
5854	var allSeatNodes = [];
5855	var emptySeatNodes = [];
5856
5857	// construct seats row and col wise
5858	for (var row = matrix.rowmin; row <= matrix.rowmax; row++) {
5859		var rowSeatFound = false;
5860		var hasDefinedSeats = false; // Track if the row has any defined seats
5861		var lastDefinedCol = matrix.colmin - 1; // Track the last column with a defined seat
5862
5863		var definedSeatsInRow = [];
5864		for (var col = matrix.colmin; col <= matrix.colmax; col++) {
5865			var pos = '' + layer + row + col;
5866			if (seatStatus[pos]) {
5867				definedSeatsInRow.push(col);
5868			}
5869		}
5870		for (var col = matrix.colmin; col <= matrix.colmax; col++) {
5871
5872			// position
5873			var pos = '' + layer + row + col;
5874
5875			// position seat details
5876			var seatinfo = seatStatus[pos];
5877
5878			// seat div
5879			var $seat = $('<div/>');
5880
5881			// empty seat
5882			if (!seatinfo) {
5883
5884				if (rowSeatFound && isSleeperSeatFound) {
5885					var isBetweenDefinedSeats = false;
5886					for (var i = 0; i < definedSeatsInRow.length - 1; i++) {
5887						if (col > definedSeatsInRow[i] && col < definedSeatsInRow[i + 1]) {
5888							isBetweenDefinedSeats = true;
5889							break;
5890						}
5891					}
5892					if (!isBetweenDefinedSeats) {
5893						continue;
5894					}
5895				}
5896
5897				$seat.html('&nbsp;');
5898
5899				emptySeatNodes.push($seat.get(0));
5900				allSeatNodes.push($seat.get(0));
5901				continue;
5902			}
5903			hasDefinedSeats = true;
5904			lastDefinedCol = col;
5905
5906			// emergency exit (mini busmap)
5907			if (seatinfo.seatType == 'EME') {
5908				$seat
5909					.addClass('emergency-exit-filer')
5910					.attr('data-code', seatinfo.code)
5911					.attr('data-discount', seatinfo.discountFare)
5912					.html($('<div/>').attr('title', seatType[seatinfo.seatType].name));
5913
5914				rowSeatFound = true;
5915				allSeatNodes.push($seat.get(0));
5916				continue;
5917			}
5918
5919			$eme = '';
5920
5921			if (seatinfo.emergencyExitDoor !== 'NA') {
5922				$eme = '<span class="emergengcy-' + seatinfo.emergencyExitDoor + '-filer"></span>';
5923			}
5924
5925			var seatTypeClass = seatType[seatinfo.seatType] ? seatType[seatinfo.seatType].class : null;
5926
5927			$seat.addClass(seatTypeClass)
5928				.addClass(seatStatusClass[seatinfo.status])
5929				.addClass(seatGenderClass[seatinfo.genderstatus.code])
5930				.attr('data-code', seatinfo.code)
5931				.attr('data-fare', seatinfo.fare)
5932				.attr('data-discount', seatinfo.discountFare)
5933				.attr('data-service', seatinfo.serviceTax)
5934				.html($eme) // seat name
5935
5936			if (seatType[seatinfo.seatType]) {
5937				if (seatType[seatinfo.seatType].category === 'SLEEPER') isSleeperSeatFound = true;
5938				if (seatType[seatinfo.seatType].category === 'SEATER') isSeaterFound = true;
5939			}
5940
5941			if (seatinfo.status === "BO" && seatinfo.genderstatus.code === "M") {
5942				$seat.addClass("seat-booked-gents");
5943			} else if (seatinfo.status === "BO" && seatinfo.genderstatus.code === "F") {
5944				$seat.addClass("seat-booked-ladies");
5945			}
5946
5947			if (seatinfo.status === "BL" && seatinfo.genderstatus.code === "M") {
5948				$seat.addClass("seat-booked-gents");
5949			} else if (seatinfo.status === "BL" && seatinfo.genderstatus.code === "F") {
5950				$seat.removeClass("seat-booked-gents");
5951				$seat.addClass("seat-booked-ladies");
5952			}
5953			
5954			// for quota seats
5955			if ((seatinfo.status === "QS") && seatinfo.genderstatus.code === "M") {
5956				$seat.addClass("seat-booked-gents");
5957			} else if ((seatinfo.status === "QS") && seatinfo.genderstatus.code === "F") {
5958				$seat.removeClass("seat-booked-gents");
5959				$seat.addClass("seat-booked-ladies");
5960			}
5961
5962			// vertical layout
5963			if (seatinfo.orientation == 1) {
5964				$seat.addClass('vertical-seat');
5965			}
5966
5967			// rest Room
5968			if (seatinfo.seatType == 'RRM') {
5969				var $restroom = $('<div/>').addClass('').attr('title', seatType[seatinfo.seatType].name);
5970				$seat.removeClass(seatStatusClass[seatinfo.status]).html($restroom);
5971			}
5972
5973			// free space
5974			if (seatinfo.seatType == 'FRS') {
5975				$seat.removeClass(seatStatusClass[seatinfo.status]).empty();
5976			}
5977
5978			rowSeatFound = true;
5979			allSeatNodes.push($seat.get(0));
5980		}
5981
5982		var $clearfix = $('<div/>').addClass('clearfix');
5983		allSeatNodes.push($clearfix.get(0));
5984	}
5985
5986	if (isSeaterFound) {
5987		$(emptySeatNodes).addClass('seat-lay-searchs');
5988	} else if (isSleeperSeatFound) {
5989		$(emptySeatNodes).addClass('sleeper-lay-searchs');
5990	}
5991
5992	return allSeatNodes;
5993}
5994
5995
5996function setCookie(name, value, days) {
5997	const d = new Date();
5998	d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000)); // Set expiration time
5999	const expires = "expires=" + d.toUTCString();
6000	document.cookie = name + "=" + value + ";" + expires + ";path=/";
6001}
6002
6003function getCookie(name) {
6004	const nameEQ = name + "=";
6005	const ca = document.cookie.split(';');
6006	for (let i = 0; i < ca.length; i++) {
6007		let c = ca[i];
6008		while (c.charAt(0) === ' ') c = c.substring(1, c.length);
6009		if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
6010	}
6011	return null;
6012}
6013
6014function generateRandomNumber() {
6015	const numbers = [1, 2, 3]; // Only 3 numbers
6016	const randomIndex = Math.floor(Math.random() * numbers.length);
6017	return numbers[randomIndex];
6018}
6019
6020function getofferDesignNumber() {
6021	const lastSetDate = getCookie('lastSetDate');
6022	const currentDate = new Date();
6023	const currentTime = currentDate.getTime();
6024
6025	const randomNumber = generateRandomNumber();
6026
6027	if (!lastSetDate) {
6028		setCookie('offerdesignNumber', randomNumber, 2);  // Expire in 2 days
6029		setCookie('lastSetDate', currentDate.toISOString(), 2);  // Expire in 2 days
6030		return randomNumber;
6031	}
6032
6033	const previousDate = new Date(lastSetDate);
6034	const timeDifference = currentTime - previousDate.getTime();
6035	const daysPassed = Math.floor(timeDifference / (1000 * 3600 * 24));
6036
6037	const designCycle = 3;
6038
6039	const currentofferDesignNumber = (Math.floor(daysPassed / 2) % designCycle) + 1;
6040
6041	if (currentofferDesignNumber !== parseInt(getCookie('offerdesignNumber'))) {
6042		setCookie('offerdesignNumber', currentofferDesignNumber, 2);  // Expire in 2 days
6043		setCookie('lastSetDate', currentDate.toISOString(), 2);  // Expire in 2 days
6044	}
6045
6046	return currentofferDesignNumber;
6047}
6048
6049function initImageSlider($slider) {
6050	const $slides = $slider.find('.slick-slide');
6051	let currentIndex = 0;
6052
6053	$slides.each((index, slide) => {
6054		$(slide).css('transform', `translateX(${100 * index}%)`).show();
6055	});
6056
6057	function updateSlides() {
6058		$slides.each((index, slide) => {
6059			const offset = 100 * (index - currentIndex);
6060			$(slide).css('transform', `translateX(${offset}%)`);
6061		});
6062		updateArrowVisibility();
6063	}
6064
6065	function updateArrowVisibility() {
6066		$('.slick-prev').toggle(currentIndex > 0);
6067		$('.slick-next').toggle(currentIndex < $slides.length - 1);
6068	}
6069	$('.slick-prev').show();
6070	$('.slick-next').show();
6071	$('.slick-prev').off('click').on('click', function () {
6072		if (currentIndex > 0) {
6073			currentIndex--;
6074			updateSlides();
6075		}
6076	});
6077
6078	$('.slick-next').off('click').on('click', function () {
6079		if (currentIndex < $slides.length - 1) {
6080			currentIndex++;
6081			updateSlides();
6082		}
6083	});
6084	updateSlides();
6085}
6086
6087function droppingChange() {
6088	if ($('input[name="boarding-point"]:checked').val() && $('input[name="dropping-point"]:checked').val()) {
6089		$(".bpdpSelecting").addClass("d-none");
6090		$(".bpdpHeight").addClass("d-none");
6091
6092		$(".boardingPointCard").removeClass("d-none");
6093		$(".droppingPointCard").removeClass("d-none");
6094		return;
6095	}
6096
6097	$(".boarding-point-title").removeClass("boardingdroppingbold");
6098	$(".dropping-point-title").addClass("boardingdroppingbold");
6099
6100	$(".boarding-design").addClass("d-none");
6101	$(".dropping-design").removeClass("d-none");
6102
6103	$(".boarding-point-list-card").addClass("d-none");
6104	$(".dropping-point-list-card").removeClass("d-none");
6105}
6106
6107function boardingDroppingSelected() {
6108
6109	if (regConnTrip.SEQ_STATUS == 'DROPPING') {
6110		return;
6111	}
6112
6113	if (!$('input[name="boarding-point"]:checked').val()) {
6114		$(".dropping-point-title").removeClass("boardingdroppingbold");
6115		$(".boarding-design, .boarding-point-list-card").removeClass("d-none");
6116		$(".boarding-point-title").addClass("boardingdroppingbold");
6117		$(".dropping-design, .dropping-point-list-card").addClass("d-none");
6118		return;
6119	}
6120
6121	$(".bpdpSelecting").addClass("d-none");
6122	$(".bpdpHeight").addClass("d-none");
6123
6124	$(".boardingPointCard").removeClass("d-none");
6125	$(".droppingPointCard").removeClass("d-none");
6126}
6127
6128function showBoardingDropping(ele) {
6129	$(".boardingPointCard").addClass("d-none");
6130	$(".droppingPointCard").addClass("d-none");
6131
6132	if (ele == 'board') {
6133		$(".dropping-point-title").removeClass("boardingdroppingbold");
6134		$(".boarding-design, .boarding-point-list-card").removeClass("d-none");
6135		$(".boarding-point-title").addClass("boardingdroppingbold");
6136		$(".dropping-design, .dropping-point-list-card").addClass("d-none");
6137	} else {
6138		$(".boarding-point-title").removeClass("boardingdroppingbold");
6139		$(".dropping-design, .dropping-point-list-card").removeClass("d-none");
6140		$(".dropping-point-title").addClass("boardingdroppingbold");
6141		$(".boarding-design, .boarding-point-list-card").addClass("d-none");
6142	}
6143
6144	$(".bpdpHeight, .bpdpSelecting").removeClass("d-none");
6145}
6146
6147function zeroSeat() {
6148	$(".boardingPointCard").addClass("d-none");
6149	$(".droppingPointCard").addClass("d-none");
6150	$("#booking-card").addClass("d-none");
6151
6152	if (isConnecting) {
6153		$(".connecting-content").removeClass("d-none");
6154		$(".bpdpHeight").addClass("d-none");
6155	}
6156
6157	$(".select-info-card").removeClass("d-none");
6158	if (!isConnecting) {
6159		$(".bpdpHeight, .bpdpSelecting").removeClass("d-none");
6160	}
6161
6162	$('input[name="boarding-point"]').prop('checked', false);
6163	$('input[name="dropping-point"]').prop('checked', false);
6164
6165	$(".boarding-point-title").addClass("boardingdroppingbold");
6166	$(".boarding-design, .boarding-point-list-card").removeClass("d-none");
6167
6168	$(".dropping-point-title").removeClass("boardingdroppingbold");
6169	$(".dropping-design, .dropping-point-list-card").addClass("d-none");
6170}
6171
6172function seatWithBoardingDropping() {
6173	$(".bpdpSelecting").addClass("d-none");
6174}
6175
6176function boardingTab() {
6177	// if (!$('input[name="dropping-point"]:checked').val()){
6178	// 	return;
6179	// }
6180	$(".boarding-point-title").addClass("boardingdroppingbold");
6181	$(".dropping-point-title").removeClass("boardingdroppingbold");
6182	$(".boarding-design, .boarding-point-list-card").removeClass("d-none");
6183	$(".dropping-design, .dropping-point-list-card").addClass("d-none");
6184}
6185
6186function droppingTab() {
6187	// if (!$('input[name="boarding-point"]:checked').val()){
6188	// 	return;
6189	// }
6190	$(".dropping-point-title").addClass("boardingdroppingbold");
6191	$(".dropping-design, .dropping-point-list-card").removeClass("d-none");
6192	$(".boarding-point-title").removeClass("boardingdroppingbold");
6193	$(".boarding-design, .boarding-point-list-card").addClass("d-none");
6194}
6195
6196function generateSharingLink(tripdetails) {
6197	if (!tripdetails || !tripdetails.fromStation || !tripdetails.toStation) {
6198		return;
6199	}
6200
6201	var data = {};
6202	data.from = tripdetails.fromStation.code;
6203	data.to = tripdetails.toStation.code;
6204	data.fS = tripdetails.fromStation.name;
6205	data.tS = tripdetails.toStation.name;
6206	data.date = tripdetails.travelDate || (tripdetails.fromStation.dateTime
6207		? moment(tripdetails.fromStation.dateTime).format('YYYY-MM-DD')
6208		: '');
6209	data.code = tripdetails.tripCode;
6210
6211	$('#retry-payment-btn')
6212		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...')
6213		.attr('disabled', true);
6214
6215	$.ajax({
6216		type: 'POST',
6217		url: 'search/sharing-link',
6218		data: data,
6219		dataType: 'json',
6220		success: function (res) {
6221			const tempInput = document.createElement('input');
6222			tempInput.value = res.data.url;
6223			document.body.appendChild(tempInput);
6224			tempInput.select();
6225			document.execCommand('copy');
6226			document.body.removeChild(tempInput);
6227
6228			$('#COPYConntooltip-' + tripdetails.tripCode)
6229				.fadeIn(300)
6230				.delay(2000)
6231				.fadeOut(300);
6232
6233			$('#COPYtooltip-' + tripdetails.tripCode)
6234				.fadeIn(300)
6235				.delay(2000)
6236				.fadeOut(300);
6237		}
6238	});
6239}
6240
6241function openSharedTrip() {
6242	const tripCode = $('#shared-trip-code').val().trim();
6243	if (!tripCode) return;
6244
6245	$('#trip-' + tripCode).find('.tripinfo-container').trigger('click');
6246}
6247
6248function trackEvent(eventCategory, eventAction, eventLabel) {
6249	if (typeof gtag === "function") {
6250		gtag('event', eventAction, {
6251			'event_category': eventCategory,
6252			'event_label': eventLabel
6253		});
6254	}
6255}
6256
6257function toggleAllPassInfoSeat() {
6258	var state = $('#all-pass-details').is(':checked');
6259
6260	$('#onward-trip, #return-trip')
6261		.find('.pass-info:not(:first)')
6262		.find('.pass-name, .pass-age, .seat-name')
6263		.toggleClass('d-none', !state);
6264}
6265
6266function forLoadingHtml() {
6267	$('.loading').addClass('d-none');
6268	$('.sorting-card, .conn-total-trip-count-div, .trip-panel').removeClass('d-none');
6269}
6270
6271function removeNumber() {
6272	event.preventDefault();
6273
6274	$('#remove-user-help').html('');
6275	var data = {};
6276	data.mobileNumber = $('#removeMobileNumber').val();
6277
6278	if (data.mobileNumber == '' || data.mobileNumber.length < 10) {
6279		$('#removeMobileNumber').addClass('is-invalid');
6280		$('#remove-user-help').danger({
6281			message: 'Invalid mobile number',
6282			delay: 5000
6283		}).on('detach', function () {
6284			$('#remove-user-form .is-invalid').removeClass('is-invalid');
6285		});
6286		return;
6287	}
6288
6289	$('.remove-user-btn').prop('disabled', true).html(
6290		'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> ' +
6291		'Deleting...'
6292	);
6293	$('#removeMobileNumber').prop('disabled', true);
6294
6295	$.ajax({
6296		type: 'POST',
6297		url: 'app/remove-user',
6298		data: data,
6299		dataType: 'json',
6300		success: function (result) {
6301			$('.remove-user-btn').prop('disabled', false).html('Delete');
6302			$('#removeMobileNumber').prop('disabled', false).removeClass('is-invalid');
6303			if (result.status == 1) {
6304				$('#remove-user-help').success('Your Account has been removed successfully');
6305			} else {
6306				$('#remove-user-help').danger({
6307					message: result.errorDesc,
6308					delay: 100000
6309				});
6310			}
6311		}
6312	});
6313}
6314
6315// for connevting trips
6316function listViewConnMaster(data, result, $tripContent) {
6317	var id = 1;
6318	$tripContent;
6319	var minConnFare = 0;
6320
6321	$.each(result, function (cbkey, cbval) {
6322		let currencySymbol = cbval.currencySymbol;
6323		var tripListConn = $($('#template-bus-list-conn-master').html());
6324
6325		tripListConn.attr({
6326			'id': `cmTrip-${cbval.tripCode}`,
6327			'data-trip-code': cbval.tripCode,
6328			'data-schedule-code-master': cbval.scheduleCode,
6329			'data-available-seat-count': cbval.availableSeatCount,
6330			'data-total-sequence': cbval.connPoints.length - 1,
6331			'data-departure': moment(cbval.fromStation.dateTime).valueOf(),
6332			'data-duriation': moment.duration(moment(cbval.toStation.dateTime, "YYYY-MM-DD HH:mm:ss").diff(moment(cbval.fromStation.dateTime, "YYYY-MM-DD HH:mm:ss"))),
6333			'data-availability': cbval.availableSeatCount,
6334			'data-from-sta-code': cbval.fromStation.code,
6335			'data-from-sta-name': cbval.fromStation.name,
6336			'data-conn-t-stations': cbval.connPoints.map(p => p.name).join(',')
6337			// 'data-fare': minFare//-- need to fix it
6338		});
6339
6340		let conn_trip_info_cnt = $(`<div class="d-flex justify-content-between _mx-10 _my-10"></div>`);
6341		const connPointsLen = cbval.connPoints.length;
6342		let conn_trip_info_temp = '';
6343		cbval.connPoints.map((p, i) => {
6344
6345			if (i === 0) {// boarding station
6346				conn_trip_info_temp +=
6347					`<div class="conn-brdSta _mt-10">
6348                        <div class="d-flex fd-c align-items-center">
6349                            <div class="_my-10"><img src="assets/images/search/boarding-location.svg" width="24px" class="_ml-5" />
6349<span class="bold _px-5">${p.name}</span></div>
6350                            <div class="_fs-12">${i == 0 ? '(' + formatDateTime(p.dateTime, 'ddd-mon-time') + ')' : ''}</div>
6351                        </div>
6352                    </div>                   
6353                    <div class="d-flex align-items-center fd-c ">
6354                        <div class=" _px-9  _py-1 "><img src="assets/images/search/night-time.svg" width="15px" height="15px"  class="_ml-5" ><span class="_fs-10">${cbval.connPoints[i].travelTime} hrs</span></div>
6355                        <div class="conn-line"></div>
6356                    </div>`;
6357
6358			} else if (i < (connPointsLen - 1)) { // connection station
6359				let waitingTime = cbval.waitingTime[`${p.fromStation}-${p.toStation}`].map(wt => wt.waitTime);
6360				conn_trip_info_temp +=
6361					`<div class=_mt-10>
6362                        <div class="d-flex fd-c align-items-center">
6363                            <div class="_my-10"><img src="assets/images/search/swap-bus.svg" width="24px"  class="_ml-5"  /><span class="bold _px-5">${p.name}</span></div>
6364                            <div class="_fs-12" ><img src="assets/images/search/waiting-time.svg" width="24px"  class="_ml-5"  /><span class="bold color-primary _px-5">${waitingTime[0]}</span></div>
6365                        </div>
6366                    </div>
6367                    <div class="d-flex align-items-center fd-c">
6368                        <div class=""><img  src="assets/images/search/night-time.svg" width="15px" height="15px" class="_ml-5"><span class="_fs-10">${cbval.connPoints[i].travelTime} hrs</span></div>
6369                         <div class="conn-line" ></div>
6370                    </div>`;
6371
6372			} else {// dropping station
6373				conn_trip_info_temp +=
6374					`<div class=_mt-10>
6375                        <div class="d-flex fd-c align-items-end">
6376                            <div class="_my-10"><img src="assets/images/search/dropping-location.svg" width="24px" class="_ml-5" /><span class="bold _px-5">${p.name}</span></div>
6377                             <div class="_fs-12">${i == connPointsLen - 1 ? '(' + formatDateTime(p.dateTime, 'ddd-mon-time') + ')' : ''}</div>
6378                        </div>
6379                    </div>`;
6380
6381			}
6382
6383		})
6384		conn_trip_info_cnt.html(conn_trip_info_temp);// add temp to conn_trip_info_cnt
6385
6386
6387		tripListConn.find('.conn_trip_info').html(conn_trip_info_cnt);//  add conn_trip_info_cnt to  conn_trip_info
6388
6389		// Set fromStation and toStation names in the HTML
6390		tripListConn.find('.bp-sta').html(cbval.fromStation.name);
6391		tripListConn.find('.dp-sta').html(cbval.toStation.name);
6392
6393		// Loop through each connection point (connPoints) and create the list items
6394		for (let index = 0, stI = 0, endI = (connPointsLen - 1); index < cbval.connPoints.length; index++) {
6395			let $li = $(`
6396				
6397                <div id="li_${cbval.tripCode}_${index}" class="closestdiv col-md">
6398					<div class="sequence-card">
6399						<input type="radio" hidden>
6400						<div class="station-head"
6401							title="${cbval.connPoints[index].name}"
6402                                style="${cbval.connPoints[index].name.length > 15 ? 'white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: inline-block; max-width: 115px;' : ''}"
6403                            >${cbval.connPoints[index].name}
6404						</div>
6405						<div class="borderofStation"><img src="assets/images/search/notselectedsequence.svg"></div>
6406					</div>
6407                </div>
6408            `);
6409
6410			// Set attributes and styles for the list item
6411			$li.attr({
6412				'data-title': cbval.connPoints[index].title,
6413				'data-station-name': cbval.connPoints[index].name,
6414				'data-tripcount': cbval.connPoints[index].tripCount,
6415				'data-index': index,
6416			});
6417
6418			// Radio button setup
6419			let $radio = $li.find('input[type="radio"]');
6420			$radio.attr({
6421				name: `station_${cbval.tripCode}`,
6422				value: cbval.connPoints[index].code,
6423				'data-fromStation': cbval.connPoints[index].code,
6424				'data-tripSequence': index
6425			})
6426
6427			// set toStation value to it additionally except last radio
6428			if (index !== endI) {
6429				$li.attr({// set values for automation
6430					'data-from-station': cbval.connPoints[index].fromStation,
6431					'data-from-station-name': cbval.connPoints[index].fromStationName,
6432					'data-bp-point': cbval.connPoints[index].bpPoint,
6433					'data-bp-point-name': cbval.connPoints[index].bpPointName,
6434					'data-to-station': cbval.connPoints[index].toStation,
6435					'data-to-station-name': cbval.connPoints[index].toStationName,
6436					'data-dp-point': cbval.connPoints[index].dpPoint,
6437					'data-dp-point-name': cbval.connPoints[index].dpPointName,
6438				})
6439				$radio.attr('data-toStation', cbval.connPoints[index + 1].code)
6440			}
6441
6442
6443			// Set the default radio button to be checked (first station)
6444			if (index === stI) {
6445				$radio.prop('checked', true);
6446			}
6447
6448			// Hide the radio button for the last station and remove border
6449			if (index === endI) {
6450				$radio.addClass('d-none');
6451				$li.css({
6452					'border-bottom': 'none',
6453				});
6454
6455				$li.find('.station-info').css({
6456					'color': "green"
6457				})
6458
6459				$li.find('.stationCollapseCtrlP').removeClass('point_cur');
6460				$li.find('.stationCollapseCtrlC').addClass('d-none');
6461			}
6462
6463			// Accordion parent/master control (label + radio button)
6464			$li.find('.stationCollapseCtrlP').attr({
6465				'data-target': `#collapse_${cbval.tripCode}_${index}`,
6466				'aria-controls': `collapse_${cbval.tripCode}_${index}`
6467			}).css({
6468				'flex': '1 0 auto'
6469			})
6470
6471			// Accordion child/slave control (collapse section)
6472			$li.find('.stationCollapseCtrlC').attr({
6473				'id': `collapse_${cbval.tripCode}_${index}`,
6474				'aria-labelledby': `li_${cbval.tripCode}_${index}`,
6475			}).css({
6476				// 'border': '1px solid #b7b7b7',
6477				// 'border-radius': '5px',
6478				// 'margin': '7px 0px',
6479				// 'background': '#fff',
6480				// 'height': 'auto',
6481			});
6482
6483			// Append the list item to the accordion container
6484			tripListConn.find('#conn-trip-pts-accordion').append($li);
6485		}
6486
6487		// Update the connection trip points text and available seats master card details
6488		tripListConn.find('.conn-txt').html(cbval.noOfConnPoints + ' Connections');
6489		tripListConn.find('.seat-avail').html(cbval.availableSeatCount > 0 ? `<span class="bold">${cbval.availableSeatCount}</span>&nbsp;Seats Available` : 'Seats not Available');
6490
6491		// Show discount availability if it exists
6492		if (cbval.discountAvail !== null || cbval.discountAvail === '') {
6493			tripListConn.find('.dis-avail').html(`Flat <span class="hl-off-percent">${cbval.discountAvail} % </span><span class="hl-off">OFF</span>`).closest('.dis-cont').removeClass('d-none');
6494		}
6495
6496		// minConnFare += Math.min.apply(null, cbval.seatFare);
6497
6498		// const minConnFare = cbval.seatFare.reduce((a, b) => a + b, 0); // total fare in master trip card
6499		const minConnFare = Math.min(...cbval.seatFare);
6500
6501		tripListConn.find('.fare').html(currencySymbol + minConnFare);
6502
6503		if (cbval.seatFare.length > 1)
6504			tripListConn.find('.starts-from').removeClass('d-none');
6505
6506		// Generate and append the trip cards
6507		// const tripListArray = listViewRegular(data, res, cbval.trip);// regular trip card design 
6508		const tripListArray = listViewConnTrip(data, result, cbval.trip);// new regular trip card design for connecting trips
6509
6510		tripListArray.forEach(tripList => {
6511			tripList.removeClass('row').find('.buslist-card').css({
6512				'box-shadow': '0px 1px 1px 1px #00000047',
6513				'border': '1px solid #efe3e34d'
6514			}).closest('.trip-infos').addClass('d-none');
6515
6516
6517			tripListConn.find('.conn-trips').append(tripList);
6518		});
6519
6520		// tripListConn.find('.info-cont').addClass('hide')
6521
6522		// Append the generated trip list container to the main container
6523		$tripContent.append(tripListConn);
6524
6525		// Events
6526		$('.trip-filter-panel').on('change', function (e) {
6527			return;
6528			applyTripListFilter(cbval);
6529		});
6530	});
6531
6532	// $tripContent.append(html);
6533
6534	$(document).find('.c-m-trip-infos').find('.info-cont').addClass('d-none')
6535	// bind on clik functionality for connecting trip
6536
6537	$(document).on('click', '.c-m-trip-infos', function (e, r) {
6538		const $this = $(this);
6539
6540		//  retrun it info-cont element
6541		if ($this.find('.info-cont').has(e.target).length > 0) return;
6542		if ($(e.target).is('.share-link-conn')) {
6543
6544			$this.find('.COPYConntooltip').attr('id', 'COPYConntooltip-' + $this.data('tripCode'));
6545
6546			const connTrips = Array.isArray(result) ? result : Object.values(result || {});
6547			const trip = connTrips.find(t => t.tripCode === $this.data('tripCode'));
6548			if (!trip) {
6549				return;
6550			}
6551			generateSharingLink(trip);
6552			trackEvent('Share Trip', 'click', 'Share Link');
6553			return;
6554		}
6555
6556		// reset booking info if connecting master trip is chaged
6557		resetConnectingLogicDatas();
6558
6559		if (!triggerConnEle.is($(this))) {
6560			triggerConnEle = $(this);
6561		}
6562
6563		$('.c-m-trip-infos').not($this).find('.info-cont').addClass('d-none');
6564
6565		// $this.find('.info-cont').toggleClass('hide');
6566		if ($this.find('.info-cont').hasClass('d-none')) {
6567			$this.find('.info-cont').removeClass('d-none');
6568			$this.find('.c-v-btn').removeClass('c-h-btn').addClass('c-hide-btn').html('Hide Buses <i class="fa fa-chevron-up _ml-5">');
6569		} else {
6570			$this.find('.info-cont').addClass('d-none');
6571			$this.find('.c-v-btn').addClass('c-h-btn').removeClass('c-hide-btn').html('View Buses <i class="fa fa-chevron-down _ml-5">');
6572		}
6573
6574		$('html, body').animate({
6575			scrollTop: $this.offset().top - 125
6576		}, 100);
6577	});
6578
6579	// bind change event for radio button to show respective bus card for station
6580	$(document).on('change', 'input[name^="station_"]', function () {
6581		const $this = $(this);
6582		const ckdSta = $this.val();
6583		const $li = $this.closest('.closestdiv');
6584		const title = $li.data('title');
6585		const tripCount = $li.data('tripcount');
6586		const $tripContainer = $this.closest('.c-m-trip-infos');
6587
6588		const totalSeq = $tripContainer.data('total-sequence');
6589
6590		let $title = `<div><b>${title}&nbsp;(${tripCount}</b> ${tripCount > 1 ? 'Buses found' : 'Bus found'} <b>)</b></div>`
6591		$tripContainer.find('.conn-title').html($title);
6592		$tripContainer.find('.c-ticket-row').each(function () {
6593			let $this = $(this);
6594			if ($this.data('from') === ckdSta) {
6595				$this.closest('.c-trip-infos').removeClass('d-none');
6596			} else {
6597				$this.closest('.c-trip-infos').addClass('d-none');
6598			}
6599		});
6600		//  update the sequence of trip based on value seleced 
6601		regConnTrip.CURRENT_SEQ = Number($this.attr('data-tripSequence'));// typecase
6602		regConnTrip.SEQ_STATUS = (regConnTrip.CURRENT_SEQ === 0) ? "BOARDING" : (regConnTrip.CURRENT_SEQ !== regConnTrip.TOTAL_SEQ) ? 'CONNECTING' : 'DROPPING';
6603
6604		if (regConnTrip.SEQ_STATUS == 'BOARDING') {
6605			$li.addClass('blue-checked');
6606		}
6607		if (regConnTrip.SEQ_STATUS == 'CONNECTING') {
6608			$li.addClass('blue-checked');
6609		}
6610		if (regConnTrip.SEQ_STATUS == 'DROPPING') {
6611			$li.removeClass('middle-checked');
6612			$li.addClass('blue-checked');
6613		}
6614
6615		$('.closestdiv').each(function () {
6616			const $currentDiv = $(this);
6617			const currentSeq = Number($currentDiv.data('index'));
6618
6619			if (currentSeq <= regConnTrip.CURRENT_SEQ) {
6620				$currentDiv.addClass('blue-checked');
6621			} else {
6622				$currentDiv.removeClass('blue-checked');
6623			}
6624		});
6625	});
6626
6627
6628	$(document).on('click', '.sequence-card', function () {
6629		const $radio = $(this).find('input[type="radio"]');
6630		const isLastCard = $(this).closest('#conn-trip-pts-accordion').children('.closestdiv').last()[0] === $(this).closest('.closestdiv')[0];
6631		if (isLastCard) {
6632			return;
6633		}
6634		if (!$radio.prop('checked')) {
6635			$radio.prop('checked', true).trigger('change');
6636		}
6637	});
6638
6639	// Trigger the change event for the initially for first radio button as default
6640	setTimeout(() => {
6641		$('.c-m-trip-infos').each(function () {
6642			$(this).find('input[name^="station_"]:first').prop('checked', true).trigger('change');
6643			handleRadioClick($(this));
6644		});
6645	}, 100);
6646}
6647
6648function handleRadioClick($radio) {
6649	var $closestDiv = $radio.closest('.closestdiv');
6650	if ($radio.is(':checked')) {
6651		$closestDiv.addClass('checked');
6652	} else {
6653		$closestDiv.removeClass('checked');
6654	}
6655}
6656
6657// regular trip card  list-view rendering
6658function listViewConnTrip(data, res, resData) {
6659
6660	return $.map(resData, function (bval, bkey) {
6661
6662		currencySymbol = bval.currencySymbol;
6663
6664		// if (trip.tripStatus.code !== 'TPO' ) {
6665		// 	return;
6666		// }
6667
6668		var template = $($('#template-bus-list-conn').html());
6669		var $tpl = $(template);
6670
6671
6672		var onwardsTag = ' <small>Starts From</small>';
6673		var perSeat = 'Per Seat from';
6674		// stage fare
6675		var stageFares = [];
6676		var discountFares = [];
6677		$.each(bval.fare || [], function (i, stage) {
6678			if (stage.availableSeatCount > 0) {
6679				stageFares.push(stage.fare);
6680			} else {
6681				stageFares.push(stage.fare);
6682			}
6683			discountFares.push(stage.discountFare || 0);
6684		});
6685		var minFare = Math.min.apply(null, stageFares);
6686		var minDiscountFare = Math.min.apply(null, discountFares);
6687
6688		var offer = parseInt(minDiscountFare / minFare * 100);
6689
6690		// amenities
6691		var amenities = [];
6692		$.each(bval.amenities || [], function (i, amenity) {
6693			amenities.push('<span class="ezeeicon-amenities" title="' + amenity.name + '" data-toggle="tooltip" data-amenities=' + amenity.code + '></span>');
6694		});
6695
6696		// via routes
6697		var viaStations = [];
6698		var viaStationslide = [];
6699		$.each(bval.viaStations || [], function (i, via) {
6700			viaStations.push(via.name);
6701			if (via.name.length > 15) {
6702				let viaroutecutstring = via.name.substring(0, 15) + '...';
6703				viaStationslide.push(viaroutecutstring);
6704			} else {
6705				viaStationslide.push(via.name);
6706			}
6707		});
6708
6709		// badges
6710		var badges = [];
6711		if (new String(bval.busCategoryCode).split('|').includes('CC01')) {
6712			badges.push('<span class="badge badge-primary" title="Air Conditioned Bus">AC</span>');
6713		}
6714
6715		// templating
6716		$tpl.attr('id', 'trip-' + bval.tripCode);
6717
6718		// $tpl.find('.trip-bustype').html(bval.schedule.displayName.length > 15 ? bval.schedule.displayName : bval.bus.busType);
6719		$tpl.find('.trip-badges').html(badges.join(''));
6720		$tpl.find('.trip-offer-amount').html(minDiscountFare)
6721		$tpl.find('.trip-offer-ribbon').toggleClass('d-none', !minDiscountFare);
6722		$tpl.find('.c-ticket-row').attr('data-from', bval.fromStation.code).attr('data-to', bval.toStation.code);
6723
6724		$tpl.find('.trip-offer').toggleClass('d-none', !minDiscountFare);
6725		$tpl.find('.hl-off-percent').html(offer + '%');
6726
6727		offerNumber = getofferDesignNumber();
6728
6729		if (offerNumber == 1) {
6730			$tpl.find('.trip-offer').addClass('offer-1');
6731			$tpl.find('.offer-icon').html('<img src="assets/images/search/offer-symbol-1.svg" alt="Rating User icon" class="">');
6732			if (minDiscountFare > 0)
6733				$tpl.find('.fare-margin').removeClass('fare-margin');
6734		} else if (offerNumber == 2) {
6735			$tpl.find('.trip-offer').addClass('offer-2');
6736			$tpl.find('.offer-icon').html('<img src="assets/images/search/offer-symbol-2.svg" alt="Rating User icon" class="">');
6737			$tpl.find('.hl-off-percent').addClass('offer-colour');
6738			if (minDiscountFare > 0)
6739				$tpl.find('.fare-margin').removeClass('fare-margin');
6740		} else if (offerNumber == 3) {
6741			$tpl.find('.trip-offer').addClass('offer-3');
6742			$tpl.find('.offer-icon').html('<img src="assets/images/search/offer-symbol-2.svg" alt="Rating User icon" class="">');
6743			$tpl.find('.hl-off-percent').addClass('offer-colour');
6744			if (minDiscountFare > 0)
6745				$tpl.find('.fare-margin').removeClass('fare-margin');
6746		}
6747
6748		$tpl.find('.trip-fare').html(currencySymbol + (minFare - minDiscountFare));
6749		$tpl.find('.trip-onwards').html(stageFares.length > 1 && onwardsTag);
6750		$tpl.find('.trip-perseat-from').html(stageFares.length > 1 && perSeat);
6751		$tpl.find('.trip-fare-original').html(currencySymbol + minFare).toggleClass('d-none', !minDiscountFare);
6752		$tpl.find('.trip-starttime').html(moment(bval.fromStation.dateTime).format('hh:mm A'));
6753		$tpl.find('.trip-endtime').html(moment(bval.toStation.dateTime).format('hh:mm A'));
6754		$tpl.find('.trip-startdate').html(moment(bval.fromStation.dateTime).format('DD MMM'));
6755		$tpl.find('.trip-enddate').html(moment(bval.toStation.dateTime).format('DD MMM'));
6756		$tpl.find('.trip-startday').html(moment(bval.fromStation.dateTime).format('ddd'));
6757		$tpl.find('.trip-endday').html(moment(bval.toStation.dateTime).format('ddd'));
6758		$tpl.find('.trip-duration').html(bval.travelTime + ' hrs');
6759		$tpl.find('.trip-seatsavail').attr('title', 'Total ' + bval.seatCount + ' Seats').html(bval.availableSeatCount);
6760		$tpl.find('.trip-via').html(viaStations.join(', '));
6761		$tpl.find('.trip-amenities').html(amenities.join(''));
6762		$tpl.find('.trip-reststop-count').html(bval.travelStopCount);
6763		$tpl.find('[data-triptab="RESTSTOPS"]').toggleClass('d-none', !bval.travelStopCount);
6764		$tpl.find('.rest-stop').toggleClass('d-none', !bval.travelStopCount);
6765
6766		if (amenities.length == 0) {
6767			$tpl.find('[data-triptab="AMENITIES"]').addClass('d-none')
6768		}
6769
6770		if (bval.availableSeatCount === 0) {
6771			$tpl.find('.trip-seatsavail').parent().hide();
6772			$tpl.find('.trip-viewbusmap').html('Sold Out').removeClass('btn-primary').addClass('btn-danger').css({ 'padding': '4px 15px' });
6773			$tpl.find('.trip-viewbusmap, .tripinfo-container').addClass('no-map');
6774		} else {
6775			$tpl.find('.trip-viewbusmap').html(bval.availableSeatCount + ' Seats')
6776		}
6777
6778		$tpl.find('.COPYConntooltip').attr('id', 'COPYConntooltip-' + bval.tripCode);
6779
6780		$.each(bval.fromStation.stationPoint || [], function (k, bp) {
6781			$tpl.find('.trip-fromstationpoint').html(bp.name);
6782			return false;
6783		});
6784
6785		$.each((bval.toStation.stationPoint || []).reverse(), function (k, dp) {
6786			$tpl.find('.trip-tostationpoint').html(dp.name);
6787			return false;
6788		});
6789
6790		//bus image profile 
6791		if (bval.busImageDetails && bval.busImageDetails.PROFILE && bval.busImageDetails.PROFILE.length > 0) {
6792
6793			const imageUrl = bval.busImageDetails.PROFILE[0].imageUrlSlugs;
6794			$tpl.find('.bus-profile').css('background-image', 'url(' + imageUrl + ')');
6795		} else {
6796			$tpl.find('.bus-profile').addClass('d-none');
6797		}
6798
6799
6800		var currentStationIndex = 0;
6801		var $viaRoutesContainer = $tpl.find('.all-via-routes');
6802		$viaRoutesContainer.html('<span class="">' + viaStationslide[currentStationIndex] + '</span>');
6803		$viaRoutesContainer.addClass('show');
6804		setInterval(function () {
6805			if (currentStationIndex >= viaStationslide.length) {
6806				currentStationIndex = 0;
6807			}
6808			$viaRoutesContainer.removeClass('show');
6809			$viaRoutesContainer.html('<span class="">' + viaStationslide[currentStationIndex] + '</span>');
6810			setTimeout(function () {
6811				$viaRoutesContainer.addClass('show');
6812			}, 100);
6813			currentStationIndex++;
6814		}, 3000);
6815
6816
6817		//journey status
6818		var currentDate = new Date(); // current date
6819		var year = currentDate.getFullYear();
6820		var month = ('0' + (currentDate.getMonth() + 1)).slice(-2);
6821		var day = ('0' + currentDate.getDate()).slice(-2);
6822
6823		var hours = ('0' + currentDate.getHours()).slice(-2);
6824		var minutes = ('0' + currentDate.getMinutes()).slice(-2);
6825		var seconds = ('0' + currentDate.getSeconds()).slice(-2);
6826
6827		var formattedDate = year + '-' + month + '-' + day; // date only
6828		var formattedDateTime = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds; // date time
6829		var formattedDateTimeObj = new Date(formattedDateTime); // current date time
6830
6831		// from station
6832		var fromDateTime = Object.values(bval.fromStation.stationPoint)[0];
6833		if (fromDateTime && fromDateTime.dateTime) {
6834			var fromDateTimeObj = new Date(fromDateTime.dateTime); // from station point date time
6835		}
6836
6837		var timeDifference = formattedDateTimeObj - fromDateTimeObj;
6838		var timeDifferenceInSeconds = Math.floor(timeDifference / 1000);
6839		var timeDifferenceInMinutes = Math.floor(timeDifferenceInSeconds / 60);
6840
6841		var absoluteTimeDifferenceInMinutes = Math.abs(timeDifferenceInMinutes); // minutes
6842		var absoluteTimeDifference = Math.abs(timeDifference); // hours
6843
6844		var timeDifferenceHours = Math.round(absoluteTimeDifference / (1000 * 60 * 60));
6845
6846		// to station 
6847		var toStationPoint = Object.values(bval.toStation.stationPoint);
6848		var toDateTime = toStationPoint[toStationPoint.length - 1];
6849
6850		if (toStationPoint.length > 0 && toStationPoint && toDateTime.dateTime) {
6851			var toDateTimeObj = new Date(toDateTime.dateTime); // to station point date time
6852		}
6853
6854		var formattedTravelDate = new Date(bval.travelDate);
6855		var formatTravelDate = formattedTravelDate.toISOString().split('T')[0]; // travel date
6856
6857		if (formattedDateTimeObj > fromDateTimeObj) {
6858			if (bval.tripStatus.code == "TCA" || (bval.tripStatus.code == "TPC" && bval.bookedSeatCount == 0)) {
6859				$tpl.find('#bus-status').removeClass('d-none').addClass('mt-35');
6860			} else {
6861				$tpl.find('#bus-status').removeClass('d-none').addClass('in-journey').html('In Journey');
6862			}
6863		} else if (timeDifferenceHours == 0) {
6864			if (bval.tripStatus.code == "TCA" || (bval.tripStatus.code == "TPC" && bval.bookedSeatCount == 0)) {
6865				$tpl.find('#bus-status').removeClass('d-none').addClass('mt-35');
6866			} else {
6867				$tpl.find('#bus-status').removeClass('d-none').addClass('hg-g').html('Depart in ' + absoluteTimeDifferenceInMinutes + ' Mins');
6868			}
6869		} else if (formattedDateTimeObj < fromDateTimeObj) {
6870			if (bval.tripStatus.code == "TCA" || (bval.tripStatus.code == "TPC" && bval.bookedSeatCount == 0)) {
6871				$tpl.find('#bus-status').removeClass('d-none').addClass('mt-35');
6872			} else {
6873				$tpl.find('#bus-status').removeClass('d-none').addClass('hg-g').html('Depart in ' + timeDifferenceHours + ' Hrs');
6874			}
6875		}
6876
6877		if (formatTravelDate == formattedDate) {
6878			$tpl.find('#bus-status').removeClass('d-none');
6879		} else {
6880			$tpl.find('#bus-status').addClass('d-none');
6881		}
6882
6883		// comingFrom-station
6884		var fromStationFirstBoarding = Object.values(bval.fromStation.stationPoint)[0];
6885
6886		if (fromStationFirstBoarding.name.length > 13) {
6887			let stationName = fromStationFirstBoarding.name.substring(0, 13) + '...';
6888			if (formattedDateTimeObj > fromDateTimeObj) {
6889				$tpl.find('.comingFrom-station').html('Starting from ' + stationName)
6890			} else {
6891				$tpl.find('.comingFrom-station').html('Coming from ' + stationName)
6892			}
6893		} else {
6894			if (formattedDateTimeObj > fromDateTimeObj) {
6895				$tpl.find('.comingFrom-station').html('Starting from ' + fromStationFirstBoarding.name)
6896			} else {
6897				$tpl.find('.comingFrom-station').html('Coming from ' + fromStationFirstBoarding.name)
6898			}
6899		}
6900
6901		if (bval.tripInfo.registrationNumber != '') {
6902			$tpl.find('.vehicle-number').removeClass('d-none');
6903			$tpl.find('.veh-register-no').html(bval.tripInfo.registrationNumber);
6904		}
6905
6906		if (bval.totalSingleSeat != 0) {
6907			$tpl.find('.single-seat-details').removeClass('d-none');
6908			$tpl.find('.single-seat').html(bval.totalSingleSeat + ' Single');
6909		}
6910
6911		if (bval.totalWindowSeat != 0) {
6912			$tpl.find('.window-seat-details').removeClass('d-none');
6913			$tpl.find('.window-seat').html(bval.totalWindowSeat + ' Window');
6914		}
6915
6916		$tpl.find('.boardingpoint-count').html(bval.fromStation.stationPoint.length);
6917		$tpl.find('.droppingpoint-count').html(bval.toStation.stationPoint.length);
6918
6919		if (isPM(bval.fromStation.dateTime)) {
6920			$tpl.find('.travelTime').html('<img class="mr_2" src="assets/images/search/night-time.svg" width="17px" height= "17px">' + bval.travelTime + ' hrs');
6921		} else {
6922			$tpl.find('.travelTime').html('<img class="mr_2" src="assets/images/search/day-time.svg" width="17px" height= "17px">' + bval.travelTime + ' hrs');
6923		}
6924
6925		var punctualityHtml = renderPunctuality(bval.punctualityList, bval.travelDate, bval.fromStation.code, bval.toStation.code);
6926		$tpl.find('.trip-punctuality').html(punctualityHtml).toggleClass('d-none', !punctualityHtml);
6927
6928		// lower
6929		var lower = renderBusSeatsV4({
6930			layer: 1,
6931			matrix: bval.lmatrix,
6932			seatStatus: bval.seatStatus
6933		});
6934
6935		$tpl.find('.mini-lower-layer-seats').html(lower);
6936
6937		// upper
6938		if (bval.umatrix) {
6939			var upper = renderBusSeatsV4({
6940				layer: 2,
6941				matrix: bval.umatrix,
6942				seatStatus: bval.seatStatus
6943			});
6944
6945			$tpl.find('.mini-upper-layer-seats').html(upper);
6946			$tpl.find('.mini-upper-layer, .mini-layer-name').removeClass('d-none');
6947		}
6948
6949		// busmap
6950		// $tpl.find('.trip-viewbusmap').on('click', function (e) {
6951		// 	if (isLoadingBusMap) return;
6952
6953		// 	if (!$(e.target).is('.boardingpoint-count, .droppingpoint-count')) {
6954		// 	!$(this).hasClass('no-map') && initBusMap(trip);
6955		// 	} else {
6956		// 		renderTripTab('STATIONPOINTS', trip);
6957		// 	}
6958		// });
6959		// $tpl.find('.tripinfo-container trip-tab-div').addClass('d-none');
6960
6961		// var scrollInProgress = false;
6962		$tpl.find('.tripinfo-container').on('click', function (e) {
6963
6964			$('#trip-' + bval.tripCode).find('.trip-tabs-content').removeClass('busgallery-background');
6965
6966			var tripElement = $('#trip-' + bval.tripCode);
6967			if (tripElement.length && !$(this).hasClass('no-map') &&
6968				!$(e.target).is('.share-link') &&
6969				!$(e.target).closest('.trip-punctuality-wrap').length &&
6970				!$(e.target).is('.boardingpoint-count') &&
6971				!$(e.target).is('.droppingpoint-count') &&
6972				!$(e.target).hasClass('rest-stop') &&
6973				!$(e.target).hasClass('via-routes') &&
6974				!$(e.target).hasClass('bus-gallery') &&
6975				!$(e.target).hasClass('bus-profile')) {
6976
6977				$('html, body').animate({
6978					scrollTop: tripElement.offset().top - 60
6979				}, 1000, 'swing', function () {
6980					tripElement.find('.trip-tab-content').slideToggle(300);
6981					$('.trip-tab-content').not(tripElement.find('.trip-tab-content')).slideUp(300);
6982				});
6983			}
6984
6985			if (isLoadingBusMap) return;
6986			if ($(e.target).closest('.trip-tabs').length > 0) {
6987				return;
6988			}
6989
6990			if ($(e.target).is('.share-link')) {
6991				generateSharingLink(bval);
6992				trackEvent('Share Trip', 'click', 'Share Link');
6993				return;
6994			}
6995
6996			if ($(e.target).closest('.trip-punctuality-wrap').length) {
6997				return;
6998			}
6999
7000			if ($(e.target).is('.boardingpoint-count, .droppingpoint-count')) {
7001				renderTripTab('STATIONPOINTS', bval);
7002				trackEvent('Trip Info', 'click', 'STATIONPOINTS');
7003				return;
7004			}
7005
7006			if ($(e.target).hasClass('rest-stop')) {
7007				renderTripTab('RESTSTOPS', bval);
7008				trackEvent('Trip Info', 'click', 'RESTSTOPS');
7009				return;
7010			}
7011
7012			if ($(e.target).hasClass('bus-gallery') || $(e.target).hasClass('bus-profile')) {
7013				$('#trip-' + bval.tripCode).find('.trip-tabs-content').addClass('busgallery-background');
7014				renderTripTab('BUSPHOTOS', bval);
7015				trackEvent('Trip Info', 'click', 'BUSPHOTOS');
7016				return;
7017			}
7018
7019			if ($(e.target).hasClass('via-routes')) {
7020				renderTripTab('VIAROUTES', bval);
7021				trackEvent('Trip Info', 'click', 'VIAROUTES');
7022				return;
7023			}
7024
7025			if (!$(this).hasClass('no-map')) {
7026				$(this).find('.trip-viewbusmap').html('Hide seats');
7027				initBusMap(bval, 'conn');
7028			}
7029		});
7030
7031		// tabs
7032		// ordering
7033		$tpl
7034			.attr('data-departure', moment(bval.fromStation.dateTime).valueOf())
7035			.attr('data-availability', bval.availableSeatCount)
7036			.attr('data-fare', minFare);
7037
7038		// tooltips
7039		$tpl.find('[data-toggle="tooltip"]').tooltip({
7040			container: template,
7041			html: true,
7042			placement: 'top',
7043			boundary: 'viewport',
7044		});
7045
7046		// hide some futures on busmap card for CONN type
7047		// if (isConnecting) {
7048		//     // if need use it
7049		// }
7050
7051		// $tripListCont.append(tripList);
7052		return $tpl;
7053	});
7054}
7055
7056function resetConnectingLogicDatas() {
7057	// get regConnTrip.WAITING_TIME data before reset  regConnTrip
7058	let waitingTime = regConnTrip.WAITING_TIME;
7059	regConnTrip = initOrResetRegConnTrip();
7060	// set waitingTime back to regConnTrip.WAITING_TIME to avoid js error
7061	regConnTrip.WAITING_TIME = waitingTime
7062
7063	$(document).find('.conn-stations').each(function () {
7064		let $this = $(this);
7065		// reset conn station to begining 
7066		$(this).find('input[name^="station_"]:first').prop('checked', true).trigger('change');
7067		// remove toggleing functionality
7068		$this.find('.stationCollapseCtrlP').attr('data-toggle', '');
7069		let $stationCollapseCtrlC = $this.find('.stationCollapseCtrlC');
7070		// reset conn station trip UI trip info
7071		$stationCollapseCtrlC.find('.seat-name').html('-');
7072		$stationCollapseCtrlC.find('.raw-fare').html('-');
7073		$stationCollapseCtrlC.find('.discount').html('-');
7074		$stationCollapseCtrlC.find('.tax').html('-');
7075		$stationCollapseCtrlC.find('.payable-fare').html('-');
7076	});
7077
7078}
7079
7080function formatDateTime(dateString, format) {
7081	const date = new Date(dateString);
7082
7083	const formatYear = () => date.getFullYear();
7084
7085	const padZero = (num) => String(num).padStart(2, '0');
7086
7087	const formatTime12Hour = () => {
7088		let hour = date.getHours();
7089		const minute = date.getMinutes();
7090		const isPM = hour >= 12;
7091		const period = isPM ? 'PM' : 'AM';
7092		if (hour > 12) {
7093			hour -= 12;
7094		} else if (hour === 0) {
7095			hour = 12;
7096		}
7097		const paddedMinute = minute < 10 ? '0' + minute : minute;
7098		return `${hour}:${paddedMinute} ${period}`;
7099	};
7100
7101	const formatTime24Hour = (withSeconds = false) => {
7102		const month = String(date.getMonth() + 1).padStart(2, '0');
7103		const day = String(date.getDate()).padStart(2, '0');
7104		const hours = String(date.getHours()).padStart(2, '0');
7105		const minutes = String(date.getMinutes()).padStart(2, '0');
7106		const seconds = String(date.getSeconds()).padStart(2, '0');
7107		if (withSeconds) {
7108			return `${formatYear()}-${month}-${day} ${hours}:${minutes}:${seconds}`;
7109		} else {
7110			return `${formatYear()}-${month}-${day} ${hours}:${minutes}`;
7111		}
7112	};
7113
7114	const formatDayOfWeek = () => date.toLocaleString('en-US', { weekday: 'short' });
7115
7116	const formatMonth = () => date.toLocaleString('en-US', { month: 'short' });
7117
7118	const formatDayWithSuffix = () => {
7119		const day = date.getDate();
7120		const suffix = (day >= 11 && day <= 13) ? 'th' : (['1', '21', '31'].indexOf(day.toString()) !== -1) ? 'st' : (['2', '22'].indexOf(day.toString()) !== -1) ? 'nd' : (['3', '23'].indexOf(day.toString()) !== -1) ? 'rd' : 'th';
7121		return `${day}${suffix}`;
7122	};
7123
7124
7125	const formatFullDateWithDay = () => {
7126		return `${formatDayOfWeek()} ${formatMonth()} ${padZero(date.getDate())} ${formatYear()}`;
7127	};
7128
7129	const formatFullDate = () => {
7130		return `${formatDayWithSuffix()} ${date.toLocaleString('default', { month: 'long' })} ${formatYear()}`;
7131	};
7132
7133	const formatISODate = () => {
7134		return `${formatYear()}-${padZero(date.getMonth() + 1)}-${padZero(date.getDate())}`;
7135	};
7136
7137	const formatMonDDMonTime = () => {
7138		return `${formatDayOfWeek()} ${padZero(date.getDate())} ${formatMonth()}, ${formatTime12Hour()}`;
7139	};
7140
7141	// Switch based on format type
7142	switch (format) {
7143		case '12-hour-time':
7144			return formatTime12Hour();
7145		case '24-hour-time':
7146			return formatTime24Hour(false);
7147		case '24-hour-time-ws':
7148			return formatTime24Hour(true);
7149		case 'full-date-with-day':
7150			return formatFullDateWithDay();
7151		case 'full-date':
7152			return formatFullDate();
7153		case 'iso-date':
7154			return formatISODate();
7155		case 'ddd DD-MM-YYYY':
7156			return moment(dateString).format('ddd DD-MM-YYYY');
7157		case 'ddd-mon-time':
7158			return `${formatDayWithSuffix()} ${formatMonth()} ${formatTime12Hour()}`;
7159		case 'd-mon-yr-time':
7160			return formatMonDDMonTime();
7161		default:
7162			return dateString;
7163	}
7164}
7165
7166function forseatSelectZero() {
7167	$('#booking-card').addClass('d-none');
7168	$('.select-info-card').removeClass('d-none');
7169	$('.connecting-content').removeClass('d-none');
7170	$('.bpdpHeight').addClass('d-none');
7171
7172	$('.seat-select-visibility').each(function () {
7173		$(this).removeClass('seat-selected');
7174		$(this).removeClass('seater-selected');
7175		$(this).removeClass('sleeper-selected');
7176	});
7177
7178	$('.conn-selected').empty();
7179}
7180
7181function initConnBlockSeats(conndata) { // for block seat connecting
7182	var data = processConnTicketData(conndata);
7183
7184	if (!$('#pass-terms').is(':checked')) {
7185		$('#pass-terms').addClass('is-invalid');
7186		return;
7187	}
7188
7189	if (!data) {
7190		return;
7191	}
7192
7193	$('#conn-block-ticket-btn')
7194		.prop('disabled', true)
7195		.html(
7196			'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> ' +
7197			'Please wait...'
7198		);
7199
7200
7201	$.ajax({
7202		type: 'POST',
7203		url: 'passenger-info/block-seats',
7204		data: data,
7205		dataType: 'json',
7206		success: function (result) {
7207			if (result.status == 1) {
7208				if (result.data.paymentGatewayProcessFlag) {
7209					if (result.data.gatewayCode == 'RAZORPAY') {
7210						var options = result.data.gatewayInputDetails;
7211						options.image = 'assets/images/logo.png';
7212						options.theme = {};
7213						options.theme.color = getComputedStyle(document.documentElement).getPropertyValue('--theme-primary-color').trim();
7214						options.modal = {};
7215						options.modal.escape = false;
7216						options.modal.confirm_close = true;
7217						options.modal.ondismiss = function () {
7218							location.href = 'passenger-info/payment-response?orderCode=' + result.data.code;
7219						};
7220						var rzp1 = new Razorpay(options);
7221						rzp1.open();
7222						return
7223					}
7224
7225					var formControl = '';
7226					$.each(result.data.gatewayInputDetails || [], function (rekey, reval) {
7227						formControl += '<input name="' + rekey + '" id="' + rekey + '" value="' + reval + '" />';
7228					});
7229					$('body').append('<form action="' + result.data.paymentRequestUrl + '" name="frm_payment" id="frm_payment" method="post" style="display:none;">' + formControl + '</form>');
7230					$('#frm_payment').submit();
7231				} else {
7232					location.href = 'passenger-info/payment-response?orderCode=' + result.data.code;
7233				}
7234			} else {
7235				$('#pass-alert').danger(result.errorDesc);
7236			}
7237			$('#conn-block-ticket-btn').prop('disabled', false).html('Continue');
7238		}
7239	});
7240}
7241
7242function connectTripDetais(connetSchedule) {
7243	let data = {};
7244	data.isConnecting = true;
7245	data.orderDetails = regConnTrip.TKT_BLK_BOOK_DETAILS.orderDetails;
7246	data.additional = regConnTrip.TKT_BLK_BOOK_DETAILS.additionalAttributes;
7247	// data.additional = connetSchedule;
7248
7249	$.each(connDetails, function (i, res) {
7250		data.connPoints = res.connPoints;
7251		data.waitingTime = res.waitingTime;
7252	});
7253
7254	let fromDate, toDate, timeString = '';
7255
7256	// for data showing in payment page; 
7257	$.each(regConnTrip.TKT_BLK_BOOK_DETAILS.orderDetails, function (i, res) {
7258
7259		if (i === 0) {
7260			data.fromstationname = res.fromStationName;
7261			data.fromstationbp = res.boardingPointName;
7262			fromDate = new Date(res.travelDate);
7263			data.fromTravelDate = formatDateTime(res.travelDate, 'd-mon-yr-time');
7264			data.fromtraveldate = res.travelDate;
7265			data.fromcode = res.fromStation;
7266		}
7267
7268		if (i === regConnTrip.TKT_BLK_BOOK_DETAILS.orderDetails.length - 1) {
7269			data.tostationname = res.toStationName;
7270			data.tostationdp = res.droppingPointName;
7271			toDate = new Date(res.travelDate);
7272			data.toTravelDate = formatDateTime(res.travelDate, 'd-mon-yr-time');
7273			data.totraveldate = res.travelDate;
7274			data.tocode = res.toStation;
7275		}
7276
7277		if (fromDate && toDate) { // difference of from date & to date
7278			let timeDifference = toDate - fromDate;
7279			let days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
7280			let hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
7281			timeString = `${days} Days ${hours} Hours`;
7282		}
7283
7284		data.dayFromToDiff = timeString;
7285	});
7286
7287	gotoConnPassengerDetails(data);
7288	// calculateConnectingFare(regConnTrip.TKT_BLK_BOOK_DETAILS.orderDetails);
7289}
7290
7291function gotoConnPassengerDetails(bookingData) {
7292
7293	if (!bookingData) {
7294		return;
7295	}
7296
7297	$('#selected-seat-next')
7298		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Please Wait...')
7299		.attr('disabled', true);
7300
7301	// submit form
7302	$('#form-seats-data').val(JSON.stringify(bookingData));
7303	$('#form-seats').attr('action', 'passenger-info').submit();
7304}
7305
7306// for passenger
7307function newTicketCalculation(offerData, hotelRelated = false) {
7308	var { onwardData, returnData, rescheduleData } = getPassengerTicketData();
7309	var addonCharges = getAddonCharges();
7310
7311
7312	var femaleDiscount;
7313	$.each(onwardData.discountList || [], function (i, discount) {
7314		if (discount.femaleDiscountFlag) {
7315			femaleDiscount = discount;
7316		}
7317	});
7318
7319	var totalfare = 0;
7320	var faredifference = 0;
7321	var offerDiscount = 0;
7322
7323	var onwardfare = 0;
7324	var onwardboardingfare = 0;
7325	var onwarddroppingfare = 0;
7326	var onwardgst = 0;
7327	var onwarddiscount = 0;
7328
7329	var returnfare = 0;
7330	var returnboardingfare = 0;
7331	var returndroppingfare = 0;
7332	var returngst = 0;
7333	var returndiscount = 0;
7334
7335	var hotelFare = 0;
7336	var hotelPersonFare = 0;
7337	var hotelDiscount = 0;
7338	var hotelGst = 0;
7339
7340	var overallTotal = 0;
7341	var overallTotalRound = 0;
7342	var discountTotal = 0;
7343	var taxTotal = 0;
7344	var hotelTotal = 0;
7345	var grandTotal = 0;
7346
7347	var ticketAmount = 0; // for to addon details ticketAmount
7348
7349	var onwardSeatCount = onwardData.seatDetails.length;
7350	$.each(onwardData.seatDetails || [], function (i, seat) {
7351		onwardfare += seat.fare;
7352		onwardgst += seat.serviceTax;
7353		onwarddiscount += seat.discountFare;
7354
7355		if (femaleDiscount) {
7356			var gender = $('.onward-trip [data-code="' + seat.seatCode + '"]').find('.pass-gender:checked').val();
7357
7358			if (gender === 'F') {
7359				onwarddiscount += (femaleDiscount.percentageFlag)
7360					? percentageOf(femaleDiscount.discountValue, seat.fare)
7361					: femaleDiscount.discountValue;
7362			}
7363		}
7364	});
7365
7366	if (onwardData.fromStation.stationPoint && Number(onwardData.fromStation.stationPoint.fare) > 0) {
7367		onwardboardingfare += Number(onwardData.fromStation.stationPoint.fare) * onwardSeatCount;
7368	}
7369
7370	if (onwardData.toStation.stationPoint && Number(onwardData.toStation.stationPoint.fare) > 0) {
7371		onwarddroppingfare += Number(onwardData.toStation.stationPoint.fare) * onwardSeatCount;
7372	}
7373
7374	if (returnData) {
7375		var returnSeatCount = returnData.seatDetails.length;
7376		$.each(returnData.seatDetails || [], function (i, seat) {
7377			returnfare += seat.fare;
7378			returngst += seat.serviceTax;
7379			returndiscount += seat.discountFare;
7380		});
7381
7382		if (returnData.fromStation.stationPoint && Number(returnData.fromStation.stationPoint.fare) > 0) {
7383			returnboardingfare += Number(returnData.fromStation.stationPoint.fare) * returnSeatCount;
7384		}
7385		if (returnData.toStation.stationPoint && Number(returnData.toStation.stationPoint.fare) > 0) {
7386			returndroppingfare += Number(returnData.toStation.stationPoint.fare) * returnSeatCount;
7387		}
7388	}
7389
7390	$('#apply-offer-help').html('');
7391	if (offerData) {
7392		
7393		var fare = onwardfare + onwardboardingfare + onwarddroppingfare;
7394        if (returnData) {
7395            fare += returnfare + returnboardingfare + returndroppingfare;
7396        }
7397		var offerValue = (offerData.percentageFlag) ? percentageOf(offerData.value, fare) : offerData.value;
7398		var offerAmount = Math.max((offerData.maxvalue || 0), offerValue);
7399
7400		$('#apply-offer-help').html('A discount of ' + currencySymbol + Number(offerAmount).toFixed(2) + ' has been applied');
7401		// discount += offerAmount;
7402
7403		// returndiscount += offerAmount;
7404		if (returnData) {
7405			offerDiscount += offerAmount;
7406		} else {
7407			onwarddiscount += offerAmount;
7408		}
7409	}
7410
7411	var onwardTotal = onwardfare + onwardboardingfare + onwarddroppingfare - onwarddiscount;
7412	var returnTotal = returnfare + returnboardingfare + returndroppingfare - returndiscount;
7413
7414	var onwardTotaRound = onwardfare + onwardboardingfare + onwarddroppingfare;
7415	var returnTotaRound = returnfare + returnboardingfare + returndroppingfare;
7416
7417	if (onwardgst > 0) {
7418		const GSTPERCENT = 5;
7419		onwardgst = percentageOf(GSTPERCENT, onwardTotal);
7420		// onwardTotal += onwardgst;
7421	}
7422
7423	if (returngst > 0) {
7424		const GSTPERCENT = 5;
7425		returngst = percentageOf(GSTPERCENT, returnTotal);
7426		// returnTotal += returngst;
7427	}
7428
7429
7430	hotelFare = $('.text-right.hotel-fare').text();
7431	hotelPersonFare = $('.text-right.hotel-person-fare').text();
7432	hotelDiscount = $('.text-right.hotel-discount').text();
7433	hotelGst = $('.text-right.hotel-gst').text();
7434
7435	var HotelRoomCount = 0;
7436	var HotelPersonCount = 0;
7437
7438	HotelRoomCount = $('.hotel-details-card.selected').find('.hotel-rooms-number').text();
7439	HotelPersonCount = $('.hotel-details-card.selected').find('.hotel-person-number').text();
7440
7441	$('.text-left.hotel-fare').text('Room Fare (' + HotelRoomCount + ' Room(s))');
7442	$('.text-left.hotel-person-fare').text('Extra Person Fare (' + HotelPersonCount + ' Person(s))');
7443
7444	if (hotelRelated && !$('.hotel-details-card').hasClass('selected')) {
7445		hotelFare = '0';
7446		hotelPersonFare = '0';
7447		hotelGst = '0';
7448		hotelDiscount = '0';
7449		$('.text-left.hotel-fare').text('Room Fare');
7450		$('.text-left.hotel-person-fare').text('Extra Person Fare');
7451	}
7452
7453	hotelFare = convertToNumber(hotelFare);
7454	hotelPersonFare = convertToNumber(hotelPersonFare);
7455	hotelDiscount = convertToNumber(hotelDiscount);
7456	hotelGst = convertToNumber(hotelGst);
7457
7458	// totalfare = Math.round(totalfare);
7459	// onwardTotal = Math.round(onwardTotal);
7460	// returnTotal = Math.round(returnTotal);
7461
7462	// onwardTotaRound = Math.round(onwardTotaRound);
7463	// returnTotaRound = Math.round(returnTotaRound);
7464
7465
7466	overallTotal = onwardTotal + returnTotal;
7467	overallTotalRound = onwardTotaRound + returnTotaRound;
7468	hotelTotal = hotelFare + hotelPersonFare;
7469	discountTotal = onwarddiscount + returndiscount + hotelDiscount + offerDiscount;
7470	taxTotal = onwardgst + returngst + hotelGst;
7471
7472	// grandTotal = overallTotal + hotelTotal + taxTotal - discountTotal;
7473	grandTotal = overallTotalRound + hotelTotal + taxTotal - discountTotal;
7474	totalfare = onwardfare + onwardboardingfare + onwarddroppingfare - onwarddiscount + onwardgst;
7475
7476	ticketAmount = overallTotalRound + onwardgst + returngst - onwarddiscount - returndiscount;
7477	// ticketAmount = Math.round(ticketAmount);
7478
7479	$('#ticket-amount').val(ticketAmount);
7480
7481	if (rescheduleData) {
7482		faredifference = Math.max(0, totalfare - rescheduleData.totalPaid + onwarddiscount);
7483		grandTotal = faredifference + rescheduleData.reschedulableAmount;
7484	}
7485
7486	var gogreen = $('#gogreen-addon-cb').is(':checked');
7487	if (addonCharges.GOGREEN && gogreen) {
7488		grandTotal += addonCharges.GOGREEN
7489		onwardTotal += addonCharges.GOGREEN
7490	}
7491
7492	var pgcharges = 0;
7493	var pgchargepercent = Number($('input[name="payment-options"]:checked').data('pgcharges')) || 0;
7494	if (pgchargepercent > 0) {
7495		pgcharges = percentageOf(pgchargepercent, grandTotal);
7496		grandTotal += pgcharges;
7497		onwardTotal += pgcharges
7498	}
7499
7500	// onwardTotal = Math.round(onwardTotal);
7501	// grandTotal = Math.round(grandTotal);
7502
7503	$('.grandtotfare').html(currencySymbol + grandTotal.toFixed(2)); // grand total in top
7504
7505	$onwardfaretable = $('#onward-pass-fare-details').empty();
7506	if (returnData) {
7507		$onwardfaretable.append(buildFareRow('ONWFARE', onwardfare));
7508	} else {
7509		$onwardfaretable.append(buildFareRow('BUSFARE', onwardfare));
7510	}
7511	$onwardfaretable.append(buildFareRow('PICKUP', onwardboardingfare));
7512	$onwardfaretable.append(buildFareRow('DROPPING', onwarddroppingfare));
7513	$onwardfaretable.append(buildFareRow('ONWDISCOUNT', onwarddiscount));
7514	$onwardfaretable.append(buildFareRow('ONWGST', onwardgst));
7515	if (!returnData) {
7516		if (gogreen) {
7517			$onwardfaretable.append(buildFareRow('GOGREEN', addonCharges.GOGREEN));
7518		}
7519		$onwardfaretable.append(buildFareRow('PGCHARGE', pgcharges));
7520		$onwardfaretable.append(emptyFareRow());
7521		$onwardfaretable.append(buildFareRow('GRANDTOTAL', totalfare));
7522	}
7523
7524	$returnfaretable = $('#return-pass-fare-details').empty();
7525	$returnfaretable.append(buildFareRow('RETFARE', returnfare));
7526	$returnfaretable.append(buildFareRow('PICKUP', returnboardingfare));
7527	$returnfaretable.append(buildFareRow('DROPPING', returndroppingfare));
7528	$returnfaretable.append(buildFareRow('RETDISCOUNT', returndiscount));
7529	$returnfaretable.append(buildFareRow('RETGST', returngst));
7530
7531	$farebreakuptable = $('#breakup-pass-fare-details').empty();
7532	if (rescheduleData) {
7533		if (faredifference > 0) {
7534			$farebreakuptable.append(buildFareRow('NEWTICKET', onwardfare));
7535			// $farebreakuptable.append(buildFareRow('DISCOUNT', discount));
7536			$farebreakuptable.append(buildFareRow('GST', onwardgst));
7537			$farebreakuptable.append(buildFareRow('OLDTICKET', rescheduleData.totalPaid));
7538			$farebreakuptable.append(emptyFareRow('<div class="border-top" />'));
7539			$farebreakuptable.append(buildFareRow('FAREDIFF', faredifference));
7540		}
7541		$farebreakuptable.append(buildFareRow('RESCHARGE', rescheduleData.reschedulableAmou
7541nt));
7542		$farebreakuptable.append(buildFareRow('PGCHARGE', pgcharges));
7543	} else {
7544		$farebreakuptable.append(buildFareRow('OVRTOTAL', overallTotalRound));
7545		$farebreakuptable.append(buildFareRow('HOTELTOTAL', hotelTotal));
7546		$farebreakuptable.append(buildFareRow('TOTALDISCOUNT', discountTotal));
7547		$farebreakuptable.append(buildFareRow('TAXTOTAL', taxTotal));
7548		if (gogreen) {
7549			$farebreakuptable.append(buildFareRow('GOGREEN', addonCharges.GOGREEN));
7550		}
7551		$farebreakuptable.append(buildFareRow('PGCHARGE', pgcharges));
7552	}
7553	$farebreakuptable.append(emptyFareRow());
7554	$farebreakuptable.append(buildFareRow('GRANDTOTAL', grandTotal));
7555
7556	if (onwardTotal == 0) {
7557		$('#pg-accordion, #pg-redirect-hint').addClass('d-none');
7558		$('#block-ticket-btn').html('Continue');
7559	}
7560}
7561
7562function formatHotelDate(date) {
7563	var d = new Date(date);
7564
7565	var year = d.getFullYear();
7566	var month = ("0" + (d.getMonth() + 1)).slice(-2);
7567	var day = ("0" + d.getDate()).slice(-2);
7568	var hours = ("0" + d.getHours()).slice(-2);
7569	var minutes = ("0" + d.getMinutes()).slice(-2);
7570	var seconds = ("0" + d.getSeconds()).slice(-2);
7571
7572	return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
7573}
7574
7575function calculateGSTExclusive(tot, gst) {
7576	let tax = (gst / 100) * tot;
7577	let payable = Number(tot) + Number(tax);
7578	return { payable: payable, tax: tax };
7579}
7580
7581function calculateGSTInclusive(tot, gst) {
7582	let payable = (tot * (100 / (100 + gst)))
7583	let tax = Number(tot) - Number(payable);
7584	return { payable: payable, tax: tax };
7585}
7586
7587function convertToNumber(value) {
7588	value = value.replace(/[^0-9.-]+/g, '').trim();
7589	if (value === '' || value === ' ') {
7590		return 0;
7591	}
7592	return parseFloat(value);
7593}
7594
7595function connTripFilter(element, id, filterType) {
7596	let currentOrderBy = element.dataset.orderby;
7597	let newOrderBy = '';
7598	switch (currentOrderBy) {
7599		case 'asc':
7600			newOrderBy = 'desc';
7601			break;
7602		case 'desc':
7603			newOrderBy = 'none';
7604			break;
7605		default:
7606			newOrderBy = 'asc';
7607			break;
7608	}
7609
7610	// Update the dataset orderby attribute
7611	element.dataset.orderby = newOrderBy;
7612
7613	// var $tripcont = $('#trip-list-container-' + id + " .conn-trips");
7614	var $tripcont = $(element).closest('.info-cont').find('.conn-trips');
7615	var tripInfos = $tripcont.find('.c-trip-infos').not('.hide');
7616	var sortOrder = $tripcont.data('sortOrder') || 'asc';
7617
7618
7619	// Switch based on filterType
7620	switch (filterType) {
7621		case 'byDays':
7622			tripInfos.each(function () {
7623				var departureTimestamp = $(this).data('departure');
7624				var departureDate = new Date(departureTimestamp);
7625				$(this).data('departureDate', departureDate);
7626			});
7627
7628			tripInfos.sort(function (a, b) {
7629				var dateA = $(a).data('departureDate');
7630				var dateB = $(b).data('departureDate');
7631
7632				if (sortOrder === 'asc') {
7633					return dateA - dateB;
7634				} else if (sortOrder === 'desc') {
7635					return dateB - dateA;
7636				}
7637			});
7638			break;
7639
7640		case 'byFare':
7641			tripInfos.each(function () {
7642				var fare = parseFloat($(this).data('fare'));
7643				$(this).data('fareValue', fare);
7644			});
7645
7646			tripInfos.sort(function (a, b) {
7647				var fareA = $(a).data('fareValue');
7648				var fareB = $(b).data('fareValue');
7649
7650				if (sortOrder === 'asc') {
7651					return fareA - fareB;
7652				} else {
7653					return fareB - fareA;
7654				}
7655			});
7656			break;
7657
7658		case 'bySeat':
7659			tripInfos.each(function () {
7660				var seat = parseFloat($(this).data('availability'));
7661				$(this).data('seatValue', seat);
7662			});
7663
7664			tripInfos.sort(function (a, b) {
7665				var seatA = $(a).data('seatValue');
7666				var seatB = $(b).data('seatValue');
7667
7668				if (sortOrder === 'asc') {
7669					return seatA - seatB;
7670				} else {
7671					return seatB - seatA;
7672				}
7673			});
7674			break;
7675
7676		case 'byTime':
7677			tripInfos.each(function () {
7678				var duration = parseFloat($(this).data('duration'));
7679				$(this).data('durationValue', duration);
7680			});
7681
7682			tripInfos.sort(function (a, b) {
7683				var durationA = $(a).data('durationValue');
7684				var durationB = $(b).data('durationValue');
7685
7686				if (sortOrder === 'asc') {
7687					return durationA - durationB;
7688				} else {
7689					return durationB - durationA;
7690				}
7691			});
7692			break;
7693
7694		default:
7695			return;
7696	}
7697
7698	$tripcont.append(tripInfos);
7699	$tripcont.data('sortOrder', sortOrder === 'asc' ? 'desc' : 'asc');
7700}
7701
7702async function sendOTPNew() {
7703	var data = {},
7704		err = 0;
7705	data.mobileNumber = $('#otp-login-mobiles').val().trim();
7706
7707	if (!validate.isMobile(data.mobileNumber)) {
7708		$('#otp-login-mobiles').addClass('is-invalid');
7709		err++;
7710	}
7711
7712    var captchaInput = $('#captchaCode').val().trim();
7713    if (!captchaInput) {
7714        $('#captchaCode').addClass('is-invalid');
7715        $('#otp-login-alerts').danger().on('detach', function () {
7716			$('#captchaCode .is-invalid').removeClass('is-invalid');
7717		});
7718		err++;
7719    }
7720
7721	if (err) {
7722		$('#otp-login-alerts').danger().on('detach', function () {
7723			$('#mobile-sections .is-invalid').removeClass('is-invalid');
7724			$('#captchaCode .is-invalid').removeClass('is-invalid');
7725		});
7726		return;
7727	}
7728	
7729	// Captcha is verified server-side within send-otp; send it in the payload.
7730	data.captacha = captchaInput;
7731
7732	$('#otp-login-alerts').html('');
7733	$('#send-otp-btns')
7734		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Sending...')
7735		.attr('disabled', true);
7736
7737	$.ajax({
7738		type: 'POST',
7739		url: 'user/sending-otp',
7740		data: data,
7741		dataType: 'json',
7742		success: function (result) {
7743			$('#send-otp-btns').prop('disabled', false).html('Submit');
7744			if (result.status == 1) {
7745				// subscribeWebOTPNew();
7746				$('#forresendmob').val(data.mobileNumber);
7747				let mb = data.mobileNumber.replace(/(?<=\d{5})\d/g, "X");
7748				$('#otp-login-alerts').success();
7749				// $('#otp-login-mobiles').val('');
7750				// $('#mobile-hide').addClass('d-none');
7751				$('#mobile-sections').addClass('d-none');
7752				$('#otp-sections').removeClass('d-none');
7753				$('.mobile-mask').html('Enter OTP We have send to this ' + mb + '.');
7754				$('.inputContainer input[name="pin1"]').focus();
7755			} else {
7756				if (result.status == 0 && result.errorCode == "TR01B") {
7757					$('#otp-login-alerts').timeExceed();
7758				} else {
7759					genCaptcha(); // reset on failure
7760					$('#otp-login-alerts').danger(result.errorDesc);
7761				}
7762			}
7763		},
7764		error: function () {
7765			$('#send-otp-btns').prop('disabled', false).html('Submit');
7766			genCaptcha();
7767		}
7768	});
7769}
7770
7771function validateOTPNew() {
7772	var data = {},
7773		err = 0;
7774	data.mobileNumber = $('#forresendmob').val().trim();
7775
7776	const otpInputs = document.querySelectorAll('.inputContainer input');
7777	let otpNumber = '';
7778
7779	otpInputs.forEach(input => {
7780		if (input.value.trim().length === 1) {
7781			otpNumber += input.value.trim();
7782		} else {
7783			otpNumber += ''; // or throw an error
7784		}
7785	});
7786
7787	data.otpNumber = otpNumber;
7788
7789	$('#otp-login-validate-alerts').html('');
7790	$('#validate-otp-btns')
7791		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Validating...')
7792		.attr('disabled', true);
7793
7794	$.ajax({
7795		type: 'POST',
7796		url: 'user/validate-otp',
7797		data: data,
7798		dataType: 'json',
7799		success: function (result) {
7800			if (result.status == 1) {
7801				$('#otp-login-validate-alerts').success();
7802				// if(location.pathname.includes('/passenger-info')){
7803				location.reload();
7804				// autofillPassInfo();
7805				// }
7806			} else if (result.status == 2) {
7807				$('#otp-login-validate-alerts').success();
7808
7809				$('#otp-sections').addClass('d-none');
7810				$('#register-sections').removeClass('d-none');
7811			} else {
7812				$('#otp-login-validate-alerts').danger(result.errorDesc);
7813				$('#validate-otp-btns').prop('disabled', false).html('Submit');
7814			}
7815		}
7816	});
7817}
7818
7819
7820function registerUserNew() {
7821	var data = {},
7822		err = 0;
7823	data.name = $('#otp-register-fnames').val().trim();
7824	data.lastname = $('#otp-register-lnames').val().trim();
7825	data.email = $('#otp-register-emails').val().trim();
7826	data.mobile = $('#forresendmob').val().trim();
7827
7828	if (data.name == '') {
7829		$('#otp-register-fnames').addClass('is-invalid');
7830		err++;
7831	}
7832	if (!validate.isEmail(data.email)) {
7833		$('#otp-register-fnames').addClass('is-invalid');
7834		err++;
7835	}
7836
7837	if (err) {
7838		$('#otp-login-register-alerts').danger().on('detach', function () {
7839			$('#register-sections .is-invalid').removeClass('is-invalid');
7840		});
7841		return;
7842	}
7843
7844	$('#otp-login-register-alerts').html('');
7845	$('#otp-register-btns')
7846		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Submitting...')
7847		.attr('disabled', true);
7848
7849	$.ajax({
7850		type: 'POST',
7851		url: 'user/update-profile',
7852		data: data,
7853		dataType: 'json',
7854		success: function (result) {
7855			$('#otp-register-btns').prop('disabled', false).html('Submit');
7856			if (result.status == 1) {
7857				$('#otp-login-register-alerts').success();
7858				// if(location.pathname.includes('/passenger-info')){
7859				location.reload();
7860				// autofillPassInfo();
7861				// }
7862			} else {
7863				$('#otp-login-register-alerts').danger(result.errorDesc);
7864			}
7865		}
7866	});
7867}
7868
7869function subscribeWebOTPNew() {
7870	if (!window.OTPCredential) return;
7871
7872	const input = document.querySelector('#otp-login-pins');
7873	const button = document.querySelector('#validate-otp-btns');
7874	if (!input || !button) return;
7875
7876	const ac = new AbortController();
7877	button.addEventListener('click', e => {
7878		ac.abort();
7879	});
7880
7881	navigator.credentials.get({
7882		otp: { transport: ['sms'] },
7883		signal: ac.signal
7884	}).then(otp => {
7885		input.value = otp.code;
7886		button.click();
7887	}).catch(err => {
7888		console.log(err);
7889	});
7890}
7891
7892const handleInput = (inputNumber) => {
7893	const currentInput = document.querySelector(`.inputContainer input:nth-child(${inputNumber})`);
7894	const nextInput = document.querySelector(`.inputContainer input:nth-child(${inputNumber + 1})`);
7895
7896	if (isNaN(currentInput.value)) return false;
7897
7898	if (currentInput.value.length === 1 && nextInput) {
7899		nextInput.disabled = false;
7900		nextInput.focus();
7901	}
7902
7903	const allInputsFilled = Array.from(document.querySelectorAll('.inputContainer input'))
7904		.every(input => input.value.length === 1);
7905
7906	const verifyBtn = document.querySelector('.verifyBtn');
7907	verifyBtn.disabled = !allInputsFilled;
7908}
7909
7910const handleBackspace = (inputNumber, event) => {
7911	if (event.key == 'Backspace') {
7912		const currentInput = document.querySelector(`.inputContainer input:nth-child(${inputNumber})`);
7913		const prevInput = document.querySelector(`.inputContainer input:nth-child(${inputNumber - 1})`);
7914
7915		if (currentInput.value.length === 0 && prevInput) {
7916			currentInput.disabled = true;
7917			currentInput.value = "";
7918			prevInput.focus();
7919		}
7920
7921		const allInputsFilled = Array.from(document.querySelectorAll('.inputContainer input'))
7922			.every(input => input.value.length === 1);
7923
7924		const verifyBtn = document.querySelector('.verifyBtn');
7925		verifyBtn.disabled = !allInputsFilled;
7926	}
7927}
7928
7929const onlyNumber = (event) => {
7930	const value = event.target.value.replace(/[^0-9]/g, '');
7931	event.target.value = value;
7932};
7933
7934function resendOTP() {
7935	var data = {},
7936		err = 0;
7937	// Use the mobile stored during the initial send as the resend key. The
7938	// server verifies this key before resending the OTP and only then removes
7939	// the single-time captcha from the session.
7940	var resendMobile = $('#forresendmob').val().trim();
7941	data.resendKey = resendMobile;
7942
7943	if (!validate.isMobile(resendMobile)) {
7944		$('#otp-login-validate-alerts').danger('Unable to resend OTP. Please start again.');
7945		return;
7946	}
7947
7948	$('#otp-login-validate-alerts').html('');
7949	$('.mobile-resend')
7950		.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Sending...')
7951		.attr('disabled', true);
7952
7953	$.ajax({
7954		type: 'POST',
7955		url: 'user/resend-otp',
7956		data: data,
7957		dataType: 'json',
7958		success: function (result) {
7959			$('.mobile-resend').prop('disabled', false).html('Resend OTP');
7960			if (result.status == 1) {
7961				$('#otp-login-validate-alerts').success();
7962			} else {
7963				$('#otp-login-validate-alerts').danger(result.errorDesc);
7964			}
7965		}
7966	});
7967}
7968
7969function loginInPassengerInfo() {
7970	$('a[data-toggle="modal"][data-target="#otp-login"]').trigger('click');
7971	$('.login-card .modal-header').html('<span class="p-2">Login is required to proceed with ticket booking.</span>');
7972	$('.login-card .modal-header').css('padding', '2rem 0 0');
7973}
7974
7975function viewAllOffer(ticketData, type) {
7976
7977	if (discountCoupon.length > 0) {
7978		// If coupons are already loaded or content is visible, just toggle the display
7979		$('.view-all-offer i').toggleClass('rotate-180');
7980		$('#coupon-details').slideToggle('slow');
7981		if (discountCoupon.length > 0) {
7982			let coupon = $('#pass-offercode').val() ?? '';
7983			couponHtml(discountCoupon, coupon);
7984		}
7985		return;
7986	}
7987
7988	if (type == 'CONN') {
7989		var data = processConnTicketData(ticketData);
7990	} else {
7991		var data = processTicketData(ticketData, 'coupon');
7992	}
7993
7994	if (!data) {
7995		// Validation failed - don't rotate icon or slide content
7996		// calculateTicketFare();
7997		if (type == 'CONN') {
7998			connCalculation();
7999		} else {
8000			newTicketCalculation();
8001		}
8002		return;
8003	}
8004
8005	// Validation passed - rotate icon and slide content
8006	$('.view-all-offer i').addClass('rotate-180');
8007	$('#coupon-details').slideDown('slow');
8008	$('#coupon-details').html('<div class="text-center">Loading...</div>');
8009	$('#apply-offer-btn')
8010		.prop('disabled', true)
8011		.html('Apply');
8012
8013	$.ajax({
8014		type: 'POST',
8015		url: 'passenger-info/view-all-offer',
8016		data: data,
8017		dataType: 'json',
8018		success: function (result) {
8019			$('#apply-offer-btn').prop('disabled', false).html('Apply');
8020			if (result.status == 1) {
8021				if(result.data.length == 0){
8022					$('#coupon-details').html('<div class="text-center">No offers found</div>');
8023					// Set discountCoupon to empty array so toggle behavior works
8024					discountCoupon = [];
8025					return;
8026				}
8027				discountCoupon = result.data;
8028				couponHtml(result.data, '', ticketData);
8029			}else{
8030				$('#coupon-details').html('<div class="text-center">No offers found</div>');
8031				// Set discountCoupon to empty array so toggle behavior works
8032				discountCoupon = [];
8033			}
8034		}
8035	});
8036}
8037
8038function couponHtml(data, coupon, ticketData) {
8039
8040	$('#pass-offercode').html('');
8041	$('#coupon-details').html('');
8042	data.forEach(item => {
8043        var html = `
8044		<div class="coupon-item-modern">
8045			<label class="coupon-radio-label">
8046				<input type="radio" name="coupon-item" value="${item.coupon}" class="coupon-item-radio" ${coupon == item.coupon ? 'checked' : ''}>
8047				<span class="custom-radio"></span>
8048			</label>
8049			<div class="coupon-content">
8050				<div class="coupon-desc">
8051					<span class="coupon-title">Avail ${item.activeDesription || 'special'} offer on bus ticket booking in ${item.parentName || ''}</span>
8052					<div class="coupon-brand-container">
8053						<div class="coupon-brand">
8054							<img src="assets/images/search/offer-symbol-2.svg" alt="Rating User icon" class="">
8055							<span class="brand-badge">${item.coupon}</span>
8056						</div>
8057						<div class="coupon-brand-value">
8058							Flat ${currencySymbol} ${item.value.toFixed(2)} off
8059						</div>
8060					</div>
8061				</div>
8062				<div class="coupon-img">
8063					<img src="assets/images/search/giftbox.svg" alt="Gift box icon" class="">
8064				</div>
8065			</div>
8066		</div>`;
8067        $('#coupon-details').append(html);
8068    });
8069
8070	// Add event listener for radio button selection
8071	$('.coupon-item-radio').on('change', function() {
8072		if ($(this).is(':checked')) {
8073			var couponValue = $(this).val();
8074			$('#pass-offercode').val(couponValue);
8075			validateOffer(ticketData);
8076		}
8077	});
8078}
8079
8080$(document).on('click', '.coupon-item-modern', function(e) {
8081	if (!$(e.target).is('.coupon-item-radio')) {
8082		$(this).find('.coupon-item-radio').prop('checked', true).trigger('change');
8083	}
8084});
8085
8086
8087function genCaptcha() {
8088    $('.captcha-refresh').addClass('rotate');
8089    setTimeout(function() {
8090        $('.captcha-refresh').removeClass('rotate');
8091    }, 500);
8092
8093    $('#captchaCode').val('');
8094    $.ajax({
8095        type: 'GET',
8096        url: 'user/generate-captcha',
8097        dataType: 'json',
8098        success: function (response) {
8099			if(response.status == 1){
8100				$('.captcha-image').attr('src', response.data);
8101			}
8102        }
8103    });
8104}
8105
8106function verifyCaptcha(captcha) {
8107    return new Promise(function(resolve) {
8108        $.ajax({
8109            type: 'POST',
8110            url: 'user/verify-captcha',
8111            data: JSON.stringify({ captacha: captcha }),
8112            dataType: 'json',
8113            contentType: 'application/json',
8114            success: function(res) {
8115                resolve(res.status === 1);
8116            },
8117            error: function() {
8118                resolve(false);
8119            }
8120        });
8121    });
8122}

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.