Compare commits

..

4 Commits

Author SHA1 Message Date
Ichitux
a8a0336ae5 Gallery + Info improvements
All checks were successful
Deploy NPM app / Deploy NPM (push) Successful in 1m22s
Co-authored-by: Copilot <copilot@github.com>
2026-05-05 19:02:59 +02:00
Ichitux
fce84ff4a6 Changes in module "mixed reservations"
All checks were successful
Deploy NPM app / Deploy NPM (push) Successful in 1m23s
2026-04-24 01:59:50 +02:00
Ichitux
823ca68119 Newer section and modular view
All checks were successful
Deploy NPM app / Deploy NPM (push) Successful in 1m14s
2026-04-14 15:48:44 +02:00
Ichitux
7a65e7a1f4 Minor fixes, texts
All checks were successful
Deploy NPM app / Deploy NPM (push) Successful in 1m6s
2026-04-01 01:15:52 +02:00
16 changed files with 406 additions and 48 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

BIN
src/assets/gallery/gal1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

BIN
src/assets/gallery/gal2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

BIN
src/assets/gallery/gal3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

BIN
src/assets/gallery/gal4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

BIN
src/assets/gallery/gal5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

BIN
src/assets/gallery/gal6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

View File

@@ -3,6 +3,7 @@ import { motion, AnimatePresence } from "framer-motion";
import { useState, useEffect } from "react";
import { ChevronUp } from "lucide-react";
import { useTranslation } from "react-i18next";
import { SECTIONS } from "@/data/event-data";
/** Botón flotante de reserva + scroll to top */
const FloatingButton = () => {
@@ -30,7 +31,7 @@ const FloatingButton = () => {
className="animate-pulse-glow rounded-full px-6 shadow-elevated"
asChild
>
<a href="#booking" className="inline-flex items-center gap-2">
<a href={SECTIONS.booking ? "#booking" : "#mixed-booking"} className="inline-flex items-center gap-2">
{/* Inline SVG: dancing couple icon */}
<svg
xmlns="http://www.w3.org/2000/svg"

View File

@@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
import { motion } from "framer-motion";
import { Button } from "@/components/ui/button";
import { useTranslation } from "react-i18next";
import { EVENT_INFO } from "@/data/event-data";
import { EVENT_INFO, SECTIONS } from "@/data/event-data";
import heroBg from "@/assets/hero-bg.jpg";
/** Calcula diferencia entre ahora y la fecha del evento */
@@ -116,7 +116,7 @@ const HeroSection = () => {
transition={{ delay: 1 }}
>
<Button variant="hero" size="lg" className="text-lg px-10 py-6" asChild>
<a href="#booking">{t('hero.bookYourPass')}</a>
<a href={SECTIONS.booking ? "#booking" : "#mixed-booking"}>{t('hero.bookYourPass')}</a>
</Button>
</motion.div>
</div>

View File

@@ -0,0 +1,213 @@
import { useState } from "react";
import { motion } from "framer-motion";
import { MIXED_BOOKING_PACKAGES, ROOM_TYPES, getFullPassPrice } from "@/data/event-data";
import type { RoomType } from "@/data/event-data";
import { useTranslation } from "react-i18next";
import { Check, Star, Circle, CheckCircle2 } from "lucide-react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Label } from "@/components/ui/label";
const FEATURED_PASS = "full";
const NON_HOTEL_FEE = 50;
const PARTY_PRICE = 25;
const MixedBookingSection = () => {
const { t } = useTranslation();
const fullPassPricing = getFullPassPrice();
const [selectedRooms, setSelectedRooms] = useState<Record<string, RoomType>>({
full: "individual",
party: "individual",
});
const [wantsHotel, setWantsHotel] = useState<Record<string, boolean | null>>({
full: null,
party: null,
});
return (
<section
id="mixed-booking"
className="section-padding bg-background scroll-mt-24 relative z-10 -mt-[40px] pt-[120px]"
style={{ borderRadius: "0 100% 0 0 / 0 120px 0 0" }}
>
<div className="container mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: false, amount: 0.15 }}
className="text-center mb-12"
>
<h2 className="font-display text-4xl md:text-5xl lg:text-7xl break-words font-bold pt-4 pb-10 leading-[1.8] text-gradient">
{t("mixedBooking.title")}
</h2>
<p className="text-muted-foreground max-w-2xl mx-auto">{t("mixedBooking.subtitle")}</p>
</motion.div>
<div className="grid sm:grid-cols-2 gap-6 lg:gap-8 max-w-4xl mx-auto items-stretch">
{MIXED_BOOKING_PACKAGES.map((pkg, i) => {
const selectedRoom = selectedRooms[pkg.id] || "individual";
const hasHotel = wantsHotel[pkg.id] === true;
// Use dynamic pricing for Full Pass, fixed price for Party Pass
// Only Full Pass has the +50€ non-hotel fee
let basePrice = pkg.id === "full" ? fullPassPricing.price : PARTY_PRICE;
let roomPrice = 0;
if (hasHotel) {
roomPrice = pkg.roomPrices[selectedRoom as keyof typeof pkg.roomPrices];
}
const passPrice = pkg.id === "full"
? (hasHotel ? basePrice : basePrice + NON_HOTEL_FEE)
: basePrice;
const price = passPrice + roomPrice;
const isFeatured = pkg.id === FEATURED_PASS;
const isLastPrice = pkg.id === "full" && fullPassPricing.isLastPrice;
const showNonHotelNote = pkg.id === "full" && !hasHotel && basePrice > 0;
const features = t(`mixedBooking.${pkg.id}Features`).split("|").map((f: string) => f.trim());
return (
<motion.div
key={pkg.id}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: false, amount: 0.15 }}
transition={{ delay: i * 0.1 }}
className={`relative flex h-full min-h-[520px] flex-col rounded-2xl overflow-hidden transition-shadow duration-300 ${
isFeatured
? "shadow-elevated border-2 border-primary/30"
: "shadow-card hover:shadow-elevated border border-border"
}`}
>
<div className="absolute top-4 right-4 z-10 flex flex-col gap-2 items-end">
{isFeatured && (
<span className="inline-flex items-center gap-1 bg-gradient-tropical text-primary-foreground text-xs font-bold px-3 py-1 rounded-full shadow-md">
<Star className="w-3 h-3 fill-current" />
{t("mixedBooking.popular")}
</span>
)}
{isLastPrice && (
<span className="inline-flex items-center gap-1 bg-red-600 text-white text-xs font-bold px-3 py-1 rounded-full shadow-md">
{t("mixedBooking.lastPrice")}
</span>
)}
</div>
<div className={`px-6 pt-8 pb-4 text-center min-h-[160px] flex flex-col justify-between ${
isFeatured ? "bg-gradient-tropical" : "bg-secondary/10"
}`}>
<div>
<h3 className={`font-display text-2xl md:text-3xl font-bold mb-1 ${
isFeatured ? "text-primary-foreground" : "text-foreground"
}`}>
{t(`mixedBooking.passTypes.${pkg.id}`)}
</h3>
<p className={`text-sm ${
isFeatured ? "text-primary-foreground/80" : "text-muted-foreground"
}`}>
{t(`mixedBooking.${pkg.id}Description`)}
</p>
</div>
</div>
<div className="px-6 pt-6 pb-4 text-center bg-card">
<p className="text-4xl md:text-5xl font-bold text-primary">
{price > 0 ? `${price}` : t("mixedBooking.priceTBD")}
</p>
<p className="text-sm font-medium text-foreground mt-2">
{t(`mixedBooking.passTypes.${pkg.id}`)}: {passPrice} {pkg.id === "full" ? t("mixedBooking.perPerson") : t("mixedBooking.perParty")}
</p>
{showNonHotelNote && (
<p className="text-xs text-red-600 font-medium mt-2">
{t("mixedBooking.nonHotelNote")}
</p>
)}
{hasHotel && (
<p className="text-sm font-medium text-foreground mt-2">
{t(`mixedBooking.roomTypes.${selectedRoom}`)}: {roomPrice}
</p>
)}
</div>
<div className="px-6 pt-4 pb-2 bg-card">
<Label className="block text-sm font-medium text-foreground mb-3">
{t("mixedBooking.hotelQuestion")}
</Label>
<div className="flex gap-3 mb-4">
<button
onClick={() => setWantsHotel((prev) => ({ ...prev, [pkg.id]: true }))}
className={`flex-1 flex items-center justify-center gap-2 px-4 py-3 rounded-xl border-2 text-sm font-medium transition-all duration-200 ${
hasHotel
? "border-primary bg-primary/5 text-primary"
: "border-input bg-background text-muted-foreground hover:border-primary/30"
}`}
>
<CheckCircle2 className={`w-5 h-5 ${hasHotel ? "text-primary" : "text-muted-foreground"}`} />
{t("mixedBooking.hotelYes")}
</button>
<button
onClick={() => setWantsHotel((prev) => ({ ...prev, [pkg.id]: false }))}
className={`flex-1 flex items-center justify-center gap-2 px-4 py-3 rounded-xl border-2 text-sm font-medium transition-all duration-200 ${
!hasHotel
? "border-primary bg-primary/5 text-primary"
: "border-input bg-background text-muted-foreground hover:border-primary/30"
}`}
>
<Circle className={`w-5 h-5 ${!hasHotel ? "text-primary" : "text-muted-foreground"}`} />
{t("mixedBooking.hotelNo")}
</button>
</div>
{hasHotel && (
<>
<Label className="block text-sm font-medium text-foreground mb-2">
{t("mixedBooking.selectRoom")}
</Label>
<Select
value={selectedRoom}
onValueChange={(value) =>
setSelectedRooms((prev) => ({
...prev,
[pkg.id]: value as RoomType,
}))
}
>
<SelectTrigger className={`w-full rounded-xl border px-4 py-3 text-sm text-foreground shadow-sm transition-colors duration-200 ${
isFeatured
? "border-primary/30 bg-primary/5 hover:border-primary/50"
: "border-input bg-background hover:border-primary/30"
}`}>
<SelectValue placeholder={t("mixedBooking.selectRoom")} />
</SelectTrigger>
<SelectContent>
{ROOM_TYPES.map((room) => (
<SelectItem key={room.id} value={room.id}>
{t(`mixedBooking.roomTypes.${room.id}`)}
</SelectItem>
))}
</SelectContent>
</Select>
</>
)}
</div>
<div className="px-6 pt-4 pb-6 flex-1 flex flex-col justify-between bg-card">
<ul className="space-y-2.5 mb-6">
{features.map((feature: string, idx: number) => (
<li key={idx} className="flex items-start gap-2.5 text-sm text-foreground/80">
<Check className={`w-4 h-4 mt-0.5 flex-shrink-0 ${
isFeatured ? "text-primary" : "text-secondary"
}`} />
<span>{feature}</span>
</li>
))}
</ul>
</div>
</motion.div>
);
})}
</div>
</div>
</section>
);
};
export default MixedBookingSection;

View File

@@ -88,6 +88,16 @@ const PracticalSection = () => {
<div key={h.method} className="bg-card rounded-lg p-3">
<p className="font-medium text-foreground text-sm">{methodLabel}</p>
<p className="text-xs text-muted-foreground">{h.details}</p>
{h.link && (
<a
href={h.link}
target="_blank"
rel="noopener noreferrer"
className="inline-block mt-2 px-3 py-1 bg-primary text-primary-foreground text-xs rounded hover:bg-primary/90 transition-colors"
>
{t("info.viewOnMap")}
</a>
)}
</div>
);
})}

View File

@@ -22,18 +22,27 @@ import djklebynho from "@/assets/staff/djklebynho.jpg";
import letialex from "@/assets/staff/letialex.jpg";
import djcathie from "@/assets/staff/djcathie.jpg";
import gal1 from "@/assets/gallery/gal1.jpg";
import gal2 from "@/assets/gallery/gal2.jpg";
import gal3 from "@/assets/gallery/gal3.jpg";
import gal4 from "@/assets/gallery/gal4.jpg";
import gal5 from "@/assets/gallery/gal5.jpg";
import gal6 from "@/assets/gallery/gal6.jpg";
// ---- INFORMACIÓN GENERAL DEL EVENTO ----
export const EVENT_INFO = {
/** Fecha del evento — formato ISO para el countdown */
date: "2026-09-04T12:00:00",
venue: "[Nombre del Venue]",
venueAddress: "[Dirección del venue, Barcelona]",
venue: "Hotel Don Angel",
venueAddress: "Carrer de la Riera, 123, 08001 Barcelona, Spain",
/** Google Maps embed URL — reemplazar con la URL real */
mapEmbedUrl: "https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2993.5!2d2.1734!3d41.3851!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x0!2zNDHCsDIzJzA2LjQiTiAywrAxMCcyNC4yIkU!5e0!3m2!1ses!2ses!4v1234567890",
mapEmbedUrl: "https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2982.0132199519758!2d2.718142676474322!3d41.63384568067116!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x12bb3e942c5ac469%3A0x9153afdd8d15d0c1!2sHotel%20Don%20Angel!5e0!3m2!1ses!2sus!4v1777971058774!5m2!1ses!2sus",
};
// ---- WEBHOOK N8N ----
/**
* CONFIGURACIÓN DEL WEBHOOK:
@@ -249,13 +258,11 @@ export const HOTEL_ROOMS = [
// ---- INFORMACIÓN PRÁCTICA ----
export const PRACTICAL_INFO = {
airports: [
{ name: "Aeropuerto de Barcelona-El Prat (BCN)", distance: "~15 km del venue" },
{ name: "Aeropuerto de Girona (GRO)", distance: "~100 km del venue" },
{ name: "Aeropuerto de Reus (REU)", distance: "~110 km del venue" },
{ name: "Aeropuerto de Barcelona-El Prat (BCN)", distance: "~85 km del Hotel" },
{ name: "Aeropuerto de Girona (GRO)", distance: "~48 km del Hotel" },
],
howToGet: [
{ method: "Metro", details: "[Línea y parada más cercana]" },
{ method: "Bus", details: "[Líneas de bus cercanas]" },
{ method: "Metro", details: "Línea y parada más cercana", link: "https://maps.app.goo.gl/YVyASwX2odX1mW5J6" },
{ method: "Taxi/Uber", details: "Disponible desde cualquier punto de Barcelona" },
],
};
@@ -266,21 +273,87 @@ export const PRACTICAL_INFO = {
* Para importar: import img from "@/assets/gallery/photo1.jpg"
*/
export const GALLERY_IMAGES = [
{ src: "", alt: "[Descripción foto 1]" },
{ src: "", alt: "[Descripción foto 2]" },
{ src: "", alt: "[Descripción foto 3]" },
{ src: "", alt: "[Descripción foto 4]" },
{ src: "", alt: "[Descripción foto 5]" },
{ src: "", alt: "[Descripción foto 6]" },
{ src: gal1, alt: "[Descripción foto 1]" },
{ src: gal2, alt: "[Descripción foto 2]" },
{ src: gal3, alt: "[Descripción foto 3]" },
{ src: gal4, alt: "[Descripción foto 4]" },
{ src: gal5, alt: "[Descripción foto 5]" },
{ src: gal6, alt: "[Descripción foto 6]" },
];
// ---- PAQUETES MIXTOS (Room + Pass) ----
export type RoomType = "individual" | "double" | "suite";
export type PassType = "full" | "party";
export const ROOM_TYPES: { id: RoomType }[] = [
{ id: "individual" },
{ id: "double" },
{ id: "suite" },
];
// ---- PRECIOS DINÁMICOS FULL PASS ----
/**
* Calcula el precio del Full Pass según la fecha actual.
* - Hasta 1 de julio: 170€
* - 1 de julio - 1 de septiembre: 190€
* - Después del inicio del evento: 200€ (último precio)
*/
export function getFullPassPrice(): { price: number; isLastPrice: boolean } {
const now = new Date();
const julyFirst = new Date("2026-07-01T00:00:00");
const septemberFirst = new Date("2026-09-01T00:00:00");
const eventStart = new Date(EVENT_INFO.date);
if (now < julyFirst) {
return { price: 170, isLastPrice: false };
} else if (now < septemberFirst) {
return { price: 190, isLastPrice: false };
} else {
// After event starts
return { price: 200, isLastPrice: true };
}
}
export const MIXED_BOOKING_PACKAGES = [
{ id: "full" as PassType, label: "full", roomPrices: { individual: 100, double: 150, suite: 213 } },
{ id: "party" as PassType, label: "party", roomPrices: { individual: 100, double: 150, suite: 213 } },
];
// ---- SECCIONES VISIBLES ----
export const SECTIONS = {
about: true,
org: true,
staff: true,
profesores: true,
schedule: true,
booking: false,
mixed_booking: true,
hotel: false,
practical: true,
gallery: true,
};
// ---- NAVEGACIÓN ----
export const NAV_LINKS = [
const HREF_TO_SECTION: Record<string, keyof typeof SECTIONS> = {
"#about": "about",
"#staff": "staff",
"#schedule": "schedule",
"#booking": "booking",
"#mixed-booking": "mixed_booking",
"#hotel": "hotel",
"#info": "practical",
"#gallery": "gallery",
};
export const NAV_LINKS = (
[
{ href: "#about" },
{ href: "#staff" },
{ href: "#schedule" },
{ href: "#booking" },
{ href: "#mixed-booking" },
{ href: "#hotel" },
{ href: "#info" },
{ href: "#gallery" },
];
] as const
).filter((link) => SECTIONS[HREF_TO_SECTION[link.href]]);

View File

@@ -4,14 +4,15 @@
"staff": "Staff",
"schedule": "Schedule",
"booking": "Book your pass",
"mixed-booking": "Packs",
"hotel": "Hotel",
"info": "Info",
"gallery": "Gallery"
},
"hero": {
"title": "Zouk Lambada Barcelona",
"subtitle": "International Dance Festival",
"dates": "June 20-22, 2025",
"subtitle": "Beach Festival",
"dates": "04 - 07 September 2026",
"location": "Barcelona, Spain",
"registerButton": "Register Now",
"whatsappButton": "Join WhatsApp Group",
@@ -56,9 +57,9 @@
"schedule": {
"title": "Schedule",
"subtitle": "Three days of workshops, shows and social dance.",
"friday": "Friday, June 20",
"saturday": "Saturday, June 21",
"sunday": "Sunday, June 22",
"friday": "Friday, September 04",
"saturday": "Saturday, September 05",
"sunday": "Sunday, September 06",
"workshop": "Workshop",
"break": "Break",
"social": "Social Dance",
@@ -123,6 +124,33 @@
"description": "[Brief room description]",
"bookButton": "Book at hotel"
},
"mixedBooking": {
"title": "Room + Pass Bundles",
"subtitle": "Room + Pass bundles for your stay.",
"priceTBD": "Price TBA",
"selectRoom": "Choose room type",
"popular": "Popular",
"lastPrice": "Last Price",
"perPerson": "/ person",
"perParty": "/ party",
"hotelQuestion": "Do you need a hotel room?",
"hotelYes": "Yes",
"hotelNo": "No",
"nonHotelNote": "+50€ fee for not staying in hotel",
"roomTypes": {
"individual": "Single Room",
"double": "Double Room",
"suite": "Triple Room"
},
"passTypes": {
"full": "Full Pass",
"party": "Party Pass"
},
"fullDescription": "Full access to all workshops, socials, and festival activities",
"fullFeatures": "All workshops|All social dances|Live shows|DJ sets",
"partyDescription": "Price for each party individually, even pool parties.",
"partyFeatures": "Friday party|Saturday party|Sunday farewell party|DJ sets"
},
"info": {
"title": "Practical Information",
"airports": "Nearby Airports",
@@ -134,7 +162,8 @@
"busLines": "[Nearby bus lines]",
"taxiDetails": "Available from anywhere in Barcelona",
"venue": "Event Venue",
"mapTitle": "Event Location"
"mapTitle": "Event Location",
"viewOnMap": "View on map"
},
"gallery": {
"title": "Gallery"

View File

@@ -4,14 +4,15 @@
"staff": "Staff",
"schedule": "Programa",
"booking": "Reservar",
"mixed-booking": "Packs",
"hotel": "Hotel",
"info": "Info",
"gallery": "Galería"
},
"hero": {
"title": "Zouk Lambada Barcelona",
"subtitle": "Festival Internacional de Baile",
"dates": "20-22 Junio 2025",
"subtitle": "Beach Festival",
"dates": "04 - 07 Setiembre 2026",
"location": "Barcelona, España",
"registerButton": "Registrarse Ahora",
"whatsappButton": "Unirse al Grupo de WhatsApp",
@@ -56,9 +57,9 @@
"schedule": {
"title": "Programa",
"subtitle": "Tres días de workshops, shows y social dance.",
"friday": "Viernes 20 Junio",
"saturday": "Sábado 21 Junio",
"sunday": "Domingo 22 Junio",
"friday": "Viernes 04 Setiembre",
"saturday": "Sábado 05 Setiembre",
"sunday": "Domingo 06 Setiembre",
"workshop": "Workshop",
"break": "Pausa",
"social": "Social Dance",
@@ -123,6 +124,33 @@
"description": "[Descripción breve de la habitación]",
"bookButton": "Reservar en el hotel"
},
"mixedBooking": {
"title": "Packs de Habitación + Pase",
"subtitle": "Combina habitación + pase para tu estancia.",
"priceTBD": "Precio por confirmar",
"selectRoom": "Elige tipo de habitación",
"popular": "Popular",
"lastPrice": "Último Precio",
"perPerson": "/ persona",
"perParty": "/ fiesta",
"hotelQuestion": "¿Necesitas habitación de hotel?",
"hotelYes": "Sí",
"hotelNo": "No",
"nonHotelNote": "+50€ por no alojarse en hotel",
"roomTypes": {
"individual": "Habitación Individual",
"double": "Habitación Doble",
"suite": "Habitación Triple"
},
"passTypes": {
"full": "Full Pass",
"party": "Party Pass"
},
"fullDescription": "Acceso completo a todos los workshops, sociales y actividades del festival",
"fullFeatures": "Todos los workshops|Todas las social dances|Shows en vivo|DJ sets",
"partyDescription": "Precio individual por cada fiesta, incluso las pool parties.",
"partyFeatures": "Fiesta del viernes|Fiesta del sábado|Fiesta despedida del domingo|DJ sets"
},
"info": {
"title": "Información Práctica",
"airports": "Aeropuertos Cercanos",
@@ -134,7 +162,8 @@
"busLines": "[Líneas de bus cercanas]",
"taxiDetails": "Disponible desde cualquier punto de Barcelona",
"venue": "Lugar del Evento",
"mapTitle": "Ubicación del evento"
"mapTitle": "Ubicación del evento",
"viewOnMap": "Ver en mapa"
},
"gallery": {
"title": "Galería"
@@ -146,7 +175,7 @@
"title": "ZoukLambadaBCN",
"contact": "Contacto",
"followUs": "Síguenos",
"email": "[email@zouklambadabcn.com]",
"email": "[info@zouklambadabcn.com]",
"copyright": "© {{year}} ZoukLambadaBCN. Todos los derechos reservados."
},
"language": {

View File

@@ -6,11 +6,13 @@ import StaffSection from "@/components/StaffSection";
import ProfesoresSection from "@/components/ProfesoresSection";
import ScheduleSection from "@/components/ScheduleSection";
import BookingSection from "@/components/BookingSection";
import MixedBookingSection from "@/components/MixedBookingSection";
import HotelSection from "@/components/HotelSection";
import PracticalSection from "@/components/PracticalSection";
import GallerySection from "@/components/GallerySection";
import FooterSection from "@/components/FooterSection";
import FloatingButton from "@/components/FloatingButton";
import { SECTIONS } from "@/data/event-data";
/**
* Landing page — Lambada Festival Barcelona
@@ -23,15 +25,16 @@ const Index = () => {
<div className="min-h-screen">
<Navbar />
<HeroSection />
<AboutSection />
<OrgSection />
<StaffSection />
<ProfesoresSection />
<ScheduleSection />
<BookingSection />
<HotelSection />
<PracticalSection />
<GallerySection />
{SECTIONS.about && <AboutSection />}
{SECTIONS.org && <OrgSection />}
{SECTIONS.staff && <StaffSection />}
{SECTIONS.profesores && <ProfesoresSection />}
{SECTIONS.schedule && <ScheduleSection />}
{SECTIONS.booking && <BookingSection />}
{SECTIONS.mixed_booking && <MixedBookingSection />}
{SECTIONS.hotel && <HotelSection />}
{SECTIONS.practical && <PracticalSection />}
{SECTIONS.gallery && <GallerySection />}
<FooterSection />
<FloatingButton />
</div>