PageSourceSearch

https://mountaincabinsutah.com/wp-content/plugins/homerunner-conve…/js/tools/thank-you-trip.js?ver=1.159.17

js mountaincabinsutah.com collected 2026-10-10 02:01:27 UTC 5,328 bytes, 155 lines download raw bytes

1/**
2 * Thank-you trip handler.
3 *
4 * Two jobs:
5 *   1. On property page load: if URL has `?trip=<hash>&slot=<slot>`, stash to sessionStorage so the
6 *      context survives the Guesty checkout redirect (which drops our query params).
7 *   2. On any page load: if sessionStorage has a pending trip context AND the current page looks
8 *      like a post-booking success state, POST to the trip REST endpoint to mark the listing booked.
9 *
10 * Depends on global `hrckTripThankYou` localized from TripBuilderTool.
11 */
12(function () {
13	'use strict';
14
15	if (typeof hrckTripThankYou === 'undefined') {
16		return;
17	}
18
19	var STORAGE_KEY = 'hrck_trip_context';
20
21	function getUrlParam(name) {
22		var search = window.location.search || '';
23		var match = new RegExp('[?&]' + name + '=([^&]+)').exec(search);
24		return match ? decodeURIComponent(match[1]) : null;
25	}
26
27	function stashIfPresent() {
28		var hash = getUrlParam('trip');
29		var slot = getUrlParam('slot');
30		var token = getUrlParam('t');
31		if (hash && slot && /^[A-Za-z0-9_-]{16}$/.test(hash)) {
32			try {
33				sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ hash: hash, slot: parseInt(slot, 10), token: token || '' }));
34			} catch (e) { /* storage blocked */ }
35		}
36	}
37
38	function readStash() {
39		try {
40			var raw = sessionStorage.getItem(STORAGE_KEY);
41			if (!raw) { return null; }
42			var parsed = JSON.parse(raw);
43			if (parsed && parsed.hash && parsed.slot) { return parsed; }
44		} catch (e) { /* noop */ }
45		return null;
46	}
47
48	function clearStash() {
49		try { sessionStorage.removeItem(STORAGE_KEY); } catch (e) { /* noop */ }
50	}
51
52	function urlReservationId() {
53		// The HR plugin's confirmation page arrives as ?reservation=<uuid>&hash=<bcrypt> —
54		// the exact Central reservation id its [homerunner-confirmation] shortcode resolves.
55		// This is the one attachment point every standard HR checkout actually provides.
56		var id = getUrlParam('reservation') || getUrlParam('reservation_id');
57		if (id && /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(id)) {
58			return id;
59		}
60		return null;
61	}
62
63	function looksLikeSuccess() {
64		// The HR confirmation page carries the reservation id + verification hash in the URL —
65		// the strongest success signal available, and present on every standard HR checkout.
66		if (urlReservationId() && getUrlParam('hash')) {
67			return true;
68		}
69		// Conservative fallbacks: HomeRunner's thank-you page commonly contains a .reservation-confirmation
70		// block or a body class of `page-thank-you`. Match either.
71		if (document.body && document.body.className) {
72			if (/thank-?you|booking-success|reservation-confirmed/i.test(document.body.className)) {
73				return true;
74			}
75		}
76		if (document.querySelector('.reservation-confirmation, .booking-confirmed, [data-reservation-id]')) {
77			return true;
78		}
79		// Also allow an explicit window flag the HR plugin can set when it renders confirmation.
80		if (typeof window.hrckBookingCompleted !== 'undefined' && window.hrckBookingCompleted) {
81			return true;
82		}
83		return false;
84	}
85
86	function extractReservationId() {
87		// URL param first: it is the Central reservation id verbatim (UUID-validated above).
88		var fromUrl = urlReservationId();
89		if (fromUrl) { return fromUrl; }
90		// Theme/site-specific attachment points; return null if not found — acceptable, the
91		// listing is still marked booked and revenue falls back to the search-time estimate.
92		var el = document.querySelector('[data-reservation-id]');
93		if (el) {
94			var id = el.getAttribute('data-reservation-id');
95			if (id) { return id; }
96		}
97		if (window.hrckReservationId) {
98			return String(window.hrckReservationId);
99		}
100		return null;
101	}
102
103	function postBooked(context, reservationId) {
104		var url = hrckTripThankYou.restBase + '/' + encodeURIComponent(context.hash)
105				+ '/listing/' + encodeURIComponent(String(context.slot)) + '/booked';
106
107		var payload = { token: context.token || '' };
108		if (reservationId) { payload.reservation_id = reservationId; }
109
110		fetch(url, {
111			method: 'POST',
112			headers: {
113				'Content-Type': 'application/json',
114				'X-WP-Nonce': hrckTripThankYou.nonce
115			},
116			body: JSON.stringify(payload)
117		})
118			.then(function (res) {
119				if (res.ok) {
120					clearStash();
121					showNotice(context.hash);
122				}
123			})
124			.catch(function () { /* silent; reservation sync is the backstop in v1.1 */ });
125	}
126
127	function showNotice(hash) {
128		var wrap = document.createElement('div');
129		wrap.className = 'hrck-trip-thank-you-notice';
130		wrap.setAttribute('role', 'status');
131		wrap.innerHTML = 'This listing is booked for your group trip. '
132			+ '<a href="/trip/' + encodeURIComponent(hash) + '">Back to your trip &rarr;</a>';
133		document.body.appendChild(wrap);
134	}
135
136	// Job 1: stash trip context on every page (no harm if URL doesn't have the params)
137	stashIfPresent();
138
139	// Job 2: if we look like a success page and have stash, mark booked.
140	if (document.readyState === 'loading') {
141		document.addEventListener('DOMContentLoaded', maybeMarkBooked);
142	} else {
143		maybeMarkBooked();
144	}
145
146	function maybeMarkBooked() {
147		var context = readStash();
148		if (!context) { return; }
149		// Give the thank-you page a moment to hydrate (Guesty checkout can be slow to settle).
150		setTimeout(function () {
151			if (!looksLikeSuccess()) { return; }
152			postBooked(context, extractReservationId());
153		}, 600);
154	}
155})();

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.