Files

400 lines
15 KiB
TypeScript
Raw Permalink 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 { useTranslations } from 'next-intl';
import { motion } from 'framer-motion';
import { Calendar, Music, Disc3, CalendarDays, Zap, GlassWater } from 'lucide-react';
/* ── static data ───────────────────────────────── */
const WEEK_DAYS = ['Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt', 'Paz'];
const ACTIVE_DAYS: Record<number, string> = {
3: '#FF5A36',
4: '#00E5FF',
5: '#00E5FF',
};
/* ── types ─────────────────────────────────────── */
type EventItem = {
id: string;
title: string;
time: string;
tag: string;
iconType: string;
colorTheme: string;
isFeatured: boolean;
};
/* ── sub-components ────────────────────────────── */
function VinylDisc() {
return (
<motion.div
animate={{ rotate: 360 }}
transition={{ duration: 4, repeat: Infinity, ease: 'linear' }}
className="w-36 h-36 md:w-44 md:h-44 rounded-full relative flex-shrink-0"
style={{
background:
'repeating-conic-gradient(#0a0f1e 0deg 18deg, #141e30 18deg 36deg)',
boxShadow: '0 0 48px rgba(0,229,255,0.35), 0 0 80px rgba(0,229,255,0.12)',
}}
>
{/* Grooves */}
{[55, 45, 35].map((size) => (
<div
key={size}
className="absolute rounded-full border border-white/[0.04]"
style={{ inset: `${(100 - size) / 2}%` }}
/>
))}
{/* Label */}
<div
className="absolute inset-[35%] rounded-full flex items-center justify-center"
style={{ background: 'radial-gradient(circle, #00E5FF, #0084A8)' }}
>
<div className="w-2 h-2 rounded-full bg-white/80" />
</div>
</motion.div>
);
}
function EqBars({ color }: { color: string }) {
const heights = [0.4, 0.8, 0.5, 1, 0.65, 0.9, 0.45, 0.75, 0.55, 0.85];
return (
<div className="flex items-end gap-[3px] h-8">
{heights.map((h, i) => (
<motion.div
key={i}
className="w-1.5 rounded-full origin-bottom"
style={{ background: color, height: `${h * 100}%` }}
animate={{ scaleY: [h, h > 0.6 ? 0.2 : 1, h] }}
transition={{
duration: 0.5 + Math.random() * 0.4,
repeat: Infinity,
repeatType: 'mirror',
delay: i * 0.07,
ease: 'easeInOut',
}}
/>
))}
</div>
);
}
function WineGlassIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M8 22h8" />
<path d="M12 15v7" />
<path d="M12 15a5 5 0 0 0 5-5c0-2-.5-4-2-8H9c-1.5 4-2 6-2 8a5 5 0 0 0 5 5Z" />
<path d="M7 10h10" />
</svg>
);
}
/* ── main component ────────────────────────────── */
export default function Events({ dbEvents = [] }: { dbEvents?: any[] }) {
const t = useTranslations('Events');
// Hardcoded fallback data if db is empty
const defaultEvents: EventItem[] = dbEvents.length > 0 ? dbEvents : [
{
id: "fallback-1",
title: t('cards.dj.title'),
time: t('cards.dj.time'),
tag: "EN POPÜLER",
iconType: "dj",
colorTheme: "cyan",
isFeatured: true,
},
{
id: "fallback-2",
title: t('cards.raki.title'),
time: t('cards.raki.time'),
tag: "PER",
iconType: "glass",
colorTheme: "coral",
isFeatured: false,
},
{
id: "fallback-3",
title: t('cards.live_music.title'),
time: t('cards.live_music.time'),
tag: "★ ÖZEL",
iconType: "music",
colorTheme: "amber",
isFeatured: false,
}
];
const featuredEvent = defaultEvents.find(e => e.isFeatured) || defaultEvents[0];
const secondaryEvents = defaultEvents.filter(e => e.id !== featuredEvent.id);
// Tema renklerini almak için yardımcı fonksiyon
const getThemeColor = (theme: string) => {
switch (theme) {
case 'cyan': return '#00E5FF';
case 'coral': return '#FF5A36';
case 'amber': return '#FFA827';
default: return '#00E5FF';
}
};
const getThemeColors = (theme: string) => {
switch (theme) {
case 'cyan': return { main: '#00E5FF', bg: '#00E5FF1A', borderSpin: 'border-spin-cyan', darkBg: '#0C1828' };
case 'coral': return { main: '#FF5A36', bg: '#FF5A361A', borderSpin: 'border-spin-coral', darkBg: '#0C0808', hoverBg: '#110a0a' };
case 'amber': return { main: '#FFA827', bg: '#FFA8271A', borderSpin: 'border-spin-amber', darkBg: '#0C0A04', hoverBg: '#110d04' };
default: return { main: '#00E5FF', bg: '#00E5FF1A', borderSpin: 'border-spin-cyan', darkBg: '#0C1828', hoverBg: '#0C1828' };
}
};
// İkon bileşenini render etme yardımcı fonksiyonu
const renderIcon = (type: string, size: number = 22) => {
switch(type) {
case 'dj': return <Disc3 size={size} />;
case 'glass': return <WineGlassIcon />;
case 'music': return <Music size={size} />;
default: return <Music size={size} />;
}
};
return (
<section
id="events"
className="pt-28 pb-36 text-white relative overflow-hidden"
style={{ background: '#080D18' }}
>
{/* Aurora background blobs */}
<div className="absolute inset-0 overflow-hidden pointer-events-none">
<div
className="absolute top-[-20%] left-[-10%] w-[600px] h-[600px] rounded-full opacity-[0.12]"
style={{ background: 'radial-gradient(circle, #00E5FF 0%, transparent 70%)' }}
/>
<div
className="absolute bottom-[-10%] right-[-5%] w-[500px] h-[500px] rounded-full opacity-[0.1]"
style={{ background: 'radial-gradient(circle, #FF5A36 0%, transparent 70%)' }}
/>
<div
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[700px] rounded-full opacity-[0.05]"
style={{ background: 'radial-gradient(circle, #FFA827 0%, transparent 70%)' }}
/>
</div>
{/* Fine dot grid */}
<div
className="absolute inset-0 opacity-[0.035] pointer-events-none"
style={{
backgroundImage: 'radial-gradient(circle, rgba(255,255,255,0.9) 1px, transparent 1px)',
backgroundSize: '36px 36px',
}}
/>
<div className="container mx-auto px-6 lg:px-12 relative z-10 space-y-10">
{/* ── Header ───────────────────────────────── */}
<div className="flex flex-col lg:flex-row lg:items-end justify-between gap-6">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
<div className="flex items-center gap-2 mb-4">
<Zap size={13} className="text-coral" />
<span className="text-xs tracking-[0.4em] uppercase font-black text-coral">
Live Events
</span>
</div>
<h2 className="font-heading text-5xl md:text-6xl font-black leading-tight">
{t('title')}
</h2>
<p className="text-white/45 mt-3 text-base max-w-md leading-relaxed">
{t('description')}
</p>
</motion.div>
<motion.button
initial={{ opacity: 0, x: 20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
className="self-start lg:self-auto flex items-center gap-2 px-7 py-3.5 rounded-full font-black text-sm text-white flex-shrink-0 transition-all hover:scale-105"
style={{ background: 'linear-gradient(135deg, #FF5A36, #FFA827)' }}
>
<CalendarDays size={15} />
{t('view_calendar')}
</motion.button>
</div>
{/* ── Weekly schedule bar ───────────────────── */}
<motion.div
initial={{ opacity: 0, y: 12 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
className="flex items-center gap-2 md:gap-4 bg-white/[0.04] rounded-2xl px-6 py-4 border border-white/[0.07]"
>
{WEEK_DAYS.map((day, i) => {
const accent = ACTIVE_DAYS[i];
const isActive = !!accent;
return (
<div key={day} className="flex-1 flex flex-col items-center gap-2">
<span
className={`text-[10px] font-black uppercase tracking-wider ${
isActive ? 'text-white' : 'text-white/25'
}`}
>
{day}
</span>
<div
className={`w-1.5 h-1.5 rounded-full transition-all ${isActive ? 'scale-125' : ''}`}
style={{
background: isActive ? accent : 'rgba(255,255,255,0.12)',
boxShadow: isActive ? `0 0 8px ${accent}` : 'none',
}}
/>
</div>
);
})}
</motion.div>
{/* ── Featured Event (Dinamic) ────────────── */}
{featuredEvent && (() => {
const c = getThemeColors(featuredEvent.colorTheme);
return (
<motion.div
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.7 }}
className={`${c.borderSpin} rounded-3xl p-px overflow-hidden`}
>
<div
className="rounded-3xl p-8 md:p-10 flex flex-col md:flex-row items-center gap-8 overflow-hidden relative"
style={{ background: c.darkBg }}
>
{/* Glow center */}
<div
className="absolute inset-0 pointer-events-none"
style={{
background: `radial-gradient(ellipse at 80% 50%, ${c.main}14 0%, transparent 60%)`,
}}
/>
{/* Left: text */}
<div className="flex-1 relative z-10">
<div className="flex items-center gap-3 mb-5">
<span
className="text-[10px] font-black uppercase tracking-[0.35em] px-3 py-1.5 rounded-full"
style={{ background: c.bg, color: c.main }}
>
{featuredEvent.tag}
</span>
<div className="flex items-center gap-1.5 text-white/40 text-xs">
<Calendar size={11} />
<span>{featuredEvent.time}</span>
</div>
</div>
<h3 className="font-heading text-4xl md:text-5xl font-black mb-3 text-white leading-tight">
{featuredEvent.title}
</h3>
<div className="flex items-center gap-3 mb-7">
<div style={{ color: c.main }}>
{renderIcon(featuredEvent.iconType, 18)}
</div>
<span className="text-white/50 text-sm">Open-air · Beach Stage</span>
</div>
<EqBars color={c.main} />
</div>
{/* Right: vinyl */}
<div className="relative z-10 flex-shrink-0">
<VinylDisc />
</div>
</div>
</motion.div>
);
})()}
{/* ── Secondary events: 2-col grid (Dinamic) ─────────── */}
{secondaryEvents.length > 0 && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
{secondaryEvents.map((evt, i) => {
const c = getThemeColors(evt.colorTheme);
return (
<motion.div
key={evt.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.1 * (i + 1) }}
className={`${c.borderSpin} rounded-3xl p-px group cursor-pointer`}
>
<div
className="rounded-3xl p-7 h-full flex flex-col gap-5 relative overflow-hidden transition-colors duration-300"
style={{ background: c.darkBg }}
>
<div
className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-400 pointer-events-none"
style={{
background: `radial-gradient(ellipse at 20% 50%, ${c.main}1A 0%, transparent 65%)`,
}}
/>
<div className="flex items-start justify-between">
<div
className="w-12 h-12 rounded-2xl flex items-center justify-center"
style={{ background: c.bg, color: c.main }}
>
{renderIcon(evt.iconType, 22)}
</div>
<span
className="text-[10px] font-black uppercase tracking-wider px-2.5 py-1 rounded-full"
style={{ background: c.bg, color: c.main }}
>
{evt.tag}
</span>
</div>
<div>
<h3 className="font-heading text-2xl font-black text-white mb-2">
{evt.title}
</h3>
<div className="flex items-center gap-1.5 text-sm text-white/40">
<Calendar size={12} />
<span>{evt.time}</span>
</div>
</div>
<div className="mt-auto opacity-0 group-hover:opacity-100 transition-opacity duration-300">
<EqBars color={c.main} />
</div>
</div>
</motion.div>
);
})}
</div>
)}
</div>
{/* Wave → sand */}
<div className="absolute bottom-0 left-0 w-full leading-none pointer-events-none">
<svg viewBox="0 0 1440 64" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" className="w-full h-16">
<path d="M0,20 C360,64 720,0 1080,40 C1260,56 1380,10 1440,20 L1440,64 L0,64 Z" fill="#FFF8EE" />
</svg>
</div>
</section>
);
}