Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d57279cb9 | |||
| 0cb96a87fc | |||
| 709809a43d | |||
| 14845f6a43 | |||
| a2236262a7 | |||
| 685ded6818 | |||
| 2b47d52b41 | |||
| 4b1a154c72 | |||
| 610e785ce8 | |||
| f5a8271149 | |||
| afc2ea67c8 | |||
| afd0f20994 | |||
| 5e87e99246 | |||
| 42da17e0ed | |||
| d0dbd8f953 | |||
| 53d950981e | |||
| f69e24ccde | |||
| c63c1c7bcd | |||
| 8fad654f10 | |||
| f688991241 | |||
| aecd434918 | |||
| 3bfc9ee9ca | |||
| 69ffbd86ea | |||
| 0f8cfb13fb | |||
| 659dcd2387 | |||
| f9ecbba79e | |||
| 0b017ed241 | |||
| 996e1d468d | |||
| 19ad5f2935 | |||
| 5463af8225 | |||
| 781355feb4 | |||
| c50bf4e63f | |||
| 4f5c85bf6e | |||
| ad1f0594d2 |
@@ -38,7 +38,7 @@ export default function ContactPage() {
|
||||
tagIcon={Mail}
|
||||
tagAnimation="slide-up"
|
||||
title="We're Here to Help"
|
||||
description="Have questions about our packages, group bookings, or special requests? Reach out to our team and we'll get back to you as soon as possible."
|
||||
description="Have questions about our packages, group bookings, or special requests? Reach out to our team and we'll get back to you as soon as possible. For groups larger than 4 people, contact us to arrange custom booking experiences."
|
||||
background={{ variant: "canvas-reveal" }}
|
||||
useInvertedBackground={false}
|
||||
imageSrc="http://img.b2bpic.net/free-photo/person-suffering-from-technology-addiction-cybersickness_23-2151552653.jpg?_wi=2"
|
||||
|
||||
128
src/app/page.tsx
128
src/app/page.tsx
@@ -48,6 +48,10 @@ export default function LandingPage() {
|
||||
|
||||
const handleBooking = () => {
|
||||
if (selectedPackage && selectedDate && selectedTime) {
|
||||
if (groupSize > 4) {
|
||||
alert(`Group size exceeds maximum of 4 people. Please contact us for custom group bookings at bookings@rageroomvienna.local or call our team.`);
|
||||
return;
|
||||
}
|
||||
const pricePerPerson = calculatePrice(packagePrices[selectedPackage], groupSize);
|
||||
const totalPrice = pricePerPerson * groupSize;
|
||||
alert(`Booking confirmed!\nPackage: ${selectedPackage}\nGroup Size: ${groupSize}\nDate: ${selectedDate}\nTime: ${selectedTime}\nTotal: €${totalPrice.toFixed(2)}`);
|
||||
@@ -55,6 +59,82 @@ export default function LandingPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const isTimeAvailable = (date: string, time: string): boolean => {
|
||||
if (!date) return false;
|
||||
const dateObj = new Date(date);
|
||||
const dayOfWeek = dateObj.getDay();
|
||||
const [hours] = time.split(':').map(Number);
|
||||
|
||||
// Monday (1) to Wednesday (3) - not bookable
|
||||
if (dayOfWeek >= 1 && dayOfWeek <= 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Thursday (4): 17:00-22:00
|
||||
if (dayOfWeek === 4) {
|
||||
return hours >= 17 && hours < 22;
|
||||
}
|
||||
|
||||
// Friday (5): 14:00-24:00
|
||||
if (dayOfWeek === 5) {
|
||||
return hours >= 14 && hours < 24;
|
||||
}
|
||||
|
||||
// Saturday (6) and Sunday (0): 12:00-24:00
|
||||
if (dayOfWeek === 6 || dayOfWeek === 0) {
|
||||
return hours >= 12 && hours < 24;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const getAvailableTimes = (date: string): string[] => {
|
||||
if (!date) return [];
|
||||
const dateObj = new Date(date);
|
||||
const dayOfWeek = dateObj.getDay();
|
||||
const allTimes = ['14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00', '22:00', '23:00'];
|
||||
|
||||
if (dayOfWeek >= 1 && dayOfWeek <= 3) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (dayOfWeek === 4) {
|
||||
return allTimes.filter(time => {
|
||||
const [hours] = time.split(':').map(Number);
|
||||
return hours >= 17 && hours < 22;
|
||||
});
|
||||
}
|
||||
|
||||
if (dayOfWeek === 5) {
|
||||
return allTimes.filter(time => {
|
||||
const [hours] = time.split(':').map(Number);
|
||||
return hours >= 14 && hours < 24;
|
||||
});
|
||||
}
|
||||
|
||||
if (dayOfWeek === 6 || dayOfWeek === 0) {
|
||||
return allTimes.filter(time => {
|
||||
const [hours] = time.split(':').map(Number);
|
||||
return hours >= 12 && hours < 24;
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
const getDateWarning = (date: string): string | null => {
|
||||
if (!date) return null;
|
||||
const dateObj = new Date(date);
|
||||
const dayOfWeek = dateObj.getDay();
|
||||
const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
||||
|
||||
if (dayOfWeek >= 1 && dayOfWeek <= 3) {
|
||||
return `${dayNames[dayOfWeek]} is not available. We're only open Thursday-Sunday.`;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="expand-hover"
|
||||
@@ -135,8 +215,9 @@ export default function LandingPage() {
|
||||
<div className="w-full max-w-3xl px-6 md:px-8 text-center">
|
||||
<div className="mb-8 md:mb-12">
|
||||
<h3 className="text-2xl md:text-3xl font-bold text-foreground mb-3">Group Discount Available</h3>
|
||||
<p className="text-lg md:text-2xl font-semibold text-primary-cta">4+ people = €40/person</p>
|
||||
<p className="text-lg md:text-2xl font-semibold text-primary-cta">4 people = €40/person (Maximum)</p>
|
||||
<p className="text-sm md:text-base text-foreground/70 mt-2">Perfect for team building and group experiences</p>
|
||||
<p className="text-xs md:text-sm text-foreground/60 mt-3 font-medium">Groups larger than 4 people: Contact us for custom bookings</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -153,7 +234,7 @@ export default function LandingPage() {
|
||||
{ text: "Book Package", onClick: () => openBookingModal('basic') },
|
||||
],
|
||||
features: [
|
||||
"30 minutes of pure destruction", "All safety gear included", "Glass and ceramics", "Solo or duo session", "Perfect for first-timers", "Group price: €40/person (4+ people)"],
|
||||
"30 minutes of pure destruction", "All safety gear included", "Glass and ceramics", "Solo or duo session", "Perfect for first-timers", "Group price: €40/person (max 4 people)"],
|
||||
},
|
||||
{
|
||||
id: "destroyer", badge: "Most Popular", badgeIcon: Sparkles,
|
||||
@@ -161,7 +242,7 @@ export default function LandingPage() {
|
||||
{ text: "Book Now", onClick: () => openBookingModal('destroyer') },
|
||||
],
|
||||
features: [
|
||||
"60 minutes of maximum chaos", "Premium safety equipment", "Glass, ceramics & electronics", "Doubles or small group", "Most items to smash", "Best value experience", "Group price: €40/person (4+ people)"],
|
||||
"60 minutes of maximum chaos", "Premium safety equipment", "Glass, ceramics & electronics", "Doubles or small group", "Most items to smash", "Best value experience", "Group price: €40/person (max 4 people)"],
|
||||
},
|
||||
{
|
||||
id: "elite", badge: "Ultimate", badgeIcon: Crown,
|
||||
@@ -169,7 +250,7 @@ export default function LandingPage() {
|
||||
{ text: "Reserve Elite", onClick: () => openBookingModal('elite') },
|
||||
],
|
||||
features: [
|
||||
"90 minutes unlimited destruction", "VIP treatment & priorities", "All destruction categories", "Small group packages", "Premium room setup", "Professional photos included", "Group price: €40/person (4+ people)"],
|
||||
"90 minutes unlimited destruction", "VIP treatment & priorities", "All destruction categories", "Small group packages", "Premium room setup", "Professional photos included", "Group price: €40/person (max 4 people)"],
|
||||
},
|
||||
]}
|
||||
animationType="slide-up"
|
||||
@@ -210,13 +291,13 @@ export default function LandingPage() {
|
||||
{
|
||||
id: "2", title: "Is it really safe?", content: "Absolutely. All participants receive thorough safety briefing, professional-grade protective equipment, and constant supervision. Our trained staff ensures a safe, controlled environment for pure adrenaline release."},
|
||||
{
|
||||
id: "3", title: "How many people can join?", content: "Sessions are designed for solo destructors up to small groups. Basic packages work great for 1-2 people. Destroyer and Elite packages support small groups. Contact us for group booking options."},
|
||||
id: "3", title: "How many people can join?", content: "Maximum group size is 4 people per session. If your group is larger than 4 people, please contact us at bookings@rageroomvienna.local to arrange custom group bookings."},
|
||||
{
|
||||
id: "4", title: "What's included in pricing?", content: "All packages include full protective gear, safety briefing, tools, smashable items (glass, ceramics, electronics), and supervised session time. Photos available in Elite package."},
|
||||
{
|
||||
id: "5", title: "Are there age restrictions?", content: "Minimum age is 16 years old (with parental consent). No maximum age limit – we welcome destructors of all ages who can safely handle the experience."},
|
||||
{
|
||||
id: "6", title: "Can I book in advance?", content: "Yes! Check available time slots on our booking calendar. We're open Thursday 5 PM–10 PM, Friday 2 PM–12 AM, Saturday & Sunday 12 PM–12 AM."},
|
||||
id: "6", title: "Can I book in advance?", content: "Yes! Check available time slots on our booking calendar. We're open Thursday 5 PM–10 PM, Friday 2 PM–12 AM, Saturday & Sunday 12 PM–12 AM. Monday–Wednesday are closed."},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
@@ -244,6 +325,7 @@ export default function LandingPage() {
|
||||
<p className="text-foreground font-semibold mb-2">Rage Room Vienna</p>
|
||||
<p className="text-foreground/70">Vienna, Austria</p>
|
||||
<p className="text-foreground/70 mt-4">Open: Thu 5PM-10PM | Fri 2PM-12AM | Sat & Sun 12PM-12AM</p>
|
||||
<p className="text-foreground/70 text-sm mt-2">Monday-Wednesday: Closed</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -328,7 +410,7 @@ export default function LandingPage() {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">Group Size</label>
|
||||
<label className="block text-sm font-medium mb-2">Group Size (Max 4 people)</label>
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={() => setGroupSize(Math.max(1, groupSize - 1))}
|
||||
@@ -338,15 +420,18 @@ export default function LandingPage() {
|
||||
</button>
|
||||
<span className="text-lg font-bold min-w-12 text-center">{groupSize}</span>
|
||||
<button
|
||||
onClick={() => setGroupSize(groupSize + 1)}
|
||||
onClick={() => setGroupSize(Math.min(4, groupSize + 1))}
|
||||
className="px-3 py-2 border rounded hover:bg-gray-100"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
{selectedPackage && groupSize >= 4 && (
|
||||
{groupSize === 4 && (
|
||||
<p className="text-sm text-green-600 mt-2 font-semibold">✓ Group discount applied! €40 per person</p>
|
||||
)}
|
||||
{groupSize > 4 && (
|
||||
<p className="text-sm text-red-600 mt-2 font-semibold">Maximum group size is 4 people. Please contact us for larger groups.</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -357,6 +442,9 @@ export default function LandingPage() {
|
||||
onChange={(e) => setSelectedDate(e.target.value)}
|
||||
className="w-full border rounded px-3 py-2"
|
||||
/>
|
||||
{getDateWarning(selectedDate) && (
|
||||
<p className="text-sm text-red-600 mt-2">{getDateWarning(selectedDate)}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -367,15 +455,16 @@ export default function LandingPage() {
|
||||
className="w-full border rounded px-3 py-2"
|
||||
>
|
||||
<option value="">Select a time</option>
|
||||
<option value="17:00">5:00 PM</option>
|
||||
<option value="18:00">6:00 PM</option>
|
||||
<option value="19:00">7:00 PM</option>
|
||||
<option value="20:00">8:00 PM</option>
|
||||
<option value="21:00">9:00 PM</option>
|
||||
{getAvailableTimes(selectedDate).map(time => (
|
||||
<option key={time} value={time}>{time}</option>
|
||||
))}
|
||||
</select>
|
||||
{selectedDate && getAvailableTimes(selectedDate).length === 0 && (
|
||||
<p className="text-sm text-red-600 mt-2">No available times for this date</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{selectedPackage && (
|
||||
{selectedPackage && groupSize <= 4 && (
|
||||
<div className="bg-gray-50 p-4 rounded-lg">
|
||||
<p className="text-sm text-gray-600">Price per person</p>
|
||||
<p className="text-2xl font-bold">€{calculatePrice(packagePrices[selectedPackage], groupSize).toFixed(2)}</p>
|
||||
@@ -383,9 +472,16 @@ export default function LandingPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{groupSize > 4 && (
|
||||
<div className="bg-red-50 p-4 rounded-lg border border-red-200">
|
||||
<p className="text-sm text-red-800 font-semibold">Group size exceeds maximum</p>
|
||||
<p className="text-sm text-red-700 mt-1">For groups larger than 4 people, please contact us at bookings@rageroomvienna.local</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={handleBooking}
|
||||
disabled={!selectedPackage || !selectedDate || !selectedTime}
|
||||
disabled={!selectedPackage || !selectedDate || !selectedTime || groupSize > 4}
|
||||
className="w-full bg-blue-600 text-white py-3 rounded-lg font-semibold hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
>
|
||||
Confirm Booking
|
||||
|
||||
Reference in New Issue
Block a user