1167 lines
59 KiB
TypeScript
1167 lines
59 KiB
TypeScript
"use client";
|
||
|
||
import { motion, AnimatePresence } from "framer-motion";
|
||
import { useRef, useState, useEffect } from "react";
|
||
import type { DemoData } from "@/data/demos";
|
||
|
||
const fadeUp = {
|
||
hidden: { opacity: 0, y: 35 },
|
||
show: { opacity: 1, y: 0, transition: { duration: 0.75, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||
};
|
||
|
||
const stagger = {
|
||
hidden: {},
|
||
show: { transition: { staggerChildren: 0.1 } },
|
||
};
|
||
|
||
const translations = {
|
||
tr: {
|
||
navBook: "Rezervasyon",
|
||
navTariffs: "Tarifeler",
|
||
navBenefits: "Ayrıcalıklar",
|
||
navApp: "Mobil Uygulama",
|
||
navReviews: "Misafir Yorumları",
|
||
callCenter: "Çağrı Merkezi",
|
||
bookNow: "Rezervasyon Yap",
|
||
badge: "NYC GÜVENİLİR PRİVATE CAB AĞI",
|
||
heroTitlePart1: "NYC'DE LÜKS",
|
||
heroTitlePart2: "BİR SEYAHAT?",
|
||
heroTitlePart3: "ÖZEL ŞOFÖRLÜ HAVAALANI TRANSFER SERVİSİ",
|
||
heroDesc: "New York genelinde 7/24 güvenli, yüksek konforlu özel araç hizmetleri. Havalimanı lounge transferlerinizi anında hesaplayın ve stressiz planlayın.",
|
||
instantBooking: "Hızlı Telefon Hattı",
|
||
getQuote: "Seyahat Hesapla",
|
||
viewTariffs: "Tarifeleri İncele",
|
||
fastFormSubtitle: "Hızlı Seyahat Formu",
|
||
fastFormTitle: "MİL HESAPLA & AYIRT",
|
||
fastFormDesc: "Konum parametrelerinizi girerek seyahat tutarınızı anında hesaplayın ve rezervasyon oluşturun.",
|
||
formName: "Ad Soyad",
|
||
formNamePlaceholder: "Adınız Soyadınız",
|
||
formPhone: "Telefon Numarası",
|
||
formPhonePlaceholder: "İletişim Numaranız",
|
||
formDate: "Tarih",
|
||
formTime: "Saat",
|
||
formPickup: "Alış Noktası",
|
||
formDropoff: "Varış Noktası",
|
||
chooseVehicle: "Araç Sınıfı Seçimi",
|
||
submitBooking: "REZERVASYONU BAŞLAT",
|
||
dispatchWarning: "Bu formu gönderdiğinizde, sürücümüz sizinle 3 dakika içinde iletişime geçecektir.",
|
||
tariffsSubtitle: "Esnek Fiyatlar",
|
||
tariffsTitle: "TARİFELERİMİZ",
|
||
tariffsDesc: "Seyahatlerinize en uygun lüks araç segmentini ve ücretlendirmelerini keşfedin.",
|
||
popular: "EN ÇOK TERCİH EDİLEN",
|
||
perMile: "/ MİL",
|
||
bookTariff: "BU TARİFEYİ SEÇ",
|
||
benefitsSubtitle: "Özel Ayrıcalıklar",
|
||
benefitsTitle: "HİZMET KALİTEMİZ",
|
||
benefitsDesc: "New York'taki iş dünyasının ve seçkin yolcuların bizi tercih etmesinin nedenleri.",
|
||
appSubtitle: "Uygulamayı İndirin",
|
||
appTitle: "MOBİL CAB UYGULAMASI",
|
||
appDesc: "CabHub mobil uygulamasını telefonunuza indirin. 7/24 GPS takibi yapın, uçuş rötar senkronizasyonu ile en özel fiyatlardan faydalanın.",
|
||
getItOn: "HEMEN İNDİRİN",
|
||
googlePlay: "Google Play Store",
|
||
appStore: "App Store",
|
||
reviewsSubtitle: "Müşteri Deneyimleri",
|
||
reviewsTitle: "MUTLU YOLCULARIMIZ",
|
||
reviewsDesc: "Sık seyahat eden iş insanlarımızın CabHub özel şoför hizmeti hakkındaki yorumları.",
|
||
callStripText: "7 GÜN 24 SAAT ÇAĞRILARINIZI CEVAPLAMAYA HAZIRIZ!",
|
||
footerRights: "Tüm hakları saklıdır.",
|
||
footerPrivacy: "Gizlilik Politikası",
|
||
footerTerms: "Kullanım Şartları",
|
||
bookingRequested: "REZERVASYON ALINDI",
|
||
nycDispatchActive: "NYC Sürücü Atama Hattı Aktif",
|
||
successDesc: "Seyahat parametrelerinizi kaydettik. En yakın CabHub lüks aracı ve sürücüsü 3 dakika içinde sizinle iletişime geçecektir. Keyifli yolculuklar dileriz!",
|
||
dismiss: "KAPAT",
|
||
conceptBanner: "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır.",
|
||
calcEstimated: "Tahmini Tutar:",
|
||
calcLoading: "Hesaplanıyor...",
|
||
min: "dk",
|
||
calculatingText: "Mesafe bazlı anlık ücretlendirme"
|
||
},
|
||
en: {
|
||
navBook: "Book Cab",
|
||
navTariffs: "Tariffs",
|
||
navBenefits: "Why Us",
|
||
navApp: "Mobile App",
|
||
navReviews: "Reviews",
|
||
callCenter: "Call Center",
|
||
bookNow: "Book Now",
|
||
badge: "NYC TRUSTED PRIVATE CAB NETWORK",
|
||
heroTitlePart1: "NEED A",
|
||
heroTitlePart2: "PREMIUM RIDE?",
|
||
heroTitlePart3: "NYC'S PREMIER PRIVATE TRANSFERS",
|
||
heroDesc: "Safe, high-fidelity premium luxury rides available 24/7 across New York City. Book instantly from our modern standard line or download our custom voucher app for secure rides.",
|
||
instantBooking: "Instant Booking Line",
|
||
getQuote: "Calculate Fare",
|
||
viewTariffs: "View Tariffs",
|
||
fastFormSubtitle: "Fast Ride Form",
|
||
fastFormTitle: "BOOK A CAB",
|
||
fastFormDesc: "Fill in your destination parameters below to calculate estimated fares and allocate a nearby premium cab.",
|
||
formName: "Name",
|
||
formNamePlaceholder: "Your full name",
|
||
formPhone: "Phone",
|
||
formPhonePlaceholder: "Contact Number",
|
||
formDate: "Date",
|
||
formTime: "Time",
|
||
formPickup: "Start Location",
|
||
formDropoff: "End Destination",
|
||
chooseVehicle: "Choose Vehicle",
|
||
submitBooking: "SUBMIT BOOKING",
|
||
dispatchWarning: "By submitting this form, you trigger immediate dispatch. A professional verified driver will contact you in under 3 minutes.",
|
||
tariffsSubtitle: "Flexible Rates",
|
||
tariffsTitle: "OUR TARIFFS",
|
||
tariffsDesc: "Choose the perfect ride category structured to fit your travel coordinates.",
|
||
popular: "POPULAR CHOICE",
|
||
perMile: "/ MILE",
|
||
bookTariff: "BOOK TARIFF",
|
||
benefitsSubtitle: "Premium Values",
|
||
benefitsTitle: "SOME BENEFITS",
|
||
benefitsDesc: "Why thousands of New Yorkers and high-profile businesses trust our private network.",
|
||
appSubtitle: "Download App",
|
||
appTitle: "BEST CAB SERVICES",
|
||
appDesc: "Download the CabHub voucher application on your phone. Book local transfers, coordinate with drivers using real-time GPS search, and access exclusive 40% member benefits dynamically.",
|
||
getItOn: "GET IT ON",
|
||
googlePlay: "Google Play",
|
||
appStore: "App Store",
|
||
reviewsSubtitle: "Testimonials",
|
||
reviewsTitle: "HAPPY CLIENTS",
|
||
reviewsDesc: "Hear what frequent business travelers say about the CabHub ride coordination.",
|
||
callStripText: "WE ARE READY TO TAKE YOUR CALL 24 HOURS, 7 DAYS!",
|
||
footerRights: "All rights reserved.",
|
||
footerPrivacy: "Privacy Policy",
|
||
footerTerms: "Terms of Service",
|
||
bookingRequested: "BOOKING REQUESTED",
|
||
nycDispatchActive: "NYC Dispatch Line Active",
|
||
successDesc: "We have registered your travel parameters. A professional verified CabHub chauffeur will reach out on your contact number in under 3 minutes. Thank you!",
|
||
dismiss: "DISMISS",
|
||
conceptBanner: "This website is a premium concept prototype designed by Ayris Tech.",
|
||
calcEstimated: "Estimated Fare:",
|
||
calcLoading: "Calculating...",
|
||
min: "min",
|
||
calculatingText: "Real-time coordinate-based pricing"
|
||
}
|
||
};
|
||
|
||
const locationsList = [
|
||
"Manhattan Midtown",
|
||
"Brooklyn Heights",
|
||
"Queens Astoria",
|
||
"JFK Airport",
|
||
"LaGuardia Airport"
|
||
];
|
||
|
||
export default function TaxiTemplate({ data }: { data: DemoData }) {
|
||
const { firma, istatistikler = [], hizmetler = [], yorumlar = [] } = data;
|
||
const [showBookingModal, setShowBookingModal] = useState(false);
|
||
const [activePlan, setActivePlan] = useState<number>(1); // Standard Class active by default
|
||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||
const [preloader, setPreloader] = useState(true);
|
||
|
||
// Fare Calculator states
|
||
const [pickupLoc, setPickupLoc] = useState("Manhattan Midtown");
|
||
const [dropoffLoc, setDropoffLoc] = useState("Brooklyn Heights");
|
||
|
||
const t = translations[lang];
|
||
|
||
const getIconSvg = (type: string) => {
|
||
switch (type) {
|
||
case "pickup":
|
||
return (
|
||
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 21v-4.875c0-.621.504-1.125 1.125-1.125h5.25c.621 0 1.125.504 1.125 1.125V21m0 0h4.5V3.545M12.75 7.5h.008v.008h-.008V7.5Zm0 2.25h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008v-.008Zm-4.5-9h.008v.008H8.25V7.5Zm0 2.25h.008v.008H8.25v-.008Zm0 2.25h.008v.008H8.25v-.008Zm0 2.25h.008v.008H8.25v-.008Zm-3.75 9H3.75V3.545m0 0A2.24 2.24 0 0 1 6 1.375c.66 0 1.272.285 1.706.777l.01.012M3.75 3.545V21h4.5M18.75 3.545V21h-4.5" />
|
||
</svg>
|
||
);
|
||
case "booking":
|
||
return (
|
||
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 0 0 6 3.75v16.5a2.25 2.25 0 0 0 2.25 2.25h7.5A2.25 2.25 0 0 0 18 20.25V3.75a2.25 2.25 0 0 0-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3" />
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 13.5l10.5-11.25L12 9h8.25L9.75 20.25 12 13.5H3.75Z" />
|
||
</svg>
|
||
);
|
||
case "bonus":
|
||
return (
|
||
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M21 11.25v8.25a1.5 1.5 0 0 1-1.5 1.5H5.25a1.5 1.5 0 0 1-1.5-1.5v-8.25M12 4.875A2.625 2.625 0 1 0 9.375 7.5H12m0-2.625V7.5m-9 3.75h18M12 7.5v13.5" />
|
||
</svg>
|
||
);
|
||
case "gps":
|
||
return (
|
||
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 6.75h15m-15 4.5h15m-15 4.5h15M3 6.75h.008v.008H3V6.75Zm0 4.5h.008v.008H3v-.008Zm0 4.5h.008v.008H3v-.008Z" />
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25s-7.5-4.108-7.5-11.25a7.5 7.5 0 1 1 15 0Z" />
|
||
</svg>
|
||
);
|
||
default:
|
||
return (
|
||
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||
</svg>
|
||
);
|
||
}
|
||
};
|
||
|
||
// 1. Lenis Smooth Scroll Setup
|
||
useEffect(() => {
|
||
let lenis: any;
|
||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||
lenis = new Lenis({ duration: 1.2, easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) });
|
||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||
requestAnimationFrame(raf);
|
||
});
|
||
return () => lenis?.destroy();
|
||
}, []);
|
||
|
||
// 2. Preloader timer
|
||
useEffect(() => {
|
||
const timer = setTimeout(() => {
|
||
setPreloader(false);
|
||
}, 1500);
|
||
return () => clearTimeout(timer);
|
||
}, []);
|
||
|
||
// Price estimate logic
|
||
const calculatePrice = () => {
|
||
if (pickupLoc === dropoffLoc) return "$5.00";
|
||
|
||
// JFK flat rates
|
||
if ((pickupLoc === "Manhattan Midtown" && dropoffLoc === "JFK Airport") ||
|
||
(pickupLoc === "JFK Airport" && dropoffLoc === "Manhattan Midtown")) {
|
||
return activePlan === 0 ? "$55.00" : activePlan === 1 ? "$75.00" : "$110.00";
|
||
}
|
||
// LaGuardia flat rates
|
||
if ((pickupLoc === "Manhattan Midtown" && dropoffLoc === "LaGuardia Airport") ||
|
||
(pickupLoc === "LaGuardia Airport" && dropoffLoc === "Manhattan Midtown")) {
|
||
return activePlan === 0 ? "$35.00" : activePlan === 1 ? "$48.00" : "$75.00";
|
||
}
|
||
|
||
// Mileage estimations based on distance
|
||
let miles = 8;
|
||
if ((pickupLoc === "Manhattan Midtown" && dropoffLoc === "Brooklyn Heights") ||
|
||
(pickupLoc === "Brooklyn Heights" && dropoffLoc === "Manhattan Midtown")) miles = 6;
|
||
else if ((pickupLoc === "Manhattan Midtown" && dropoffLoc === "Queens Astoria") ||
|
||
(pickupLoc === "Queens Astoria" && dropoffLoc === "Manhattan Midtown")) miles = 7;
|
||
else if ((pickupLoc === "Brooklyn Heights" && dropoffLoc === "Queens Astoria") ||
|
||
(pickupLoc === "Queens Astoria" && dropoffLoc === "Brooklyn Heights")) miles = 10;
|
||
else if ((pickupLoc === "Brooklyn Heights" && dropoffLoc === "JFK Airport") ||
|
||
(pickupLoc === "JFK Airport" && dropoffLoc === "Brooklyn Heights")) miles = 16;
|
||
else if ((pickupLoc === "Brooklyn Heights" && dropoffLoc === "LaGuardia Airport") ||
|
||
(pickupLoc === "LaGuardia Airport" && dropoffLoc === "Brooklyn Heights")) miles = 14;
|
||
else if ((pickupLoc === "Queens Astoria" && dropoffLoc === "JFK Airport") ||
|
||
(pickupLoc === "JFK Airport" && dropoffLoc === "Queens Astoria")) miles = 12;
|
||
else if ((pickupLoc === "Queens Astoria" && dropoffLoc === "LaGuardia Airport") ||
|
||
(pickupLoc === "LaGuardia Airport" && dropoffLoc === "Queens Astoria")) miles = 6;
|
||
else if ((pickupLoc === "JFK Airport" && dropoffLoc === "LaGuardia Airport") ||
|
||
(pickupLoc === "LaGuardia Airport" && dropoffLoc === "JFK Airport")) miles = 12;
|
||
|
||
const basePrice = miles * 1.6 + 5.0;
|
||
const multiplier = activePlan === 0 ? 1.0 : activePlan === 1 ? 1.5 : 2.2;
|
||
return `$${(basePrice * multiplier).toFixed(2)}`;
|
||
};
|
||
|
||
// Dynamic Localization handlers
|
||
const getLocalizedStat = (deger: string) => {
|
||
if (deger.toLowerCase().includes("economy")) {
|
||
return {
|
||
title: lang === "tr" ? "Ekonomi Sınıfı" : "Economy Class",
|
||
desc: lang === "tr" ? "Şehir içi seyahatleriniz için ideal, konforlu ve ekonomik ulaşım. Mil başı $1.50." : "Optimal zero-emission trips to any destination within boroughs. $1.5/MI"
|
||
};
|
||
}
|
||
if (deger.toLowerCase().includes("standard")) {
|
||
return {
|
||
title: lang === "tr" ? "Standart Sınıf" : "Standard Class",
|
||
desc: lang === "tr" ? "Havaalanı ve eyaletler arası transferler için premium sedanlar. Mil başı $2.25." : "Premium transfers. Verified luxury sedans covering tri-state airport hubs. $2.25/MI"
|
||
};
|
||
}
|
||
return {
|
||
title: lang === "tr" ? "Business Sınıfı" : "Business Class",
|
||
desc: lang === "tr" ? "Lüks araç filomuz ve öncelikli sürücü atama ayrıcalığı. Mil başı $3.50." : "First class executive. Top-tier luxury vehicles with priority lane dispatch. $3.50/MI"
|
||
};
|
||
};
|
||
|
||
const getLocalizedService = (baslik: string, aciklama: string) => {
|
||
if (baslik.toLowerCase().includes("pickup") || baslik.toLowerCase().includes("home")) {
|
||
return {
|
||
title: lang === "tr" ? "ADRESTEN ALIM" : "HOME PICKUP",
|
||
desc: lang === "tr" ? "Kapınızdan veya otel lobinizden bagaj desteği ve koordinatlı karşılama ile lüks seyahat başlangıcı." : "We run services to serve you more better and to your convenience."
|
||
};
|
||
}
|
||
if (baslik.toLowerCase().includes("booking") || baslik.toLowerCase().includes("fast")) {
|
||
return {
|
||
title: lang === "tr" ? "KOLAY REZERVASYON" : "FAST BOOKING",
|
||
desc: lang === "tr" ? "Sadece birkaç tıkla seyahat parametrelerinizi belirleyin, stressiz rezervasyon yapın." : "Our book method is very fast and easy. It won't stress you."
|
||
};
|
||
}
|
||
if (baslik.toLowerCase().includes("bonus") || baslik.toLowerCase().includes("member")) {
|
||
return {
|
||
title: lang === "tr" ? "MİL & ÜYELİK AVANTAJLARI" : "BONUSES FOR RIDE",
|
||
desc: lang === "tr" ? "Bizimle yaptığınız her yolculukta mil puanları toplayın, sonraki rezervasyonlarda %40'a varan indirim kazanın." : "When you run services frequently we give you different bonuses that can put a smile on your face."
|
||
};
|
||
}
|
||
return {
|
||
title: lang === "tr" ? "7/24 AKTİF GPS TAKİBİ" : "GPS SEARCHING",
|
||
desc: lang === "tr" ? "Uçuş rötar senkronizasyonu ve 7/24 anlık uydu üzerinden konum takibi ile mutlak güvendesiniz." : "We run services incase you aren't sure of your destination. So you don't have to worry."
|
||
};
|
||
};
|
||
|
||
const getLocalizedTestimonial = (yazar: string) => {
|
||
if (yazar.toLowerCase().includes("john")) {
|
||
return lang === "tr"
|
||
? "CabHub NYC iş seyahatlerimde en güvendiğim ulaşım ortağım oldu. Standart sınıf araçları pırıl pırıldı ve sürücü tüm kestirmeleri biliyordu."
|
||
: "CabHub NYC provided the most reliable ride during my business trip. The standard class vehicle was pristine and the driver knew all the shortcuts.";
|
||
}
|
||
return lang === "tr"
|
||
? "Hızlı rezervasyon sistemi tek kelimeyle kusursuz çalışıyor. Adresten alım tam dakikasında gerçekleşti ve GPS takibi kendimi inanılmaz güvende hissettirdi."
|
||
: "The fast booking system works like a charm. Home pickup was exactly on time and the GPS tracking made me feel incredibly secure.";
|
||
};
|
||
|
||
const css = `
|
||
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;700;900&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Syne:wght@700;800&display=swap');
|
||
|
||
:root {
|
||
--color-taxi-yellow: #F5C518;
|
||
--color-taxi-yellow-rgb: 245, 197, 24;
|
||
--color-coal-dark: #07080A;
|
||
--color-coal-card: #121418;
|
||
--color-coal-card-hover: #181C22;
|
||
--color-text-white: #FFFFFF;
|
||
--color-text-gray: rgba(255, 255, 255, 0.6);
|
||
}
|
||
|
||
.font-industrial {
|
||
font-family: 'Syne', 'Oswald', sans-serif;
|
||
}
|
||
|
||
.font-sans-premium {
|
||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||
}
|
||
|
||
.spinning-badge {
|
||
animation: spin 25s linear infinite;
|
||
}
|
||
|
||
@keyframes spin {
|
||
from { transform: rotate(0deg); }
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
|
||
.bg-mesh-grid {
|
||
background-image:
|
||
linear-gradient(rgba(245, 197, 24, 0.03) 1px, transparent 1px),
|
||
linear-gradient(90deg, rgba(245, 197, 24, 0.03) 1px, transparent 1px);
|
||
background-size: 40px 40px;
|
||
}
|
||
|
||
.glowing-bar {
|
||
box-shadow: 0 0 15px rgba(245, 197, 24, 0.4);
|
||
}
|
||
|
||
.pulse-glow {
|
||
animation: pulse 2s infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0% { box-shadow: 0 0 0 0 rgba(245, 197, 24, 0.5); }
|
||
70% { box-shadow: 0 0 0 15px rgba(245, 197, 24, 0); }
|
||
100% { box-shadow: 0 0 0 0 rgba(245, 197, 24, 0); }
|
||
}
|
||
|
||
.hero-title-clamp {
|
||
font-size: clamp(34px, 5.8vw, 84px);
|
||
letter-spacing: -0.01em;
|
||
line-height: 0.95;
|
||
}
|
||
`;
|
||
|
||
return (
|
||
<>
|
||
<style>{css}</style>
|
||
|
||
{/* ── IMZA AN: HIGH-TECH PRELOADER ── */}
|
||
<AnimatePresence>
|
||
{preloader && (
|
||
<motion.div
|
||
className="fixed inset-0 z-50 bg-[#07080A] flex flex-col items-center justify-center p-6"
|
||
exit={{
|
||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||
}}
|
||
>
|
||
<div className="max-w-md text-center space-y-6">
|
||
<motion.span
|
||
className="text-[9px] font-black tracking-[4px] uppercase text-[#F5C518] block font-sans-premium"
|
||
initial={{ opacity: 0, y: 10 }}
|
||
animate={{ opacity: 1, y: 0 }}
|
||
transition={{ duration: 0.5 }}
|
||
>
|
||
CABHUB DISPATCH SYSTEM
|
||
</motion.span>
|
||
<div className="h-[2px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||
<motion.div
|
||
className="absolute inset-y-0 left-0 bg-[#F5C518] glowing-bar"
|
||
initial={{ width: "0%" }}
|
||
animate={{ width: "100%" }}
|
||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||
/>
|
||
</div>
|
||
<motion.h2
|
||
className="font-industrial text-white text-base font-black tracking-widest uppercase"
|
||
initial={{ opacity: 0 }}
|
||
animate={{ opacity: 1 }}
|
||
transition={{ delay: 0.4, duration: 0.5 }}
|
||
>
|
||
connecting...
|
||
</motion.h2>
|
||
</div>
|
||
</motion.div>
|
||
)}
|
||
</AnimatePresence>
|
||
|
||
{/* ── MANDATORY FLOATING DEMO BANNER ── */}
|
||
<div className="fixed bottom-4 left-4 z-40 bg-[#121418]/95 backdrop-blur-md border border-[#F5C518]/20 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||
<div className="w-1.5 h-1.5 rounded-full bg-[#F5C518] animate-pulse" />
|
||
<span className="text-[9px] font-black uppercase tracking-[1.5px] text-white/90 font-sans-premium">
|
||
{t.conceptBanner}
|
||
</span>
|
||
</div>
|
||
|
||
{/* ── MAIN CONTENT CONTAINER (Sleek Obsidian Theme) ── */}
|
||
<div className="bg-[#07080A] text-white min-h-screen font-sans-premium selection:bg-[#F5C518] selection:text-black overflow-hidden relative">
|
||
|
||
{/* Decorative Mesh Background */}
|
||
<div className="absolute inset-0 bg-mesh-grid pointer-events-none z-0" />
|
||
|
||
{/* Floating Ambient Yellow Glow Orbs */}
|
||
<div className="absolute top-[20%] left-[-10%] w-[500px] h-[500px] bg-[#F5C518]/5 blur-[120px] rounded-full pointer-events-none z-0" />
|
||
<div className="absolute bottom-[20%] right-[-10%] w-[500px] h-[500px] bg-[#F5C518]/3 blur-[140px] rounded-full pointer-events-none z-0" />
|
||
|
||
{/* ── FLOATING NAVBAR ── */}
|
||
<motion.header
|
||
className="fixed top-4 left-4 right-4 z-50 px-4"
|
||
initial={{ y: -80, opacity: 0 }}
|
||
animate={{ y: 0, opacity: 1 }}
|
||
transition={{ duration: 0.7, ease: "easeOut" }}
|
||
>
|
||
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-[#121418]/80 backdrop-blur-xl border border-white/5 rounded-2xl shadow-[0_15px_30px_rgba(0,0,0,0.5)]">
|
||
{/* Logo */}
|
||
<a href="#" className="flex items-center gap-2 group">
|
||
<div className="w-10 h-10 rounded-xl bg-[#F5C518] flex items-center justify-center shadow-[0_0_15px_rgba(245,197,24,0.3)] transition-transform group-hover:scale-105">
|
||
<svg className="w-6 h-6 fill-black" viewBox="0 0 24 24">
|
||
<path d="M22 10.07V6c0-.55-.45-1-1-1h-2v-.07c0-.9-.72-1.63-1.61-1.68C17.15 3.12 17 3.32 17 3.5V5h-2V3.5c0-.18-.15-.38-.39-.25-.89.05-1.61.78-1.61 1.68V5H5c-.55 0-1 .45-1 1v4.07c-1.19.43-2 1.56-2 2.93v3c0 .55.45 1 1 1h1v1.5c0 .83.67 1.5 1.5 1.5h1c.83 0 1.5-.67 1.5-1.5V18h10v1.5c0 .83.67 1.5 1.5 1.5h1c.83 0 1.5-.67 1.5-1.5V18h1c.55 0 1-.45 1-1v-3c0-1.37-.81-2.5-2-2.93z" />
|
||
</svg>
|
||
</div>
|
||
<span className="text-xl font-black tracking-wider text-white font-industrial uppercase">
|
||
CAB<span className="text-[#F5C518]">HUB</span>
|
||
</span>
|
||
</a>
|
||
|
||
{/* Navigation Links */}
|
||
<nav className="hidden lg:flex items-center gap-8">
|
||
{[
|
||
{ label: t.navBook, href: "#booking-flow" },
|
||
{ label: t.navTariffs, href: "#tariffs" },
|
||
{ label: t.navBenefits, href: "#benefits" },
|
||
{ label: t.navApp, href: "#app-showcase" },
|
||
{ label: t.navReviews, href: "#testimonials" }
|
||
].map(item => (
|
||
<a
|
||
key={item.label}
|
||
href={item.href}
|
||
className="text-[11px] font-bold tracking-[1.5px] uppercase text-white/70 hover:text-[#F5C518] transition-colors relative py-1 cursor-pointer group"
|
||
>
|
||
{item.label}
|
||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#F5C518] transition-all group-hover:w-full" />
|
||
</a>
|
||
))}
|
||
</nav>
|
||
|
||
{/* Quick Contact & Action */}
|
||
<div className="flex items-center gap-6">
|
||
{/* Language Switcher */}
|
||
<div className="flex items-center gap-1 bg-white/5 border border-white/10 rounded-xl p-1 shrink-0">
|
||
<button
|
||
onClick={() => setLang("tr")}
|
||
className={`text-[9px] font-black px-2.5 py-1.5 rounded-lg transition-all cursor-pointer font-sans-premium ${
|
||
lang === "tr" ? "bg-[#F5C518] text-black shadow-sm" : "text-white/60 hover:text-white"
|
||
}`}
|
||
>
|
||
TR
|
||
</button>
|
||
<button
|
||
onClick={() => setLang("en")}
|
||
className={`text-[9px] font-black px-2.5 py-1.5 rounded-lg transition-all cursor-pointer font-sans-premium ${
|
||
lang === "en" ? "bg-[#F5C518] text-black shadow-sm" : "text-white/60 hover:text-white"
|
||
}`}
|
||
>
|
||
EN
|
||
</button>
|
||
</div>
|
||
|
||
<motion.button
|
||
onClick={() => setShowBookingModal(true)}
|
||
className="text-[11px] font-black tracking-[2px] uppercase text-black bg-[#F5C518] hover:bg-white px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_5px_15px_rgba(245,197,24,0.2)] hidden sm:block"
|
||
whileHover={{ scale: 1.03 }}
|
||
whileTap={{ scale: 0.98 }}
|
||
>
|
||
{t.bookNow}
|
||
</motion.button>
|
||
</div>
|
||
</div>
|
||
</motion.header>
|
||
|
||
{/* ── HERO & BOOKING SECTION ── */}
|
||
<section className="relative min-h-screen pt-32 pb-20 flex items-center z-10 px-6">
|
||
<div className="max-w-7xl mx-auto w-full">
|
||
<div className="grid lg:grid-cols-12 gap-12 items-center">
|
||
|
||
{/* Left Column: Heading and Badge */}
|
||
<motion.div
|
||
className="lg:col-span-7 z-20"
|
||
variants={stagger}
|
||
initial="hidden"
|
||
animate="show"
|
||
>
|
||
{/* Yellow Accent Badge */}
|
||
<motion.div
|
||
variants={fadeUp}
|
||
className="inline-flex items-center gap-2 text-[10px] font-black uppercase tracking-widest text-[#F5C518] mb-6 bg-[#F5C518]/10 border border-[#F5C518]/20 px-4 py-2 rounded-full"
|
||
>
|
||
<span className="w-1.5 h-1.5 rounded-full bg-[#F5C518] animate-pulse" />
|
||
{t.badge}
|
||
</motion.div>
|
||
|
||
<motion.h1
|
||
variants={fadeUp}
|
||
className="font-industrial font-black text-white mb-6 uppercase hero-title-clamp"
|
||
>
|
||
{t.heroTitlePart1}
|
||
<br />
|
||
<span className="text-[#F5C518]">{t.heroTitlePart2}</span>
|
||
</motion.h1>
|
||
|
||
<motion.p
|
||
variants={fadeUp}
|
||
className="text-white/60 text-sm lg:text-base leading-relaxed max-w-xl mb-10 font-medium"
|
||
>
|
||
{t.heroDesc}
|
||
</motion.p>
|
||
|
||
{/* Call Booking Center */}
|
||
<motion.div
|
||
variants={fadeUp}
|
||
className="flex items-center gap-6 mb-12"
|
||
>
|
||
<div className="w-14 h-14 rounded-2xl bg-[#121418] border border-[#F5C518]/20 flex items-center justify-center shrink-0">
|
||
<svg className="w-6 h-6 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-2.824-1.802-5.12-4.098-6.922-6.922l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H3.75A2.25 2.25 0 0 0 2.25 4.5v2.25Z" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<div className="text-[11px] uppercase tracking-widest text-white/40 font-bold">{t.instantBooking}</div>
|
||
<a href={`tel:${firma.telefon}`} className="text-3xl font-black text-white hover:text-[#F5C518] transition-colors font-industrial tracking-wide">
|
||
{firma.telefon}
|
||
</a>
|
||
</div>
|
||
</motion.div>
|
||
|
||
{/* CTA Buttons */}
|
||
<motion.div variants={fadeUp} className="flex gap-4">
|
||
<a
|
||
href="#booking-flow"
|
||
className="px-8 py-4 rounded-xl bg-[#F5C518] hover:bg-white text-black font-black text-xs uppercase tracking-wider transition-all shadow-[0_5px_20px_rgba(245,197,24,0.3)] cursor-pointer"
|
||
>
|
||
{t.getQuote}
|
||
</a>
|
||
<a
|
||
href="#tariffs"
|
||
className="px-8 py-4 rounded-xl border border-white/10 bg-white/5 hover:bg-white/10 text-white font-black text-xs uppercase tracking-wider transition-all cursor-pointer"
|
||
>
|
||
{t.viewTariffs}
|
||
</a>
|
||
</motion.div>
|
||
</motion.div>
|
||
|
||
{/* Right Column: Hero Car & Parallax Plate */}
|
||
<div className="lg:col-span-5 relative flex justify-center lg:justify-end">
|
||
<motion.div
|
||
className="relative w-full max-w-md lg:max-w-lg h-[400px] lg:h-[480px] flex items-center justify-center"
|
||
initial={{ opacity: 0, scale: 0.95 }}
|
||
animate={{ opacity: 1, scale: 1 }}
|
||
transition={{ duration: 0.85, ease: "easeOut" }}
|
||
>
|
||
{/* Outer circle overlay */}
|
||
<div className="absolute inset-0 rounded-full border-2 border-dashed border-[#F5C518]/10 animate-[spin_60s_linear_infinite]" />
|
||
|
||
{/* High fidelity Yellow cab image */}
|
||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||
<img
|
||
src="/cab_hero_yellow.png"
|
||
alt="CabHub Yellow Sedan Premium NYC Cab"
|
||
className="w-full h-full object-contain relative z-10 drop-shadow-[0_20px_50px_rgba(245,197,24,0.15)]"
|
||
/>
|
||
|
||
{/* Floating badge rotating around */}
|
||
<div className="absolute bottom-0 right-0 z-20 w-32 h-32 flex items-center justify-center">
|
||
<svg className="absolute w-full h-full spinning-badge" viewBox="0 0 100 100">
|
||
<path id="badgePath" d="M 50, 50 m -35, 0 a 35,35 0 1,1 70,0 a 35,35 0 1,1 -70,0" fill="none" />
|
||
<text className="font-industrial font-bold text-[8.5px] fill-[#F5C518] tracking-[1.8px]">
|
||
<textPath xlinkHref="#badgePath">
|
||
BOOK A RIDE • PREMIUM CAR SERVICE • 24/7 •
|
||
</textPath>
|
||
</text>
|
||
</svg>
|
||
<div className="w-12 h-12 rounded-full bg-[#121418] border border-[#F5C518]/30 flex items-center justify-center z-10 shadow-lg">
|
||
<svg className="w-5 h-5 fill-[#F5C518]" viewBox="0 0 24 24">
|
||
<path d="M22 10.07V6c0-.55-.45-1-1-1h-2v-.07c0-.9-.72-1.63-1.61-1.68C17.15 3.12 17 3.32 17 3.5V5h-2V3.5c0-.18-.15-.38-.39-.25-.89.05-1.61.78-1.61 1.68V5H5c-.55 0-1 .45-1 1v4.07c-1.19.43-2 1.56-2 2.93v3c0 .55.45 1 1 1h1v1.5c0 .83.67 1.5 1.5 1.5h1c.83 0 1.5-.67 1.5-1.5V18h10v1.5c0 .83.67 1.5 1.5 1.5h1c.83 0 1.5-.67 1.5-1.5V18h1c.55 0 1-.45 1-1v-3c0-1.37-.81-2.5-2-2.93z" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</motion.div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── INTERACTIVE TARIFF CALCULATOR WIDGET ── */}
|
||
<section id="booking-flow" className="py-24 relative z-10 px-6 border-t border-[#F5C518]/10 bg-[#0B0C0E]">
|
||
<div className="max-w-7xl mx-auto">
|
||
|
||
<div className="bg-[#121418] rounded-3xl border border-white/5 p-8 md:p-12 shadow-2xl relative">
|
||
{/* Glow border header indicator */}
|
||
<div className="absolute top-0 left-12 right-12 h-0.5 bg-gradient-to-r from-transparent via-[#F5C518] to-transparent glowing-bar" />
|
||
|
||
<div className="text-center max-w-xl mx-auto mb-12">
|
||
<span className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.fastFormSubtitle}</span>
|
||
<h2 className="font-industrial text-3xl md:text-4xl font-black uppercase text-white">
|
||
{t.fastFormTitle}
|
||
</h2>
|
||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||
{t.fastFormDesc}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Form Grid */}
|
||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||
{[
|
||
{ label: t.formName, placeholder: t.formNamePlaceholder, type: "text" },
|
||
{ label: t.formPhone, placeholder: t.formPhonePlaceholder, type: "tel" },
|
||
{ label: t.formDate, placeholder: "", type: "date" },
|
||
{ label: t.formTime, placeholder: "", type: "time" },
|
||
].map((field, idx) => (
|
||
<div key={idx} className="flex flex-col">
|
||
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{field.label}</label>
|
||
<input
|
||
type={field.type}
|
||
placeholder={field.placeholder}
|
||
className="px-4 py-3.5 rounded-xl border border-white/5 bg-[#0B0C0E] text-sm text-white placeholder-white/20 focus:outline-none focus:border-[#F5C518] focus:ring-1 focus:ring-[#F5C518] transition-all font-sans-clean font-medium"
|
||
/>
|
||
</div>
|
||
))}
|
||
|
||
{/* Interactive Pickup Location */}
|
||
<div className="flex flex-col">
|
||
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{t.formPickup}</label>
|
||
<select
|
||
value={pickupLoc}
|
||
onChange={(e) => setPickupLoc(e.target.value)}
|
||
className="px-4 py-3.5 rounded-xl border border-white/5 bg-[#0B0C0E] text-sm text-white focus:outline-none focus:border-[#F5C518] transition-all font-sans-clean font-medium cursor-pointer"
|
||
>
|
||
{locationsList.map(loc => <option key={loc} value={loc} className="bg-[#121418] text-white">{loc}</option>)}
|
||
</select>
|
||
</div>
|
||
|
||
{/* Interactive Dropoff Location */}
|
||
<div className="flex flex-col">
|
||
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{t.formDropoff}</label>
|
||
<select
|
||
value={dropoffLoc}
|
||
onChange={(e) => setDropoffLoc(e.target.value)}
|
||
className="px-4 py-3.5 rounded-xl border border-white/5 bg-[#0B0C0E] text-sm text-white focus:outline-none focus:border-[#F5C518] transition-all font-sans-clean font-medium cursor-pointer"
|
||
>
|
||
{locationsList.map(loc => <option key={loc} value={loc} className="bg-[#121418] text-white">{loc}</option>)}
|
||
</select>
|
||
</div>
|
||
|
||
{/* Choose Vehicle */}
|
||
<div className="flex flex-col md:col-span-2">
|
||
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{t.chooseVehicle}</label>
|
||
<div className="grid grid-cols-3 gap-2 h-full">
|
||
{["Economy", "Standard", "Business"].map((option, oIdx) => (
|
||
<button
|
||
key={option}
|
||
onClick={() => setActivePlan(oIdx)}
|
||
className={`py-3.5 px-3 rounded-xl border text-xs font-bold transition-all cursor-pointer flex items-center justify-center gap-1.5 ${
|
||
activePlan === oIdx
|
||
? "bg-[#F5C518] text-black border-[#F5C518]"
|
||
: "bg-[#0B0C0E] text-white/60 border-white/5 hover:border-white/20"
|
||
}`}
|
||
>
|
||
<span className="w-1.5 h-1.5 rounded-full" style={{ backgroundColor: activePlan === oIdx ? "black" : "#F5C518" }} />
|
||
{option}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* ESTIMATED FARE BANNER */}
|
||
<div className="mt-8 p-6 bg-[#0B0C0E] border border-white/5 rounded-2xl flex flex-col sm:flex-row justify-between items-center gap-4">
|
||
<div className="flex items-center gap-3">
|
||
<div className="w-10 h-10 rounded-xl bg-[#F5C518]/10 border border-[#F5C518]/20 flex items-center justify-center shrink-0">
|
||
<span className="text-[#F5C518] text-lg font-black font-industrial">$</span>
|
||
</div>
|
||
<div>
|
||
<span className="text-white/40 text-[9px] uppercase tracking-widest font-black block">{t.calculatingText}</span>
|
||
<span className="font-industrial text-white text-sm font-bold uppercase tracking-wider">{t.calcEstimated} <span className="text-[#F5C518] text-base">{calculatePrice()}</span></span>
|
||
</div>
|
||
</div>
|
||
<div className="text-[10px] font-bold text-white/40 leading-relaxed font-sans-clean text-center sm:text-right">
|
||
Flat-rate airport vouchers apply dynamically between JFK / LaGuardia and Manhattan.
|
||
</div>
|
||
</div>
|
||
|
||
{/* Submit Action */}
|
||
<div className="mt-8 pt-4 flex flex-col md:flex-row justify-between items-center gap-4">
|
||
<p className="text-white/40 text-xs font-medium max-w-md text-center md:text-left">
|
||
{t.dispatchWarning}
|
||
</p>
|
||
<motion.button
|
||
onClick={() => setShowBookingModal(true)}
|
||
className="w-full md:w-auto px-10 py-4.5 rounded-xl bg-[#F5C518] hover:bg-white text-black font-black text-xs uppercase tracking-widest transition-all cursor-pointer shadow-[0_5px_15px_rgba(245,197,24,0.3)] shrink-0"
|
||
whileHover={{ scale: 1.02 }}
|
||
whileTap={{ scale: 0.98 }}
|
||
>
|
||
{t.submitBooking}
|
||
</motion.button>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── OUR TARIFFS (Subscription Cards) ── */}
|
||
<section id="tariffs" className="py-32 relative z-10 px-6 bg-[#07080A]">
|
||
<div className="max-w-7xl mx-auto">
|
||
|
||
<div className="text-center max-w-xl mx-auto mb-20">
|
||
<span className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.tariffsSubtitle}</span>
|
||
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white">
|
||
{t.tariffsTitle}
|
||
</h2>
|
||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||
{t.tariffsDesc}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Three Tariff Cards Grid */}
|
||
<div className="grid lg:grid-cols-3 gap-8">
|
||
{istatistikler.map((stat, sIdx) => {
|
||
const locStat = getLocalizedStat(stat.deger);
|
||
const isPopular = stat.deger === "Standard Class";
|
||
return (
|
||
<motion.div
|
||
key={sIdx}
|
||
className={`relative rounded-3xl p-8 flex flex-col justify-between transition-all duration-300 group ${
|
||
isPopular
|
||
? "bg-[#121418] border-2 border-[#F5C518] shadow-[0_15px_40px_rgba(245,197,24,0.08)]"
|
||
: "bg-[#121418]/60 border border-white/5 hover:border-white/15"
|
||
}`}
|
||
initial={{ opacity: 0, y: 30 }}
|
||
whileInView={{ opacity: 1, y: 0 }}
|
||
viewport={{ once: true }}
|
||
transition={{ duration: 0.5, delay: sIdx * 0.1 }}
|
||
whileHover={{ y: -6 }}
|
||
>
|
||
{isPopular && (
|
||
<div className="absolute -top-3.5 left-1/2 -translate-x-1/2 px-4 py-1 bg-[#F5C518] text-black text-[9px] font-black uppercase tracking-widest rounded-full z-10">
|
||
{t.popular}
|
||
</div>
|
||
)}
|
||
|
||
<div>
|
||
{/* Car vector silhouette placeholder */}
|
||
<div className="h-28 flex items-center justify-center border-b border-white/5 mb-8 relative">
|
||
<svg className={`w-32 h-16 ${isPopular ? "fill-[#F5C518]" : "fill-white/30 group-hover:fill-[#F5C518]"} transition-colors`} viewBox="0 0 24 24">
|
||
<path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z" />
|
||
</svg>
|
||
</div>
|
||
|
||
<h3 className="font-industrial font-black text-2xl uppercase tracking-wider text-white mb-2">
|
||
{locStat.title}
|
||
</h3>
|
||
<p className="text-white/60 text-xs leading-relaxed mb-8 font-medium">
|
||
{locStat.desc}
|
||
</p>
|
||
</div>
|
||
|
||
<div>
|
||
{/* Price Display */}
|
||
<div className="flex items-baseline gap-1.5 mb-8">
|
||
<span className="text-3xl font-black text-[#F5C518] font-industrial">
|
||
{sIdx === 0 ? "$1.50" : sIdx === 1 ? "$2.20" : "$3.50"}
|
||
</span>
|
||
<span className="text-white/40 text-xs uppercase tracking-widest font-bold">{t.perMile}</span>
|
||
</div>
|
||
|
||
<motion.button
|
||
onClick={() => {
|
||
setActivePlan(sIdx);
|
||
const el = document.getElementById("booking-flow");
|
||
el?.scrollIntoView({ behavior: "smooth" });
|
||
}}
|
||
className={`w-full py-4.5 rounded-xl font-black text-xs uppercase tracking-widest transition-all cursor-pointer ${
|
||
isPopular
|
||
? "bg-[#F5C518] hover:bg-white text-black shadow-lg"
|
||
: "bg-[#0B0C0E] hover:bg-white/5 text-white/70 border border-white/5 hover:border-white/10"
|
||
}`}
|
||
whileHover={{ scale: 1.02 }}
|
||
whileTap={{ scale: 0.98 }}
|
||
>
|
||
{t.bookTariff}
|
||
</motion.button>
|
||
</div>
|
||
|
||
</motion.div>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── OUR BENEFITS ── */}
|
||
<section id="benefits" className="py-28 relative z-10 px-6 bg-[#0B0C0E] border-t border-[#F5C518]/5">
|
||
<div className="max-w-7xl mx-auto">
|
||
|
||
<div className="text-center max-w-xl mx-auto mb-20">
|
||
<span className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.benefitsSubtitle}</span>
|
||
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white">
|
||
{t.benefitsTitle}
|
||
</h2>
|
||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||
{t.benefitsDesc}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Grid display of benefits */}
|
||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||
{hizmetler.map((benefit, bIdx) => {
|
||
const locBenefit = getLocalizedService(benefit.baslik, benefit.aciklama);
|
||
return (
|
||
<motion.div
|
||
key={bIdx}
|
||
className="bg-[#121418] rounded-2xl p-8 border border-white/5 hover:border-[#F5C518]/30 transition-all duration-300 flex flex-col items-center text-center group cursor-default shadow-sm"
|
||
initial={{ opacity: 0, y: 20 }}
|
||
whileInView={{ opacity: 1, y: 0 }}
|
||
viewport={{ once: true }}
|
||
transition={{ duration: 0.5, delay: bIdx * 0.1 }}
|
||
whileHover={{ y: -4 }}
|
||
>
|
||
<div className="w-16 h-16 rounded-2xl bg-[#0B0C0E] border border-white/5 flex items-center justify-center mb-6 transition-transform group-hover:scale-105 group-hover:border-[#F5C518]/30">
|
||
{getIconSvg(benefit.ikon)}
|
||
</div>
|
||
|
||
<h3 className="font-industrial font-black text-lg text-white mb-3 tracking-wider uppercase">
|
||
{locBenefit.title}
|
||
</h3>
|
||
<p className="text-white/50 text-[11px] leading-relaxed font-medium">
|
||
{locBenefit.desc}
|
||
</p>
|
||
</motion.div>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── APP DOWNLOAD SHOWCASE ── */}
|
||
<section id="app-showcase" className="py-32 relative z-10 px-6 bg-[#07080A] border-t border-[#F5C518]/5">
|
||
<div className="max-w-7xl mx-auto">
|
||
<div className="grid lg:grid-cols-12 gap-16 items-center">
|
||
|
||
{/* Left Column: Heading and action badges */}
|
||
<motion.div
|
||
className="lg:col-span-6 z-20"
|
||
initial="hidden"
|
||
whileInView="show"
|
||
viewport={{ once: true, amount: 0.2 }}
|
||
variants={stagger}
|
||
>
|
||
<motion.span
|
||
variants={fadeUp}
|
||
className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial"
|
||
>
|
||
{t.appSubtitle}
|
||
</motion.span>
|
||
<motion.h2
|
||
variants={fadeUp}
|
||
className="font-industrial text-4xl lg:text-5xl font-black tracking-tight text-white uppercase mb-6"
|
||
>
|
||
{t.appTitle}
|
||
</motion.h2>
|
||
<motion.p
|
||
variants={fadeUp}
|
||
className="text-white/60 text-sm leading-relaxed mb-10 max-w-md font-medium"
|
||
>
|
||
{t.appDesc}
|
||
</motion.p>
|
||
|
||
{/* Badges buttons */}
|
||
<motion.div
|
||
variants={fadeUp}
|
||
className="flex items-center gap-4 flex-wrap"
|
||
>
|
||
{/* Google Play */}
|
||
<a href="#" className="flex items-center gap-3 px-6 py-3 rounded-xl bg-[#121418] hover:bg-[#181C22] border border-white/5 hover:border-white/10 transition-colors shadow-lg cursor-pointer group">
|
||
<svg className="w-6 h-6 fill-[#F5C518]" viewBox="0 0 24 24">
|
||
<path d="M5 2c-.37 0-.71.18-.91.49l10.96 10.96 3.1-3.1L5.6 3.12C5.41 3.04 5.21 2 5 2zm10.75 11.21L4.69 22.42c.19-.07.38-.17.51-.29l12.65-7.3a1.5 1.5 0 0 0 .15-.15l-2.25-1.47zM3.19 3.81C3.07 4.17 3 4.58 3 5v14c0 .42.07.83.19 1.19l9.31-9.31-9.31-9.07z" />
|
||
</svg>
|
||
<div className="text-left">
|
||
<div className="text-[8px] text-white/40 uppercase tracking-wider font-bold">{t.getItOn}</div>
|
||
<div className="text-xs font-black text-white font-industrial tracking-wide">{t.googlePlay}</div>
|
||
</div>
|
||
</a>
|
||
|
||
{/* App Store */}
|
||
<a href="#" className="flex items-center gap-3 px-6 py-3 rounded-xl bg-[#121418] hover:bg-[#181C22] border border-white/5 hover:border-white/10 transition-colors shadow-lg cursor-pointer group">
|
||
<svg className="w-6 h-6 fill-[#F5C518]" viewBox="0 0 24 24">
|
||
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M15.97 4.17c.66-.81 1.11-1.93.99-3.06-1 .04-2.21.67-2.93 1.49-.62.69-1.16 1.84-1.01 2.96 1.12.09 2.27-.57 2.95-1.39z" />
|
||
</svg>
|
||
<div className="text-left">
|
||
<div className="text-[8px] text-white/40 uppercase tracking-wider font-bold">{t.getItOn}</div>
|
||
<div className="text-xs font-black text-white font-industrial tracking-wide">{t.appStore}</div>
|
||
</div>
|
||
</a>
|
||
</motion.div>
|
||
</motion.div>
|
||
|
||
{/* Right Column: Hand holding smartphone flatlay mockup */}
|
||
<div className="lg:col-span-6 relative flex justify-center lg:justify-end">
|
||
<motion.div
|
||
className="relative w-full max-w-md lg:max-w-lg h-[450px] lg:h-[520px] rounded-[36px] overflow-hidden shadow-2xl border border-white/10 group"
|
||
initial={{ opacity: 0, x: 40 }}
|
||
whileInView={{ opacity: 1, x: 0 }}
|
||
viewport={{ once: true }}
|
||
transition={{ duration: 0.7 }}
|
||
>
|
||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||
<img
|
||
src="/cab_app_mockup.png"
|
||
alt="CabHub Booking Digital Phone Interface Map"
|
||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-[4000ms]"
|
||
/>
|
||
</motion.div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── TESTIMONIAL GRID ── */}
|
||
<section id="testimonials" className="py-28 relative z-10 px-6 bg-[#0B0C0E] border-t border-[#F5C518]/5">
|
||
<div className="max-w-7xl mx-auto">
|
||
|
||
<div className="text-center max-w-xl mx-auto mb-20">
|
||
<span className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.reviewsSubtitle}</span>
|
||
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white">
|
||
{t.reviewsTitle}
|
||
</h2>
|
||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||
{t.reviewsDesc}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Testimonials 2-Column Layout */}
|
||
<div className="grid md:grid-cols-2 gap-8">
|
||
{yorumlar.map((y, yIdx) => {
|
||
const locTestimonial = getLocalizedTestimonial(y.yazar);
|
||
return (
|
||
<motion.div
|
||
key={yIdx}
|
||
className="bg-[#121418] border border-white/5 rounded-3xl p-8 flex flex-col justify-between transition-all duration-300 hover:border-[#F5C518]/30 group"
|
||
initial={{ opacity: 0, y: 30 }}
|
||
whileInView={{ opacity: 1, y: 0 }}
|
||
viewport={{ once: true }}
|
||
transition={{ duration: 0.5, delay: yIdx * 0.1 }}
|
||
whileHover={{ y: -4 }}
|
||
>
|
||
{/* Rating Stars SVG */}
|
||
<div className="flex gap-1 mb-6">
|
||
{[...Array(5)].map((_, starIdx) => (
|
||
<svg key={starIdx} className="w-4.5 h-4.5 fill-[#F5C518]" viewBox="0 0 24 24">
|
||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||
</svg>
|
||
))}
|
||
</div>
|
||
|
||
<p className="text-white/70 text-xs leading-relaxed italic mb-8 font-medium">
|
||
“{locTestimonial}”
|
||
</p>
|
||
|
||
<div className="flex items-center gap-3">
|
||
<div className="w-10 h-10 rounded-full border border-white/10 flex items-center justify-center text-xs font-sans-premium font-black bg-[#0B0C0E] select-none text-[#F5C518]">
|
||
{y.yazar.charAt(0)}
|
||
</div>
|
||
<div>
|
||
<h4 className="font-industrial text-white text-xs font-black uppercase tracking-wider">
|
||
{y.yazar}
|
||
</h4>
|
||
<span className="text-[9px] text-white/40 uppercase tracking-widest font-bold">
|
||
{y.tarih}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
</motion.div>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── BOTTOM CALL RESERVATION DIRECT STRIP ── */}
|
||
<section className="relative z-10 bg-[#F5C518] text-black py-8 px-6 text-center pulse-glow overflow-hidden">
|
||
<div className="max-w-7xl mx-auto relative z-10 flex flex-col md:flex-row justify-between items-center gap-4">
|
||
<h3 className="font-industrial font-black text-base md:text-xl uppercase tracking-wider text-black text-center md:text-left">
|
||
{t.callStripText}
|
||
</h3>
|
||
<a href={`tel:${firma.telefon}`} className="inline-flex items-center gap-3 px-8 py-3.5 bg-black hover:bg-white text-white hover:text-black rounded-xl font-industrial font-black tracking-widest uppercase transition-all shadow-[0_5px_15px_rgba(0,0,0,0.3)] text-sm cursor-pointer">
|
||
📞 {firma.telefon}
|
||
</a>
|
||
</div>
|
||
{/* subtle moving abstract banner lines */}
|
||
<div className="absolute inset-0 bg-white/5 mix-blend-overlay opacity-30 pointer-events-none" />
|
||
</section>
|
||
|
||
{/* ── FOOTER ── */}
|
||
<footer className="bg-[#0B0C0E] border-t border-white/5 pt-24 pb-8 px-6 relative z-10">
|
||
<div className="max-w-7xl mx-auto">
|
||
|
||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/5">
|
||
|
||
{/* About Column */}
|
||
<div className="md:col-span-2">
|
||
<span className="font-industrial text-2xl font-black text-white tracking-wider uppercase mb-4 block">
|
||
CAB<span className="text-[#F5C518]">HUB</span>
|
||
</span>
|
||
<p className="text-white/50 text-xs leading-relaxed max-w-sm mb-8 font-medium">
|
||
{firma.slogan} — Safe, verified, high-fidelity premium luxury sedan cab rides across New York City and global destinations.
|
||
</p>
|
||
<div className="text-white/60 text-xs font-medium space-y-2">
|
||
<p className="flex items-center gap-2">📍 <span className="text-white/80">{firma.adres}</span></p>
|
||
<p className="flex items-center gap-2">📧 <span className="text-white/80">{firma.email}</span></p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Download links */}
|
||
<div>
|
||
<h4 className="font-industrial text-[#F5C518] text-xs font-black uppercase tracking-wider mb-6">
|
||
DOWNLOAD APP
|
||
</h4>
|
||
<div className="space-y-4">
|
||
<a href="#" className="block text-white/50 hover:text-[#F5C518] text-xs transition-colors font-medium">
|
||
Google Play Store App
|
||
</a>
|
||
<a href="#" className="block text-white/50 hover:text-[#F5C518] text-xs transition-colors font-medium">
|
||
Apple iOS App Store
|
||
</a>
|
||
<a href="#" className="block text-white/50 hover:text-[#F5C518] text-xs transition-colors font-medium">
|
||
Direct Web Voucher Portal
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Navigation links */}
|
||
<div>
|
||
<h4 className="font-industrial text-[#F5C518] text-xs font-black uppercase tracking-wider mb-6">
|
||
USEFUL LINKS
|
||
</h4>
|
||
<div className="space-y-4">
|
||
{["Book a Cab", "Economy & Business Tariffs", "Our Core Benefits", "Happy Reviews", "Terms & Regulations"].map(item => (
|
||
<a
|
||
key={item}
|
||
href="#"
|
||
className="block text-white/50 hover:text-[#F5C518] text-xs transition-colors font-medium"
|
||
>
|
||
{item}
|
||
</a>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/30 text-xs font-medium font-sans-premium">
|
||
<p>© 2026 {firma.adi}. {t.footerRights}</p>
|
||
<div className="flex gap-4">
|
||
<a href="#" className="hover:text-white transition-colors">{t.footerPrivacy}</a>
|
||
<span>·</span>
|
||
<a href="#" className="hover:text-white transition-colors">{t.footerTerms}</a>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</footer>
|
||
|
||
{/* ── FAST BOOKING SUCCESS MODAL ── */}
|
||
<AnimatePresence>
|
||
{showBookingModal && (
|
||
<motion.div
|
||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/85 backdrop-blur-sm"
|
||
initial={{ opacity: 0 }}
|
||
animate={{ opacity: 1 }}
|
||
exit={{ opacity: 0 }}
|
||
>
|
||
<motion.div
|
||
className="bg-[#121418] rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-[#F5C518]/20"
|
||
initial={{ scale: 0.95, y: 20 }}
|
||
animate={{ scale: 1, y: 0 }}
|
||
exit={{ scale: 0.95, y: 20 }}
|
||
>
|
||
{/* Close Button */}
|
||
<button
|
||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-[#0B0C0E] border border-white/5 flex items-center justify-center text-white/40 hover:text-[#F5C518] hover:border-[#F5C518]/20 transition-all cursor-pointer"
|
||
onClick={() => setShowBookingModal(false)}
|
||
>
|
||
✕
|
||
</button>
|
||
|
||
{/* Visual success indicator */}
|
||
<div className="w-16 h-16 rounded-2xl bg-[#F5C518]/10 border border-[#F5C518]/20 flex items-center justify-center mb-6">
|
||
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||
</svg>
|
||
</div>
|
||
|
||
<h3 className="font-industrial font-black text-white text-2xl mb-1 uppercase tracking-wider">
|
||
{t.bookingRequested}
|
||
</h3>
|
||
<p className="text-[#F5C518] font-mono text-[10px] mb-6 uppercase tracking-widest font-bold">
|
||
{t.nycDispatchActive}
|
||
</p>
|
||
|
||
<p className="text-white/60 text-xs leading-relaxed mb-8 font-medium">
|
||
{t.successDesc}
|
||
</p>
|
||
|
||
<motion.button
|
||
className="w-full py-4.5 rounded-xl bg-[#F5C518] hover:bg-white text-black font-black text-xs uppercase tracking-widest cursor-pointer shadow-[0_5px_15px_rgba(245,197,24,0.3)]"
|
||
whileHover={{ scale: 1.02 }}
|
||
whileTap={{ scale: 0.98 }}
|
||
onClick={() => setShowBookingModal(false)}
|
||
>
|
||
{t.dismiss}
|
||
</motion.button>
|
||
</motion.div>
|
||
</motion.div>
|
||
)}
|
||
</AnimatePresence>
|
||
|
||
</div>
|
||
</>
|
||
);
|
||
}
|