← back to Jill Website
views/partials/booking-widget.ejs
304 lines
<!-- Booking Widget Section -->
<section class="booking-widget" style="padding: 5rem 0; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
<div class="container">
<div class="section-header" style="color: white;">
<h2 style="color: white;">Book Your Experience</h2>
<p style="color: rgba(255, 255, 255, 0.95);">Secure your reservations for unforgettable activities in Nosara</p>
</div>
<div class="booking-widget-container" style="max-width: 1000px; margin: 0 auto; background: white; border-radius: 20px; padding: 3rem; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);">
<!-- Widget Frame Container -->
<div id="booking-widget-frame" class="widget-frame" style="min-height: 500px; display: flex; flex-direction: column; align-items: center; justify-content: center;">
<!-- Loading State -->
<div id="widget-loading" class="widget-loading">
<div style="text-align: center;">
<i class="fas fa-spinner fa-spin" style="font-size: 3rem; color: var(--primary-color); margin-bottom: 1rem;"></i>
<p style="font-size: 1.1rem; color: var(--text-color);">Loading booking system...</p>
</div>
</div>
<!-- Iframe will be inserted here by JavaScript -->
<iframe
id="booking-iframe"
src=""
style="width: 100%; min-height: 600px; border: none; border-radius: 10px; display: none;"
title="Activity Booking Widget"
frameborder="0"
allow="payment"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
></iframe>
</div>
<!-- Fallback Content (shown if widget fails to load) -->
<div id="booking-fallback" class="booking-fallback" style="display: none; text-align: center; padding: 2rem;">
<div style="max-width: 600px; margin: 0 auto;">
<i class="fas fa-exclamation-triangle" style="font-size: 3rem; color: #ff9800; margin-bottom: 1.5rem;"></i>
<h3 style="color: var(--primary-color); margin-bottom: 1rem;">Booking System Temporarily Unavailable</h3>
<p style="font-size: 1.1rem; line-height: 1.8; color: var(--text-color); margin-bottom: 2rem;">
We're sorry for the inconvenience. Our online booking system is temporarily unavailable.
Please contact us directly to make your reservation.
</p>
<div style="background: var(--light); padding: 2rem; border-radius: 15px; margin-bottom: 2rem;">
<h4 style="color: var(--primary-color); margin-bottom: 1rem;">
<i class="fas fa-phone"></i> Contact Us Directly
</h4>
<div style="margin-bottom: 1rem;">
<strong>Email:</strong>
<a href="mailto:info@nosarabeachfront.com" style="color: var(--accent-color); text-decoration: none;">
info@nosarabeachfront.com
</a>
</div>
<div style="margin-bottom: 1rem;">
<strong>Phone:</strong>
<% const phoneNumber = '+50626824242'; %>
<a href="tel:<%= typeof formatPhoneForTel !== 'undefined' ? formatPhoneForTel(phoneNumber) : phoneNumber %>" style="color: var(--accent-color); text-decoration: none;">
<%= typeof formatPhoneNumber !== 'undefined' ? formatPhoneNumber(phoneNumber) : phoneNumber %>
</a>
</div>
<div>
<strong>WhatsApp:</strong>
<a href="https://wa.me/<%= phoneNumber.replace(/\D/g, '') %>" target="_blank" rel="noopener noreferrer" style="color: var(--accent-color); text-decoration: none;">
<%= typeof formatPhoneNumber !== 'undefined' ? formatPhoneNumber(phoneNumber) : phoneNumber %>
</a>
</div>
</div>
<div style="display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap;">
<a href="/#contact" class="btn-primary" style="padding: 1rem 2rem; border-radius: 50px; text-decoration: none; display: inline-block; background: var(--primary-color); color: var(--white);">
<i class="fas fa-envelope"></i> Contact Form
</a>
<a href="mailto:info@nosarabeachfront.com" class="btn-secondary" style="padding: 1rem 2rem; border-radius: 50px; text-decoration: none; display: inline-block; background: var(--accent-color); color: var(--white);">
<i class="fas fa-paper-plane"></i> Send Email
</a>
<a href="https://wa.me/50626824242" target="_blank" rel="noopener noreferrer" class="btn-secondary" style="padding: 1rem 2rem; border-radius: 50px; text-decoration: none; display: inline-block; background: #25D366; color: var(--white);">
<i class="fab fa-whatsapp"></i> WhatsApp
</a>
</div>
</div>
</div>
</div>
<!-- Booking Information -->
<div style="max-width: 900px; margin: 3rem auto; padding: 2rem; background: rgba(255, 255, 255, 0.95); border-radius: 15px;">
<div style="text-align: center; margin-bottom: 2rem;">
<h3 style="color: var(--primary-color); margin-bottom: 1rem;">
<i class="fas fa-info-circle"></i> Booking Information
</h3>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 2rem;">
<div style="text-align: center;">
<i class="fas fa-check-circle" style="font-size: 2rem; color: #4CAF50; margin-bottom: 0.5rem;"></i>
<h4 style="color: var(--dark); margin-bottom: 0.5rem;">Instant Confirmation</h4>
<p style="color: var(--text-color); font-size: 0.95rem;">Receive immediate booking confirmation</p>
</div>
<div style="text-align: center;">
<i class="fas fa-shield-alt" style="font-size: 2rem; color: #2196F3; margin-bottom: 0.5rem;"></i>
<h4 style="color: var(--dark); margin-bottom: 0.5rem;">Secure Payment</h4>
<p style="color: var(--text-color); font-size: 0.95rem;">Safe and encrypted transactions</p>
</div>
<div style="text-align: center;">
<i class="fas fa-calendar-check" style="font-size: 2rem; color: #FF9800; margin-bottom: 0.5rem;"></i>
<h4 style="color: var(--dark); margin-bottom: 0.5rem;">Flexible Options</h4>
<p style="color: var(--text-color); font-size: 0.95rem;">Choose dates and times that work for you</p>
</div>
<div style="text-align: center;">
<i class="fas fa-headset" style="font-size: 2rem; color: #9C27B0; margin-bottom: 0.5rem;"></i>
<h4 style="color: var(--dark); margin-bottom: 0.5rem;">24/7 Support</h4>
<p style="color: var(--text-color); font-size: 0.95rem;">We're here to help anytime</p>
</div>
</div>
</div>
</div>
</section>
<style>
/* Booking Widget Styles */
.booking-widget-container {
position: relative;
}
.widget-frame {
transition: min-height 0.3s ease;
}
.widget-loading {
transition: opacity 0.3s ease;
}
.widget-loading.hidden {
opacity: 0;
pointer-events: none;
}
#booking-iframe.loaded {
display: block !important;
}
/* Responsive Styles */
@media (max-width: 768px) {
.booking-widget {
padding: 3rem 0 !important;
}
.booking-widget-container {
padding: 1.5rem !important;
border-radius: 15px !important;
}
#booking-iframe {
min-height: 500px !important;
}
.booking-fallback {
padding: 1rem !important;
}
.booking-fallback h3 {
font-size: 1.3rem !important;
}
.booking-fallback p {
font-size: 1rem !important;
}
.booking-fallback > div > div {
padding: 1.5rem !important;
}
.booking-fallback .btn-primary,
.booking-fallback .btn-secondary {
width: 100%;
margin-bottom: 0.5rem;
}
}
@media (max-width: 480px) {
.section-header h2 {
font-size: 1.8rem !important;
}
.section-header p {
font-size: 0.95rem !important;
}
}
</style>
<script>
(function() {
// Configuration
const WIDGET_CONFIG = {
// Replace this URL with your actual booking widget URL
widgetUrl: 'https://booking.example.com/widget?partner=nosara',
loadTimeout: 10000, // 10 seconds
enableTestMode: <%= process.env.NODE_ENV === 'development' ? 'true' : 'false' %>
};
// DOM Elements
const iframe = document.getElementById('booking-iframe');
const loading = document.getElementById('widget-loading');
const fallback = document.getElementById('booking-fallback');
const frameContainer = document.getElementById('booking-widget-frame');
let loadTimeout;
let widgetLoaded = false;
// Initialize widget
function initializeWidget() {
// In test/development mode, show fallback after short delay
if (WIDGET_CONFIG.enableTestMode) {
console.log('[Booking Widget] Running in test mode - will show fallback');
setTimeout(showFallback, 2000);
return;
}
// Set iframe source
if (WIDGET_CONFIG.widgetUrl && WIDGET_CONFIG.widgetUrl !== 'https://booking.example.com/widget?partner=nosara') {
iframe.src = WIDGET_CONFIG.widgetUrl;
// Set load timeout
loadTimeout = setTimeout(() => {
if (!widgetLoaded) {
console.error('[Booking Widget] Load timeout exceeded');
showFallback();
}
}, WIDGET_CONFIG.loadTimeout);
// Listen for iframe load event
iframe.addEventListener('load', onWidgetLoad);
iframe.addEventListener('error', onWidgetError);
} else {
// No widget URL configured, show fallback
console.warn('[Booking Widget] No widget URL configured');
setTimeout(showFallback, 1000);
}
}
// Handle successful widget load
function onWidgetLoad() {
clearTimeout(loadTimeout);
widgetLoaded = true;
// Hide loading, show iframe
loading.classList.add('hidden');
setTimeout(() => {
loading.style.display = 'none';
iframe.classList.add('loaded');
}, 300);
console.log('[Booking Widget] Loaded successfully');
}
// Handle widget load error
function onWidgetError() {
clearTimeout(loadTimeout);
console.error('[Booking Widget] Failed to load');
showFallback();
}
// Show fallback content
function showFallback() {
loading.classList.add('hidden');
setTimeout(() => {
loading.style.display = 'none';
iframe.style.display = 'none';
fallback.style.display = 'block';
}, 300);
console.log('[Booking Widget] Showing fallback content');
}
// Listen for messages from iframe (optional - for advanced integration)
window.addEventListener('message', function(event) {
// Verify origin for security
// if (event.origin !== 'https://booking.example.com') return;
const data = event.data;
if (data.type === 'booking-widget-ready') {
console.log('[Booking Widget] Widget ready signal received');
onWidgetLoad();
} else if (data.type === 'booking-widget-resize') {
// Handle dynamic height adjustment
if (data.height) {
iframe.style.minHeight = data.height + 'px';
}
} else if (data.type === 'booking-widget-error') {
console.error('[Booking Widget] Widget error:', data.error);
showFallback();
}
});
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeWidget);
} else {
initializeWidget();
}
})();
</script>