20 Commits

Author SHA1 Message Date
0d57279cb9 Update src/app/page.tsx 2026-03-05 22:48:41 +00:00
0cb96a87fc Update src/app/contact/page.tsx 2026-03-05 22:48:41 +00:00
709809a43d Switch to version 3: modified src/app/styles/variables.css 2026-03-05 22:43:18 +00:00
14845f6a43 Switch to version 3: modified src/app/page.tsx 2026-03-05 22:43:18 +00:00
a2236262a7 Switch to version 4: modified src/app/styles/variables.css 2026-03-05 22:26:40 +00:00
685ded6818 Switch to version 4: modified src/app/page.tsx 2026-03-05 22:26:39 +00:00
2b47d52b41 Switch to version 3: modified src/app/page.tsx 2026-03-05 22:26:34 +00:00
4b1a154c72 Switch to version 3: added src/app/contact/page.tsx 2026-03-05 22:26:34 +00:00
610e785ce8 Switch to version 2: modified src/app/page.tsx 2026-03-05 22:26:31 +00:00
f5a8271149 Switch to version 1: modified src/app/page.tsx 2026-03-05 22:26:19 +00:00
afc2ea67c8 Switch to version 2: remove src/app/contact/page.tsx 2026-03-05 22:26:11 +00:00
afd0f20994 Switch to version 2: modified src/app/page.tsx 2026-03-05 22:26:11 +00:00
5e87e99246 Switch to version 3: modified src/app/styles/variables.css 2026-03-05 22:26:00 +00:00
42da17e0ed Switch to version 3: modified src/app/page.tsx 2026-03-05 22:25:59 +00:00
d0dbd8f953 Merge version_4 into main
Merge version_4 into main
2026-03-05 22:25:19 +00:00
f69e24ccde Merge version_4 into main
Merge version_4 into main
2026-03-05 22:24:29 +00:00
8fad654f10 Merge version_4 into main
Merge version_4 into main
2026-03-05 22:23:06 +00:00
aecd434918 Merge version_4 into main
Merge version_4 into main
2026-03-05 22:22:31 +00:00
69ffbd86ea Merge version_4 into main
Merge version_4 into main
2026-03-05 22:21:50 +00:00
659dcd2387 Merge version_4 into main
Merge version_4 into main
2026-03-05 22:15:48 +00:00
3 changed files with 139 additions and 47 deletions

View File

@@ -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"

View File

@@ -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"
@@ -96,20 +176,16 @@ export default function LandingPage() {
testimonials={[
{
name: "Marcus K.", handle: "Stressed Executive", testimonial: "Best stress relief I've ever experienced. Walked in angry, left smiling. Booking again!", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg?_wi=1"
},
imageSrc: "http://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg?_wi=1"},
{
name: "Lisa M.", handle: "Corporate Manager", testimonial: "The team loved it! We came as a group and it was the perfect team building activity. Absolutely cathartic.", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg?_wi=2"
},
imageSrc: "http://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg?_wi=2"},
{
name: "Daniel R.", handle: "Fitness Enthusiast", testimonial: "Incredible workout disguised as entertainment. The adrenaline rush is unmatched. Worth every euro.", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg?_wi=3"
},
imageSrc: "http://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg?_wi=3"},
{
name: "Sophie V.", handle: "Break-Up Survivor", testimonial: "Exactly what I needed. Therapeutic, fun, and exhilarating. Five stars all the way!", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg?_wi=4"
},
imageSrc: "http://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg?_wi=4"},
]}
testimonialRotationInterval={5000}
imageSrc="http://img.b2bpic.net/free-photo/person-suffering-from-technology-addiction-cybersickness_23-2151552653.jpg?_wi=1"
@@ -135,6 +211,16 @@ export default function LandingPage() {
</div>
<div id="pricing" data-section="pricing">
<div className="w-full bg-gradient-to-b from-background to-background py-12 md:py-16 flex items-center justify-center">
<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 (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>
<PricingCardEight
title="Choose Your Explosion"
description="Three fury-fueled packages designed to match your rage level. All include protective gear, tools, and unlimited smashing."
@@ -148,8 +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 discount: €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,
@@ -157,8 +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 discount: €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,
@@ -166,8 +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 discount: €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"
@@ -204,23 +287,17 @@ export default function LandingPage() {
useInvertedBackground={false}
faqs={[
{
id: "1", title: "What should I wear?", content: "Wear comfortable, sturdy clothing and closed-toe shoes. We provide full protective gear including helmet, gloves, and safety vest. No special attire needed we'll gear you up for maximum safety."
},
id: "1", title: "What should I wear?", content: "Wear comfortable, sturdy clothing and closed-toe shoes. We provide full protective gear including helmet, gloves, and safety vest. No special attire needed we'll gear you up for maximum safety."},
{
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: "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: "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: "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 PM10 PM, Friday 2 PM12 AM, Saturday & Sunday 12 PM12 AM."
},
id: "6", title: "Can I book in advance?", content: "Yes! Check available time slots on our booking calendar. We're open Thursday 5 PM10 PM, Friday 2 PM12 AM, Saturday & Sunday 12 PM12 AM. MondayWednesday are closed."},
]}
/>
</div>
@@ -248,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>
@@ -263,7 +341,7 @@ export default function LandingPage() {
description="Choose your package above and select your time slot on our calendar. Or get in touch with questions our team is ready to help you plan the perfect destruction session."
buttons={[
{ text: "Book a Session", onClick: () => openBookingModal('destroyer') },
{ text: "Email Us", href: "mailto:bookings@rageroomvienna.local?subject=Rage%20Room%20Inquiry" },
{ text: "Contact Us", href: "mailto:bookings@rageroomvienna.local" },
]}
buttonAnimation="slide-up"
background={{ variant: "downward-rays-static" }}
@@ -332,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))}
@@ -342,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>
@@ -361,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>
@@ -371,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>
@@ -387,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

View File

@@ -10,15 +10,15 @@
--accent: #ffffff;
--background-accent: #ffffff; */
--background: #0a0a0a;
--card: #1a1a1a;
--foreground: #ffffffe6;
--primary-cta: #e6e6e6;
--primary-cta-text: #0a0a0a;
--secondary-cta: #1a1a1a;
--secondary-cta-text: #ffffffe6;
--accent: #737373;
--background-accent: #737373;
--background: #f5f4f0;
--card: #ffffff;
--foreground: #1a1a1a;
--primary-cta: #2c2c2c;
--primary-cta-text: #f5f4f0;
--secondary-cta: #f5f4f0;
--secondary-cta-text: #1a1a1a;
--accent: #8a8a8a;
--background-accent: #e8e6e1;
/* text sizing - set by ThemeProvider */
/* --text-2xs: clamp(0.465rem, 0.62vw, 0.62rem);