flotta
|
|
@ -70,9 +70,9 @@ export default function PricingPage() {
|
|||
</Link>
|
||||
|
||||
<div className="space-y-4">
|
||||
<h1 className="text-5xl md:text-8xl font-black text-white tracking-tighter leading-none">
|
||||
<h1 className="text-5xl md:text-8xl font-black text-white tracking-tighter leading-none uppercase">
|
||||
{t.pricing.title} <br />
|
||||
<span className="text-secondary/40 italic">{t.pricing.titleAccent}</span>
|
||||
<span className="text-slate-900 italic">{t.pricing.titleAccent}</span>
|
||||
</h1>
|
||||
<p className="text-xl text-white/70 max-w-2xl leading-relaxed font-medium">
|
||||
{t.pricing.description}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export default function ConditionsPage() {
|
|||
<div className="space-y-4">
|
||||
<h1 className="text-5xl md:text-8xl font-black text-white tracking-tighter leading-none uppercase">
|
||||
{t.conditionsPage.title} <br />
|
||||
<span className="text-secondary/40 italic">{t.conditionsPage.titleAccent}</span>
|
||||
<span className="text-slate-900 italic">{t.conditionsPage.titleAccent}</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
"use client"
|
||||
|
||||
import { useState, useEffect } from "react"
|
||||
import Navbar from "@/components/navbar"
|
||||
import Footer from "@/components/footer"
|
||||
import PageReveal from "@/components/page-reveal"
|
||||
|
|
@ -9,36 +10,53 @@ import Link from "next/link"
|
|||
import Image from "next/image"
|
||||
import { useLanguage } from "@/lib/language-context"
|
||||
import { motion } from "framer-motion"
|
||||
import { GalleryDialog } from "@/components/gallery-dialog"
|
||||
|
||||
export default function FleetPage() {
|
||||
const { t } = useLanguage()
|
||||
const [galleryData, setGalleryData] = useState<Record<string, string[]>>({})
|
||||
const [isGalleryOpen, setIsGalleryOpen] = useState(false)
|
||||
const [selectedGallery, setSelectedGallery] = useState<string[]>([])
|
||||
const [selectedVehicleName, setSelectedVehicleName] = useState("")
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/gallery.json')
|
||||
.then(res => res.json())
|
||||
.then(data => setGalleryData(data))
|
||||
.catch(err => console.error('Error fetching gallery:', err))
|
||||
}, [])
|
||||
|
||||
const openGallery = (categoryId: string, vehicleName: string) => {
|
||||
const images = galleryData[categoryId] || []
|
||||
if (images.length > 0) {
|
||||
setSelectedGallery(images)
|
||||
setSelectedVehicleName(vehicleName)
|
||||
setIsGalleryOpen(true)
|
||||
}
|
||||
}
|
||||
|
||||
const vehicles = [
|
||||
{
|
||||
id: "vclass",
|
||||
categoryId: "vip",
|
||||
data: t.fleetPage.vehicles.vclass,
|
||||
image: "/images/fleet/v-class.jpg",
|
||||
image: "/images/fleet/Flotta_VIP_kezdő.png",
|
||||
large: true,
|
||||
icon: Users
|
||||
},
|
||||
{
|
||||
id: "eclass",
|
||||
data: t.fleetPage.vehicles.eclass,
|
||||
image: "/images/fleet/e-class.jpg",
|
||||
large: false,
|
||||
icon: Briefcase
|
||||
},
|
||||
{
|
||||
id: "superb",
|
||||
categoryId: "personal",
|
||||
data: t.fleetPage.vehicles.superb,
|
||||
image: "/images/fleet/superb.jpg",
|
||||
large: false,
|
||||
image: "/images/fleet/3_skoda_repter.png",
|
||||
large: true,
|
||||
icon: Wind
|
||||
},
|
||||
{
|
||||
id: "transit",
|
||||
categoryId: "minibus",
|
||||
data: t.fleetPage.vehicles.transit,
|
||||
image: "/images/fleet/transit.jpg",
|
||||
image: "/images/fleet/Tourneo_hatter_hegy.png",
|
||||
large: true,
|
||||
icon: Users
|
||||
}
|
||||
|
|
@ -159,24 +177,27 @@ export default function FleetPage() {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-x-8 gap-y-4 pt-4">
|
||||
{vehicle.data.features.map((feature: string, fIdx: number) => (
|
||||
<div key={fIdx} className="flex items-center gap-3 text-white/80">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-primary" />
|
||||
<span className="text-[10px] md:text-xs font-black uppercase tracking-widest">{feature}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{vehicle.data.features && vehicle.data.features.length > 0 && (
|
||||
<div className="flex flex-wrap gap-x-8 gap-y-4 pt-4">
|
||||
{vehicle.data.features.map((feature: string, fIdx: number) => (
|
||||
<div key={fIdx} className="flex items-center gap-3 text-white/80">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-primary" />
|
||||
<span className="text-[10px] md:text-xs font-black uppercase tracking-widest">{feature}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="pt-8 border-t border-white/10 flex items-center justify-between">
|
||||
<Link
|
||||
href="https://app.skyflytravel.hu/public/offers/new"
|
||||
target="_blank"
|
||||
className="inline-flex items-center gap-4 text-primary font-black uppercase tracking-[0.2em] text-[10px] hover:gap-6 transition-all"
|
||||
>
|
||||
{t.nav.cta}
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Link>
|
||||
<div className="flex flex-wrap gap-6 items-center">
|
||||
<button
|
||||
onClick={() => openGallery(vehicle.categoryId, vehicle.data.name)}
|
||||
className="inline-flex items-center gap-4 text-primary font-black uppercase tracking-[0.2em] text-[10px] hover:gap-6 transition-all cursor-pointer group/btn"
|
||||
>
|
||||
{t.common.moreImages}
|
||||
<ChevronRight className="w-4 h-4 group-hover/btn:translate-x-1 transition-transform" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="hidden md:flex gap-4">
|
||||
<div className="w-12 h-12 rounded-2xl bg-white/10 backdrop-blur-md flex items-center justify-center text-white border border-white/10 group-hover:bg-primary/20 group-hover:border-primary/30 transition-all">
|
||||
|
|
@ -224,7 +245,15 @@ export default function FleetPage() {
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<Footer />
|
||||
|
||||
<GalleryDialog
|
||||
isOpen={isGalleryOpen}
|
||||
onClose={() => setIsGalleryOpen(false)}
|
||||
images={selectedGallery}
|
||||
vehicleName={selectedVehicleName}
|
||||
/>
|
||||
|
||||
<Footer />
|
||||
</PageReveal>
|
||||
)
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ export default function ContactPage() {
|
|||
<div className="space-y-4">
|
||||
<h1 className="text-5xl md:text-8xl font-black text-white tracking-tighter leading-none uppercase">
|
||||
{t.contactPage.title} <br />
|
||||
<span className="text-secondary/40 italic">{t.contactPage.titleAccent}</span>
|
||||
<span className="text-slate-900 italic">{t.contactPage.titleAccent}</span>
|
||||
</h1>
|
||||
<p className="text-xl text-white/70 max-w-2xl leading-relaxed font-medium">
|
||||
{t.contactPage.description}
|
||||
|
|
@ -96,7 +96,7 @@ export default function ContactPage() {
|
|||
<a
|
||||
key={`${value}-${valueIdx}`}
|
||||
href={href}
|
||||
className="text-2xl font-black text-slate-900 hover:text-primary transition-colors"
|
||||
className="text-2xl font-black text-slate-900 hover:text-primary transition-colors block"
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export default function Home() {
|
|||
<div className="absolute inset-0 bg-indigo-500/10 blur-3xl rounded-full scale-110 group-hover:scale-125 transition-transform" />
|
||||
<Card className="relative w-full aspect-square md:w-[450px] md:h-[450px] rounded-[3rem] overflow-hidden border-none shadow-2xl">
|
||||
<Image
|
||||
src="/images/mercedes.jpg"
|
||||
src="/images/Mercedes Vito_.JPG"
|
||||
alt="Egyéb személyszállítás"
|
||||
fill
|
||||
sizes="(min-width: 768px) 450px, 90vw"
|
||||
|
|
|
|||
|
|
@ -22,13 +22,7 @@ export default function ServicesPage() {
|
|||
const { t } = useLanguage()
|
||||
|
||||
const packageEntries = [
|
||||
{
|
||||
unique: t.servicesPage.packages.classic.unique,
|
||||
name: t.servicesPage.packages.classic.title,
|
||||
desc: t.servicesPage.packages.classic.desc,
|
||||
toAirport: t.servicesPage.packages.classic.toAirport,
|
||||
toCity: t.servicesPage.packages.classic.toCity
|
||||
},
|
||||
|
||||
{
|
||||
unique: t.servicesPage.packages.express.unique,
|
||||
name: t.servicesPage.packages.express.title,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { X, ChevronLeft, ChevronRight, Maximize2, ImageIcon } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface GalleryDialogProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
images: string[];
|
||||
vehicleName: string;
|
||||
}
|
||||
|
||||
export function GalleryDialog({ isOpen, onClose, images, vehicleName }: GalleryDialogProps) {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [direction, setDirection] = useState(0);
|
||||
|
||||
// Lock scroll when open
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else {
|
||||
document.body.style.overflow = 'unset';
|
||||
}
|
||||
return () => {
|
||||
document.body.style.overflow = 'unset';
|
||||
};
|
||||
}, [isOpen]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const nextImage = () => {
|
||||
setDirection(1);
|
||||
setCurrentIndex((prev) => (prev + 1) % images.length);
|
||||
};
|
||||
|
||||
const prevImage = () => {
|
||||
setDirection(-1);
|
||||
setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
|
||||
};
|
||||
|
||||
const variants = {
|
||||
enter: (direction: number) => ({
|
||||
x: direction > 0 ? 1000 : -1000,
|
||||
opacity: 0,
|
||||
scale: 0.9,
|
||||
}),
|
||||
center: {
|
||||
zIndex: 1,
|
||||
x: 0,
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
},
|
||||
exit: (direction: number) => ({
|
||||
zIndex: 0,
|
||||
x: direction < 0 ? 1000 : -1000,
|
||||
opacity: 0,
|
||||
scale: 0.9,
|
||||
}),
|
||||
};
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="fixed inset-0 z-[100] flex items-center justify-center bg-black/95 backdrop-blur-xl"
|
||||
>
|
||||
{/* Close Button */}
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="absolute top-8 right-8 z-[110] p-4 text-white/50 hover:text-white hover:bg-white/10 rounded-full transition-all"
|
||||
>
|
||||
<X className="w-8 h-8" />
|
||||
</button>
|
||||
|
||||
{/* Header Info */}
|
||||
<div className="absolute top-8 left-8 z-[110] flex flex-col gap-2">
|
||||
<h3 className="text-2xl font-black uppercase tracking-[0.3em] text-white">
|
||||
{vehicleName}
|
||||
</h3>
|
||||
<div className="flex items-center gap-4 text-primary text-[10px] font-black tracking-widest uppercase">
|
||||
<ImageIcon className="w-4 h-4" />
|
||||
<span>{currentIndex + 1} / {images.length} Kép</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Stage */}
|
||||
<div className="relative w-full h-full max-w-7xl px-4 md:px-12 flex items-center justify-center overflow-hidden">
|
||||
<AnimatePresence initial={false} custom={direction}>
|
||||
{images.length > 0 && (
|
||||
<motion.div
|
||||
key={currentIndex}
|
||||
custom={direction}
|
||||
variants={variants}
|
||||
initial="enter"
|
||||
animate="center"
|
||||
exit="exit"
|
||||
transition={{
|
||||
x: { type: "spring", stiffness: 300, damping: 30 },
|
||||
opacity: { duration: 0.3 },
|
||||
scale: { duration: 0.4 }
|
||||
}}
|
||||
className="absolute inset-0 flex items-center justify-center p-4 md:p-12"
|
||||
>
|
||||
<div className="relative w-full h-full shadow-2xl shadow-primary/10 rounded-[2rem] overflow-hidden border border-white/10">
|
||||
<Image
|
||||
src={images[currentIndex]}
|
||||
alt={`${vehicleName} view ${currentIndex + 1}`}
|
||||
fill
|
||||
className="object-cover"
|
||||
priority
|
||||
quality={100}
|
||||
/>
|
||||
|
||||
{/* Vignette Overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent pointer-events-none" />
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* Navigation Handles */}
|
||||
<button
|
||||
onClick={prevImage}
|
||||
className="absolute left-8 z-[110] w-16 h-16 rounded-full border border-white/10 bg-black/20 backdrop-blur-md flex items-center justify-center text-white hover:bg-primary hover:border-primary transition-all group active:scale-95"
|
||||
>
|
||||
<ChevronLeft className="w-8 h-8 group-hover:-translate-x-1 transition-transform" />
|
||||
</button>
|
||||
<button
|
||||
onClick={nextImage}
|
||||
className="absolute right-8 z-[110] w-16 h-16 rounded-full border border-white/10 bg-black/20 backdrop-blur-md flex items-center justify-center text-white hover:bg-primary hover:border-primary transition-all group active:scale-95"
|
||||
>
|
||||
<ChevronRight className="w-8 h-8 group-hover:translate-x-1 transition-transform" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Thumbnails Sidebar/Bottom Bar */}
|
||||
<div className="absolute bottom-8 left-0 right-0 z-[110] flex justify-center gap-4 px-8 overflow-x-auto pb-4 scrollbar-hide">
|
||||
{images.map((img, idx) => (
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => {
|
||||
setDirection(idx > currentIndex ? 1 : -1);
|
||||
setCurrentIndex(idx);
|
||||
}}
|
||||
className={cn(
|
||||
"relative w-32 h-20 rounded-xl overflow-hidden border-2 transition-all flex-shrink-0 active:scale-95",
|
||||
currentIndex === idx
|
||||
? "border-primary scale-110 shadow-lg shadow-primary/20"
|
||||
: "border-white/10 opacity-40 hover:opacity-100"
|
||||
)}
|
||||
>
|
||||
<Image
|
||||
src={img}
|
||||
alt="Thumbnail"
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Subtle noise/texture overlay for premium feel */}
|
||||
<div className="fixed inset-0 pointer-events-none opacity-[0.03] bg-[url('/images/noise.png')] mix-blend-overlay" />
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 353 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 260 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 357 KiB |
|
After Width: | Height: | Size: 151 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 349 KiB |
|
After Width: | Height: | Size: 358 KiB |
|
After Width: | Height: | Size: 144 KiB |
|
After Width: | Height: | Size: 352 KiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 246 KiB |
|
After Width: | Height: | Size: 302 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 366 KiB |
|
|
@ -4,7 +4,8 @@
|
|||
brand: "SkyFly Travel",
|
||||
email: "info@skyflytravel.hu",
|
||||
phone: "+36 30 554 3838",
|
||||
tiktokHandle: "@skyflytravel.transfer"
|
||||
tiktokHandle: "@skyflytravel.transfer",
|
||||
moreImages: "További képek"
|
||||
},
|
||||
meta: {
|
||||
title: "SkyFly Travel - Gyors, megbízható, kényelmes reptéri transzferek!",
|
||||
|
|
@ -280,13 +281,7 @@
|
|||
toCityDesc: "Összeültetésnél a viszonyítási alap: Tervezett leszállás + 20-30 perc csomagfelvétel."
|
||||
},
|
||||
packages: {
|
||||
classic: {
|
||||
title: "Gyűjtő CLASSIC",
|
||||
unique: "Egyedi jellemző \"Gyűjtő CLASSIC\":",
|
||||
desc: "Igazodva más utasokhoz, szabad kapacitás függvényében. Igénybe vehető, ha van más utasunk is, és teljesül a feltétel: min. 30 perc max. 1,5 óra alkalmazkodás.",
|
||||
toAirport: "Az ideális utas felvételhez képest max. 1-1,5 órával korábbi indulás.",
|
||||
toCity: "Tervezett leszállás, csomagfelvétel után max. 1-1,5 órával későbbi indulás."
|
||||
},
|
||||
|
||||
express: {
|
||||
title: "Gyűjtő EXPRESS",
|
||||
unique: "Egyedi jellemző \"Gyűjtő EXPRESS\":",
|
||||
|
|
@ -304,14 +299,14 @@
|
|||
family: {
|
||||
title: "CSALÁDI",
|
||||
unique: "Egyedi jellemző \"CSALÁDI\":",
|
||||
desc: "Időben és térben nem kell más utashoz igazodni. Teljesítés: egyterű személygépjárművel, feltétele: max. 3 normál bőrönd, és 3 kézipoggyász.",
|
||||
desc: "Időben és térben nem kell más utashoz igazodni. Teljesítés: egyterű személygépjárművel, feltétele: min. 1 gyerek (0-14 éves), max. 3 normál bőrönd, és 3 kézipoggyász.",
|
||||
toAirport: "Az utas felvételi időpont az utas számára legideálisabb időpontban.",
|
||||
toCity: "Nincs várakozás."
|
||||
},
|
||||
bigFamily: {
|
||||
title: "NAGY CSALÁDI",
|
||||
unique: "Egyedi jellemző \"Nagy\" CSALÁDI:",
|
||||
desc: "Időben és térben nem kell más utashoz igazodni. Teljesítés: kisbusszal, feltétele: max. 6 normál bőrönd, és 6 kézipoggyász.",
|
||||
desc: "Időben és térben nem kell más utashoz igazodni. Teljesítés: kisbusszal, feltétele: min. 1 gyerek (0-14 éves), max. 6 normál bőrönd, és 6 kézipoggyász.",
|
||||
toAirport: "Az utas felvételi időpont az utas számára legideálisabb időpontban.",
|
||||
toCity: "Nincs várakozás."
|
||||
}
|
||||
|
|
@ -323,7 +318,7 @@
|
|||
"Autóink tisztaságára, műszaki állapotára nagy hangsúlyt fektetünk.",
|
||||
"A flottához tartozó gépkocsikat tervezett rendszerességgel cseréljük, hogy folyamatosan új autókkal álljunk utasaink rendelkezésére.",
|
||||
"A SkyFly Travel rendelkezik minden hatályos jogszabály által előírt személyszállítói engedéllyel.",
|
||||
"Sofőreink szakképzettek, GKI engedéllyel, PÁV-II tanúsítvánnyal és több éves tapasztalattal rendelkeznek.",
|
||||
|
||||
"NON-STOP ügyelet megrendelt fuvarokra (+36 30 5543838)",
|
||||
"Háztól – Házig szállítjuk (Ön által megadott címről/címre)"
|
||||
]
|
||||
|
|
@ -361,17 +356,17 @@
|
|||
{
|
||||
title: "2. A szolgáltatás megrendelése, információ-, ajánlatkérés",
|
||||
content: [
|
||||
"Foglalási szándékát honlapunkon az online foglalási felület kitöltésével tudja leadni. Ajánlatkérését kérjük szíveskedjen email-ben vagy az „ÜZENET” fül alatti űrlap kitöltésével megküldeni részünkre. Foglalása kizárólag a visszaigazolásunk megküldésével válik teljessé, e-nélkül foglalási szándéknak minősül. A foglalásokat szabad kapacitás függvényében tudjuk visszaigazolni a szándék beérkezésétól számítva max. 3 munkanapon belül, írásban, az Ön által megadott email címre megküldve.",
|
||||
"Foglalási szándékát / Árajánlat kérését honlapunkon az Online foglalás / Ajánlat menüpont alatti felület kitöltésével tudja leadni. Egyéb személyszállítás, vagy szolgáltatással kapcsolatos kérdések felmerülése esetén küldjön email-t vagy töltse ki Üzenetküldési űrlapunkat, melyet a Kapcsolat menüpont alatt talál. Foglalása kizárólag a visszaigazolásunk megküldésével válik teljessé, e-nélkül foglalási szándéknak minősül. A foglalásokat szabad kapacitás függvényében tudjuk visszaigazolni a szándék beérkezésétól számítva legfeljebb 2 munkanapon belül, írásban, az Ön által megadott email címre megküldve.",
|
||||
"Amennyiben foglalási szándékát az út előtti munkanap 12:00 után jelzi, szabad kapacitás függvényében feláras szolgáltatás keretében tudjuk vállalni, melynek díja plusz 2.500 Ft. Ez esetben, kérem szíveskedjen mindképp munkatársunkkal is egyeztetni ügyeleti telefonszámunkon: +36305543838",
|
||||
"Amennyiben szolgáltatással kapcsolatos információkra van szüksége, kérjük hívja hotline vonalunkat: +36 30 5543838, vagy tegye fel kérdéseit emailben: info@skyflytravel.hu.",
|
||||
"Az árlistában nem szereplő útvonalak, extra csomagmennyiség (a viteldíj magában foglalja: 1 db kézipoggyász és 1 normál méretű bőrönd max. 20 Kg / fő szállítását) vagy egyedi személyszállítás esetén kérje gyorsan és egyszerűen itt: ÜZENET KÜLDÉS",
|
||||
"Amennyiben szolgáltatással kapcsolatos információkra van szüksége, kérjük hívja hotline vonalunkat: +36 30 5543838, vagy tegye fel kérdéseit emailben: info@skyflytravel.hu. Munkaidőn kívül hotline vonalunkat szíveskedjen abban az esetben hívni csak, ha SOS kérdése, problémája merül fel az általunk nyújtott szolgáltatással kapcsolatban.",
|
||||
"Az árlistában nem szereplő útvonalak, extra csomagmennyiség (a viteldíj magában foglalja: 1 db kézipoggyász és 1 normál méretű bőrönd max. 20 Kg / fő szállítását) vagy egyedi személyszállítás esetén lépjen velünk kapcsolatban email-ben: info@skyflytravel.hu vagy töltse ki Üzenetküldési űrlapunkat a Kapcsolat menüpont alatt.",
|
||||
"Helytelen, nem valós adatok megadása esetén (pl. hibás dátum, időpont, cím, telefonszám) nem tudjuk garantálni a szolgáltatás teljesítését."
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "3. Fizetés módja",
|
||||
content: [
|
||||
"Sofőrünknél készpénzben, bankszámlánkra történő előreutalással, vagy egyedi megállapodás alapján utólagos átutalással."
|
||||
"Sofőrünknél készpénzben vagy bankkártyával (korlátozott mennyiségben, előre egyeztetés alapján), bankszámlánkra történő előreutalással, vagy egyedi megállapodás alapján utólagos átutalással."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -385,9 +380,9 @@
|
|||
title: "5. Várakozás, gépkésés",
|
||||
content: [
|
||||
"A reptéren való várakozási idő eltérő, attól függően, hogy a SkyFly Travel által nyújtott szolgáltatási csomagok közül melyiket kívánja igénybe venni.",
|
||||
"Vienna International Airport (Schwechat): miután felvette a csomagokat és menetkész, kérem szíveskedjen felfáradni az emeletre (érkezési csarnok, McDonald’s szemben lift vagy mozgó lépcső), majd forduljon jobbra és az utolsó kijáraton szíveskedj kifáradni, sofőrünk ott fogja várni a visszaigazolt utasfelvételi időpontban névvel ellátott táblával. Amennyiben táblást várás kérnek az érkezési csarnokban a parkolás díj 2.500 Ft, mely az utast terheli.",
|
||||
"Vienna International Airport (Schwechat): miután felvette a csomagokat és menetkész, kérem szíveskedjen felfáradni az emeletre (érkezési csarnok, Burger King-gel szemben lift vagy mozgó lépcső használatával), majd forduljon jobbra és az utolsó kijáraton szíveskedj kifáradni. Mikor már a találkozási pontra tart, szíveskedjen sofőrünkkel felvenni a kapcsolatot (elérhetőségét az út előtti munkanapon email-ben küldjük), hogy egyeztessenek a részletekről. Amennyiben táblást várás kérnek az érkezési csarnokban a parkolás díj 2.500 Ft, mely az utast terheli.",
|
||||
"Budapest Liszt Ferenc Repülőtér: utasaink két lehetőség közül választhatnak- az utazás előtti utolsó munkanap elküldjük sofőrünk telefonszámát, melyen őt kell értesíteni, ha felvették csomagjaikat. Másik lehetőség, hogy névvel ellátott táblával várjuk az érkezési csarnokban, ez esetben a parkolási díj (3.000 Ft) az utast terheli.",
|
||||
"Bratislava Repülőtér: sofőrünk az érkezési csarnokban névvel ellátott táblával várja az utasokat."
|
||||
"Bratislava Repülőtér: miután felvették a csomagokat, kérjük szíveskedjen sofőrünket hívni az út előtti munkanapon email-ben kapott elérhetőségen."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -432,34 +427,27 @@
|
|||
},
|
||||
categories: {
|
||||
vip: "VIP Prémium",
|
||||
business: "Üzleti kategória",
|
||||
family: "Családi és csoportos",
|
||||
minibus: "Kisbusz"
|
||||
personal: "Személygépjárművek",
|
||||
minibus: "Kisbuszok"
|
||||
},
|
||||
vehicles: {
|
||||
vclass: {
|
||||
name: "Mercedes-Benz V-Class",
|
||||
name: "Mercedes E - class / Mercedes V-class / Mercedes Vito",
|
||||
category: "VIP Prémium",
|
||||
description: "A luxus és tágas tér találkozása. Ideális üzleti delegációk vagy prémium kényelmet kereső családok számára.",
|
||||
features: ["6-7 Utas", "4-6 Bőrönd", "Klíma", "Bőr belső", "Wifi"]
|
||||
},
|
||||
eclass: {
|
||||
name: "Mercedes-Benz E-Class",
|
||||
category: "Üzleti kategória",
|
||||
description: "Elegancia és megbízhatóság. Professzionális megjelenés üzleti utazásokhoz és repülőtéri transzferekhez.",
|
||||
features: ["3 Utas", "2 Bőrönd", "Dokumentum hűtő", "Bőr belső"]
|
||||
features: []
|
||||
},
|
||||
superb: {
|
||||
name: "Skoda Superb Combi",
|
||||
category: "Üzleti kategória",
|
||||
description: "Kategóriájának legnagyobb lábtere és csomagtere. A tökéletes választás hosszú távú utazásokhoz.",
|
||||
features: ["4 Utas", "3 Bőrönd", "Hatalmas csomagtér", "Extra lábtér"]
|
||||
name: "Skoda Octavia / Skoda SuperB / Skoda Enyq / Renault Grand Scenic",
|
||||
category: "Személygépjárművek",
|
||||
description: "Elegancia, megbízhatóság, kényelem legyen szó akár üzleti útról vagy családi transzferről.",
|
||||
features: []
|
||||
},
|
||||
transit: {
|
||||
name: "Ford Transit / Renault Trafic",
|
||||
category: "Kisbusz",
|
||||
description: "Nagyobb csoportok számára a legpraktikusabb megoldás. Gazdaságos és kényelmes utazás 8 főig.",
|
||||
features: ["8 Utas", "8 Bőrönd", "Extra csomagtér", "Dupla klíma"]
|
||||
name: "Ford Transit / Ford Tourneo Custom / Renault Trafic / Opel Vivaro",
|
||||
category: "Kisbuszok",
|
||||
description: "Nagyobb csoportok számára a legpraktikusabb megoldás. Gazdaságos és kényelmes utazás 1-8 főig. Nagyobb létszám esetén több kisbusz rendelhető egy időben.",
|
||||
features: []
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -534,7 +522,7 @@
|
|||
title: "Információk",
|
||||
infoLine: "Info vonal (iroda munkanapokon 08:00-16:00ig):",
|
||||
infoLineValues: ["+36 96 283676", "+36 30 5543838"],
|
||||
dutyLine: "0-24 ügyelet megrendelt fuvarokra:",
|
||||
dutyLine: "0-24 ügyelet: Megrendelt fuvarokra, SOS kérdések, határidőn túli megrendelések esetére:",
|
||||
dutyLineValue: "+36 30 5543838",
|
||||
phone: "Hotline (0-24):",
|
||||
phoneValue: "+36 30 554 3838",
|
||||
|
|
@ -664,7 +652,8 @@
|
|||
brand: "SkyFly Travel",
|
||||
email: "info@skyflytravel.hu",
|
||||
phone: "+36 30 554 3838",
|
||||
tiktokHandle: "@skyflytravel.transfer"
|
||||
tiktokHandle: "@skyflytravel.transfer",
|
||||
moreImages: "More images"
|
||||
},
|
||||
meta: {
|
||||
title: "SkyFly Travel - Fast, reliable, comfortable airport transfers!",
|
||||
|
|
@ -940,13 +929,7 @@
|
|||
toCityDesc: "Factors when assigning passengers to groups: Scheduled time of arrival + 20-30 min for baggage claim."
|
||||
},
|
||||
packages: {
|
||||
classic: {
|
||||
title: "Economy CLASSIC",
|
||||
unique: "Unique feature \"Economy CLASSIC\":",
|
||||
desc: "Free seats are sold, if available, adapting to other passengers' schedule. min. 30 min max. 1.5 hours adjustment.",
|
||||
toAirport: "Passengers are picked up maximum 1-1.5 hrs earlier than the ideal pick-up time.",
|
||||
toCity: "Passengers leave the airport maximum 1-1.5 hrs later than scheduled time of arrival and baggage claim."
|
||||
},
|
||||
|
||||
express: {
|
||||
title: "Economy EXPRESS",
|
||||
unique: "Unique feature \"Economy EXPRESS\":",
|
||||
|
|
@ -964,14 +947,14 @@
|
|||
family: {
|
||||
title: "FAMILY",
|
||||
unique: "Unique feature \"FAMILY\":",
|
||||
desc: "No need to adapt to other passengers. Performed by a passenger car/SUV, max. 3 standard suitcases and 3 hand luggage.",
|
||||
desc: "No need to adapt to other passengers. Performed by a passenger car/SUV, min. 1 child (0-14 years), max. 3 standard suitcases and 3 hand luggage.",
|
||||
toAirport: "Pick-up time is ideal for the passenger.",
|
||||
toCity: "No waiting time."
|
||||
},
|
||||
bigFamily: {
|
||||
title: "BIG FAMILY",
|
||||
unique: "Unique feature \"Big\" FAMILY:",
|
||||
desc: "No need to adapt to other passengers. Performed by a minivan, max. 6 standard suitcases and 6 hand luggage.",
|
||||
desc: "No need to adapt to other passengers. Performed by a minivan, min. 1 child (0-14 years), max. 6 standard suitcases and 6 hand luggage.",
|
||||
toAirport: "Pick-up time is ideal for the passenger.",
|
||||
toCity: "No waiting time."
|
||||
}
|
||||
|
|
@ -983,7 +966,7 @@
|
|||
"We focus on the cleanness and the technical condition of our cars.",
|
||||
"We continuously renew our fleets to be at your service with new cars.",
|
||||
"SkyFly Travel has all passenger licenses required by current law.",
|
||||
"Our drivers are trained professionals with GKI license, PÁV-II certification and years of experience.",
|
||||
|
||||
"NON-STOP hotline for booked transfers (+36 30 5543838)",
|
||||
"Door-to-door transfer (from given address to given address)"
|
||||
]
|
||||
|
|
@ -1021,15 +1004,17 @@
|
|||
{
|
||||
title: "2. Placing an order, inquiries, requesting a quote",
|
||||
content: [
|
||||
"You can place an order by filling in the online order form, by sending an email to info@skyflytravel.hu or by sending a text message to +36 30 5543838. Deadline for placing an order: 12:00 noon the last working day before departure. Orders placed after the deadline are dealt with on an individual basis.",
|
||||
"For information about our service, please call our hotline or send us an email with your questions. For destinations not listed in our price list and for extra luggage (the fare includes: 1 piece of hand luggage and 1 large suitcase, approx. 20 kg per person) or for unique passenger transport solutions, please ask for a quote via email.",
|
||||
"In case the data provided are incorrect (e.g. incorrect date, time, address or phone number), we cannot guarantee the performance of the service."
|
||||
"You can submit your booking request / quote request by filling out the form under the Online Booking / Quote menu on our website. For other passenger transport or service-related questions, please send an email or fill out our Message Form, which can be found under the Contact menu. Your booking is only finalized upon receipt of our written confirmation; without it, it is considered a booking request. Bookings are confirmed pending free capacity within a maximum of 2 business days from receipt, sent in writing to your provided email address.",
|
||||
"If you submit your booking request after 12:00 on the business day preceding your travel, we can only provide the service under a surcharge (HUF 2,500), subject to availability. In this case, please make sure to coordinate with our staff via our duty phone line: +36305543838.",
|
||||
"If you need information regarding our service, please call our hotline at +36 30 5543838 or send your questions by email to info@skyflytravel.hu. Outside of business hours, please only call our hotline if you have an SOS question or problem related to the service we provide.",
|
||||
"For routes not listed in the price list, extra luggage capacity (the fare includes 1 hand luggage and 1 standard suitcase max. 20 kg per person), or unique passenger transport solutions, please contact us via email at info@skyflytravel.hu or fill out our Message Form under the Contact menu.",
|
||||
"In case the data provided are incorrect (e.g., incorrect date, time, address, or phone number), we cannot guarantee the performance of the service."
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "3. Payment methods",
|
||||
content: [
|
||||
"Payment in cash to the driver, prepayment by wire transfer, or post payment by wire transfer according to specific agreement."
|
||||
"Payment in cash or by bank card (in limited availability, by prior arrangement) to the driver, prepayment by wire transfer, or post-payment by wire transfer according to specific agreement."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -1042,10 +1027,10 @@
|
|||
{
|
||||
title: "5. Waiting time, delayed flights",
|
||||
content: [
|
||||
"Time spent at the airport varies depending which SkyFly Travel package you intend to use.",
|
||||
"Vienna International Airport (Schwechat): meeting point at the airport: from the arrival hall please go upstairs with the moving steps (you can find opposite of McDonald’s), after that turn right and go out at the last exit of Terminal 3. If you want that we wait for you with a sign in the arriving hall, the additional charge is 2.500 HUF.",
|
||||
"Budapest Liszt Ferenc Airport: there are two options - we either send passengers the driver’s phone number the last working day before the flight, so that they can get in contact once their baggage is claimed. Passengers can also choose to be met at arrivals, by our driver holding a name plate. In the latter case passengers have to pay the additional parking fee (HUF 3.000 HUF).",
|
||||
"Bratislava Airport: passengers are met by our driver at arrivals, holding a name plate."
|
||||
"Waiting time at the airport varies depending on which SkyFly Travel service package you intend to use.",
|
||||
"Vienna International Airport (Schwechat): after collecting your luggage and being ready to depart, please go upstairs (using the elevator or escalator opposite Burger King in the arrivals hall), then turn right and exit through the last door. When you are heading to the meeting point, please contact our driver (contact details will be sent via email on the business day preceding your travel) to coordinate the details. If you request a pickup with a name sign in the arrivals hall, a parking fee of HUF 2,500 applies, which is borne by the passenger.",
|
||||
"Budapest Liszt Ferenc Airport: our passengers can choose from two options - we send our driver's phone number on the last business day before travel, whom you should notify once you have collected your luggage. Alternatively, we can wait for you in the arrivals hall with a name sign, in which case a parking fee (HUF 3,000) is borne by the passenger.",
|
||||
"Bratislava Airport: after collecting your luggage, please call our driver at the contact number provided in the email received on the business day preceding your travel."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -1089,34 +1074,27 @@
|
|||
},
|
||||
categories: {
|
||||
vip: "VIP Premium",
|
||||
business: "Business Class",
|
||||
family: "Family & Group",
|
||||
minibus: "Minibus"
|
||||
personal: "Passenger Cars",
|
||||
minibus: "Minibuses"
|
||||
},
|
||||
vehicles: {
|
||||
vclass: {
|
||||
name: "Mercedes-Benz V-Class",
|
||||
name: "Mercedes E - class / Mercedes V-class / Mercedes Vito",
|
||||
category: "VIP Premium",
|
||||
description: "Where luxury meets spaciousness. Ideal for business delegations or families seeking premium comfort.",
|
||||
features: ["6-7 Passengers", "4-6 Suitcases", "Climate control", "Leather interior", "Wifi"]
|
||||
},
|
||||
eclass: {
|
||||
name: "Mercedes-Benz E-Class",
|
||||
category: "Business Class",
|
||||
description: "Elegance and reliability. Professional appearance for business trips and airport transfers.",
|
||||
features: ["3 Passengers", "2 Suitcases", "Document cooler", "Leather interior"]
|
||||
features: []
|
||||
},
|
||||
superb: {
|
||||
name: "Skoda Superb Combi",
|
||||
category: "Business Class",
|
||||
description: "Largest legroom and trunk in its category. The perfect choice for long-distance travel.",
|
||||
features: ["4 Passengers", "3 Suitcases", "Huge trunk", "Extra legroom"]
|
||||
name: "Skoda Octavia - Skoda SuperB - Skoda Enyq - Renault Grand Scenic",
|
||||
category: "Passenger Cars",
|
||||
description: "Elegance, reliability, comfort whether it's for business trips or family transfers.",
|
||||
features: []
|
||||
},
|
||||
transit: {
|
||||
name: "Ford Transit / Renault Trafic",
|
||||
category: "Minibus",
|
||||
description: "The most practical solution for larger groups. Economical and comfortable travel for up to 8 people.",
|
||||
features: ["8 Passengers", "8 Suitcases", "Extra luggage space", "Dual climate control"]
|
||||
name: "Ford Transit / Ford Tourneo Custom / Renault Trafic / Opel Vivaro",
|
||||
category: "Minibuses",
|
||||
description: "The most practical solution for larger groups. Economical and comfortable travel for 1-8 people. Multiple minibuses can be ordered at once for larger groups.",
|
||||
features: []
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -1186,7 +1164,7 @@
|
|||
title: "Information",
|
||||
infoLine: "Info line (office hours Mon-Fri 08:00-16:00):",
|
||||
infoLineValues: ["+36 96 283676", "+36 30 5543838"],
|
||||
dutyLine: "24/7 duty for booked transfers:",
|
||||
dutyLine: "24/7 Duty: For booked transfers, SOS questions, or orders after the deadline:",
|
||||
dutyLineValue: "+36 30 5543838",
|
||||
phone: "Hotline (0-24):",
|
||||
phoneValue: "+36 30 554 3838",
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"dev": "npm run generate:gallery && next dev",
|
||||
"generate:gallery": "node scripts/generate-gallery.mjs",
|
||||
"optimize:images": "node scripts/optimize-images.mjs",
|
||||
"build": "npm run optimize:images && next build",
|
||||
"build": "npm run generate:gallery && npm run optimize:images && next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"vip": [
|
||||
"/images/gallery/vip/Flotta_VIP_kezdő.png",
|
||||
"/images/gallery/vip/Mercedes Vito_belső.jpeg",
|
||||
"/images/gallery/vip/mercedes E-class.JPG",
|
||||
"/images/gallery/vip/vito.jpg"
|
||||
],
|
||||
"personal": [
|
||||
"/images/gallery/personal/3 skoda reptér.png",
|
||||
"/images/gallery/personal/Enyaq reptér.png",
|
||||
"/images/gallery/personal/Skoda SuperB-inside.jpeg",
|
||||
"/images/gallery/personal/Skoda SuperB.jpeg",
|
||||
"/images/gallery/personal/skoda_enyaq 2.jpg"
|
||||
],
|
||||
"minibus": [
|
||||
"/images/gallery/minibus/Ford Tourneo belső.JPG",
|
||||
"/images/gallery/minibus/Ford Tourneo.JPG",
|
||||
"/images/gallery/minibus/Ford Transit.jpg",
|
||||
"/images/gallery/minibus/Tourneo háttér hegy.png",
|
||||
"/images/gallery/minibus/új Trafic_2.JPG"
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 353 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 366 KiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 349 KiB |
|
After Width: | Height: | Size: 358 KiB |
|
After Width: | Height: | Size: 246 KiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 357 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 302 KiB |
|
|
@ -0,0 +1,55 @@
|
|||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const ROOT = process.cwd();
|
||||
const GALLERY_ROOT = path.join(ROOT, "public", "images", "gallery");
|
||||
const OUTPUT_FILE = path.join(ROOT, "public", "gallery.json");
|
||||
|
||||
async function exists(p) {
|
||||
try {
|
||||
await fs.access(p);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
if (!(await exists(GALLERY_ROOT))) {
|
||||
console.log("Gallery root not found, creating empty gallery.json");
|
||||
await fs.writeFile(OUTPUT_FILE, JSON.stringify({ vip: [], personal: [], minibus: [] }, null, 2));
|
||||
return;
|
||||
}
|
||||
|
||||
const categories = ["vip", "personal", "minibus"];
|
||||
const result = {};
|
||||
|
||||
for (const category of categories) {
|
||||
const categoryPath = path.join(GALLERY_ROOT, category);
|
||||
if (await exists(categoryPath)) {
|
||||
const files = await fs.readdir(categoryPath);
|
||||
const images = files
|
||||
.filter((file) => {
|
||||
const ext = path.extname(file).toLowerCase();
|
||||
return [".jpg", ".jpeg", ".png", ".webp", ".gif", ".svg"].includes(ext);
|
||||
})
|
||||
.sort()
|
||||
.map((img) => `/images/gallery/${category}/${img}`);
|
||||
|
||||
result[category] = images;
|
||||
} else {
|
||||
result[category] = [];
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeFile(OUTPUT_FILE, JSON.stringify(result, null, 2));
|
||||
console.log(`Gallery metadata generated at ${OUTPUT_FILE}`);
|
||||
console.log(`Summary: ${Object.keys(result).map(c => `${c}: ${result[c].length}`).join(", ")}`);
|
||||
} catch (err) {
|
||||
console.error("Error generating gallery metadata:", err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||