'use client';
import Link from 'next/link';
import Image from 'next/image';
import { motion } from 'framer-motion';
import { DynamicImport } from '@/components/DynamicImport';
import { REVIEWS } from '@/data/reviews';
import dynamic from 'next/dynamic';
// Dynamically import heavy components with proper code splitting
const LazyMap = dynamic(() => import('@/components/ui/Map'), {
loading: () => <div className="h-[400px] w-full bg-slate-100 animate-pulse rounded-lg"></div>,
ssr: false,
});
const LazyFAQ = dynamic(() => import('@/components/ui/FAQ').then(mod => mod.default), {
loading: () => <div className="py-4 space-y-2" aria-label="Loading FAQs">
{[1, 2, 3].map(i => (
<div key={i} className="h-20 bg-slate-100 animate-pulse rounded-lg mb-2"></div>
))}
</div>,
});
const LazyReviews = dynamic(() => import('@/components/ui/Reviews').then(mod => mod.default), {
loading: () => <div className="py-4 space-y-2" aria-label="Loading reviews">
{[1, 2, 3].map(i => (
<div key={i} className="h-32 bg-slate-100 animate-pulse rounded-lg mb-2"></div>
))}
</div>,
ssr: false,
});
const LazyEvents = dynamic(() => import('@/app/events/page'), {
loading: () => <div className="py-4" aria-label="Loading events">
<div className="h-64 bg-slate-100 animate-pulse rounded-lg"></div>
</div>,
ssr: false,
});
// Animation variants
const fadeIn = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 }
};
const staggerContainer = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.1
}
}
};
const itemVariant = {
hidden: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.5,
ease: 'easeOut'
}
}
};
type ClientContentProps = {
mediaItems: Array<{
src: string;
alt: string;
width?: number;
height?: number;
quality?: number;
}>;
services: Array<{
image: string;
title: string;
description: string;
url: string;
cta: string;
}>;
faq: Array<{
question: string;
answer: string;
}>;
};
// Menu categories data
const MENU_CATEGORIES = [
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" className="h-10 w-10 text-orange-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M18 8h1a4 4 0 0 1 0 8h-1"></path>
<path d="M2 8h16v9a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V8z"></path>
<line x1="6" y1="1" x2="6" y2="4"></line>
<line x1="10" y1="1" x2="10" y2="4"></line>
<line x1="14" y1="1" x2="14" y2="4"></line>
</svg>
),
title: "Майсторски Коктейли",
description: "Класически, Сауър и наши уникални Авторски рецепти.",
bgColor: "bg-orange-100",
iconColor: "text-orange-600"
},
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" className="h-10 w-10 text-amber-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M8 22h8"></path>
<path d="M7 10h10"></path>
<path d="M12 15v-5"></path>
<path d="M12 15a3 3 0 1 0 0 6 3 3 0 0 0 0-6z"></path>
<path d="M17 10a5 5 0 0 0-10 0"></path>
</svg>
),
title: "Богат Бар",
description: "Впечатляваща селекция от уиски, джин, водка, ром, ракия и други качествени алкохолни напитки.",
bgColor: "bg-amber-100",
iconColor: "text-amber-600"
},
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" className="h-10 w-10 text-amber-800" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M17 8h1a4 4 0 1 1 0 8h-1"></path>
<path d="M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V8z"></path>
<line x1="6" y1="1" x2="6" y2="4"></line>
<line x1="10" y1="1" x2="10" y2="4"></line>
<line x1="14" y1="1" x2="14" y2="4"></line>
</svg>
),
title: "Кафе Специалитети",
description: "От перфектно еспресо до креативни латета и топъл шоколад.",
bgColor: "bg-brown-100",
iconColor: "text-amber-800"
},
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" className="h-10 w-10 text-blue-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M8 2h8"></path>
<path d="M12 2v10"></path>
<path d="M17 12a5 5 0 0 1-10 0"></path>
<path d="M12 12v8"></path>
<path d="M8 20h8"></path>
</svg>
),
title: "Свежест във Всяка Глътка",
description: "Домашни лимонади, фрешове, смутита и разнообразие от безалкохолни.",
bgColor: "bg-blue-100",
iconColor: "text-blue-600"
},
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" className="h-10 w-10 text-red-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M10 6.5c1 -1 2 -1 3 -1s2 0 3 1c1 1 1 2 1 3c0 1 0 2 -1 3c-1 1 -2 1 -3 1s-2 0 -3 -1c-1 -1 -1 -2 -1 -3c0 -1 0 -2 1 -3z"></path>
<path d="M9 6.5c0 3.5 -4 3.5 -4 6c0 1.5 1.5 2.5 3 2.5c1.5 0 3 -1 3 -2.5"></path>
<path d="M9 18l3 3l3 -3"></path>
<path d="M15 16l3.5 -5.5"></path>
</svg>
),
title: "Вино и Бира",
description: "Подбрани вина на чаша/бутилка и микс от крафт и класически бири.",
bgColor: "bg-red-100",
iconColor: "text-red-600"
},
{
icon: (
<svg xmlns="http://www.w3.org/2000/svg" className="h-10 w-10 text-green-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M6 19c0 1 1 2 2 2h8c1 0 2 -1 2 -2"></path>
<path d="M4 5v1a1 1 0 0 0 1 1h1"></path>
<path d="M14 5v1a1 1 0 0 1 -1 1h-1"></path>
<path d="M6 8v12"></path>
<path d="M18 8v12"></path>
<path d="M6 8h12"></path>
<path d="M3 5a2 2 0 0 1 2 -2h2m4 0h2m4 0h2a2 2 0 0 1 2 2"></path>
</svg>
),
title: "Апетитна Храна",
description: "Идеални за споделяне плата, хрупкави картофки, начос, сандвичи, салати и сладки изкушения.",
bgColor: "bg-green-100",
iconColor: "text-green-600"
}
];
export function ClientContent({ mediaItems, services, faq }: ClientContentProps) {
return (
<>
{/* Optimized Image Carousel */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 0.4 }}
className="relative overflow-hidden"
>
<div
className="carousel carousel-center rounded-xl space-x-4 p-4 w-full"
style={{
scrollBehavior: 'smooth',
overscrollBehavior: 'none',
WebkitOverflowScrolling: 'touch'
}}
onScroll={(e) => {
const target = e.target as HTMLDivElement;
const scrollLeft = target.scrollLeft;
const scrollWidth = target.scrollWidth;
const clientWidth = target.clientWidth;
// Only handle infinite scroll if we're actively scrolling
if (target.dataset.isScrolling === 'true') {
// If we're at the end, jump back to the middle without animation
if (scrollLeft + clientWidth >= scrollWidth - 50) {
target.scrollLeft = scrollWidth / 2;
}
// If we're at the start, jump to the middle without animation
if (scrollLeft <= 50) {
target.scrollLeft = scrollWidth / 2;
}
}
}}
onTouchStart={(e) => {
const target = e.target as HTMLDivElement;
target.dataset.isScrolling = 'true';
}}
onTouchEnd={(e) => {
const target = e.target as HTMLDivElement;
target.dataset.isScrolling = 'false';
}}
onMouseDown={(e) => {
const target = e.target as HTMLDivElement;
target.dataset.isScrolling = 'true';
}}
onMouseUp={(e) => {
const target = e.target as HTMLDivElement;
target.dataset.isScrolling = 'false';
}}
>
{/* Duplicate last few images at the start for infinite scroll */}
{mediaItems.slice(-3).map((item, index) => (
<motion.div
className="carousel-item"
key={`start-${index}`}
whileHover={{ scale: 1.02 }}
transition={{ duration: 0.3 }}
>
<Image
src={item.src}
alt={item.alt}
className="h-[300px] w-auto object-cover rounded-lg shadow-md"
width={item.width || 400}
height={item.height || 250}
loading="lazy"
sizes="(max-width: 640px) 100vw, (max-width: 768px) 50vw, 400px"
quality={item.quality || 75}
/>
</motion.div>
))}
{/* Main images */}
{mediaItems.map((item, index) => (
<motion.div
className="carousel-item"
key={index}
whileHover={{ scale: 1.02 }}
transition={{ duration: 0.3 }}
>
<Image
src={item.src}
alt={item.alt}
className="h-[300px] w-auto object-cover rounded-lg shadow-md"
width={item.width || 400}
height={item.height || 250}
loading={index < 2 ? "eager" : "lazy"}
fetchPriority={index === 0 ? "high" : "auto"}
sizes="(max-width: 640px) 100vw, (max-width: 768px) 50vw, 400px"
priority={index === 0}
quality={item.quality || 75}
/>
</motion.div>
))}
{/* Duplicate first few images at the end for infinite scroll */}
{mediaItems.slice(0, 3).map((item, index) => (
<motion.div
className="carousel-item"
key={`end-${index}`}
whileHover={{ scale: 1.02 }}
transition={{ duration: 0.3 }}
>
<Image
src={item.src}
alt={item.alt}
className="h-[300px] w-auto object-cover rounded-lg shadow-md"
width={item.width || 400}
height={item.height || 250}
loading="lazy"
sizes="(max-width: 640px) 100vw, (max-width: 768px) 50vw, 400px"
quality={item.quality || 75}
/>
</motion.div>
))}
</div>
</motion.div>
<div className="h-20" />
{/* Menu Section */}
<motion.div
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={fadeIn}
transition={{ duration: 0.8 }}
>
<motion.h3
className="text-2xl font-bold text-center md:text-3xl"
variants={fadeIn}
>
Открийте Нашите Вкусове: Кафе, Коктейли, Храна и Още
</motion.h3>
<div className="h-5" />
<motion.div
className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 gap-y-6"
variants={staggerContainer}
>
{MENU_CATEGORIES.map((category, index) => (
<motion.div
key={index}
className="flex flex-col items-center"
variants={itemVariant}
>
<div className={`p-4 rounded-full mb-3`}>
{category.icon}
</div>
<h4 className="font-bold text-lg mb-1">{category.title}</h4>
<p className="text-center text-gray-600">{category.description}</p>
</motion.div>
))}
</motion.div>
<div className="h-8" />
<motion.div
className="flex justify-center"
variants={fadeIn}
transition={{ delay: 0.4, duration: 0.8 }}
>
<Link href="/menu">
<motion.button
className="btn btn-outline"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
Разгледай пълното меню
</motion.button>
</Link>
</motion.div>
</motion.div>
<div className="h-20" />
{/* Events Section */}
<motion.div
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={fadeIn}
transition={{ duration: 0.8 }}
>
<DynamicImport loadingStrategy="on-visible">
<LazyEvents />
</DynamicImport>
</motion.div>
<div className="h-20" />
{/* Services Section */}
<motion.div
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={fadeIn}
transition={{ duration: 0.8 }}
>
<motion.h3
className="text-2xl font-bold text-center md:text-3xl"
variants={fadeIn}
>
Какво предлагаме
</motion.h3>
<div className="h-5" />
<motion.div
className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 gap-6"
variants={staggerContainer}
>
{services.map((service, index) => (
<motion.div
className="card bg-white shadow-xl col-span-1 rounded-lg overflow-hidden"
key={index}
variants={itemVariant}
whileHover={{
y: -10,
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)'
}}
transition={{ duration: 0.3 }}
>
<figure className="relative overflow-hidden">
<Image
className="rounded-t-lg w-full h-48 object-cover transition-transform duration-500"
src={service.image}
alt={service.title}
width={400}
height={300}
loading={index < 1 ? "eager" : "lazy"}
sizes="(max-width: 640px) 100vw, (max-width: 1200px) 50vw, 33vw"
quality={75}
/>
</figure>
<div className="card-body px-4 py-4">
<h2 className="card-title font-bold">{service.title}</h2>
<p className="text-gray-600">{service.description}</p>
<div className="card-actions justify-end mt-2">
<Link href={service.url}>
<motion.button
className="btn btn-outline btn-sm"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
{service.cta}
</motion.button>
</Link>
</div>
</div>
</motion.div>
))}
</motion.div>
</motion.div>
<div className="h-20" />
{/* FAQ Section */}
<motion.div
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={fadeIn}
transition={{ duration: 0.8 }}
>
<motion.h3
className="text-2xl font-bold text-center md:text-3xl"
variants={fadeIn}
>
Често задавани въпроси
</motion.h3>
<div className="h-5" />
<DynamicImport loadingStrategy="on-visible">
<LazyFAQ questions={faq} />
</DynamicImport>
</motion.div>
<div className="h-20" />
{/* Reviews Section */}
<motion.div
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={fadeIn}
transition={{ duration: 0.8 }}
>
<motion.h3
className="text-2xl font-bold text-center md:text-3xl"
variants={fadeIn}
>
Какво казват нашите клиенти
</motion.h3>
<div className="h-5" />
<motion.p
className="text-lg text-center md:text-xl text-gray-600 mb-8"
variants={fadeIn}
transition={{ delay: 0.2, duration: 0.8 }}
>
Отзиви от Google Maps
</motion.p>
<DynamicImport loadingStrategy="on-visible">
<LazyReviews reviews={REVIEWS} />
</DynamicImport>
</motion.div>
<div className="h-20" />
{/* Map Section - Load this last and only when visible */}
<motion.div
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={fadeIn}
transition={{ duration: 0.8 }}
>
<motion.h3
className="text-2xl font-bold text-center md:text-3xl"
variants={fadeIn}
>
Къде се намираме
</motion.h3>
<div className="h-10" />
<DynamicImport loadingStrategy="on-visible">
<LazyMap />
</DynamicImport>
</motion.div>
</>
);
}