|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Performance Venue Booking</title> |
|
<script src="https://cdn.tailwindcss.com"></script> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
<style> |
|
|
|
@keyframes fadeIn { |
|
from { opacity: 0; transform: translateY(10px); } |
|
to { opacity: 1; transform: translateY(0); } |
|
} |
|
|
|
.fade-in { |
|
animation: fadeIn 0.5s ease-out forwards; |
|
} |
|
|
|
|
|
.custom-checkbox { |
|
display: none; |
|
} |
|
|
|
.custom-checkbox + label:before { |
|
content: ''; |
|
display: inline-block; |
|
width: 20px; |
|
height: 20px; |
|
margin-right: 10px; |
|
border: 2px solid #4f46e5; |
|
border-radius: 4px; |
|
background-color: white; |
|
vertical-align: middle; |
|
} |
|
|
|
.custom-checkbox:checked + label:before { |
|
background-color: #4f46e5; |
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z'/%3E%3C/svg%3E"); |
|
background-position: center; |
|
background-repeat: no-repeat; |
|
background-size: 60%; |
|
} |
|
|
|
|
|
::-webkit-scrollbar { |
|
width: 8px; |
|
} |
|
|
|
::-webkit-scrollbar-track { |
|
background: #f1f1f1; |
|
border-radius: 10px; |
|
} |
|
|
|
::-webkit-scrollbar-thumb { |
|
background: #888; |
|
border-radius: 10px; |
|
} |
|
|
|
::-webkit-scrollbar-thumb:hover { |
|
background: #555; |
|
} |
|
</style> |
|
</head> |
|
<body class="bg-gray-100 min-h-screen"> |
|
<div class="container mx-auto px-4 py-8"> |
|
|
|
<header class="mb-10"> |
|
<div class="flex justify-between items-center"> |
|
<div class="flex items-center space-x-2"> |
|
<i class="fas fa-theater-masks text-indigo-600 text-3xl"></i> |
|
<h1 class="text-2xl font-bold text-gray-800">StageMasters</h1> |
|
</div> |
|
<nav class="hidden md:block"> |
|
<ul class="flex space-x-8"> |
|
<li><a href="#" class="text-gray-700 hover:text-indigo-600 transition">Venues</a></li> |
|
<li><a href="#" class="text-gray-700 hover:text-indigo-600 transition">Artists</a></li> |
|
<li><a href="#" class="text-gray-700 hover:text-indigo-600 transition">Pricing</a></li> |
|
<li><a href="#" class="text-gray-700 hover:text-indigo-600 transition">Support</a></li> |
|
</ul> |
|
</nav> |
|
<button class="md:hidden text-gray-700"> |
|
<i class="fas fa-bars text-2xl"></i> |
|
</button> |
|
</div> |
|
</header> |
|
|
|
|
|
<div class="max-w-5xl mx-auto fade-in"> |
|
<div class="overflow-hidden shadow-lg rounded-xl"> |
|
<div class="grid lg:grid-cols-12 bg-white"> |
|
|
|
<div class="lg:col-span-7 p-8 bg-gray-50 border-r border-gray-200"> |
|
<div class="flex justify-between items-center mb-6"> |
|
<h2 class="text-2xl font-bold text-gray-800">Select Date & Time</h2> |
|
<div class="flex items-center space-x-3"> |
|
<button id="prev-month" class="p-2 rounded-full hover:bg-gray-200 transition"> |
|
<i class="fas fa-chevron-left text-gray-600"></i> |
|
</button> |
|
<button id="next-month" class="p-2 rounded-full hover:bg-gray-200 transition"> |
|
<i class="fas fa-chevron-right text-gray-600"></i> |
|
</button> |
|
</div> |
|
</div> |
|
|
|
<div id="month-year" class="text-xl font-semibold text-center mb-6 text-indigo-700"></div> |
|
|
|
<div class="grid grid-cols-7 gap-2 mb-6"> |
|
<div class="text-center font-medium text-gray-500">Sun</div> |
|
<div class="text-center font-medium text-gray-500">Mon</div> |
|
<div class="text-center font-medium text-gray-500">Tue</div> |
|
<div class="text-center font-medium text-gray-500">Wed</div> |
|
<div class="text-center font-medium text-gray-500">Thu</div> |
|
<div class="text-center font-medium text-gray-500">Fri</div> |
|
<div class="text-center font-medium text-gray-500">Sat</div> |
|
</div> |
|
|
|
<div id="calendar-grid" class="grid grid-cols-7 gap-2 mb-8"></div> |
|
|
|
<div class="mb-6"> |
|
<h3 class="font-semibold text-gray-700 mb-3">Available Time Slots</h3> |
|
<div id="time-slots" class="grid grid-cols-2 sm:grid-cols-3 gap-3"> |
|
|
|
</div> |
|
</div> |
|
|
|
<div> |
|
<h3 class="font-semibold text-gray-700 mb-3">Performance Duration</h3> |
|
<div class="flex flex-wrap gap-2"> |
|
<button class="duration-btn px-4 py-2 rounded-full bg-indigo-100 text-indigo-700 font-medium hover:bg-indigo-200 transition" data-duration="1">1 hour</button> |
|
<button class="duration-btn px-4 py-2 rounded-full bg-gray-100 text-gray-700 font-medium hover:bg-gray-200 transition" data-duration="2">2 hours</button> |
|
<button class="duration-btn px-4 py-2 rounded-full bg-gray-100 text-gray-700 font-medium hover:bg-gray-200 transition" data-duration="3">3 hours</button> |
|
<button class="duration-btn px-4 py-2 rounded-full bg-gray-100 text-gray-700 font-medium hover:bg-gray-200 transition" data-duration="all">Full day</button> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="lg:col-span-5 p-8"> |
|
<h2 class="text-2xl font-bold text-gray-800 mb-6">Chandelier Booking Summary</h2> |
|
|
|
<div class="bg-gray-50 rounded-lg p-4 mb-6"> |
|
<div class="flex items-center space-x-3 mb-4"> |
|
<div class="w-16 h-16 rounded-md overflow-hidden"> |
|
<img src="https://images.unsplash.com/photo-1551818255-e6e10975bc17?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" alt="Venue Image" class="w-full h-full object-cover"> |
|
</div> |
|
<div> |
|
<h3 class="font-semibold">4th Street</h3> |
|
<p class="text-sm text-gray-600"><i class="fas fa-map-marker-alt text-indigo-500 mr-1"></i>Pop Up Location, Santa Monica</p> |
|
</div> |
|
</div> |
|
|
|
<div class="space-y-3"> |
|
<div class="flex justify-between"> |
|
<span class="text-gray-600">Capacity:</span> |
|
<span class="font-medium">50 seated / 100 standing</span> |
|
</div> |
|
<div class="flex justify-between"> |
|
<span class="text-gray-600">Stage size:</span> |
|
<span class="font-medium">10m x 8m</span> |
|
</div> |
|
<div class="flex justify-between"> |
|
<span class="text-gray-600">Equipment:</span> |
|
<span class="font-medium">Sound system, lights</span> |
|
</div> |
|
<div class="flex justify-between"> |
|
<span class="text-gray-600">Dressing rooms:</span> |
|
<span class="font-medium">1 available</span> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="space-y-4"> |
|
<div class="flex justify-between items-center border-b border-gray-200 pb-2"> |
|
<div> |
|
<h4 class="font-medium text-gray-700">Selected Date</h4> |
|
<p id="selected-date" class="text-sm text-gray-500">Not selected</p> |
|
</div> |
|
<button id="edit-date" class="text-indigo-600 hover:text-indigo-800 transition"> |
|
<i class="fas fa-edit"></i> |
|
</button> |
|
</div> |
|
|
|
<div class="flex justify-between items-center border-b border-gray-200 pb-2"> |
|
<div> |
|
<h4 class="font-medium text-gray-700">Time Slot</h4> |
|
<p id="selected-time" class="text-sm text-gray-500">Not selected</p> |
|
</div> |
|
<button id="edit-time" class="text-indigo-600 hover:text-indigo-800 transition"> |
|
<i class="fas fa-edit"></i> |
|
</button> |
|
</div> |
|
|
|
<div class="flex justify-between items-center border-b border-gray-200 pb-2"> |
|
<div> |
|
<h4 class="font-medium text-gray-700">Performance Duration</h4> |
|
<p id="selected-duration" class="text-sm text-gray-500">Not selected</p> |
|
</div> |
|
<button id="edit-duration" class="text-indigo-600 hover:text-indigo-800 transition"> |
|
<i class="fas fa-edit"></i> |
|
</button> |
|
</div> |
|
|
|
<div class="pt-2"> |
|
<div class="flex justify-between mb-1"> |
|
<span class="text-gray-600">Base rate:</span> |
|
<span id="base-rate" class="font-medium">$0.00</span> |
|
</div> |
|
<div class="flex justify-between mb-1"> |
|
<span class="text-gray-600">Equipment fee:</span> |
|
<span id="equipment-fee" class="font-medium">$50.00</span> |
|
</div> |
|
<div class="flex justify-between font-bold text-lg"> |
|
<span>Total:</span> |
|
<span id="total-cost" class="text-indigo-600">$0.00</span> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="mt-8"> |
|
<input type="checkbox" id="terms-check" class="custom-checkbox"> |
|
<label for="terms-check" class="text-sm text-gray-600 cursor-pointer">I agree to the <a href="#" class="text-indigo-600 hover:underline">terms and conditions</a> and <a href="#" class="text-indigo-600 hover:underline">venue policies</a></label> |
|
|
|
<button id="book-now-btn" class="w-full mt-4 bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-3 px-4 rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed" disabled> |
|
Book Now |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div id="success-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50 hidden"> |
|
<div class="bg-white rounded-xl p-8 max-w-md w-full text-center fade-in"> |
|
<div class="w-20 h-20 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4"> |
|
<i class="fas fa-check text-green-500 text-3xl"></i> |
|
</div> |
|
<h2 class="text-2xl font-bold text-gray-800 mb-2">Booking Confirmed!</h2> |
|
<p class="text-gray-600 mb-6">Your performance slot has been successfully booked.</p> |
|
<div class="bg-gray-50 rounded-lg p-4 mb-6"> |
|
<div id="confirmation-details" class="space-y-2 text-left"> |
|
|
|
</div> |
|
</div> |
|
<button id="close-modal" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-4 rounded-lg transition"> |
|
Back to Dashboard |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
|
let currentDate = new Date(); |
|
let selectedDate = null; |
|
let selectedTime = null; |
|
let selectedDuration = null; |
|
|
|
const monthYearEl = document.getElementById('month-year'); |
|
const calendarGridEl = document.getElementById('calendar-grid'); |
|
const timeSlotsEl = document.getElementById('time-slots'); |
|
const selectedDateEl = document.getElementById('selected-date'); |
|
const selectedTimeEl = document.getElementById('selected-time'); |
|
const selectedDurationEl = document.getElementById('selected-duration'); |
|
const baseRateEl = document.getElementById('base-rate'); |
|
const equipmentFeeEl = document.getElementById('equipment-fee'); |
|
const totalCostEl = document.getElementById('total-cost'); |
|
const bookNowBtn = document.getElementById('book-now-btn'); |
|
const successModal = document.getElementById('success-modal'); |
|
const confirmationDetails = document.getElementById('confirmation-details'); |
|
|
|
|
|
renderCalendar(currentDate.getFullYear(), currentDate.getMonth()); |
|
|
|
|
|
document.getElementById('prev-month').addEventListener('click', function() { |
|
currentDate.setMonth(currentDate.getMonth() - 1); |
|
renderCalendar(currentDate.getFullYear(), currentDate.getMonth()); |
|
}); |
|
|
|
document.getElementById('next-month').addEventListener('click', function() { |
|
currentDate.setMonth(currentDate.getMonth() + 1); |
|
renderCalendar(currentDate.getFullYear(), currentDate.getMonth()); |
|
}); |
|
|
|
|
|
document.querySelectorAll('.duration-btn').forEach(btn => { |
|
btn.addEventListener('click', function() { |
|
|
|
document.querySelectorAll('.duration-btn').forEach(b => { |
|
b.classList.remove('bg-indigo-100', 'text-indigo-700'); |
|
b.classList.add('bg-gray-100', 'text-gray-700'); |
|
}); |
|
|
|
|
|
this.classList.remove('bg-gray-100', 'text-gray-700'); |
|
this.classList.add('bg-indigo-100', 'text-indigo-700'); |
|
|
|
selectedDuration = this.dataset.duration; |
|
selectedDurationEl.textContent = selectedDuration === 'all' ? 'Full day (8 hours)' : `${selectedDuration} hour(s)`; |
|
updateTotalCost(); |
|
checkBookingReady(); |
|
}); |
|
}); |
|
|
|
|
|
document.getElementById('edit-date').addEventListener('click', function() { |
|
selectedDate = null; |
|
selectedDateEl.textContent = 'Not selected'; |
|
checkBookingReady(); |
|
}); |
|
|
|
document.getElementById('edit-time').addEventListener('click', function() { |
|
selectedTime = null; |
|
selectedTimeEl.textContent = 'Not selected'; |
|
checkBookingReady(); |
|
}); |
|
|
|
document.getElementById('edit-duration').addEventListener('click', function() { |
|
selectedDuration = null; |
|
document.querySelectorAll('.duration-btn').forEach(b => { |
|
b.classList.remove('bg-indigo-100', 'text-indigo-700'); |
|
b.classList.add('bg-gray-100', 'text-gray-700'); |
|
}); |
|
selectedDurationEl.textContent = 'Not selected'; |
|
checkBookingReady(); |
|
}); |
|
|
|
|
|
document.getElementById('terms-check').addEventListener('change', checkBookingReady); |
|
|
|
|
|
bookNowBtn.addEventListener('click', function() { |
|
if (!selectedDate || !selectedTime || !selectedDuration) return; |
|
|
|
|
|
confirmationDetails.innerHTML = ` |
|
<p><strong>Venue:</strong> Grand Performance Hall</p> |
|
<p><strong>Date:</strong> ${selectedDate.toDateString()}</p> |
|
<p><strong>Time:</strong> ${selectedTime}</p> |
|
<p><strong>Duration:</strong> ${selectedDuration === 'all' ? 'Full day (8 hours)' : selectedDuration + ' hour(s)'}</p> |
|
<p><strong>Total:</strong> ${totalCostEl.textContent}</p> |
|
`; |
|
|
|
successModal.classList.remove('hidden'); |
|
}); |
|
|
|
|
|
document.getElementById('close-modal').addEventListener('click', function() { |
|
successModal.classList.add('hidden'); |
|
}); |
|
|
|
|
|
function renderCalendar(year, month) { |
|
monthYearEl.textContent = new Date(year, month).toLocaleString('default', { month: 'long', year: 'numeric' }); |
|
calendarGridEl.innerHTML = ''; |
|
|
|
|
|
const firstDay = new Date(year, month, 1).getDay(); |
|
const daysInMonth = new Date(year, month + 1, 0).getDate(); |
|
|
|
|
|
for (let i = 0; i < firstDay; i++) { |
|
const cell = document.createElement('div'); |
|
cell.className = 'h-12'; |
|
calendarGridEl.appendChild(cell); |
|
} |
|
|
|
|
|
for (let day = 1; day <= daysInMonth; day++) { |
|
const date = new Date(year, month, day); |
|
const cell = document.createElement('button'); |
|
cell.className = 'h-12 rounded-full flex items-center justify-center font-medium hover:bg-gray-100 transition'; |
|
cell.textContent = day; |
|
|
|
|
|
if (day === new Date().getDate() && month === new Date().getMonth() && year === new Date().getFullYear()) { |
|
cell.classList.add('bg-indigo-100', 'text-indigo-700'); |
|
} |
|
|
|
|
|
if (date < new Date(new Date().setHours(0, 0, 0, 0))) { |
|
cell.classList.add('text-gray-400', 'cursor-not-allowed'); |
|
cell.disabled = true; |
|
} else { |
|
cell.addEventListener('click', function() { |
|
|
|
document.querySelectorAll('#calendar-grid button').forEach(c => { |
|
c.classList.remove('bg-indigo-600', 'text-white'); |
|
}); |
|
|
|
|
|
cell.classList.add('bg-indigo-600', 'text-white'); |
|
|
|
selectedDate = date; |
|
selectedDateEl.textContent = date.toDateString(); |
|
generateTimeSlots(); |
|
checkBookingReady(); |
|
}); |
|
} |
|
|
|
calendarGridEl.appendChild(cell); |
|
} |
|
} |
|
|
|
function generateTimeSlots() { |
|
if (!selectedDate) return; |
|
|
|
timeSlotsEl.innerHTML = ''; |
|
|
|
|
|
const startHour = 9; |
|
const endHour = 22; |
|
const hourDiff = endHour - startHour; |
|
|
|
for (let i = 0; i < hourDiff; i++) { |
|
const hour = startHour + i; |
|
const ampm = hour >= 12 ? 'PM' : 'AM'; |
|
const displayHour = hour > 12 ? hour - 12 : hour; |
|
|
|
|
|
if (Math.random() > 0.7) continue; |
|
|
|
const timeSlot = document.createElement('button'); |
|
timeSlot.className = 'bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg py-2 px-3 text-sm font-medium transition'; |
|
timeSlot.textContent = `${displayHour}:00 ${ampm}`; |
|
|
|
|
|
if (selectedTime === timeSlot.textContent) { |
|
timeSlot.classList.remove('bg-gray-100', 'text-gray-700'); |
|
timeSlot.classList.add('bg-indigo-600', 'text-white'); |
|
} |
|
|
|
timeSlot.addEventListener('click', function() { |
|
|
|
document.querySelectorAll('#time-slots button').forEach(t => { |
|
t.classList.remove('bg-indigo-600', 'text-white'); |
|
t.classList.add('bg-gray-100', 'text-gray-700'); |
|
}); |
|
|
|
|
|
timeSlot.classList.remove('bg-gray-100', 'text-gray-700'); |
|
timeSlot.classList.add('bg-indigo-600', 'text-white'); |
|
|
|
selectedTime = timeSlot.textContent; |
|
selectedTimeEl.textContent = selectedTime; |
|
updateTotalCost(); |
|
checkBookingReady(); |
|
}); |
|
|
|
timeSlotsEl.appendChild(timeSlot); |
|
} |
|
|
|
|
|
if (timeSlotsEl.children.length === 0) { |
|
timeSlotsEl.innerHTML = '<p class="text-gray-500 col-span-3 text-center">No standard slots available.<br><button class="text-indigo-600 font-medium mt-2">Request custom time</button></p>'; |
|
} |
|
} |
|
|
|
function updateTotalCost() { |
|
if (!selectedDate || !selectedTime || !selectedDuration) return; |
|
|
|
|
|
let baseRate = 0; |
|
const day = selectedDate.getDay(); |
|
|
|
if (selectedDuration === '1') baseRate = day === 0 || day === 6 ? 300 : 250; |
|
else if (selectedDuration === '2') baseRate = day === 0 || day === 6 ? 500 : 400; |
|
else if (selectedDuration === '3') baseRate = day === 0 || day === 6 ? 700 : 550; |
|
else if (selectedDuration === 'all') baseRate = day === 0 || day === 6 ? 1200 : 1000; |
|
|
|
baseRateEl.textContent = `$${baseRate.toFixed(2)}`; |
|
|
|
|
|
const equipmentFee = selectedDuration === 'all' ? 250 : 150; |
|
equipmentFeeEl.textContent = `$${equipmentFee.toFixed(2)}`; |
|
|
|
|
|
const total = baseRate + equipmentFee; |
|
totalCostEl.textContent = `$${total.toFixed(2)}`; |
|
} |
|
|
|
function checkBookingReady() { |
|
const termsChecked = document.getElementById('terms-check').checked; |
|
const isReady = selectedDate && selectedTime && selectedDuration && termsChecked; |
|
|
|
bookNowBtn.disabled = !isReady; |
|
} |
|
}); |
|
</script> |
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=privateuserh/chandelier-performance-module" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
</html> |