465 lines
17 KiB
TypeScript
465 lines
17 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
|
|
interface PaletteOption {
|
|
id: string;
|
|
name: string;
|
|
colors: string[];
|
|
desc: string;
|
|
}
|
|
|
|
interface EventTypeOption {
|
|
id: string;
|
|
label: string;
|
|
icon: string;
|
|
}
|
|
|
|
interface ElementOption {
|
|
id: string;
|
|
label: string;
|
|
icon: string;
|
|
tag: string;
|
|
}
|
|
|
|
const eventTypes: EventTypeOption[] = [
|
|
{ id: 'wedding', label: 'Wedding & Engagement', icon: '💍' },
|
|
{ id: 'milestone_birthday', label: 'Milestone Birthday (30th/50th)', icon: '🎂' },
|
|
{ id: 'baby_shower', label: 'Baby Shower / Gender Reveal', icon: '👶' },
|
|
{ id: 'themed_party', label: 'Themed / 1st Birthday', icon: '🍓' },
|
|
{ id: 'corporate_gala', label: 'Corporate Gala & Brand Launch', icon: '🥂' },
|
|
];
|
|
|
|
const palettes: PaletteOption[] = [
|
|
{
|
|
id: 'royal_noir',
|
|
name: 'Royal Noir Gala',
|
|
colors: ['#000000', '#D4AF37', '#990000'],
|
|
desc: 'Onyx black marble, reflective chrome gold, and deep crimson.',
|
|
},
|
|
{
|
|
id: 'sweet_berry',
|
|
name: 'Berry Sweet Pastel',
|
|
colors: ['#E0006F', '#FFB6C1', '#002244'],
|
|
desc: 'Strawberry red, blush baby pink, and deep midnight navy.',
|
|
},
|
|
{
|
|
id: 'tuscan_garden',
|
|
name: 'Tuscan Sunshine & Flora',
|
|
colors: ['#F5C518', '#FFFFFF', '#4A5D4E'],
|
|
desc: 'Warm sun yellow, crisp bridal white, and silk eucalyptus greenery.',
|
|
},
|
|
{
|
|
id: 'tropical_neon',
|
|
name: 'Tropical Luxe Brights',
|
|
colors: ['#FF007F', '#FF6600', '#00F0FF'],
|
|
desc: 'Vibrant hot pink, electric orange, and bright turquoise.',
|
|
},
|
|
{
|
|
id: 'celestial_moon',
|
|
name: 'Midnight & Gold Moon',
|
|
colors: ['#0B1B3D', '#C8A2C8', '#D4AF37'],
|
|
desc: 'Royal navy, soft lavender drape, and gold starburst accents.',
|
|
},
|
|
];
|
|
|
|
const decorElements: ElementOption[] = [
|
|
{ id: 'balloon_cascade', label: 'Organic Balloon Cloud Cascade', icon: '🎈', tag: 'Most Popular' },
|
|
{ id: 'arch_panels', label: 'Custom Multi-Arch Wood Panels', icon: '🏛️', tag: 'Signature' },
|
|
{ id: 'mosaic_letters', label: 'Giant 3D Balloon Mosaic Letters', icon: '🔤', tag: 'High Impact' },
|
|
{ id: 'beverage_station', label: 'Arched Drink & Treat Station', icon: '🍸', tag: 'Interactive' },
|
|
{ id: 'floral_accents', label: 'Silk Florals & Botanical Sprigs', icon: '🌹', tag: 'Luxury' },
|
|
{ id: 'custom_lettering', label: '3D Gold Script Custom Name Sign', icon: '✨', tag: 'Personalized' },
|
|
];
|
|
|
|
export default function MoodBoardEstimator() {
|
|
const [selectedEventType, setSelectedEventType] = useState<string>('milestone_birthday');
|
|
const [selectedPalette, setSelectedPalette] = useState<string>('royal_noir');
|
|
const [selectedElements, setSelectedElements] = useState<string[]>([
|
|
'balloon_cascade',
|
|
'arch_panels',
|
|
'custom_lettering',
|
|
]);
|
|
|
|
const toggleElement = (id: string) => {
|
|
setSelectedElements((prev) =>
|
|
prev.includes(id) ? prev.filter((el) => el !== id) : [...prev, id]
|
|
);
|
|
};
|
|
|
|
const currentEventType = eventTypes.find((e) => e.id === selectedEventType)?.label || '';
|
|
const currentPalette = palettes.find((p) => p.id === selectedPalette);
|
|
const selectedElementLabels = decorElements
|
|
.filter((e) => selectedElements.includes(e.id))
|
|
.map((e) => e.label);
|
|
|
|
const handleApplyToBooking = () => {
|
|
const visionString = `Custom Design Studio Selection:
|
|
• Celebration: ${currentEventType}
|
|
• Color Palette: ${currentPalette?.name} (${currentPalette?.desc})
|
|
• Core Decor Elements: ${selectedElementLabels.join(', ')}`;
|
|
|
|
// Dispatch custom event to prefill booking form
|
|
window.dispatchEvent(
|
|
new CustomEvent('prefillWiseHeartedBooking', {
|
|
detail: {
|
|
eventType: currentEventType,
|
|
vision: visionString,
|
|
services: selectedElementLabels,
|
|
},
|
|
})
|
|
);
|
|
|
|
// Smoothly scroll to contact form
|
|
const contactSection = document.getElementById('contact');
|
|
if (contactSection) {
|
|
contactSection.scrollIntoView({ behavior: 'smooth' });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<section
|
|
id="custom-studio"
|
|
style={{
|
|
padding: 'clamp(70px, 10vw, 110px) 0',
|
|
backgroundColor: '#050505',
|
|
position: 'relative',
|
|
borderBottom: '1px solid var(--border-gold)',
|
|
}}
|
|
>
|
|
<div className="container" style={{ maxWidth: '1120px' }}>
|
|
{/* Section Header */}
|
|
<div style={{ textAlign: 'center', marginBottom: '45px', padding: '0 8px' }}>
|
|
<span
|
|
style={{
|
|
fontSize: '0.85rem',
|
|
fontWeight: 800,
|
|
color: 'var(--color-pink-light)',
|
|
letterSpacing: '0.15em',
|
|
textTransform: 'uppercase',
|
|
display: 'block',
|
|
marginBottom: '10px',
|
|
}}
|
|
>
|
|
🎨 Interactive Custom Studio
|
|
</span>
|
|
<h2
|
|
style={{
|
|
fontSize: 'clamp(2rem, 3.8vw, 2.8rem)',
|
|
fontWeight: 800,
|
|
marginBottom: '16px',
|
|
}}
|
|
>
|
|
Design Your <span className="gold-gradient-text">Dream Setup</span>
|
|
</h2>
|
|
<p
|
|
style={{
|
|
fontSize: '1.05rem',
|
|
color: '#94A3B8',
|
|
maxWidth: '700px',
|
|
margin: '0 auto',
|
|
lineHeight: 1.6,
|
|
}}
|
|
>
|
|
Select your celebration type, color palette, and preferred backdrop elements below to generate your personalized setup preview in real time!
|
|
</p>
|
|
</div>
|
|
|
|
{/* 3-Step Interactive Grid */}
|
|
<div
|
|
style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
|
gap: '24px',
|
|
marginBottom: '40px',
|
|
}}
|
|
>
|
|
{/* STEP 1: Celebration Type */}
|
|
<div
|
|
className="glass-panel"
|
|
style={{
|
|
padding: '24px 20px',
|
|
border: '1px solid rgba(212, 175, 55, 0.3)',
|
|
borderRadius: '20px',
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '16px' }}>
|
|
<span
|
|
style={{
|
|
background: 'var(--color-gold-gradient)',
|
|
color: '#000',
|
|
width: '26px',
|
|
height: '26px',
|
|
borderRadius: '50%',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
fontWeight: 800,
|
|
fontSize: '0.85rem',
|
|
}}
|
|
>
|
|
1
|
|
</span>
|
|
<h3 style={{ fontSize: '1.15rem', fontWeight: 800, color: '#FFFFFF', margin: 0 }}>
|
|
Celebration Type
|
|
</h3>
|
|
</div>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
{eventTypes.map((et) => {
|
|
const isSelected = selectedEventType === et.id;
|
|
return (
|
|
<button
|
|
key={et.id}
|
|
type="button"
|
|
onClick={() => setSelectedEventType(et.id)}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: '12px',
|
|
padding: '12px 14px',
|
|
borderRadius: '12px',
|
|
background: isSelected ? 'rgba(212, 175, 55, 0.15)' : 'rgba(255, 255, 255, 0.03)',
|
|
border: isSelected ? '1.5px solid var(--color-gold)' : '1px solid rgba(255, 255, 255, 0.08)',
|
|
color: isSelected ? '#FFFFFF' : '#CBD5E1',
|
|
fontSize: '0.92rem',
|
|
fontWeight: isSelected ? 700 : 500,
|
|
cursor: 'pointer',
|
|
textAlign: 'left',
|
|
transition: 'all 0.2s ease',
|
|
}}
|
|
>
|
|
<span style={{ fontSize: '1.25rem' }}>{et.icon}</span>
|
|
<span>{et.label}</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
{/* STEP 2: Color Palette */}
|
|
<div
|
|
className="glass-panel"
|
|
style={{
|
|
padding: '24px 20px',
|
|
border: '1px solid rgba(224, 0, 111, 0.3)',
|
|
borderRadius: '20px',
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '16px' }}>
|
|
<span
|
|
style={{
|
|
background: 'var(--color-pink-gradient)',
|
|
color: '#FFF',
|
|
width: '26px',
|
|
height: '26px',
|
|
borderRadius: '50%',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
fontWeight: 800,
|
|
fontSize: '0.85rem',
|
|
}}
|
|
>
|
|
2
|
|
</span>
|
|
<h3 style={{ fontSize: '1.15rem', fontWeight: 800, color: '#FFFFFF', margin: 0 }}>
|
|
Signature Palette
|
|
</h3>
|
|
</div>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
{palettes.map((p) => {
|
|
const isSelected = selectedPalette === p.id;
|
|
return (
|
|
<button
|
|
key={p.id}
|
|
type="button"
|
|
onClick={() => setSelectedPalette(p.id)}
|
|
style={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: '4px',
|
|
padding: '12px 14px',
|
|
borderRadius: '12px',
|
|
background: isSelected ? 'rgba(224, 0, 111, 0.15)' : 'rgba(255, 255, 255, 0.03)',
|
|
border: isSelected ? '1.5px solid var(--color-pink-light)' : '1px solid rgba(255, 255, 255, 0.08)',
|
|
cursor: 'pointer',
|
|
textAlign: 'left',
|
|
transition: 'all 0.2s ease',
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }}>
|
|
<span style={{ fontSize: '0.92rem', fontWeight: isSelected ? 700 : 600, color: isSelected ? '#FFFFFF' : '#CBD5E1' }}>
|
|
{p.name}
|
|
</span>
|
|
<div style={{ display: 'flex', gap: '4px' }}>
|
|
{p.colors.map((c, i) => (
|
|
<div
|
|
key={i}
|
|
style={{
|
|
width: '14px',
|
|
height: '14px',
|
|
borderRadius: '50%',
|
|
backgroundColor: c,
|
|
border: '1px solid rgba(255,255,255,0.4)',
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<span style={{ fontSize: '0.78rem', color: '#94A3B8' }}>{p.desc}</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
{/* STEP 3: Decor Elements */}
|
|
<div
|
|
className="glass-panel"
|
|
style={{
|
|
padding: '24px 20px',
|
|
border: '1px solid rgba(212, 175, 55, 0.3)',
|
|
borderRadius: '20px',
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '16px' }}>
|
|
<span
|
|
style={{
|
|
background: 'var(--color-gold-gradient)',
|
|
color: '#000',
|
|
width: '26px',
|
|
height: '26px',
|
|
borderRadius: '50%',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
fontWeight: 800,
|
|
fontSize: '0.85rem',
|
|
}}
|
|
>
|
|
3
|
|
</span>
|
|
<h3 style={{ fontSize: '1.15rem', fontWeight: 800, color: '#FFFFFF', margin: 0 }}>
|
|
Backdrop & Elements
|
|
</h3>
|
|
</div>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
{decorElements.map((el) => {
|
|
const isSelected = selectedElements.includes(el.id);
|
|
return (
|
|
<button
|
|
key={el.id}
|
|
type="button"
|
|
onClick={() => toggleElement(el.id)}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
padding: '10px 12px',
|
|
borderRadius: '12px',
|
|
background: isSelected ? 'rgba(212, 175, 55, 0.15)' : 'rgba(255, 255, 255, 0.03)',
|
|
border: isSelected ? '1.5px solid var(--color-gold)' : '1px solid rgba(255, 255, 255, 0.08)',
|
|
color: isSelected ? '#FFFFFF' : '#CBD5E1',
|
|
fontSize: '0.88rem',
|
|
fontWeight: isSelected ? 700 : 500,
|
|
cursor: 'pointer',
|
|
textAlign: 'left',
|
|
transition: 'all 0.2s ease',
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
<span>{el.icon}</span>
|
|
<span>{el.label}</span>
|
|
</div>
|
|
<span
|
|
style={{
|
|
fontSize: '0.72rem',
|
|
fontWeight: 700,
|
|
color: isSelected ? 'var(--color-gold-light)' : '#64748B',
|
|
background: isSelected ? 'rgba(212, 175, 55, 0.2)' : 'transparent',
|
|
padding: '2px 6px',
|
|
borderRadius: '6px',
|
|
}}
|
|
>
|
|
{isSelected ? '✓ Added' : '+ Add'}
|
|
</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Live Customized Preview Banner & CTA */}
|
|
<div
|
|
style={{
|
|
background: 'linear-gradient(135deg, rgba(20, 20, 20, 0.95) 0%, rgba(10, 10, 10, 0.98) 100%)',
|
|
border: '2px solid var(--color-gold)',
|
|
borderRadius: '24px',
|
|
padding: '24px 28px',
|
|
boxShadow: '0 20px 50px rgba(0,0,0,0.8), 0 0 30px rgba(212, 175, 55, 0.2)',
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
flexWrap: 'wrap',
|
|
gap: '20px',
|
|
}}
|
|
>
|
|
<div style={{ flex: '1 1 400px' }}>
|
|
<span
|
|
style={{
|
|
fontSize: '0.8rem',
|
|
fontWeight: 800,
|
|
color: 'var(--color-pink-light)',
|
|
letterSpacing: '0.12em',
|
|
textTransform: 'uppercase',
|
|
display: 'block',
|
|
marginBottom: '6px',
|
|
}}
|
|
>
|
|
✦ YOUR CUSTOM EVENT SPECIFICATION ✦
|
|
</span>
|
|
<div style={{ fontSize: '1.25rem', fontWeight: 800, color: '#FFFFFF', marginBottom: '8px' }}>
|
|
{currentEventType} <span style={{ color: 'var(--color-gold)' }}>•</span> {currentPalette?.name}
|
|
</div>
|
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px', marginTop: '4px' }}>
|
|
{selectedElementLabels.map((lbl, idx) => (
|
|
<span
|
|
key={idx}
|
|
style={{
|
|
fontSize: '0.78rem',
|
|
background: 'rgba(255, 255, 255, 0.08)',
|
|
border: '1px solid rgba(255, 255, 255, 0.15)',
|
|
padding: '3px 8px',
|
|
borderRadius: '8px',
|
|
color: '#E2E8F0',
|
|
}}
|
|
>
|
|
{lbl}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<button
|
|
type="button"
|
|
onClick={handleApplyToBooking}
|
|
className="btn-gold"
|
|
style={{
|
|
padding: '16px 32px',
|
|
fontSize: '1rem',
|
|
fontWeight: 800,
|
|
cursor: 'pointer',
|
|
boxShadow: '0 6px 25px rgba(212, 175, 55, 0.5)',
|
|
}}
|
|
>
|
|
<span>✨</span> Lock In Design & Get Quote →
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|