canina/frontend/application/app/HomeClient.tsx
parsa aghaei ba9472c938
Some checks failed
Deploy Canina / deploy (push) Successful in 2m23s
E2E Playwright Tests / Run Full E2E & Security Suites (push) Failing after 0s
fix(home): fix mobile slider vertical scroll chaining, unify view-all headers, and enhance CTA and navigation cards
2026-09-06 12:00:41 +03:30

249 lines
18 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { useEffect, useState } from "react";
import Hero from "../components/Hero";
import SmartAdvisor from "../components/SmartAdvisor";
import FeaturedProducts from "../components/FeaturedProducts";
import VetGallery from "../components/VetGallery";
import TestimonialsSection from "../components/TestimonialsSection";
import BlogPreviewSection from "../components/BlogPreviewSection";
import FAQSection from "../components/FAQSection";
import BannerPlacement from "../components/BannerPlacement";
import Link from 'next/link';
import { toPersian } from "../lib/utils";
import { useSettingsStore } from "../lib/store/settingsStore";
import api from "../lib/services/api";
import Image from "next/image";
import { Banner, Testimonial, SmartAdvisorRule, HomeApiResponse } from "../lib/types";
import { Pill, BookOpen, Sparkles, ArrowLeft, ShieldCheck, Stethoscope } from "lucide-react";
interface HomeClientProps {
initialData?: HomeApiResponse | null;
}
export default function HomeClient({ initialData }: HomeClientProps) {
const getText = useSettingsStore((state) => state.getText);
const [banners, setBanners] = useState<Banner[]>(initialData?.heroBanners || []);
const [testimonials, setTestimonials] = useState<Testimonial[]>(initialData?.vetTestimonials || []);
const [rules, setRules] = useState<SmartAdvisorRule[]>(initialData?.smartAdvisorRules || []);
useEffect(() => {
// Fetch banners
api.get('/banners')
.then(res => {
if (Array.isArray(res.data)) {
setBanners(res.data);
}
})
.catch(err => console.error('[HomeClient] Banners fetch error:', err));
// Fetch testimonials
api.get('/testimonials')
.then(res => {
if (Array.isArray(res.data)) {
setTestimonials(res.data);
}
})
.catch(err => console.error('[HomeClient] Testimonials fetch error:', err));
// Fetch smart advisor rules
api.get('/smart-advisor/rules')
.then(res => {
if (Array.isArray(res.data)) {
setRules(res.data);
}
})
.catch(err => console.error('[HomeClient] Smart Advisor rules fetch error:', err));
}, []);
const heroBanners = banners.filter(b => b.position === 'home_hero' && b.isActive !== false);
return (
<>
<Hero banners={heroBanners} />
<SmartAdvisor rules={rules} />
<BannerPlacement banners={banners} position="home_middle" />
<FeaturedProducts />
<VetGallery testimonials={testimonials} />
<TestimonialsSection />
<BlogPreviewSection />
<FAQSection />
{/* Navigation to Sections */}
<section className="py-8 sm:py-14 bg-medical-gray-50 border-y border-medical-gray-100 font-sans">
<div className="max-w-7xl mx-auto px-4 grid md:grid-cols-2 gap-5 sm:gap-8">
{/* Specialty Shop Card */}
<Link
href="/shop"
className="group relative overflow-hidden rounded-3xl sm:rounded-[2.5rem] bg-gradient-to-br from-white via-blue-50/50 to-canina-blue/10 p-6 sm:p-10 border border-blue-200/70 shadow-md hover:shadow-2xl hover:border-canina-blue/50 hover:-translate-y-1 transition-all duration-500 block"
>
{/* Ambient Glows */}
<div className="absolute -top-16 -left-16 w-44 h-44 bg-canina-blue/15 rounded-full blur-3xl group-hover:scale-150 transition-transform duration-700 pointer-events-none" />
<div className="absolute -bottom-16 -right-16 w-36 h-36 bg-blue-400/10 rounded-full blur-2xl pointer-events-none" />
<div className="relative z-10 flex flex-col h-full justify-between">
<div>
<div className="flex items-center justify-between gap-3 mb-4">
<div className="w-12 h-12 sm:w-14 sm:h-14 rounded-2xl bg-canina-blue text-white flex items-center justify-center shadow-lg shadow-canina-blue/25 group-hover:scale-110 group-hover:rotate-6 transition-all">
<Pill className="w-6 h-6 sm:w-7 sm:h-7" />
</div>
<span className="px-3 py-1 rounded-full bg-blue-100/80 text-canina-blue text-[11px] font-black tracking-wider uppercase font-vazir border border-blue-200/60 shadow-xs">
محصولات دارویی و مکمل
</span>
</div>
<h3 className="text-2xl sm:text-3xl font-black text-medical-gray-900 mb-2 sm:mb-3 group-hover:text-canina-blue transition-colors font-lalezar tracking-wide">
{getText('nav_card_shop_title', "داروخانه تخصصی مکمل‌ها")}
</h3>
<p className="text-sm sm:text-base text-medical-gray-600 mb-6 sm:mb-8 leading-relaxed font-shabnam">
{getText('nav_card_shop_desc', "دسترسی مستقیم به کامل‌ترین مجموعه مکمل‌های آلمانی اصل بر اساس علائم بالینی و نیازهای پت شما.")}
</p>
</div>
<div className="pt-4 border-t border-blue-100/80 flex items-center justify-between text-canina-blue font-black text-xs sm:text-sm font-vazir">
<span>{getText('nav_card_shop_cta', "ورود به فروشگاه و کاتالوگ")}</span>
<div className="w-8 h-8 rounded-xl bg-canina-blue/10 flex items-center justify-center group-hover:bg-canina-blue group-hover:text-white transition-all">
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform rtl:rotate-0" />
</div>
</div>
</div>
</Link>
{/* Scientific Wiki Card */}
<Link
href="/wiki"
className="group relative overflow-hidden rounded-3xl sm:rounded-[2.5rem] bg-gradient-to-br from-white via-emerald-50/50 to-teal-500/10 p-6 sm:p-10 border border-emerald-200/70 shadow-md hover:shadow-2xl hover:border-emerald-500/50 hover:-translate-y-1 transition-all duration-500 block"
>
{/* Ambient Glows */}
<div className="absolute -top-16 -left-16 w-44 h-44 bg-emerald-500/15 rounded-full blur-3xl group-hover:scale-150 transition-transform duration-700 pointer-events-none" />
<div className="absolute -bottom-16 -right-16 w-36 h-36 bg-teal-400/10 rounded-full blur-2xl pointer-events-none" />
<div className="relative z-10 flex flex-col h-full justify-between">
<div>
<div className="flex items-center justify-between gap-3 mb-4">
<div className="w-12 h-12 sm:w-14 sm:h-14 rounded-2xl bg-emerald-600 text-white flex items-center justify-center shadow-lg shadow-emerald-600/25 group-hover:scale-110 group-hover:-rotate-6 transition-all">
<BookOpen className="w-6 h-6 sm:w-7 sm:h-7" />
</div>
<span className="px-3 py-1 rounded-full bg-emerald-100/80 text-emerald-800 text-[11px] font-black tracking-wider uppercase font-vazir border border-emerald-200/60 shadow-xs">
تحقیقات بینالمللی
</span>
</div>
<h3 className="text-2xl sm:text-3xl font-black text-medical-gray-900 mb-2 sm:mb-3 group-hover:text-emerald-700 transition-colors font-lalezar tracking-wide">
{getText('nav_card_wiki_title', "دانشنامه علمی و مقالات")}
</h3>
<p className="text-sm sm:text-base text-medical-gray-600 mb-6 sm:mb-8 leading-relaxed font-shabnam">
{getText('nav_card_wiki_desc', "آشنایی تخصصی با ترکیبات دارویی نایاب نظیر صدف لب‌سبز، هیدروکسی‌آپاتیت و استانداردهای دارویی آلمان.")}
</p>
</div>
<div className="pt-4 border-t border-emerald-100/80 flex items-center justify-between text-emerald-700 font-black text-xs sm:text-sm font-vazir">
<span>{getText('nav_card_wiki_cta', "مطالعه دانشنامه ترکیبات")}</span>
<div className="w-8 h-8 rounded-xl bg-emerald-600/10 flex items-center justify-center group-hover:bg-emerald-600 group-hover:text-white transition-all">
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform rtl:rotate-0" />
</div>
</div>
</div>
</Link>
</div>
</section>
{/* About Section Teaser */}
<section className="py-8 sm:py-16 bg-white overflow-hidden font-sans">
<div className="max-w-7xl mx-auto px-4 grid lg:grid-cols-2 gap-8 lg:gap-24 items-center">
<div className="relative overflow-hidden rounded-2xl sm:rounded-[3rem]">
<div className="absolute -top-10 -right-10 w-40 h-40 bg-canina-blue/5 rounded-full blur-3xl" />
<Image
src={getText('about_image_url', "/assets/images/regenerated_image_1779109861747.png")}
alt={getText('about_image_alt', "آزمایشگاه تخصصی تولید مکمل‌های دارویی کنینا آلمان")}
className="rounded-2xl sm:rounded-[3rem] shadow-2xl relative z-10 grayscale-[10%] w-full object-cover"
width={640}
height={425}
loading="lazy"
/>
<div className="absolute bottom-3 left-3 sm:bottom-6 sm:left-6 bg-canina-blue text-white p-3 sm:p-6 md:p-8 rounded-xl sm:rounded-[2rem] shadow-2xl z-20 max-w-[85%] sm:max-w-[80%] border border-white/10">
<div className="text-xl sm:text-4xl font-black mb-0.5 sm:mb-1 font-lalezar tracking-wide">{getText('about_badge_title', getText('quality', "کیفیت"))}</div>
<div className="text-[9px] sm:text-xs uppercase tracking-widest font-bold opacity-90 font-vazir">{getText('about_badge_subtitle', getText('ultra_pharmaceutical', "استانداردهای فوق‌دارویی"))}</div>
</div>
</div>
<div>
<div className="text-canina-blue text-xs font-bold uppercase tracking-[0.2em] mb-2 sm:mb-4 font-vazir">
{getText('about_label', "میراث ما از آلمان")}
</div>
<h2 className="text-2xl sm:text-3xl lg:text-5xl font-black text-medical-gray-900 leading-tight mb-6 sm:mb-12 font-lalezar tracking-wide">
{getText('about_title', "چرا برند آلمانی Canina مرجع دامپزشکان است؟")}
</h2>
<div className="space-y-4 sm:space-y-6">
{[
{ title: getText('about_item1_title', "مواد اولیه نایاب"), desc: getText('about_item1_desc', "استفاده از پودر صدف لب‌سبز اصل نیوزیلند و مواد ارگانیک با گرید دارویی.") },
{ title: getText('about_item2_title', "فاقد مواد نگهدارنده"), desc: getText('about_item2_desc', "تمامی محصولات ۱۰۰٪ طبیعی و فاقد رنگ‌های مصنوعی و طعم‌دهنده‌های شیمیایی هستند.") },
{ title: getText('about_item3_title', "تاییدیه اروپا"), desc: getText('about_item3_desc', "مطابق با سخت‌گیرانه‌ترین استانداردهای ایمنی مواد غذایی و دارویی در اتحادیه اروپا.") }
].map((item, idx) => (
<div key={idx} className="flex gap-4 items-center">
<div className="w-12 h-12 rounded-2xl bg-medical-gray-50 flex items-center justify-center flex-shrink-0 text-canina-blue font-black font-lalezar text-xl shadow-sm">
{toPersian(idx + 1)}
</div>
<div>
<h3 className="text-lg font-bold text-medical-gray-900 mb-1 font-shabnam">{item.title}</h3>
<p className="text-sm text-slate-700 leading-relaxed font-medium font-sans">{item.desc}</p>
{idx === 0 && (
<span className="text-[10px] text-slate-600 mt-1 block font-medium">
{getText('about_item1_footnote', "* تهیه شده با بالاترین استانداردهای دارویی انسان - کاملاً بی‌خطر در صورت لیسیده شدن توسط حیوان.")}
</span>
)}
{idx === 2 && (
<span className="text-[10px] text-slate-600 mt-1 block font-medium">
{getText('about_item3_footnote', "* تاییدیه رسمی ایمنی مواد غذایی و دارویی (HACCP & IFS) از اتحادیه اروپا.")}
</span>
)}
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* Bottom Banner Placement */}
<BannerPlacement banners={banners} position="home_bottom" />
{/* Call to Action - Elevated with Rich Aesthetics */}
<section className="bg-gradient-to-br from-canina-dark via-canina-blue to-[#0b4d8c] py-14 sm:py-20 relative overflow-hidden font-sans shadow-2xl">
{/* Background Pattern and Highlights */}
<div className="absolute inset-0 opacity-15 bg-[radial-gradient(#ffffff_1.5px,transparent_1.5px)] [background-size:24px_24px] pointer-events-none" />
<div className="absolute -top-24 -right-24 w-96 h-96 bg-cyan-400/20 rounded-full blur-3xl pointer-events-none" />
<div className="absolute -bottom-24 -left-24 w-96 h-96 bg-amber-400/15 rounded-full blur-3xl pointer-events-none" />
<div className="max-w-4xl mx-auto px-4 text-center relative z-10">
<div className="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full bg-white/10 backdrop-blur-md border border-white/20 text-white text-xs font-bold font-vazir mb-6 shadow-md">
<Sparkles className="w-3.5 h-3.5 text-amber-300" />
<span>مشاوره و تشخیص هوشمند بالینی</span>
</div>
<h2 className="text-3xl sm:text-4xl lg:text-5xl font-black text-white mb-6 leading-tight font-lalezar tracking-wide drop-shadow-md">
{getText('cta_title', "می‌خواهید بدانید کدام محصول برای پت شما مناسب‌تر است؟")}
</h2>
<p className="text-blue-100/90 text-base sm:text-lg mb-8 sm:mb-10 leading-relaxed font-shabnam max-w-2xl mx-auto">
{getText('cta_desc', "با استفاده از دستیار هوشمند تشخیصی یا تماس با تیم متخصص دامپزشکی کنینا ایران، بهترین رژیم مکمل درمانی را دریافت کنید.")}
</p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-3.5 sm:gap-5">
<Link
href="/smart-advisor"
className="w-full sm:w-auto inline-flex items-center justify-center gap-2.5 bg-white text-canina-blue px-8 py-4 sm:px-10 sm:py-4.5 rounded-2xl font-black text-base sm:text-lg hover:scale-105 hover:bg-amber-300 hover:text-slate-950 transition-all shadow-xl shadow-black/20 font-vazir group cursor-pointer"
>
<Stethoscope className="w-5 h-5 text-canina-blue group-hover:text-slate-950 transition-colors" />
<span>{getText('cta_btn_primary', "دریافت رژیم مکمل هوشمند")}</span>
</Link>
<Link
href="/trust-seals"
className="w-full sm:w-auto inline-flex items-center justify-center gap-2.5 bg-white/10 hover:bg-white/20 backdrop-blur-md border border-white/30 text-white px-8 py-4 sm:px-10 sm:py-4.5 rounded-2xl font-black text-base sm:text-lg hover:scale-105 transition-all font-vazir shadow-md cursor-pointer"
>
<ShieldCheck className="w-5 h-5 text-emerald-300" />
<span>{getText('cta_btn_secondary', "پروانه دامپزشکی و اصالت کالا")}</span>
</Link>
</div>
</div>
</section>
</>
);
}