diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml index c5e94da..cb53dc7 100644 --- a/.gitea/workflows/deploy.yaml +++ b/.gitea/workflows/deploy.yaml @@ -1,9 +1,9 @@ -name: Deploy NPM app +name: Deploy Docker container run-name: ${{ gitea.actor }} is deploying to PROD servers. on: [ push, fork, pull ] jobs: - Deploy NPM: + Deploy: runs-on: ubuntu-latest steps: - name: Check out repository code @@ -18,7 +18,7 @@ jobs: script: | cd /home/zouklambadabcn.com/public_html/ git pull - npm install - npm run build - pm2 restart ZLB + docker compose down + docker compose up -d --build + docker image prune -f - run: echo "🍏 This job's status is ${{ job.status }}." diff --git a/src/components/MixedBookingSection.tsx b/src/components/MixedBookingSection.tsx index 3801fe7..931600d 100644 --- a/src/components/MixedBookingSection.tsx +++ b/src/components/MixedBookingSection.tsx @@ -3,7 +3,7 @@ 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, ExternalLink } from "lucide-react"; +import { Check, Star, Circle, CheckCircle2, ExternalLink, MapPin, Calendar, Clock, Navigation } from "lucide-react"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; @@ -11,6 +11,7 @@ import { Button } from "@/components/ui/button"; const FEATURED_PASS = "full"; const NON_HOTEL_FEE = 50; const PARTY_PRICE = 25; +const GOOGLE_MAPS_URL = "https://www.google.com/maps/search/Sala+Vivaldi+Barcelona"; const MixedBookingSection = () => { const { t } = useTranslation(); @@ -43,23 +44,21 @@ const MixedBookingSection = () => {

{t("mixedBooking.subtitle")}

-
- {MIXED_BOOKING_PACKAGES.map((pkg, i) => { +
+ {MIXED_BOOKING_PACKAGES.filter(pkg => pkg.id !== "whiteparty").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; @@ -233,6 +232,96 @@ const MixedBookingSection = () => { ); })} + + {/* White Party Special Card */} + + {/* Tropical beach background */} +
+
+ + {/* Content overlay */} +
+ {/* Header */} +
+
+
+

+ WHITE PARTY +

+

+ {t("mixedBooking.whitepartyDescription")} +

+
+
+ + {/* Event details */} +
+
+
+ + {t("mixedBooking.whitepartyDate")} +
+
+ + {t("mixedBooking.whitepartyTime")} +
+
+ +
+ Sala Vivaldi + C/Llança, 5 +
+
+
+ + {/* Warning */} +
+

+ {t("mixedBooking.whitepartyNotIncluded")} +

+
+
+ + {/* Features */} +
+
    + {t("mixedBooking.whitepartyFeatures").split("|").map((feature: string, idx: number) => ( +
  • + + {feature.trim()} +
  • + ))} +
+
+ + {/* Google Maps Button */} + +
+
diff --git a/src/data/event-data.ts b/src/data/event-data.ts index 0856c1d..7cfa8b4 100644 --- a/src/data/event-data.ts +++ b/src/data/event-data.ts @@ -280,7 +280,7 @@ export const GALLERY_IMAGES = [ // ---- PAQUETES MIXTOS (Room + Pass) ---- export type RoomType = "individual" | "double" | "suite"; -export type PassType = "full" | "party"; +export type PassType = "full" | "party" | "whiteparty"; export const ROOM_TYPES: { id: RoomType }[] = [ { id: "individual" }, @@ -314,6 +314,7 @@ export function getFullPassPrice(): { price: number; isLastPrice: boolean; valid 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 } }, + { id: "whiteparty" as PassType, label: "whiteparty", roomPrices: { individual: 0, double: 0, suite: 0 } }, ]; // ---- SECCIONES VISIBLES ---- diff --git a/src/locales/en.json b/src/locales/en.json index 729bc60..45a20ea 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -147,13 +147,20 @@ }, "passTypes": { "full": "Full Pass", - "party": "Party Pass" + "party": "Party Pass", + "whiteparty": "White Party" }, "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", - "goToReservations": "Go to reservations" + "whitepartyDescription": "Closing party in Sala Vivaldi, with an elegant and exclusive atmosphere.", + "whitepartyFeatures": "Dress code: White|Amazing DJ", + "whitepartyNotIncluded": "Not included in Full Pass - Separate payment required", + "whitepartyTime": "21h to 1h", + "whitepartyDate": "Monday 7 September", + "goToReservations": "Go to reservations", + "viewOnMap": "View on Google Maps" }, "info": { "title": "Practical Information", diff --git a/src/locales/es.json b/src/locales/es.json index 267e1a8..4e32466 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -147,13 +147,20 @@ }, "passTypes": { "full": "Full Pass", - "party": "Party Pass" + "party": "Party Pass", + "whiteparty": "White Party" }, "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", - "goToReservations": "Ir a reservas" + "whitepartyDescription": "Fiesta de clausura en la Sala Vivaldi, con un ambiente elegante y exclusivo.", + "whitepartyFeatures": "Código de vestimenta: Blanco|DJ Inigualable", + "whitepartyNotIncluded": "No incluido en Full Pass - Pago separado requerido", + "whitepartyTime": "21h a 1h", + "whitepartyDate": "Lunes 7 de Septiembre", + "goToReservations": "Ir a reservas", + "viewOnMap": "Ver en Google Maps" }, "info": { "title": "Información Práctica",