- Fix seed-products.ts TS error (implicit any) and BOM handling - Re-run full seed to restore correct Persian encoding in DB - Fix productService query→search param mismatch - Fix IngredientWiki hardcoded port 4000→use settingsStore - Restore seed-products-data.json from git after accidental corruption
144 lines
7.4 KiB
TypeScript
144 lines
7.4 KiB
TypeScript
"use client";
|
||
import React, { useState } from "react";
|
||
import { Play, PlayCircle, Star, ShieldCheck, X } from "lucide-react";
|
||
import { motion, AnimatePresence } from "motion/react";
|
||
import { useRouter } from "next/navigation";
|
||
|
||
const VIDEOS = [
|
||
{
|
||
id: "v1",
|
||
title: "نحوه آمادهسازی کانیهیدروکس",
|
||
doctor: "دکتر کلاوس هنینگ",
|
||
duration: "۱:۴۵",
|
||
thumbnail: "https://images.unsplash.com/photo-1576091160550-217359f42f8c?auto=format&fit=crop&q=80&w=400",
|
||
videoUrl: "https://www.w3schools.com/html/mov_bbb.mp4", // Placeholder real-looking video
|
||
description: "آموزش گام به گام آمادهسازی پودر Canhydrox GAG برای جذب حداکثری در دستگاه گوارش."
|
||
},
|
||
{
|
||
id: "v2",
|
||
title: "اهمیت صدف لبسبز",
|
||
doctor: "دکتر النا اشمیت",
|
||
duration: "۲:۲۰",
|
||
thumbnail: "https://images.unsplash.com/photo-1599443015574-be5fe8a05783?auto=format&fit=crop&q=80&w=400",
|
||
videoUrl: "https://www.w3schools.com/html/movie.mp4",
|
||
description: "چرا صدف لبسبز نیوزیلندی نایابترین و موثرترین ماده برای بازسازی مفصل است؟"
|
||
},
|
||
{
|
||
id: "v3",
|
||
title: "تغذیه هوشمند تولهسگها",
|
||
doctor: "دکتر هلگا فیشر",
|
||
duration: "۳:۱۰",
|
||
thumbnail: "https://images.unsplash.com/photo-1583337130417-3346a1be7dee?auto=format&fit=crop&q=80&w=400",
|
||
videoUrl: "https://www.w3schools.com/html/mov_bbb.mp4",
|
||
description: "دوز مصرفی مکملهای کلسیم در نژادهای بزرگ برای جلوگیری از بدشکلیهای استخوانی."
|
||
}
|
||
];
|
||
|
||
export default function VetGallery({ testimonials = [] }: { testimonials?: any[] }) {
|
||
const router = useRouter();
|
||
const displayItems = testimonials.length > 0 ? testimonials : VIDEOS;
|
||
const [selectedVideo, setSelectedVideo] = useState<any>(null);
|
||
|
||
return (
|
||
<section className="py-24 bg-white font-vazir" dir="rtl">
|
||
<div className="max-w-7xl mx-auto px-4">
|
||
<div className="flex flex-col md:flex-row md:items-end justify-between mb-16 gap-6">
|
||
<div className="max-w-2xl">
|
||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-full text-[10px] font-black uppercase tracking-widest mb-4">
|
||
<Star className="w-3 h-3" />
|
||
Vet Insights
|
||
</div>
|
||
<h2 className="text-4xl md:text-5xl font-black text-medical-gray-900 italic leading-tight">
|
||
مشاوره ویدئویی <span className="text-canina-blue underline decoration-4 decoration-canina-blue/20 underline-offset-8">دوست دامپزشک پت شما</span>
|
||
</h2>
|
||
<p className="text-lg text-medical-gray-500 font-medium mt-6">
|
||
متخصصین آلمانی کانینا مستقیماً با شما صحبت میکنند. نحوه مصرف، مزایای رقابتی و دانش تخصصی پشت هر محصول.
|
||
</p>
|
||
</div>
|
||
<button
|
||
onClick={() => router.push('/videos')}
|
||
className="inline-flex items-center gap-2 text-canina-blue font-bold text-sm hover:translate-x-1 transition-transform rtl:hover:-translate-x-1"
|
||
>
|
||
مشاهده همه ویدئوها
|
||
<Play className="w-4 h-4" />
|
||
</button>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||
{displayItems.map((video: any, index: number) => (
|
||
<motion.button
|
||
key={video.id}
|
||
whileHover={{ y: -8 }}
|
||
onClick={() => setSelectedVideo(video)}
|
||
className="w-full text-right block group cursor-pointer focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none rounded-[2rem] p-2"
|
||
>
|
||
<div className="relative aspect-video rounded-[2rem] overflow-hidden mb-4 shadow-xl">
|
||
<div className="absolute inset-0 bg-medical-gray-900/20 group-hover:bg-transparent transition-colors z-10" />
|
||
<img
|
||
src={video.thumbnail || video.imageUrl || '/images/vets/vet1.webp'}
|
||
alt={video.title || video.vetName}
|
||
className="w-full h-full object-cover grayscale-[30%] group-hover:grayscale-0 transition-all duration-700"
|
||
/>
|
||
<div className="absolute inset-0 flex items-center justify-center z-20">
|
||
<div className="w-16 h-16 bg-white/90 backdrop-blur-sm rounded-full flex items-center justify-center text-canina-blue scale-90 group-hover:scale-100 group-hover:bg-white transition-all shadow-xl">
|
||
<Play className="w-6 h-6 ml-1" />
|
||
</div>
|
||
</div>
|
||
<div className="absolute bottom-4 right-4 bg-black/60 backdrop-blur-md text-white px-2 py-1 rounded-lg text-xs font-black z-20 font-vazir flex items-center gap-1 shadow-lg">
|
||
<span>⏱️</span>
|
||
<span>{video.duration || (index === 0 ? '۱:۴۵' : index === 1 ? '۲:۲۰' : '۳:۱۰')}</span>
|
||
</div>
|
||
</div>
|
||
<h4 className="text-lg font-black text-medical-gray-900 mb-2 group-hover:text-canina-blue transition-colors leading-tight font-vazir">
|
||
{video.title || video.quote?.substring(0, 40) + '...'}
|
||
</h4>
|
||
<div className="flex items-center gap-2 text-medical-gray-500 font-bold text-sm font-vazir">
|
||
<ShieldCheck className="w-4 h-4 text-canina-blue" />
|
||
{video.doctor || video.vetName}
|
||
</div>
|
||
</motion.button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* Video Modal */}
|
||
<AnimatePresence>
|
||
{selectedVideo && (
|
||
<div className="fixed inset-0 z-[110] flex items-center justify-center p-4">
|
||
<motion.div
|
||
initial={{ opacity: 0 }}
|
||
animate={{ opacity: 1 }}
|
||
exit={{ opacity: 0 }}
|
||
onClick={() => setSelectedVideo(null)}
|
||
className="absolute inset-0 bg-medical-gray-900/90 backdrop-blur-xl"
|
||
/>
|
||
<motion.div
|
||
initial={{ opacity: 0, scale: 0.9 }}
|
||
animate={{ opacity: 1, scale: 1 }}
|
||
exit={{ opacity: 0, scale: 0.9 }}
|
||
className="bg-black w-full max-w-5xl aspect-video rounded-[3rem] overflow-hidden relative z-10 shadow-2xl border border-white/10"
|
||
>
|
||
<button
|
||
onClick={() => setSelectedVideo(null)}
|
||
className="absolute top-6 left-6 text-white/50 hover:text-white z-20 transition-colors bg-black/20 p-2 rounded-full"
|
||
>
|
||
<X className="w-8 h-8" />
|
||
</button>
|
||
<video
|
||
src={selectedVideo.videoUrl}
|
||
controls
|
||
autoPlay
|
||
className="w-full h-full object-contain"
|
||
/>
|
||
<div className="absolute bottom-0 left-0 right-0 p-8 bg-gradient-to-t from-black/80 to-transparent">
|
||
<h3 className="text-white text-2xl font-black mb-2">{selectedVideo.title}</h3>
|
||
<p className="text-white/60 text-sm font-medium">{selectedVideo.doctor}</p>
|
||
</div>
|
||
</motion.div>
|
||
</div>
|
||
)}
|
||
</AnimatePresence>
|
||
</section>
|
||
);
|
||
}
|