canina/frontend/application/components/ArchivePage.tsx

730 lines
39 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 React, { useState, useMemo, useEffect, useCallback } from "react";
import { toPersian } from "../lib/utils";
import { Product, PetType } from "../lib/data/products";
import { usePetStore } from "../lib/store/usePetStore";
import { productService } from "../lib/services/productService";
import Link from "next/link";
import { motion, AnimatePresence } from "motion/react";
import { ProductCardSkeleton } from "./Skeleton";
import { toast } from "sonner";
import {
Search,
Filter,
Dog,
Cat,
ShieldCheck,
ChevronLeft,
ChevronRight,
Activity,
Sparkles,
Stethoscope,
HeartPulse,
Heart,
AlertCircle,
Plus,
Loader2
} from "lucide-react";
import { useCartStore } from "../lib/store/cartStore";
import { useSettingsStore } from "../lib/store/settingsStore";
import SafeImage from "./SafeImage";
import BannerPlacement from "./BannerPlacement";
import { Banner } from "../lib/types";
const ICON_MAP: Record<string, React.ReactNode> = {
joints: <HeartPulse className="w-4 h-4" />,
immune: <ShieldCheck className="w-4 h-4" />,
energy: <Activity className="w-4 h-4" />,
"special-care": <Stethoscope className="w-4 h-4" />,
general: <Heart className="w-4 h-4" />,
nutrition: <Sparkles className="w-4 h-4" />,
};
const CATEGORY_MAP: Record<string, { category?: string; query?: string; symptoms?: string[] }> = {
// Main Categories
"joints": { category: "joints" },
"immune": { category: "immune" },
"energy": { category: "energy" },
"special-care": { category: "special-care" },
// Persian Fallbacks (for robust matching)
"مفاصل و استخوان": { category: "joints" },
"تقویت سیستم ایمنی و گوارش": { category: "immune" },
"ویتامین‌ها و انرژی‌بخش‌ها": { category: "energy" },
"مراقبت‌های ویژه (پوست، دندان و چشم)": { category: "special-care" },
// Solutions
"آرتروز سگ‌های پیر": { category: "joints", symptoms: ["درد مفاصل", "سختی در بلند شدن", "لنگیدن"] },
"رشد استخوانی توله‌سگ": { category: "joints", symptoms: ["رشد سریع توله‌سگ"] },
"تقویت رباط و تاندون": { category: "joints", query: "تاندون" },
"پیشگیری از بیماری": { category: "immune", symptoms: ["ضعف بعد از بیماری"] },
"رفع اسهال و یبوست": { category: "immune", symptoms: ["اسهال", "یبوست", "اسهال مزمن"] },
"پروبیوتیک‌ها": { category: "immune", query: "فیبر" },
"مکمل‌های مولتی‌ویتامین": { category: "energy", query: "ویتامین" },
"افزایش اشتها": { category: "energy", symptoms: ["بی‌اشتهایی"] },
"رشد و بلوغ": { category: "energy", query: "انرژی" },
"سلامت پوست و مفاصل": { category: "special-care", symptoms: ["خشکی پوست", "ریزش مو", "خارش"] },
"رفع جرم دندان": { category: "special-care", symptoms: ["جرم دندان", "بوی بد دهان", "التهاب لثه"] },
"شستشوی چشم": { category: "special-care", query: "چشم" },
};
const ArchiveProductCard: React.FC<{ product: Product }> = ({ product }) => {
const { addItem } = useCartStore();
const cartItem = useCartStore((s) => s.items.find(i => i.product.id === product.id));
const [isAdding, setIsAdding] = useState(false);
const activePet = usePetStore(state => state.pets.find(p => p.id === state.activePetId) || null);
const productUrl = `/shop/${product.slug || product.id}`;
const handleAddToCart = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
setIsAdding(true);
addItem(product, 1);
toast.success(`${product.name} به سبد خرید اضافه شد`);
setTimeout(() => setIsAdding(false), 400);
};
const compatibility = useMemo(() => {
if (!activePet) return null;
const sameSpecies = product.suitableFor === activePet.type || product.suitableFor === "هر دو";
const matchedSymptom = (activePet.medicalConditions || []).find(mc =>
(product.symptoms || []).some(s => mc.includes(s) || s.includes(mc))
);
if (!sameSpecies) return { type: 'alert', text: `مخصوص ${product.suitableFor}` };
if (matchedSymptom) return { type: 'success', text: `توصیه شده برای ${matchedSymptom} ${activePet.name}` };
if (sameSpecies) return { type: 'neutral', text: `مناسب برای ${activePet.name}` };
return null;
}, [product, activePet]);
return (
<motion.div
layout
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="h-full"
>
<Link
href={productUrl}
className="group bg-white rounded-[2.5rem] border border-medical-gray-200 overflow-hidden hover:shadow-2xl transition-all flex flex-col h-full relative"
>
{product.specialBadge && (
<div className="absolute top-4 right-4 z-10 bg-canina-blue text-white text-[9px] font-black uppercase tracking-widest px-3 py-1 rounded-full shadow-lg">
{product.specialBadge}
</div>
)}
{compatibility && (
<div className={`absolute top-14 right-4 z-10 text-[8px] font-black uppercase tracking-widest px-3 py-1 rounded-full shadow-md flex items-center gap-1 ${compatibility.type === 'alert' ? 'bg-amber-100 text-amber-700' :
compatibility.type === 'success' ? 'bg-green-100 text-green-700' : 'bg-medical-gray-100 text-medical-gray-600'
}`}>
{compatibility.type === 'alert' ? <AlertCircle className="w-2.5 h-2.5" /> : compatibility.type === 'success' ? <Heart className="w-2.5 h-2.5" /> : <Sparkles className="w-2.5 h-2.5" />}
{compatibility.text}
</div>
)}
<div className="aspect-square bg-medical-gray-50 flex items-center justify-center p-8 overflow-hidden relative">
<SafeImage
src={product.image}
alt={product.name}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw)"
className="w-full h-full group-hover:scale-110 transition-transform duration-700"
imgClassName="object-contain"
/>
<div className="absolute bottom-4 left-4 flex gap-2">
{(product.suitableFor === "سگ" || product.suitableFor === "هر دو") && (
<div className="w-7 h-7 bg-white rounded-lg flex items-center justify-center text-medical-gray-400 border border-medical-gray-100 shadow-sm">
<Dog className="w-4 h-4" />
</div>
)}
{(product.suitableFor === "گربه" || product.suitableFor === "هر دو") && (
<div className="w-7 h-7 bg-white rounded-lg flex items-center justify-center text-medical-gray-400 border border-medical-gray-100 shadow-sm">
<Cat className="w-4 h-4" />
</div>
)}
</div>
</div>
<div className="p-6 flex flex-col flex-1">
<div className="text-[10px] font-bold text-canina-blue uppercase tracking-widest mb-2">{product.category}</div>
<div className="flex flex-col gap-1 mb-3">
<h3 dir="rtl" className="text-base font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors leading-tight text-right font-vazir">
{product.nameFa || product.name}
</h3>
{product.nameEn && (
<span dir="ltr" className="text-[11px] font-bold text-slate-400 font-sans text-left block">
{product.nameEn}
</span>
)}
</div>
<div className="flex flex-wrap gap-1">
{product.symptoms.slice(0, 2).map((s, i) => (
<span key={i} className="text-[9px] font-bold bg-medical-gray-100 text-medical-gray-500 px-2 py-0.5 rounded-md">
{s}
</span>
))}
</div>
<div className="mt-auto flex items-center justify-between pt-4 border-t border-medical-gray-50 gap-2">
{!useSettingsStore.getState().getText("catalog_hide_prices", "false").includes("true") ? (
<span className="font-black text-medical-gray-900 font-vazir text-sm sm:text-base">{product.price}</span>
) : (
<span className="text-xs font-bold text-amber-600 bg-amber-50 px-2 py-1 rounded-md">تماس جهت استعلام قیمت</span>
)}
{(product.packageSize !== undefined && product.packageSize !== null ? Number(product.packageSize) : 100) <= 0 ? (
<span className="px-2.5 py-1.5 rounded-xl bg-rose-50 text-rose-600 border border-rose-100 text-[11px] font-bold font-vazir">
ناموجود
</span>
) : !useSettingsStore.getState().getText("catalog_disable_cart", "false").includes("true") && (
cartItem && cartItem.quantity > 0 ? (
<div
onClick={(e) => { e.preventDefault(); e.stopPropagation(); }}
className="flex items-center gap-1 bg-canina-blue/10 border border-canina-blue/20 rounded-xl p-1"
>
<button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
useCartStore.getState().updateQuantity(product.id, cartItem.quantity + 1);
}}
className="w-7 h-7 rounded-lg bg-canina-blue text-white flex items-center justify-center font-bold text-xs"
>
+
</button>
<span className="w-5 text-center font-black text-canina-blue text-xs font-vazir">
{toPersian(cartItem.quantity)}
</span>
<button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
useCartStore.getState().updateQuantity(product.id, cartItem.quantity - 1);
}}
className="w-7 h-7 rounded-lg bg-white text-medical-gray-700 flex items-center justify-center font-bold text-xs shadow-sm"
>
-
</button>
</div>
) : (
<button
onClick={handleAddToCart}
disabled={isAdding}
className="px-3 py-2 rounded-xl bg-canina-blue text-white text-xs font-black flex items-center gap-1.5 hover:bg-canina-dark transition-all disabled:opacity-50 shadow-md shadow-canina-blue/20"
>
{isAdding ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Plus className="w-3.5 h-3.5" />}
<span>خرید</span>
</button>
)
)}
</div>
</div>
</Link>
</motion.div>
);
};
import { useRouter } from 'next/navigation';
export default function ArchivePage({
initialCategory = "all",
initialSearch = "",
initialPetType = "all",
initialSymptoms = ""
}: {
initialCategory?: string,
initialSearch?: string,
initialPetType?: string,
initialSymptoms?: string
}) {
const router = useRouter();
const [prescriptionFilter, setPrescriptionFilter] = useState<"all" | "prescription" | "otc">("all");
const [selectedCategory, setSelectedCategory] = useState(initialCategory);
const [selectedPet, setSelectedPet] = useState<PetType | "all">((initialPetType as PetType) || "all");
const [activeSymptoms, setActiveSymptoms] = useState<string[]>(initialSymptoms ? initialSymptoms.split(',') : []);
const [searchQuery, setSearchQuery] = useState(initialSearch);
const [isUpdating, setIsUpdating] = useState(false);
const [isMobileFilterOpen, setIsMobileFilterOpen] = useState(false);
const [filteredProducts, setFilteredProducts] = useState<Product[]>([]);
const [sortBy, setSortBy] = useState<string>("createdAt");
const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc");
const [symptomSearch, setSymptomSearch] = useState("");
const [categories, setCategories] = useState<{ id: string; label: string; icon: React.ReactNode }[]>([]);
const [symptoms, setSymptoms] = useState<string[]>([]);
const [banners, setBanners] = useState<Banner[]>([]);
useEffect(() => {
const loadFiltersAndBanners = async () => {
try {
const [filters, bannerData] = await Promise.all([
productService.getActiveFilters(),
productService.getBanners()
]);
const mapped = [
{ id: "all", label: "همه محصولات", icon: <Activity className="w-4 h-4" /> },
...filters.categories.map(c => ({
id: c.slug,
label: c.name,
icon: ICON_MAP[c.slug] || <Activity className="w-4 h-4" />
}))
];
setCategories(mapped);
setSymptoms(filters.symptoms);
if (Array.isArray(bannerData)) {
setBanners(bannerData);
}
} catch (e) {
console.error("Failed to load active filters or banners:", e);
}
};
loadFiltersAndBanners();
}, []);
const CATEGORY_LABELS = useMemo(() => {
const labels: Record<string, string> = { all: "همه محصولات" };
categories.forEach(c => {
labels[c.id] = c.label;
});
return labels;
}, [categories]);
// Sync state with prop change (e.g. from Header menu)
useEffect(() => {
// Normalize Input (Trim and lowercase)
const normSearch = (initialSearch || "").trim().toLowerCase();
const normCat = initialCategory.trim().toLowerCase();
const mapKey = normSearch || normCat;
const mapping = CATEGORY_MAP[mapKey];
if (selectedCategory === initialCategory && searchQuery === initialSearch) {
return;
}
Promise.resolve().then(() => {
setIsUpdating(true);
// Reset ALL other filters when a new category/solution is selected from menu
setSelectedPet("all");
setActiveSymptoms([]);
setSearchQuery("");
if (mapping) {
if (mapping.category) setSelectedCategory(mapping.category);
if (mapping.query) setSearchQuery(mapping.query);
if (mapping.symptoms) {
setActiveSymptoms(mapping.symptoms);
}
} else {
setSelectedCategory(initialCategory);
setSearchQuery(initialSearch);
if (initialSearch && symptoms.includes(initialSearch)) {
setActiveSymptoms([initialSearch]);
}
}
});
const timer = setTimeout(() => {
window.scrollTo({ top: 0, behavior: "smooth" });
}, 400);
return () => clearTimeout(timer);
}, [initialCategory, initialSearch, selectedCategory, searchQuery, symptoms]);
// Update URL Query Parameters
useEffect(() => {
const params = new URLSearchParams();
if (selectedCategory && selectedCategory !== "all") params.set('category', selectedCategory);
if (selectedPet && selectedPet !== "all") params.set('petType', selectedPet);
if (searchQuery) params.set('search', searchQuery);
if (activeSymptoms.length > 0) params.set('symptoms', activeSymptoms.join(','));
if (prescriptionFilter !== "all") params.set('rx', prescriptionFilter);
const queryString = params.toString();
const newUrl = `/shop${queryString ? `?${queryString}` : ''}`;
router.push(newUrl, { scroll: false });
}, [selectedCategory, selectedPet, searchQuery, activeSymptoms, prescriptionFilter, router]);
const fetchProducts = useCallback(async () => {
setIsUpdating(true);
try {
const res = await productService.getProducts({
category: selectedCategory,
petType: selectedPet,
query: searchQuery,
sortBy,
sortOrder,
limit: 999,
});
let result = res.data;
// Filter with OR logic (union of symptoms) if symptoms are active
if (activeSymptoms.length > 0) {
result = result.filter(p => p.symptoms && p.symptoms.some(s => activeSymptoms.includes(s)));
}
// Filter by prescription requirement (OTC vs Prescription)
if (prescriptionFilter === "prescription") {
result = result.filter(p => Boolean(p.requiresRx) || p.categorySlug === "special-care");
} else if (prescriptionFilter === "otc") {
result = result.filter(p => !p.requiresRx && p.categorySlug !== "special-care");
}
setFilteredProducts(result);
} catch (error) {
console.error("Failed to fetch products:", error);
toast.error("خطا در دریافت لیست محصولات از سرور. لطفاً صفحه را رفرش کنید.");
} finally {
setIsUpdating(false);
}
}, [selectedCategory, selectedPet, searchQuery, sortBy, sortOrder, activeSymptoms, prescriptionFilter]);
useEffect(() => {
Promise.resolve().then(() => fetchProducts());
}, [fetchProducts]);
const toggleSymptom = (s: string) => {
setActiveSymptoms(prev => prev.includes(s) ? prev.filter(item => item !== s) : [...prev, s]);
};
return (
<div className="min-h-screen bg-medical-gray-50 pb-20 px-4 pt-10 font-vazir" dir="rtl">
<div className="max-w-7xl mx-auto">
{/* Standard Breadcrumb Navigation, Mobile Filter & Integrated Back Button */}
<div className="flex items-center justify-between mb-8 pb-4 border-b border-medical-gray-200/60 font-vazir gap-2" dir="rtl">
{/* Breadcrumb - right side in RTL */}
<div className="flex items-center gap-1.5 text-xs font-bold text-medical-gray-400 overflow-hidden min-w-0">
<span className="hidden sm:inline cursor-pointer hover:text-canina-blue transition-colors shrink-0" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="hidden sm:block w-3 h-3 text-medical-gray-300 shrink-0" />
<span className="cursor-pointer hover:text-canina-blue transition-colors shrink-0" onClick={() => { setSelectedCategory("all"); }}>کاتالوگ</span>
{selectedCategory !== "all" && (
<>
<ChevronLeft className="w-3 h-3 text-medical-gray-300 shrink-0" />
<span className="text-canina-blue font-black truncate">{CATEGORY_LABELS[selectedCategory] || selectedCategory}</span>
</>
)}
</div>
<div className="flex items-center gap-2 shrink-0">
{/* Mobile Filter Button */}
<button
onClick={() => setIsMobileFilterOpen(!isMobileFilterOpen)}
className="lg:hidden flex-shrink-0 flex items-center gap-1.5 bg-canina-blue text-white px-3 py-1.5 rounded-lg text-xs font-bold shadow-xs cursor-pointer"
>
<Filter className="w-3.5 h-3.5" />
<span>فیلترها {activeSymptoms.length > 0 || selectedPet !== "all" || selectedCategory !== "all" ? "•" : ""}</span>
</button>
{/* Back Button - leftmost in RTL */}
<button
onClick={() => router.push('/')}
className="flex-shrink-0 px-3 py-1.5 bg-white border border-medical-gray-200 rounded-lg text-medical-gray-600 shadow-xs flex items-center gap-1.5 font-bold text-xs hover:border-canina-blue hover:text-canina-blue transition-all cursor-pointer"
>
<span>بازگشت</span>
<ChevronLeft className="w-3.5 h-3.5" />
</button>
</div>
</div>
{/* Shop Top Banner Placement */}
<BannerPlacement banners={banners} position="shop_top" className="!px-0 !py-2 mb-6" />
<div className="flex flex-col lg:flex-row gap-8">
{/* Mobile Overlay Backdrop */}
{isMobileFilterOpen && (
<div
className="lg:hidden fixed inset-0 bg-black/50 z-40 backdrop-blur-xs transition-opacity"
onClick={() => setIsMobileFilterOpen(false)}
/>
)}
{/* Sidebar Filters - Collapsible on Mobile */}
<aside className={`lg:w-72 flex-shrink-0 space-y-6 ${isMobileFilterOpen ? 'fixed inset-y-0 right-0 z-50 w-4/5 max-w-xs bg-white p-6 overflow-y-auto shadow-2xl space-y-6' : 'hidden lg:block'}`}>
<div className="bg-white rounded-[2rem] lg:p-6 border-0 lg:border lg:border-medical-gray-200 shadow-none lg:shadow-sm">
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-2">
<Filter className="w-5 h-5 text-canina-blue" />
<h3 className="font-black text-medical-gray-900">فیلترهای تخصصی</h3>
</div>
<button
onClick={() => setIsMobileFilterOpen(false)}
className="lg:hidden text-xs text-medical-gray-400 font-bold p-1 hover:text-red-500"
>
بستن
</button>
</div>
<div className="space-y-6">
{/* Prescription / Household Filter */}
<div>
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block mb-3">نوع دسترسی و نسخه</span>
<div className="flex flex-col gap-2">
{[
{ id: "all", label: "همه داروها و مکمل‌ها" },
{ id: "otc", label: "مکمل‌های خانگی (بدون نیاز به نسخه)" },
{ id: "prescription", label: "داروها و مکمل‌های تخصصی (با نسخه)" },
].map(type => (
<button
key={type.id}
onClick={() => setPrescriptionFilter(type.id as "all" | "prescription" | "otc")}
className={`w-full py-2 px-3 rounded-xl text-xs font-bold border transition-all text-right flex items-center justify-between ${prescriptionFilter === type.id ? 'bg-canina-blue border-canina-blue text-white shadow-md' : 'bg-white border-medical-gray-200 text-medical-gray-600 hover:bg-medical-gray-50'}`}
>
<span>{type.label}</span>
{prescriptionFilter === type.id && <Sparkles className="w-3.5 h-3.5 text-amber-300" />}
</button>
))}
</div>
</div>
{/* Pet Type */}
<div>
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block mb-3">نوع پت</span>
<div className="grid grid-cols-3 gap-2">
{[
{ id: "all", label: "هر دو", icon: <Activity className="w-3 h-3" /> },
{ id: "سگ", label: "سگ", icon: <Dog className="w-3 h-3" /> },
{ id: "گربه", label: "گربه", icon: <Cat className="w-3 h-3" /> },
].map(pet => (
<button
key={pet.id}
onClick={() => setSelectedPet(pet.id as PetType | "all")}
className={`py-2 rounded-xl text-[10px] font-black border transition-all flex flex-col items-center gap-1 ${selectedPet === pet.id ? 'bg-canina-blue border-canina-blue text-white shadow-lg shadow-canina-blue/20' : 'bg-white border-medical-gray-200 text-medical-gray-400'}`}
>
{pet.icon}
{pet.label}
</button>
))}
</div>
</div>
{/* Solutions */}
<div>
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block mb-3">راهکار درمانی</span>
<div className="flex flex-col gap-2">
{categories.map(cat => (
<button
key={cat.id}
onClick={() => { setSelectedCategory(cat.id); setIsMobileFilterOpen(false); }}
className={`flex items-center gap-3 px-4 py-3 rounded-2xl text-xs font-bold transition-all border ${selectedCategory === cat.id ? 'bg-canina-blue border-canina-blue text-white' : 'bg-white border-medical-gray-100 text-medical-gray-600 hover:border-canina-blue/30'}`}
>
{cat.icon}
{cat.label}
</button>
))}
</div>
</div>
{/* Symptoms Pill Tags with Search Field */}
<div>
<div className="flex items-center justify-between mb-3">
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">جستجو بر اساس علائم</span>
{activeSymptoms.length > 0 && (
<button
onClick={() => setActiveSymptoms([])}
className="text-[10px] font-bold text-canina-blue hover:underline"
>
پاک کردن
</button>
)}
</div>
<div className="relative mb-3">
<input
type="text"
placeholder="جستجوی علائم..."
value={symptomSearch}
onChange={(e) => setSymptomSearch(e.target.value)}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 text-xs outline-none focus:border-canina-blue font-vazir"
/>
</div>
<div className="flex flex-wrap gap-1.5 max-h-48 overflow-y-auto scrollbar-thin scrollbar-thumb-medical-gray-200 scrollbar-track-transparent pr-0.5">
{symptoms.length === 0 ? (
<span className="text-[10px] text-medical-gray-400">در حال بارگذاری...</span>
) : symptoms
.filter(s => s.toLowerCase().includes(symptomSearch.toLowerCase()))
.map(s => (
<button
key={s}
onClick={() => toggleSymptom(s)}
className={`px-2.5 py-1 rounded-full text-[10px] font-bold transition-all border whitespace-nowrap ${activeSymptoms.includes(s)
? 'bg-canina-blue border-canina-blue text-white shadow-sm shadow-canina-blue/30'
: 'bg-medical-gray-50 border-medical-gray-200 text-medical-gray-500 hover:border-canina-blue/40 hover:text-canina-blue'
}`}
>
{s}
</button>
))}
</div>
</div>
</div>
</div>
{/* Promo Card */}
<div className="bg-medical-gray-900 rounded-[2rem] p-6 text-white relative overflow-hidden group">
<div className="absolute -top-10 -left-10 w-32 h-32 bg-canina-blue rounded-full blur-3xl opacity-20 group-hover:opacity-40 transition-opacity" />
<h4 className="text-lg font-black italic mb-4 relative z-10 underline decoration-canina-blue underline-offset-8">مشاوره رایگان</h4>
<p className="text-xs text-white/60 leading-relaxed mb-6 relative z-10">اگر نمیدانید کدام ترکیب برای پت شما مناسب است، همین حالا با دامپزشکان ما تماس بگیرید.</p>
<a href="tel:0218888" className="w-full bg-white text-medical-gray-900 py-3 rounded-xl text-xs font-black hover:scale-105 transition-transform relative z-10 flex items-center justify-center">شماره تماس: ۰۲۱-۸۸۸۸</a>
</div>
</aside>
{/* Main Content */}
<main className="flex-1 relative">
<div className="flex flex-col sm:flex-row items-center justify-between mb-6 gap-4">
<h2 className="text-3xl font-black text-medical-gray-900">کاتولوگ دارویی <span className="text-canina-blue">Canina</span></h2>
<div className="flex flex-wrap sm:flex-nowrap items-center gap-3 w-full sm:w-auto">
{/* Sort Dropdown */}
<div className="flex items-center gap-2 bg-white border border-medical-gray-200 rounded-2xl px-3 py-2 text-xs font-bold shadow-xs">
<span className="text-medical-gray-400 whitespace-nowrap">مرتبسازی:</span>
<select
value={`${sortBy}:${sortOrder}`}
onChange={(e) => {
const [b, o] = e.target.value.split(':');
setSortBy(b);
setSortOrder(o as 'asc' | 'desc');
}}
className="bg-transparent font-black text-medical-gray-800 outline-none cursor-pointer"
>
<option value="createdAt:desc">جدیدترین</option>
<option value="createdAt:asc">قدیمیترین</option>
<option value="priceValue:asc">ارزانترین</option>
<option value="priceValue:desc">گرانترین</option>
<option value="nameFa:asc">نام (الف - ی)</option>
</select>
</div>
<div className="relative w-full sm:w-64">
<Search className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-medical-gray-400" />
<input
type="text"
placeholder="جستجوی محصول..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full bg-white border border-medical-gray-200 rounded-full py-2.5 pr-11 pl-4 text-xs font-bold focus:outline-none focus:ring-2 focus:ring-canina-blue/20"
/>
</div>
</div>
</div>
{/* Active Filters Bar with X Dismiss Cross Buttons */}
{(selectedCategory !== "all" || selectedPet !== "all" || activeSymptoms.length > 0 || searchQuery) && (
<div className="flex flex-wrap items-center gap-2 mb-6 bg-white p-4 rounded-2xl border border-medical-gray-200 shadow-sm font-vazir" dir="rtl">
<span className="text-xs font-black text-medical-gray-400 ml-2">فیلترهای فعال:</span>
{selectedCategory !== "all" && (
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-xl text-xs font-black border border-canina-blue/20">
{CATEGORY_LABELS[selectedCategory] || selectedCategory}
<button onClick={() => setSelectedCategory("all")} className="hover:text-red-500 text-sm leading-none"></button>
</span>
)}
{selectedPet !== "all" && (
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-xl text-xs font-black border border-canina-blue/20">
پت: {selectedPet}
<button onClick={() => setSelectedPet("all")} className="hover:text-red-500 text-sm leading-none"></button>
</span>
)}
{activeSymptoms.map(sym => (
<span key={sym} className="inline-flex items-center gap-1.5 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-xl text-xs font-black border border-canina-blue/20">
علائم: {sym}
<button onClick={() => toggleSymptom(sym)} className="hover:text-red-500 text-sm leading-none"></button>
</span>
))}
{searchQuery && (
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-xl text-xs font-black border border-canina-blue/20">
جستجو: {searchQuery}
<button onClick={() => setSearchQuery("")} className="hover:text-red-500 text-sm leading-none"></button>
</span>
)}
<button
onClick={() => { setSelectedCategory("all"); setSelectedPet("all"); setActiveSymptoms([]); setSearchQuery(""); }}
className="text-xs font-bold text-red-500 hover:underline mr-auto"
>
حذف همه فیلترها
</button>
</div>
)}
<AnimatePresence mode="wait">
{isUpdating ? (
<div key="skeleton" className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6">
{Array.from({ length: 8 }).map((_, i) => (
<ProductCardSkeleton key={i} />
))}
</div>
) : filteredProducts.length > 0 ? (
<>
<div key="grid" className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6">
<AnimatePresence mode="popLayout">
{filteredProducts.map((p: Product) => (
<ArchiveProductCard key={p.id} product={p} />
))}
</AnimatePresence>
</div>
{/* SEO Category Rich Description Section (Rendered below products to maintain primary UX while boosting category SEO) */}
{selectedCategory !== "all" && (
<div className="mt-12 bg-white border border-medical-gray-200 rounded-[2.5rem] p-8 md:p-10 shadow-sm space-y-4 font-vazir">
<div className="flex items-center gap-2">
<span className="w-2.5 h-2.5 rounded-full bg-canina-blue" />
<h3 className="text-lg md:text-xl font-black text-medical-gray-900">
راهنمای تخصصی و درمانی {CATEGORY_LABELS[selectedCategory] || selectedCategory}
</h3>
</div>
<p className="text-xs md:text-sm text-medical-gray-600 leading-relaxed">
{selectedCategory === 'joints' &&
'مکمل‌های تخصصی مفاصل و استخوان کنینا آلمان (Canina Pharma) فرموله شده با عصاره خالص صدف سبز نیوزیلند (GAG)، گلوکوزامین، کندرویتین سولفات و مواد معدنی فعال جهت درمان و پیشگیری از آرتروز، دیسپلازی مفصل ران، ضعف لیگامنت‌ها و تسریع روند بهبود شکستگی‌های استخوانی در سگ‌ها و گربه‌ها.'}
{selectedCategory === 'immune' &&
'مکمل‌های تقویت سیستم ایمنی و سلامت دستگاه گوارش کنینا شامل پروبیوتیک‌های زیست‌سازگار، اینولین، ال‌گلوتامین و مخمر آبجو ارگانیک با هدف تنظیم فلور روده، جلوگیری از عفونت‌های مزمن، رفع اسهال و یبوست و افزایش مقاومت طبیعی بدن پت در برابر پاتوژن‌ها.'}
{selectedCategory === 'energy' &&
'مولتی‌ویتامین‌ها و انرژی‌بخش‌های بالینی کنینا با نسبت بالانس‌شده ویتامین‌های A، D3، E و گروه B، به همراه اسیدهای چرب امگا ۳ و ۶ برای ارتقای شادابی، بهبود اشتهای از دست رفته، پشتیبانی از توله‌های در حال رشد و حیوانات در دوران نقاهت و سالمندی.'}
{selectedCategory === 'special-care' &&
'محصولات درمانی و مراقبت ویژه پوست، مو، چشم و دهان و دندان کنینا بدون مواد شیمیایی آسیب‌رسان و با استاندارد دارویی اروپا برای پیشگیری از ایجاد پلاک دندان، درمان ریزش موی ناشی از کمبودهای تغذیه‌ای و التهابات آلرژیک.'}
{!['joints', 'immune', 'energy', 'special-care'].includes(selectedCategory) &&
'تمامی مکمل‌های درمانی و تقویتی کنینا آلمان با ۱۰۰٪ ترکیبات ارگانیک و مطابق با بالاترین استانداردهای داروسازی اروپا (IFS & HACCP) تولید و به صورت رسمی در ایران توزیع می‌گردند.'}
</p>
<div className="pt-2 flex flex-wrap gap-2 text-[11px] font-bold text-canina-blue">
<span className="bg-canina-blue/5 px-3 py-1 rounded-lg border border-canina-blue/10">فرمولاسیون اختصاصی Canina Pharma آلمان</span>
<span className="bg-canina-blue/5 px-3 py-1 rounded-lg border border-canina-blue/10">مورد تایید کلینیکهای تخصصی دامپزشکی</span>
<span className="bg-canina-blue/5 px-3 py-1 rounded-lg border border-canina-blue/10">پروانه بهداشتی واردات رسمی</span>
</div>
</div>
)}
</>
) : (
<div key="empty" className="bg-white rounded-[3rem] p-20 text-center border-2 border-dashed border-medical-gray-200 flex flex-col items-center">
<div className="w-20 h-20 bg-medical-gray-50 rounded-full flex items-center justify-center text-medical-gray-300 mb-6">
<Search className="w-10 h-10" />
</div>
<h3 className="text-2xl font-black text-medical-gray-900 mb-2">محصولی یافت نشد!</h3>
<p className="text-medical-gray-400 max-w-sm mb-8 font-bold">با فیلترهای فعلی محصولی مطابق با نیاز شما پیدا نکردیم. لطفاً فیلترها را گستردهتر کنید یا دکمه ریست را بزنید.</p>
<button
onClick={() => {
router.push('/shop');
setSelectedCategory("all");
setSelectedPet("all");
setActiveSymptoms([]);
setSearchQuery("");
}}
className="bg-canina-blue text-white px-8 py-3 rounded-xl font-black text-sm hover:scale-105 transition-transform shadow-lg shadow-canina-blue/20"
>
پاک کردن همه فیلترها و نمایش همه
</button>
</div>
)}
</AnimatePresence>
</main>
</div>
</div>
</div>
);
}