Files
moygroup/app/[lang]/galeri/GaleriClient.tsx
T

155 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useState } from "react";
import Image from "next/image";
import { m, AnimatePresence } from "framer-motion";
import { X, ZoomIn } from "lucide-react";
import { Badge } from "@/app/components/ui/badge";
import type { Dictionary } from "@/types/dictionary";
export default function GaleriClient({ dict }: { lang?: string; dict: Dictionary }) {
const t = dict.gallery;
const CATEGORIES = [t.all, t.venues, "Beach", "Bungalov", "Kite Surf", "Hotel"] as const;
type Category = string;
const IMAGES = [
{ src: "https://media.ayris.tech/upload/moygrup/kitebeach/moyheader-scaled.jpg", cat: t.venues, title: "Kite Beach Genel Görünüm" },
{ src: "https://media.ayris.tech/upload/moygrup/kitebeach/A1_0177-scaled.jpg", cat: "Beach", title: "Sahil Manzarası" },
{ src: "https://media.ayris.tech/upload/moygrup/kitebeach/A1_7609-scaled.jpg", cat: "Beach", title: "Kum ve Deniz" },
{ src: "https://media.ayris.tech/upload/moygrup/kitebeach/A1_7612-scaled.jpg", cat: "Beach", title: "Kite Sahili" },
{ src: "https://media.ayris.tech/upload/moygrup/kitebeach/A1_7630-scaled.jpg", cat: "Beach", title: "Rüzgar ve Deniz" },
{ src: "https://media.ayris.tech/upload/moygrup/kitebeach/A1_7684-scaled.jpg", cat: "Beach", title: "Kite Beach Dinlenme" },
{ src: "https://media.ayris.tech/upload/moygrup/kitebeach/images.jpeg", cat: "Beach", title: "Sahil Keyfi" },
{ src: "https://media.ayris.tech/upload/moygrup/kitehotel/kite3.png", cat: "Hotel", title: "Kite Beach Hotel" },
{ src: "https://media.ayris.tech/upload/moygrup/kitehotel/kite4.png", cat: "Hotel", title: "Hotel Odalar" },
{ src: "https://media.ayris.tech/upload/moygrup/kitehotel/kite5.png", cat: "Hotel", title: "Oda İçi Tasarım" },
{ src: "https://media.ayris.tech/upload/moygrup/kitehotel/kite6.png", cat: "Hotel", title: "Oda Detayları" },
{ src: "https://media.ayris.tech/upload/moygrup/kitesurf/Timeless-moments-at-Kite-Beach.-Where-every-wave-tells-a-story.-@mustfreeee-1.jpg", cat: "Kite Surf", title: "Kitesurf Heyecanı" },
{ src: "https://media.ayris.tech/upload/moygrup/kitesurf/Timeless-moments-at-Kite-Beach.-Where-every-wave-tells-a-story.-@mustfreeee-2.jpg", cat: "Kite Surf", title: "Dalgalarla Dans" },
{ src: "https://media.ayris.tech/upload/moygrup/kitesurf/Timeless-moments-at-Kite-Beach.-Where-every-wave-tells-a-story.-@mustfreeee-3.jpg", cat: "Kite Surf", title: "Profesyonel Kitesurf" },
{ src: "https://media.ayris.tech/upload/moygrup/kitesurf/Timeless-moments-at-Kite-Beach.-Where-every-wave-tells-a-story.-@mustfreeee-4.jpg", cat: "Kite Surf", title: "Rüzgarla Sörf" },
{ src: "https://media.ayris.tech/upload/moygrup/kitesurf/Timeless-moments-at-Kite-Beach.-Where-every-wave-tells-a-story.-@mustfreeee-5.jpg", cat: "Kite Surf", title: "Deniz ve Özgürlük" },
{ src: "https://media.ayris.tech/upload/moygrup/kitesurf/Timeless-moments-at-Kite-Beach.-Where-every-wave-tells-a-story.-@mustfreeee.jpg", cat: "Kite Surf", title: "Kitesurf Eğitimi" },
];
const [active, setActive] = useState<Category>(t.all);
const [lightbox, setLightbox] = useState<{ src: string, cat: string, title: string } | null>(null);
const filtered = active === t.all ? IMAGES : IMAGES.filter((img) => img.cat === active);
return (
<div className="min-h-screen bg-[var(--color-moy-dark)]">
{/* Hero */}
<div className="pt-40 pb-16 text-center px-6">
<p className="text-[10px] uppercase tracking-[0.28em] text-[var(--color-moy-gold)] mb-4">{t.eyebrow}</p>
<h1 className="text-5xl md:text-6xl font-serif text-white mb-6">{t.title}</h1>
<p className="text-gray-400 text-base max-w-md mx-auto leading-relaxed">
{t.subtitle}
</p>
</div>
{/* Filter pills */}
<div className="flex flex-wrap justify-center gap-3 px-6 mb-14">
{CATEGORIES.map((cat) => (
<button
key={cat}
onClick={() => setActive(cat)}
className={[
"px-5 py-2 text-[10px] uppercase tracking-[0.16em] font-medium transition-all duration-200",
active === cat
? "bg-[var(--color-moy-gold)] text-[var(--color-moy-dark)]"
: "border border-white/15 text-gray-400 hover:border-[var(--color-moy-gold)]/50 hover:text-[var(--color-moy-gold)]",
].join(" ")}
>
{cat}
</button>
))}
</div>
{/* Grid */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 pb-28">
<m.div
layout
className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"
>
<AnimatePresence mode="popLayout">
{filtered.map((img) => (
<m.div
key={img.src}
layout
initial={{ opacity: 0, scale: 0.94 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.94 }}
transition={{ duration: 0.35, ease: [0.16, 1, 0.3, 1] }}
className="group relative aspect-square cursor-pointer overflow-hidden"
onClick={() => setLightbox(img)}
>
<Image
src={img.src}
alt={img.title}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
className="object-cover transition-transform duration-700 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-[var(--color-moy-dark)]/0 group-hover:bg-[var(--color-moy-dark)]/50 transition-all duration-300 flex flex-col items-center justify-center gap-3">
<ZoomIn
size={28}
className="text-white opacity-0 group-hover:opacity-100 transition-opacity duration-300 translate-y-2 group-hover:translate-y-0"
/>
<span className="text-white text-sm font-serif opacity-0 group-hover:opacity-100 transition-opacity duration-300">
{img.title}
</span>
</div>
<Badge
variant="dark"
className="absolute top-3 left-3 opacity-0 group-hover:opacity-100 transition-opacity duration-300"
>
{img.cat}
</Badge>
</m.div>
))}
</AnimatePresence>
</m.div>
</div>
{/* Lightbox */}
<AnimatePresence>
{lightbox && (
<m.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-[300] bg-black/90 flex items-center justify-center p-6"
onClick={() => setLightbox(null)}
>
<button
className="absolute top-6 right-6 text-white/60 hover:text-white transition-colors"
onClick={() => setLightbox(null)}
>
<X size={28} />
</button>
<m.div
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.9, opacity: 0 }}
transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
className="max-w-4xl w-full"
onClick={(e) => e.stopPropagation()}
>
<Image
src={lightbox.src}
alt={lightbox.title}
width={1200}
height={800}
className="w-full h-auto max-h-[80vh] object-contain"
/>
<p className="text-center text-white font-serif text-xl mt-4">{lightbox.title}</p>
</m.div>
</m.div>
)}
</AnimatePresence>
</div>
);
}