Developing a Long-Term Vision for Success Introduction Ever feel like you’re just treading water, no clear destination in sight? Creating a long-term vision is like mapping out your path to not only stay afloat but to swim confidently towards your desired success. Whether it’s your personal aspirations or professional ambitions, having a clear, actionable plan …
Developing a Long-Term Vision for Success Introduction Ever feel like you’re just treading water, no clear destination in sight? Creating a long-term vision is like mapping out your path to not only stay afloat but to swim confidently towards your desired success. Whether it’s your personal aspirations or professional ambitions, having a clear, actionable plan …
Adaptability and Resilience in Business Introduction Ever wonder how some businesses not only survive but thrive amidst upheavals and changing market conditions? The secret sauce often boils down to two key ingredients: adaptability and resilience. In today’s fast-changing business environment, the ability to pivot and persevere isn’t just nice to have; it’s essential. This blog …
Financial Discipline and Management Introduction Ever find yourself scratching your head at the end of the month, wondering where all your cash disappeared to? You’re not alone! In today’s fast-paced world, maintaining financial discipline can seem like a herculean task. But don’t worry, we’ve got you covered with some foolproof strategies to whip your finances …
Brutally Honest Business advice 5/8 Introduction Have you ever found yourself sweating bullets at the thought of having a tough talk at work? Whether it’s mediating conflicts, navigating through misunderstandings, or just trying to boost team spirit, mastering these chats is crucial. In this post, we’ll go through some real-deal advice, using insights from our …
Brutally Honest Business advice 4/8 Introduction to Brutally Honest Business Advice Ready to roll up your sleeves and dive deep into the nitty-gritty of business success? You’re in the right place! In this series, we’re not just scratching the surface; we’re going full-on excavator mode to unearth the brutally honest truths of achieving your business …
Brutally Honest Business advice 2/8 Introduction Hey there, future moguls! If you’re on the quest to not just start but seriously scale your business, you’ve surely realized it’s no walk in the park. Success demands more than just a great idea; it requires strategy, persistence, and a borderline obsession with your customers. Whether you’re dreaming …
Brutally Honest Business advice 2/8 Introduction Hey there, future moguls! If you’re on the quest to not just start but seriously scale your business, you’ve surely realized it’s no walk in the park. Success demands more than just a great idea; it requires strategy, persistence, and a borderline obsession with your customers. Whether you’re dreaming …
Brutally Honest Business advice 2/8 Introduction Hey there! Let’s dive into why being open and honest isn’t just good karma; it’s a smart business strategy. Imagine building a bridge where each brick represents trust. Without transparency, that bridge could crumble under the weight of misunderstandings and half-truths. In today’s business climate, where choices abound, clear …
Blog Post 1: Mastering the Fundamentals of Business Introduction Ever wondered what makes a business not just survive but thrive? In a world brimming with startups and entrepreneurial ventures, mastering the fundamentals of business is not just important—it’s crucial. From understanding the core of what your customers need to maintaining a robust financial backbone, these …
${success ? "" : `Contact Us on WhatsApp`}`;
}
function showSameDayClosedMessage() {
const box = $("#ppc5-availability-result");
box.className = "ppc5-result ppc5-result--error";
box.innerHTML = resultCard("Same-Day Booking Closed", "It is after 6:00 PM in Vancouver. Please contact us on WhatsApp, mention that you are a crew member, and ask for Front Desk.");
box.focus();
}
function availabilityFailure(result) {
if (result.nights.some(night => night.crewAllocation === 0)) return ["Crew Offer Unavailable for Selected Date", "Crew self-booking is not available for one or more selected dates. Please contact us on WhatsApp for alternate availability."];
if (result.nights.some(night => night.crewRemaining === 0)) return ["Crew Allocation Reached", "The crew allocation for one or more selected dates has been reached. Please contact us and we will check whether additional pods can be offered."];
return ["Crew Availability Is Not Available", "Crew availability is not available for one or more selected dates. Please contact us and we will check other options."];
}
async function runAvailability(advance) {
if (!validateStep(1)) return false;
const data = getFormData();
const pod = selectedPod();
const box = $("#ppc5-availability-result");
const button = $("#ppc5-check-availability");
availability = null;
box.classList.add("ppc5-hidden");
if (!config) {
box.className = "ppc5-result ppc5-result--error";
box.innerHTML = resultCard("Crew Offer Is Still Loading", "Please wait a moment, then check availability again.");
box.focus();
return false;
}
if (!config.offerEnabled) {
box.className = "ppc5-result ppc5-result--error";
box.innerHTML = resultCard("Crew Offer Unavailable", "Crew self-booking is currently unavailable. Please contact us on WhatsApp.");
box.focus();
return false;
}
if (!findRatePeriod(data.checkInDate, data.checkOutDate)) {
box.className = "ppc5-result ppc5-result--error";
box.innerHTML = resultCard("Crew Offer Unavailable for Selected Date", "The crew offer does not cover all selected stay dates. Please contact us for alternate availability.");
box.focus();
return false;
}
button.disabled = true;
button.textContent = "Checking…";
try {
const result = await checkCrewAvailability({ checkInDate: data.checkInDate, checkOutDate: data.checkOutDate, roomTypeID: pod.roomTypeID });
availability = result;
if (result.available) {
const minimum = Math.min(...result.nights.map(night => Math.min(night.crewRemaining, night.cloudbedsRoomsAvailable)));
box.className = "ppc5-result ppc5-result--success";
box.innerHTML = resultCard("Crew Availability Confirmed", `${pod.label} is available for all ${result.nights.length} night${result.nights.length === 1 ? "" : "s"}. At least ${minimum} crew pod${minimum === 1 ? "" : "s"} remain per selected night.`, true);
$("#ppc5-live").textContent = "Crew availability confirmed for every selected night.";
if (advance) showStep(2);
} else {
const [title, message] = availabilityFailure(result);
box.className = "ppc5-result ppc5-result--error";
box.innerHTML = resultCard(title, message);
box.focus();
}
return result.available;
} catch (error) {
box.className = "ppc5-result ppc5-result--error";
box.innerHTML = resultCard("Availability Check Unavailable", "We could not safely confirm availability. No booking was made. Please retry or contact us on WhatsApp.");
box.focus();
return false;
} finally {
button.disabled = false;
button.textContent = "Check Availability";
}
}
function buildPayload() {
const data = getFormData();
const pod = selectedPod();
return {
checkInDate: data.checkInDate,
checkOutDate: data.checkOutDate,
roomTypeID: pod.roomTypeID,
podType: pod.type,
guest: {
firstName: data.firstName.trim(), lastName: data.lastName.trim(), email: data.email.trim(),
phone: data.phone.trim(), airline: data.airline.trim(), crewRole: data.crewRole,
returningCrew: data.returningCrew === "true"
},
arrival: {
eta: data.eta,
earlyCheckInRequested: data.earlyRequested !== "none",
earlyCheckInOption: data.earlyRequested,
earlyCheckInTime: null,
lateCheckOutRequested: data.lateRequested !== "none",
lateCheckOutOption: data.lateRequested,
lateCheckOutTime: null
},
damageDepositAuthorizationConfirmed: data.cardAuthorizationComplete === "on",
policyAccepted: true
};
}
async function submitBooking(event) {
event.preventDefault();
if (!validateStep(5)) return;
// Recheck immediately before creation in case the guest crossed 6:00 PM during the form.
const cutoff = getSameDayCutoffState();
if ($("#ppc5-checkin").value === cutoff.date && cutoff.closed) {
showStep(1);
setError($("#ppc5-checkin"), "Same-day booking is closed after 6:00 PM. Please contact us on WhatsApp.");
showSameDayClosedMessage();
return;
}
const button = $("#ppc5-create");
const errorBox = $("#ppc5-submit-error");
errorBox.classList.add("ppc5-hidden");
button.disabled = true;
button.textContent = "Creating Reservation…";
try {
// FAIL CLOSED: first-time crew images require an approved private upload API.
// Do not remove this guard until the backend securely stores the image and
// returns an opaque upload token that can be linked to the reservation.
const returningCrewSelection = $("input[name=returningCrew]:checked");
if (!DEMO_MODE && returningCrewSelection && returningCrewSelection.value === "false") {
throw new Error("Secure RAIC/Crew ID image storage is not connected. No image or reservation was sent.");
}
if (!(await runAvailability(false))) throw new Error("Availability changed. Please return to Step 1 and review the message.");
const payload = buildPayload();
const response = await createCrewReservation(payload);
if (!response || !response.success || !response.reservationNumber) throw new Error("The reservation could not be created.");
const pod = selectedPod();
const rows = [
["Reservation number", response.reservationNumber], ["Check-in", formatDate(payload.checkInDate)],
["Check-out", formatDate(payload.checkOutDate)], ["Pod type", pod.label],
["Amount due", response.amountDue != null ? `${money(response.amountDue, response.currency || "CAD")} CAD` : "Provided by Panda Pod payment request"],
["Payment status", response.paymentStatus || "PENDING"]
];
$("#ppc5-success-summary").innerHTML = rows.map(([key, value]) => `
Recent Comments