238 lines
13 KiB
TypeScript
238 lines
13 KiB
TypeScript
"use client"
|
|
|
|
import Image from "next/image"
|
|
import { Button } from "@/components/ui/button"
|
|
import { useLanguage } from "@/lib/language-context"
|
|
import { useEffect, useState } from "react"
|
|
import { ChevronLeft, ChevronRight } from "lucide-react"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
export default function Footer() {
|
|
const { t, language } = useLanguage()
|
|
const year = new Date().getFullYear().toString()
|
|
|
|
const [ratingsData, setRatingsData] = useState<any>(null)
|
|
const [allReviews, setAllReviews] = useState<any[]>([])
|
|
const [currentPage, setCurrentPage] = useState(0)
|
|
const [isTransitioning, setIsTransitioning] = useState(false)
|
|
|
|
const reviewsPerPage = 2
|
|
|
|
useEffect(() => {
|
|
const fetchRatings = async () => {
|
|
try {
|
|
const response = await fetch(`/ratings_${language}.json`)
|
|
const data = await response.json()
|
|
setRatingsData(data)
|
|
const reviews = data?.data?.[0]?.reviews ?? []
|
|
setAllReviews(reviews)
|
|
} catch (error) {
|
|
console.error("Error fetching ratings:", error)
|
|
}
|
|
}
|
|
fetchRatings()
|
|
}, [language])
|
|
|
|
const totalPages = Math.ceil(allReviews.length / reviewsPerPage)
|
|
|
|
const handlePageChange = (direction: 'next' | 'prev') => {
|
|
if (isTransitioning) return
|
|
setIsTransitioning(true)
|
|
setTimeout(() => {
|
|
if (direction === 'next') {
|
|
setCurrentPage((prev) => (prev + 1) % totalPages)
|
|
} else {
|
|
setCurrentPage((prev) => (prev - 1 + totalPages) % totalPages)
|
|
}
|
|
setIsTransitioning(false)
|
|
}, 300)
|
|
}
|
|
|
|
const currentReviews = allReviews.slice(
|
|
currentPage * reviewsPerPage,
|
|
(currentPage + 1) * reviewsPerPage
|
|
)
|
|
|
|
const ratingValue = ratingsData?.data?.[0]?.rating ?? 5.0
|
|
const ratingCount = ratingsData?.data?.[0]?.userRatingCount ?? 0
|
|
const ratingPercent = Math.max(0, Math.min(100, (ratingValue / 5) * 100))
|
|
const reviewUrl = "https://g.page/r/CRltVP4lAy7lEBM/review"
|
|
const reviewPreviewText = (text: string) => (text.length > 140 ? `${text.slice(0, 140).trimEnd()}...` : text)
|
|
const reviewStars = (value: number) => {
|
|
const safe = Math.max(0, Math.min(5, Math.round(value)))
|
|
return "★".repeat(safe) + "☆".repeat(5 - safe)
|
|
}
|
|
|
|
return (
|
|
<section className="py-16 md:py-20 bg-slate-950 text-white overflow-hidden">
|
|
<div className="max-w-6xl mx-auto px-6">
|
|
<div className="grid gap-12 lg:grid-cols-2 items-start">
|
|
<div className="space-y-8 text-center lg:text-left flex flex-col items-center lg:items-start transition-all duration-700">
|
|
<h2 className="text-4xl md:text-6xl font-black tracking-tighter uppercase leading-[0.9]">{t.footer.ready}</h2>
|
|
<p className="text-xl text-slate-400 max-w-xl">
|
|
{t.footer.description}
|
|
</p>
|
|
<div className="flex justify-center lg:justify-start gap-6 pt-4">
|
|
<Button size="lg" asChild className="rounded-full px-12 h-14 text-sm font-bold uppercase tracking-widest bg-primary hover:bg-primary/90 transition-all shadow-2xl hover:scale-105 active:scale-95">
|
|
<a href="https://app.skyflytravel.hu/public/offers/new">
|
|
{t.footer.cta}
|
|
</a>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="relative group">
|
|
<div className="relative rounded-[2rem] bg-white/[0.03] border border-white/10 p-6 md:p-7 backdrop-blur-2xl shadow-[0_32px_64px_-16px_rgba(0,0,0,0.5)] transition-all duration-500 hover:border-white/20">
|
|
<div className="flex items-center justify-between gap-4 mb-6">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-1.5 h-1.5 bg-primary rounded-full animate-pulse" />
|
|
<div className="text-[10px] font-black uppercase tracking-[0.4em] text-white/50">
|
|
{t.footer.reviewsTitle}
|
|
</div>
|
|
</div>
|
|
{totalPages > 1 && (
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={() => handlePageChange('prev')}
|
|
className="p-1.5 rounded-full border border-white/5 hover:border-white/20 hover:bg-white/5 transition-all text-white/40 hover:text-white"
|
|
disabled={isTransitioning}
|
|
aria-label={language === "hu" ? "Előző vélemények" : "Previous reviews"}
|
|
>
|
|
<ChevronLeft className="w-4 h-4" />
|
|
</button>
|
|
<div className="text-[10px] font-bold text-white/20 tracking-widest px-1">
|
|
{currentPage + 1} / {totalPages}
|
|
</div>
|
|
<button
|
|
onClick={() => handlePageChange('next')}
|
|
className="p-1.5 rounded-full border border-white/5 hover:border-white/20 hover:bg-white/5 transition-all text-white/40 hover:text-white"
|
|
disabled={isTransitioning}
|
|
aria-label={language === "hu" ? "Következő vélemények" : "Next reviews"}
|
|
>
|
|
<ChevronRight className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="flex items-center gap-6 mb-8">
|
|
<div className="text-4xl md:text-5xl font-black text-white tracking-tighter leading-none">
|
|
{ratingValue.toFixed(1)}
|
|
</div>
|
|
<div className="space-y-1.5">
|
|
<div className="flex items-center gap-1.5">
|
|
<span
|
|
className="text-[14px] md:text-[16px] leading-none tracking-[0.2em] font-semibold"
|
|
style={{
|
|
backgroundImage: `linear-gradient(90deg, #fde047 ${ratingPercent}%, rgba(255,255,255,0.2) ${ratingPercent}%)`,
|
|
WebkitBackgroundClip: "text",
|
|
color: "transparent",
|
|
}}
|
|
aria-hidden="true"
|
|
>
|
|
★★★★★
|
|
</span>
|
|
</div>
|
|
<div className="text-[10px] font-black uppercase tracking-[0.3em] text-white/40 ml-0.5">
|
|
{ratingCount} {t.hero.rating}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="relative min-h-[260px]">
|
|
<div className={cn(
|
|
"grid gap-3 transition-all duration-300",
|
|
isTransitioning ? "opacity-0 translate-y-2 scale-[0.99] blur-sm" : "opacity-100 translate-y-0 scale-100 blur-0"
|
|
)}>
|
|
{currentReviews.map((review, idx) => (
|
|
<div key={`${review.author ?? "review"}-${idx}`} className="group/card rounded-[1.8rem] bg-white/[0.02] border border-white/5 p-5 transition-all duration-300 hover:bg-white/[0.05] hover:border-white/10">
|
|
<div className="flex items-center justify-between gap-4 mb-4">
|
|
<div className="text-[11px] tracking-[0.25em] text-yellow-400/80 drop-shadow-[0_0_8px_rgba(250,204,21,0.3)]">
|
|
{reviewStars(review.rating ?? 5)}
|
|
</div>
|
|
<div className="text-[9px] uppercase tracking-[0.2em] font-black text-white/30 group-hover/card:text-white/50 transition-colors">
|
|
{review.author ?? "Google Reviewer"}
|
|
</div>
|
|
</div>
|
|
<p className="text-sm text-white/70 leading-relaxed font-medium [display:-webkit-box] [-webkit-line-clamp:3] [-webkit-box-orient:vertical] overflow-hidden italic">
|
|
"{reviewPreviewText(review.text ?? "")}"
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-8 pt-6 border-t border-white/5 flex items-center justify-between">
|
|
<a
|
|
href={reviewUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="inline-flex items-center gap-3 text-[10px] font-black uppercase tracking-[0.4em] text-white/40 hover:text-primary transition-all group/cta"
|
|
>
|
|
<span className="group-hover/cta:translate-x-1 transition-transform">{t.footer.reviewsCta}</span>
|
|
<div className="w-5 h-px bg-white/10 group-hover/cta:bg-primary transition-colors" />
|
|
</a>
|
|
|
|
<div className="flex gap-1">
|
|
{Array.from({ length: totalPages }).map((_, i) => (
|
|
<div
|
|
key={i}
|
|
className={cn(
|
|
"h-0.5 transition-all duration-500",
|
|
currentPage === i ? "w-4 bg-primary" : "w-2 bg-white/10"
|
|
)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-12 mt-12 border-t border-white/5 space-y-6 text-center">
|
|
<div className="flex flex-wrap justify-center gap-x-8 gap-y-2 text-slate-400 text-xs font-bold uppercase tracking-widest">
|
|
<a href="/docs/impresszum.pdf" target="_blank" rel="noopener noreferrer" className="hover:text-primary transition-colors">
|
|
{t.footer.impressum}
|
|
</a>
|
|
<a href="/docs/ADATVEDELEMI_SZABALYZAT_ZT.pdf" target="_blank" rel="noopener noreferrer" className="hover:text-primary transition-colors">
|
|
{t.footer.privacy}
|
|
</a>
|
|
</div>
|
|
<div className="flex flex-wrap justify-center gap-4">
|
|
<a href="https://www.facebook.com/airporttransfer.gyor" target="_blank" rel="noopener noreferrer" aria-label="Facebook" className="opacity-80 hover:opacity-100 transition-opacity">
|
|
<Image src="/images/social/facebook.png" alt="Facebook" width={20} height={20} className="object-contain" />
|
|
</a>
|
|
<a href="https://x.com/SkyFlyTravel1" target="_blank" rel="noopener noreferrer" aria-label="X (Twitter)" className="opacity-80 hover:opacity-100 transition-opacity">
|
|
<Image src="/images/social/twitter.png" alt="X (Twitter)" width={20} height={20} className="object-contain" />
|
|
</a>
|
|
<a href="https://skyflytravel.blogspot.com/" target="_blank" rel="noopener noreferrer" aria-label="Blogspot" className="opacity-80 hover:opacity-100 transition-opacity">
|
|
<Image src="/images/social/blogspot.png" alt="Blogspot" width={20} height={20} className="object-contain" />
|
|
</a>
|
|
<a href="https://www.tiktok.com/@skyflytravel.transfer" target="_blank" rel="noopener noreferrer" aria-label="TikTok" className="opacity-80 hover:opacity-100 transition-opacity">
|
|
<svg viewBox="0 0 24 24" className="w-5 h-5 fill-white" aria-hidden="true">
|
|
<path d="M12.525.02c1.31-.036 2.612-.01 3.91-.01.1.993.414 1.956.96 2.784.73 1.096 1.764 1.93 2.97 2.45v3.91c-.815-.09-1.62-.315-2.38-.64-.816-.35-1.545-.88-2.15-1.53-.102.043-.102.164-.102.26v9.06c0 1.54-.34 3.05-1 4.41-.65 1.35-1.63 2.5-2.83 3.33-1.4.95-3.08 1.45-4.79 1.45-1.68 0-3.32-.48-4.73-1.39-1.21-.79-2.2-1.9-2.86-3.21-.71-1.37-1.07-2.9-1.07-4.47s.36-3.1 1.07-4.47c.66-1.31 1.65-2.42 2.86-3.21 1.25-.8 2.69-1.23 4.18-1.25.102 0 .204-.006.307-.006v3.94c-.037-.006-.074-.012-.112-.012-1.25.038-2.44.57-3.31 1.49-.89.92-1.38 2.16-1.38 3.45 0 1.29.49 2.53 1.38 3.45.87.92 2.06 1.45 3.31 1.49 1.25-.038 2.44-.57 3.31-1.49.89-.92 1.38-2.16 1.38-3.45V0l.024.02z" />
|
|
</svg>
|
|
</a>
|
|
<a href="https://www.instagram.com/skyfly_travel/" target="_blank" rel="noopener noreferrer" aria-label="Instagram" className="opacity-80 hover:opacity-100 transition-opacity">
|
|
<Image src="/images/social/instagram.png" alt="Instagram" width={20} height={20} className="object-contain" />
|
|
</a>
|
|
</div>
|
|
<div className="text-slate-600 text-[10px] font-bold uppercase tracking-widest">
|
|
{t.footer.copyright.replace("{year}", year)} {t.footer.rights}
|
|
</div>
|
|
<div className="text-slate-900/10 text-[8px] leading-tight select-none">
|
|
{t.footer.seoLine}
|
|
</div>
|
|
<div className="flex flex-col items-center gap-1 text-slate-800 text-[9px] font-bold uppercase tracking-widest pt-2 sm:flex-row sm:justify-center sm:gap-4">
|
|
<a href="https://transzfer.lap.hu" target="_blank" rel="noopener noreferrer" className="hover:text-primary transition-colors">transzfer.lap.hu</a>
|
|
<span className="opacity-20 hidden sm:inline">|</span>
|
|
<a href="https://utasszallitas.lap.hu" target="_blank" rel="noopener noreferrer" className="hover:text-primary transition-colors">utasszallitas.lap.hu</a>
|
|
<span className="opacity-20 hidden sm:inline">|</span>
|
|
<a href="https://repuloter.lap.hu" target="_blank" rel="noopener noreferrer" className="hover:text-primary transition-colors">repuloter.lap.hu</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|